From a7468d3f40342dbc53f026c56c7bc0f75a01b20f Mon Sep 17 00:00:00 2001 From: deadvey Date: Thu, 3 Apr 2025 21:42:37 +0100 Subject: [PATCH] Gemini version --- src/main.rs | 249 +++++++++++++++++++++------------------------------- 1 file changed, 99 insertions(+), 150 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2659a30..b1e49ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::io::{stdin,stdout,Write}; use colored::Colorize; use regex::Regex; use url::{Url, ParseError}; +use std::fs; fn clear_screen() { println!("clearing"); @@ -11,179 +12,127 @@ fn clear_screen() { .expect("Failed to clear screen"); } -fn parse_markdown(page_content: String) -> (String, Vec) { +fn parse_gemtext(page_content: String) -> (String, Vec) { let mut parsed_page_content: String = "".to_string(); let mut hyperlink_number_counter: u64 = 0; let mut links: Vec = Vec::new(); - let (screen_width, _screen_height) = termion::terminal_size().unwrap(); // So the horizontal line (
) spans the whole console + let mut preformatted_code_toggle = false; - for line in page_content.lines() { - let mut parsed_line: String = line.to_string(); - // Bold - let bold_regex = Regex::new(r"((\*\*)|(__))(.*?)((\*\*)|(__))").unwrap(); - parsed_line = bold_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - caps[4].bold().to_string() - }).to_string(); + for line in page_content.lines() { + let mut parsed_line: String = line.to_string(); + let mut remove_line = false; - // Strikethrough - let strikethrough_regex = Regex::new(r"~~(.*?)~~").unwrap(); - parsed_line = strikethrough_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - caps[1].strikethrough().to_string() - }).to_string(); + // preformatted text + let preformatted_text_regex = Regex::new(r"^```(.*)").unwrap(); + parsed_line = preformatted_text_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + // Flip the toggle + preformatted_code_toggle = ! preformatted_code_toggle; - // Horizontal lines - let hr_regex = Regex::new(r"^(\*\*\*)|(---)|(___)$").unwrap(); - parsed_line = hr_regex.replace_all(&parsed_line, |_caps: ®ex::Captures| { - let mut result: String = "\n".to_string(); - for _x in 0..screen_width/2 { - result += "- "; + if caps[1] == *"" + { + remove_line = true; + } + + // Remove the ``` + format!("{}", &caps[1].magenta()) + }).to_string(); + + if preformatted_code_toggle == false + { + // Block quotes + let block_quotes_regex = Regex::new(r"^>(.*)").unwrap(); + parsed_line = block_quotes_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!(" | {}", &caps[1].red()) + }).to_string(); + + // Unordered list ([ ]+|^)- (.*) + let unordered_list_regex = Regex::new(r"^([ \t]+|^)(-|\+|\*).(.*)").unwrap(); + parsed_line = unordered_list_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!("{} • {}", &caps[1], &caps[3]) + }).to_string(); + + // HyperLink + let hyperlink_regex = Regex::new(r"=>\s(\S*)\s(.*)").unwrap(); + parsed_line = hyperlink_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + // Check if the character before the link is not '!' + let result = format!("[{}] {}", hyperlink_number_counter, &caps[2].blue().underline()); + let url = caps[1].to_string(); + links.push(url); + hyperlink_number_counter += 1; + result + }).to_string(); + + let quick_hyperlink_regex = Regex::new(r"=>\s(.*)").unwrap(); + parsed_line = quick_hyperlink_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + hyperlink_number_counter += 1; + let url = caps[1].to_string(); + links.push(url); + format!("[{}] {}", hyperlink_number_counter, &caps[1].blue().underline()) + }).to_string(); } - result += "\n"; - result - }).to_string(); - - // html br tag support - let br_regex = Regex::new(r"(.*?)
(.*?)").unwrap(); - parsed_line = br_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - format!("{}{}{}", &caps[1], "\n", &caps[2]) - }).to_string(); - - // Italics - let italic_regex = Regex::new(r"\*(.*?)\*").unwrap(); - parsed_line = italic_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - caps[1].italic().to_string() - }).to_string(); - let italic_regex = Regex::new(r"_(.*?)_").unwrap(); - parsed_line = italic_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - caps[1].italic().to_string() - }).to_string(); - - // Block quotes - let block_quotes_regex = Regex::new(r"^>(.*)").unwrap(); - parsed_line = block_quotes_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - format!(" | {}", &caps[1]) - }).to_string(); - - // Ordered list - let ordered_list_regex = Regex::new(r"^([ \t]+|^)([0-9]+)\. (.*)").unwrap(); - parsed_line = ordered_list_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - format!("{} {}. {}", &caps[1], &caps[2], &caps[3]) - }).to_string(); - - // Unordered list ([ ]+|^)- (.*) - let unordered_list_regex = Regex::new(r"^([ \t]+|^)(-|\+|\*).(.*)").unwrap(); - parsed_line = unordered_list_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - format!("{} • {}", &caps[1], &caps[3]) - }).to_string(); - - // Inline code - let inline_code_regex = Regex::new(r"`([^`]+?)`").unwrap(); - parsed_line = inline_code_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - format!("{}", &caps[1].magenta()) - }).to_string(); - - // HyperLink - let hyperlink_regex = Regex::new(r"(.*?)\[(.*?)\]\((.*?)\)").unwrap(); - parsed_line = hyperlink_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - // Check if the character before the link is not '!' - if !caps[1].ends_with('!') { // caps[1] is everything before the link - let result = format!("{}{}[{}]", &caps[1], &caps[2].blue().underline(), hyperlink_number_counter); - let url = caps[3].to_string(); - links.push(url); - hyperlink_number_counter += 1; - result - } else { - // If it's an image (starts with !), return the link as is - let url = caps[3].to_string(); - links.push(url); - hyperlink_number_counter += 1; - format!("({})[{}]", &caps[2].green(), hyperlink_number_counter) + else if preformatted_code_toggle == true + { + parsed_line = parsed_line.magenta().to_string(); } - }).to_string(); - - let quick_hyperlink_regex = Regex::new(r"<(.*:\/\/.*)>").unwrap(); - parsed_line = quick_hyperlink_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { - hyperlink_number_counter += 1; - let url = caps[1].to_string(); - links.push(url); - format!("{}[{}]", &caps[1].blue().underline(), hyperlink_number_counter) - }).to_string(); + if remove_line == false + { + parsed_page_content+=&(parsed_line + "\n"); + } + } - parsed_page_content+=&(parsed_line + "\n"); - } - - // multiline code - let multiline_code_regex = Regex::new(r"(?ms)```((.*?\n)+?)```").unwrap(); - parsed_page_content = multiline_code_regex.replace_all(&parsed_page_content, |caps: ®ex::Captures| { - // Capture the code inside the %% blocks - let code_block = &caps[1]; - - // Add a tab to each line in the block - let indented_code = code_block - .lines() - .map(|line| format!("\t{}", line)) // Insert tab at the start of each line - .collect::>() - .join("\n"); - - // Return the formatted block with magenta color - format!("{}", indented_code.magenta()) - }).to_string(); return (parsed_page_content, links); } -fn fetch_page(url: &Url) -> String { +fn fetch_page(url: &Url) { let full_url_formatted = format!("{}", url); - // Call curl using Com, mand - let output = Command::new("curl") - .arg(full_url_formatted) + let output = Command::new("gemget") + .args([full_url_formatted, "-o".to_string(), "/tmp/page".to_string()]) .output() - .expect("Failed to execute curl command"); + .expect("Failed to execute gemget command"); // Check if the command was successful - if output.status.success() { - let page: String = String::from_utf8_lossy(&output.stdout).to_string(); - return page - } else { - eprintln!("Error:\n{}", String::from_utf8_lossy(&output.stderr)); - let result: String = "error".to_string(); - return result - } + if ! output.status.success() { + println!("{}\n{:?}\n", "Failed to fetch page:".red(), output); + } } fn render_page(url: Url, source: bool) -> Vec { clear_screen(); - let mut content = fetch_page(&url); + fetch_page(&url); let mut links = Vec::new(); - let (screen_width, _screen_height) = termion::terminal_size().unwrap(); + if let Ok(mut content) = fs::read_to_string::("/tmp/page".to_string()) { + Command::new("rm") + .arg("/tmp/page") + .output() + .expect("Failed to delete tmp page"); + let (screen_width, _screen_height) = termion::terminal_size().unwrap(); - if source == true { - content += &format!("{}", &"Viewing source code".yellow()); - } - else if &content[..13] == "" { - (content, links) = parse_markdown((&content[13..]).to_string()); - } - else { - content += &format!("{}", &"Warning: This page is invalid markdown, it should contain at the very start of the file, showing raw text".yellow()); - } + if source == true { + content += &format!("{}", &"Viewing source code".yellow()); + } + else { + (content, links) = parse_gemtext(content); + } - for _i in 0..screen_width { - print!("—"); - } - print!("{}\n", url); - for _i in 0..screen_width { - print!("—"); - } - println!("\n\n{}", content); - for _i in 0..screen_width { - print!("—"); - } - println!(); + for _i in 0..screen_width { + print!("-"); + } + print!("{}\n", url); + for _i in 0..screen_width { + print!("-"); + } + println!("\n\n{}", content); + for _i in 0..screen_width { + print!("-"); + } + println!(); - // Return links (you can add link parsing logic) - return links; + // Return links (you can add link parsing logic) + } + return links; } fn input() -> String{ @@ -207,17 +156,17 @@ fn parse_url(user_input: String, previous_url: &Url) -> Result user_input } else if user_input[..1] == *"/" { - format!("http://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input) + format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input) } else { println!("prepending scheme to user input"); - format!("http://{}", user_input) // Prepend 'mttp://' if no scheme is found + format!("gemini://{}", user_input) // Prepend 'mttp://' if no scheme is found }; println!("Parsing: {}", to_parse); if let Ok(mut url) = Url::parse(&to_parse) { if url.port() == None { - let _ = url.set_port(Some(3477)); + let _ = url.set_port(Some(1965)); } println!("{:?}",url); println!("{}",url.as_str()); @@ -235,7 +184,7 @@ fn main() { println!("Enter a url: "); let user_input = input(); - if user_input == "q" { + if user_input == "q" || user_input == "quit" || user_input == "exit" { std::process::exit(0); } let mut load_page: bool = true;