#![feature(round_char_boundary)] #![feature(exact_size_is_empty)] use std::io::Read; use std::path::Path; use ::organic::parser::parse; use organic::compare_document; use organic::emacs_parse_anonymous_org_document; use organic::emacs_parse_file_org_document; use organic::get_emacs_version; use organic::get_org_mode_version; use organic::parser::parse_with_settings; use organic::parser::sexp::sexp; use organic::GlobalSettings; use organic::LocalFileAccessInterface; #[cfg(feature = "tracing")] use crate::init_tracing::init_telemetry; #[cfg(feature = "tracing")] use crate::init_tracing::shutdown_telemetry; #[cfg(feature = "tracing")] mod init_tracing; #[cfg(not(feature = "tracing"))] fn main() -> Result<(), Box> { main_body() } #[cfg(feature = "tracing")] fn main() -> Result<(), Box> { let rt = tokio::runtime::Runtime::new()?; let result = rt.block_on(async { init_telemetry()?; let main_body_result = main_body(); shutdown_telemetry()?; main_body_result }); result } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn main_body() -> Result<(), Box> { let args = std::env::args().skip(1); if args.is_empty() { let org_contents = read_stdin_to_string()?; run_anonymous_parse(org_contents) } else { for arg in args { run_parse_on_file(arg)? } Ok(()) } } fn read_stdin_to_string() -> Result> { let mut stdin_contents = String::new(); std::io::stdin() .lock() .read_to_string(&mut stdin_contents)?; Ok(stdin_contents) } fn run_anonymous_parse>(org_contents: P) -> Result<(), Box> { let org_contents = org_contents.as_ref(); eprintln!("Using emacs version: {}", get_emacs_version()?.trim()); eprintln!("Using org-mode version: {}", get_org_mode_version()?.trim()); let rust_parsed = parse(org_contents)?; let org_sexp = emacs_parse_anonymous_org_document(org_contents)?; let (_remaining, parsed_sexp) = sexp(org_sexp.as_str()).map_err(|e| e.to_string())?; println!("{}\n\n\n", org_contents); println!("{}", org_sexp); println!("{:#?}", rust_parsed); // We do the diffing after printing out both parsed forms in case the diffing panics let diff_result = compare_document(&parsed_sexp, &rust_parsed)?; diff_result.print(org_contents)?; if diff_result.is_bad() { Err("Diff results do not match.")?; } Ok(()) } fn run_parse_on_file>(org_path: P) -> Result<(), Box> { let org_path = org_path.as_ref(); eprintln!("Using emacs version: {}", get_emacs_version()?.trim()); eprintln!("Using org-mode version: {}", get_org_mode_version()?.trim()); let parent_directory = org_path .parent() .ok_or("Should be contained inside a directory.")?; let org_contents = std::fs::read_to_string(org_path)?; let org_contents = org_contents.as_str(); let file_access_interface = LocalFileAccessInterface { working_directory: Some(parent_directory.to_path_buf()), }; let global_settings = { let mut global_settings = GlobalSettings::default(); global_settings.file_access = &file_access_interface; global_settings }; let rust_parsed = parse_with_settings(org_contents, &global_settings)?; let org_sexp = emacs_parse_file_org_document(org_path)?; let (_remaining, parsed_sexp) = sexp(org_sexp.as_str()).map_err(|e| e.to_string())?; println!("{}\n\n\n", org_contents); println!("{}", org_sexp); println!("{:#?}", rust_parsed); // We do the diffing after printing out both parsed forms in case the diffing panics let diff_result = compare_document(&parsed_sexp, &rust_parsed)?; diff_result.print(org_contents)?; if diff_result.is_bad() { Err("Diff results do not match.")?; } Ok(()) }