馃 The Definitive Gemini Protocol Toolkit
gemini gemini-protocol gemtext parser zero-dependency toolkit ast converter html markdown cli networking
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 94 lines 3.2 kB view raw
1//! This example demonstrates a chain of Germ's capabilities by fetching a 2//! Gemini capsule, parsing the response content into an abstract syntax tree, 3//! and converting the abstract syntax tree back to Gemtext, identical to the 4//! Gemini response content. 5 6use std::env; 7 8fn main() { 9 // Try to obtain a URL from the command line arguments or use the default one 10 let url_string = 11 env::args().nth(1).unwrap_or_else(|| "gemini://fuwn.me/".to_string()); 12 // Form a valid URL to a Gemini capsule 13 let url = match url::Url::parse(&url_string) { 14 Ok(url) => url, 15 Err(error) => { 16 eprintln!("Error parsing URL '{}': {}", url_string, error); 17 std::process::exit(1); 18 } 19 }; 20 21 // Perform a blocking request to the Gemini capsule 22 let request = germ::request::blocking::request(&url); 23 24 match request { 25 // If the request was successful: 26 Ok(response) => { 27 // Obtain the content of the Gemini response 28 let response_content = 29 &*response.content().clone().unwrap_or_else(|| "".to_string()); 30 // Parse the Gemini response content into an abstract syntax tree 31 let ast = germ::ast::Ast::from_string(response_content); 32 // Convert the abstract syntax tree back to Gemtext, identical to the 33 // Gemini response content, constructed from the parsed abstract syntax 34 // tree 35 let gemtext = ast.to_gemtext(); 36 37 // Print the Gemtext 38 println!("{}", gemtext); 39 40 // Check if the response content and reconstruction are identical 41 if response_content == gemtext { 42 println!( 43 "\nValidation: Response content and reconstruction are identical" 44 ); 45 } else { 46 println!("\nValidation: Response content and reconstruction differ"); 47 print_diff(response_content, &gemtext); 48 } 49 } 50 // If the request was unsuccessful, print an error message and exit 51 Err(error) => { 52 eprintln!("Error fetching '{}': {}", url_string, error); 53 std::process::exit(1); 54 } 55 } 56} 57 58fn print_diff(original: &str, reconstructed: &str) { 59 use std::io::{self, Write}; 60 61 let mut stdout = io::stdout(); 62 let original_lines = original.lines().collect::<Vec<&str>>(); 63 let reconstructed_lines = reconstructed.lines().collect::<Vec<&str>>(); 64 let max_lines = original_lines.len().max(reconstructed_lines.len()); 65 let mut has_printed_diff = false; 66 67 for i in 0..max_lines { 68 let original_line = original_lines.get(i).unwrap_or(&""); 69 let reconstructed_line = reconstructed_lines.get(i).unwrap_or(&""); 70 71 if original_line != reconstructed_line { 72 if has_printed_diff { 73 let _ = writeln!(stdout); 74 } 75 76 let _ = writeln!(stdout, "Line {}:", i + 1); 77 let _ = writeln!(stdout, " Original: '{}'", original_line); 78 let _ = writeln!(stdout, " Reconstructed: '{}'", reconstructed_line); 79 80 has_printed_diff = true; 81 } 82 } 83 84 if original_lines.len() != reconstructed_lines.len() { 85 if has_printed_diff { 86 let _ = writeln!(stdout); 87 } 88 89 let _ = writeln!(stdout, "Length difference:"); 90 let _ = writeln!(stdout, " Original: {} lines", original_lines.len()); 91 let _ = 92 writeln!(stdout, " Reconstructed: {} lines", reconstructed_lines.len()); 93 } 94}