We were running into issues where the documents grew too large for being passed as a string to emacs, and we need to handle #+setupfile so we need to start handling org-mode documents as files and not just as anonymous streams of text. The anonymous stream of text handling will remain because the automated tests use it.
148 lines
5.1 KiB
Rust
148 lines
5.1 KiB
Rust
#![feature(round_char_boundary)]
|
|
#![feature(exact_size_is_empty)]
|
|
use std::io::Read;
|
|
use std::path::Path;
|
|
|
|
use ::organic::parser::document;
|
|
#[cfg(feature = "compare")]
|
|
use organic::compare_document;
|
|
#[cfg(feature = "compare")]
|
|
use organic::emacs_parse_anonymous_org_document;
|
|
#[cfg(feature = "compare")]
|
|
use organic::emacs_parse_file_org_document;
|
|
#[cfg(feature = "compare")]
|
|
use organic::get_emacs_version;
|
|
#[cfg(feature = "compare")]
|
|
use organic::get_org_mode_version;
|
|
#[cfg(feature = "compare")]
|
|
use organic::parser::sexp::sexp_with_padding;
|
|
|
|
#[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<dyn std::error::Error>> {
|
|
main_body()
|
|
}
|
|
|
|
#[cfg(feature = "tracing")]
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
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<dyn std::error::Error>> {
|
|
let args = std::env::args();
|
|
if args.is_empty() {
|
|
let org_contents = read_stdin_to_string()?;
|
|
run_anonymous_parse(org_contents)
|
|
} else {
|
|
for arg in args.skip(1) {
|
|
run_parse_on_file(arg)?
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn read_stdin_to_string() -> Result<String, Box<dyn std::error::Error>> {
|
|
let mut stdin_contents = String::new();
|
|
std::io::stdin()
|
|
.lock()
|
|
.read_to_string(&mut stdin_contents)?;
|
|
Ok(stdin_contents)
|
|
}
|
|
|
|
#[cfg(feature = "compare")]
|
|
fn run_anonymous_parse<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
|
|
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 (remaining, rust_parsed) = document(org_contents).map_err(|e| e.to_string())?;
|
|
let org_sexp = emacs_parse_anonymous_org_document(org_contents)?;
|
|
let (_remaining, parsed_sexp) =
|
|
sexp_with_padding(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.")?;
|
|
}
|
|
if remaining != "" {
|
|
Err(format!("There was unparsed text remaining: {}", remaining))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(not(feature = "compare"))]
|
|
fn run_anonymous_parse<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
|
|
eprintln!(
|
|
"This program was built with compare disabled. Only parsing with organic, not comparing."
|
|
);
|
|
let (_remaining, rust_parsed) = document(org_contents.as_ref()).map_err(|e| e.to_string())?;
|
|
println!("{:#?}", rust_parsed);
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(feature = "compare")]
|
|
fn run_parse_on_file<P: AsRef<Path>>(org_path: P) -> Result<(), Box<dyn std::error::Error>> {
|
|
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());
|
|
// TODO: This should take into account the original file path when parsing in Organic, not just in emacs.
|
|
let org_contents = std::fs::read_to_string(org_path)?;
|
|
let org_contents = org_contents.as_str();
|
|
let (remaining, rust_parsed) = document(org_contents).map_err(|e| e.to_string())?;
|
|
let org_sexp = emacs_parse_file_org_document(org_path)?;
|
|
let (_remaining, parsed_sexp) =
|
|
sexp_with_padding(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.")?;
|
|
}
|
|
if remaining != "" {
|
|
Err(format!("There was unparsed text remaining: {}", remaining))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(not(feature = "compare"))]
|
|
fn run_parse_on_file<P: AsRef<Path>>(org_path: P) -> Result<(), Box<dyn std::error::Error>> {
|
|
let org_path = org_path.as_ref();
|
|
eprintln!(
|
|
"This program was built with compare disabled. Only parsing with organic, not comparing."
|
|
);
|
|
// TODO: This should take into account the original file path when parsing
|
|
let org_contents = std::fs::read_to_string(org_path)?;
|
|
let org_contents = org_contents.as_str();
|
|
let (_remaining, rust_parsed) = document(org_contents).map_err(|e| e.to_string())?;
|
|
println!("{:#?}", rust_parsed);
|
|
Ok(())
|
|
}
|