From 1321e0dcaf9b177e3737c2e2e491170ec0c02fa5 Mon Sep 17 00:00:00 2001 From: deadvey Date: Thu, 3 Apr 2025 22:15:38 +0100 Subject: [PATCH] works ish --- src/main.rs | 112 +++++++++++-------------------------------- src/parse_gemtext.rs | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 85 deletions(-) create mode 100644 src/parse_gemtext.rs diff --git a/src/main.rs b/src/main.rs index b1e49ed..fc3a3ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,88 +1,22 @@ use std::process::{Command}; use std::io::{stdin,stdout,Write}; use colored::Colorize; -use regex::Regex; use url::{Url, ParseError}; use std::fs; +const DEBUG_MODE: bool = false; + +// Import other files +mod parse_gemtext; + fn clear_screen() { - println!("clearing"); - Command::new("clear") - .status() - .expect("Failed to clear screen"); -} - -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 mut preformatted_code_toggle = false; - - for line in page_content.lines() { - let mut parsed_line: String = line.to_string(); - let mut remove_line = false; - - // 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; - - 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(); - } - else if preformatted_code_toggle == true - { - parsed_line = parsed_line.magenta().to_string(); - } - - if remove_line == false - { - parsed_page_content+=&(parsed_line + "\n"); - } - } - - - return (parsed_page_content, links); + if DEBUG_MODE == false + { + println!("clearing"); + Command::new("clear") + .status() + .expect("Failed to clear screen"); + } } fn fetch_page(url: &Url) { @@ -114,7 +48,7 @@ fn render_page(url: Url, source: bool) -> Vec { content += &format!("{}", &"Viewing source code".yellow()); } else { - (content, links) = parse_gemtext(content); + (content, links) = parse_gemtext::parse_gemtext(content); } for _i in 0..screen_width { @@ -155,12 +89,8 @@ fn parse_url(user_input: String, previous_url: &Url) -> Result println!("Contains different scheme or is a path"); user_input } - else if user_input[..1] == *"/" { - format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input) - } else { - println!("prepending scheme to user input"); - format!("gemini://{}", user_input) // Prepend 'mttp://' if no scheme is found + format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input) }; println!("Parsing: {}", to_parse); @@ -192,19 +122,30 @@ fn main() { let mut historical_position: usize = 0; let mut links: Vec = Vec::new(); let mut source: bool = false; // Wether to view source of markdown page or rendered version - if let Ok(mut url) = parse_url(user_input, &Url::parse(&"http://deadvey.com").unwrap()) { // Change this and make internal pages ;) + if let Ok(mut url) = parse_url(user_input, &Url::parse(&"gemini://geminiprotocol.net").unwrap()) { // Change this and make internal pages ;) history.push(url.clone()); 'mainloop: loop { if load_page { links = render_page(history[historical_position].clone(), source); println!("Enter reference number to follow, h for help, or q to quit"); } + url = history[historical_position].clone(); load_page = false; let user_input = input(); if user_input == "q" { break 'mainloop; } + else if user_input == "d" { + println!( + "load_page: {}\nhistory: {:?}\nhistorical_postition: {}\nlinks: {:?}\nsource: {}", + load_page, + history, + historical_position, + links, + source + ); + } else if user_input == "r" { load_page = true; continue; @@ -243,6 +184,7 @@ fn main() { else if user_input == "h" { println!("Source code: https://git.javalsai.dynv6.net/deadvey/markdown-webbrowser q: quit +d: debug info h: help r: reload s: view source code of page diff --git a/src/parse_gemtext.rs b/src/parse_gemtext.rs new file mode 100644 index 0000000..daa3c45 --- /dev/null +++ b/src/parse_gemtext.rs @@ -0,0 +1,91 @@ +use colored::Colorize; +use regex::Regex; + +pub 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 mut preformatted_code_toggle = false; + + // Regex patterns + let preformatted_text_regex = Regex::new(r"^```(.*)").unwrap(); + let header1_regex = Regex::new(r"^# (.*)").unwrap(); + let header2_regex = Regex::new(r"^## (.*)").unwrap(); + let header3_regex = Regex::new(r"^### (.*)").unwrap(); + let block_quotes_regex = Regex::new(r"^>(.*)").unwrap(); + let unordered_list_regex = Regex::new(r"^([ \t]+|^)(\*).(.*)").unwrap(); + let hyperlink_regex = Regex::new(r"=>\s(\S*)\s(.*)").unwrap(); + let quick_hyperlink_regex = Regex::new(r"=>\s(.*)").unwrap(); + + for line in page_content.lines() { + let mut parsed_line: String = line.to_string(); + let mut remove_line = false; + + // preformatted text + parsed_line = preformatted_text_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + // Flip the toggle + preformatted_code_toggle = ! preformatted_code_toggle; + + if caps[1] == *"" + { + remove_line = true; + } + + // Remove the ``` + format!("{}", &caps[1].magenta()) + }).to_string(); + + if preformatted_code_toggle == false + { + // Headers + parsed_line = header1_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!("{}", &caps[1].blue().bold().underline()) + }).to_string(); + parsed_line = header2_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!("{}", &caps[1].blue().bold()) + }).to_string(); + parsed_line = header3_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!("{}", &caps[1].bold()) + }).to_string(); + + // Block quotes + parsed_line = block_quotes_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!(" | {}", &caps[1].red()) + }).to_string(); + + // Unordered list ([ ]+|^)- (.*) + parsed_line = unordered_list_regex.replace_all(&parsed_line, |caps: ®ex::Captures| { + format!("{} • {}", &caps[1], &caps[3]) + }).to_string(); + + // HyperLink + 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(); + + 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(); + } + else if preformatted_code_toggle == true + { + parsed_line = parsed_line.magenta().to_string(); + } + + if remove_line == false + { + parsed_page_content+=&(parsed_line + "\n"); + } + } + + + return (parsed_page_content, links); +}