works ish

This commit is contained in:
deadvey 2025-04-03 22:15:38 +01:00
parent a7468d3f40
commit 1321e0dcaf
2 changed files with 118 additions and 85 deletions

View File

@ -1,88 +1,22 @@
use std::process::{Command}; use std::process::{Command};
use std::io::{stdin,stdout,Write}; use std::io::{stdin,stdout,Write};
use colored::Colorize; use colored::Colorize;
use regex::Regex;
use url::{Url, ParseError}; use url::{Url, ParseError};
use std::fs; use std::fs;
const DEBUG_MODE: bool = false;
// Import other files
mod parse_gemtext;
fn clear_screen() { fn clear_screen() {
println!("clearing"); if DEBUG_MODE == false
Command::new("clear") {
.status() println!("clearing");
.expect("Failed to clear screen"); Command::new("clear")
} .status()
.expect("Failed to clear screen");
fn parse_gemtext(page_content: String) -> (String, Vec<String>) { }
let mut parsed_page_content: String = "".to_string();
let mut hyperlink_number_counter: u64 = 0;
let mut links: Vec<String> = 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: &regex::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: &regex::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: &regex::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: &regex::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: &regex::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);
} }
fn fetch_page(url: &Url) { fn fetch_page(url: &Url) {
@ -114,7 +48,7 @@ fn render_page(url: Url, source: bool) -> Vec<String> {
content += &format!("{}", &"Viewing source code".yellow()); content += &format!("{}", &"Viewing source code".yellow());
} }
else { else {
(content, links) = parse_gemtext(content); (content, links) = parse_gemtext::parse_gemtext(content);
} }
for _i in 0..screen_width { for _i in 0..screen_width {
@ -155,12 +89,8 @@ fn parse_url(user_input: String, previous_url: &Url) -> Result<Url, ParseError>
println!("Contains different scheme or is a path"); println!("Contains different scheme or is a path");
user_input user_input
} }
else if user_input[..1] == *"/" {
format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input)
}
else { else {
println!("prepending scheme to user input"); format!("gemini://{}/{}",Url::host_str(previous_url).expect("ivalid").to_string(), user_input)
format!("gemini://{}", user_input) // Prepend 'mttp://' if no scheme is found
}; };
println!("Parsing: {}", to_parse); println!("Parsing: {}", to_parse);
@ -192,19 +122,30 @@ fn main() {
let mut historical_position: usize = 0; let mut historical_position: usize = 0;
let mut links: Vec<String> = Vec::new(); let mut links: Vec<String> = Vec::new();
let mut source: bool = false; // Wether to view source of markdown page or rendered version 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()); history.push(url.clone());
'mainloop: loop { 'mainloop: loop {
if load_page { if load_page {
links = render_page(history[historical_position].clone(), source); links = render_page(history[historical_position].clone(), source);
println!("Enter reference number to follow, h for help, or q to quit"); println!("Enter reference number to follow, h for help, or q to quit");
} }
url = history[historical_position].clone();
load_page = false; load_page = false;
let user_input = input(); let user_input = input();
if user_input == "q" { if user_input == "q" {
break 'mainloop; 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" { else if user_input == "r" {
load_page = true; load_page = true;
continue; continue;
@ -243,6 +184,7 @@ fn main() {
else if user_input == "h" { else if user_input == "h" {
println!("Source code: https://git.javalsai.dynv6.net/deadvey/markdown-webbrowser println!("Source code: https://git.javalsai.dynv6.net/deadvey/markdown-webbrowser
q: quit q: quit
d: debug info
h: help h: help
r: reload r: reload
s: view source code of page s: view source code of page

91
src/parse_gemtext.rs Normal file
View File

@ -0,0 +1,91 @@
use colored::Colorize;
use regex::Regex;
pub fn parse_gemtext(page_content: String) -> (String, Vec<String>) {
let mut parsed_page_content: String = "".to_string();
let mut hyperlink_number_counter: u64 = 0;
let mut links: Vec<String> = 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: &regex::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: &regex::Captures| {
format!("{}", &caps[1].blue().bold().underline())
}).to_string();
parsed_line = header2_regex.replace_all(&parsed_line, |caps: &regex::Captures| {
format!("{}", &caps[1].blue().bold())
}).to_string();
parsed_line = header3_regex.replace_all(&parsed_line, |caps: &regex::Captures| {
format!("{}", &caps[1].bold())
}).to_string();
// Block quotes
parsed_line = block_quotes_regex.replace_all(&parsed_line, |caps: &regex::Captures| {
format!(" | {}", &caps[1].red())
}).to_string();
// Unordered list ([ ]+|^)- (.*)
parsed_line = unordered_list_regex.replace_all(&parsed_line, |caps: &regex::Captures| {
format!("{}{}", &caps[1], &caps[3])
}).to_string();
// HyperLink
parsed_line = hyperlink_regex.replace_all(&parsed_line, |caps: &regex::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: &regex::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);
}