diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 6bd231c..5c42e7d 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -1,25 +1,123 @@ use super::sexp::Token; use crate::parser::Document; +use crate::parser::Section; + +#[derive(Debug)] +pub struct DiffResult { + status: DiffStatus, + name: String, + children: Vec, +} + +#[derive(Debug)] +pub enum DiffStatus { + Good, + ChildBad, + Bad, +} + +impl DiffResult { + pub fn print(&self) -> Result<(), Box> { + self.print_indented(0) + } + + fn print_indented(&self, indentation: usize) -> Result<(), Box> { + println!( + "{}{:?} {}", + " ".repeat(indentation), + self.status, + self.name + ); + for child in self.children.iter() { + child.print_indented(indentation + 1)?; + } + Ok(()) + } +} pub fn compare_document<'s>( emacs: &'s Token<'s>, rust: &'s Document<'s>, -) -> Result<(), Box> { - compare_document_indented(0, emacs, rust) -} - -fn compare_document_indented<'s>( - indentation: usize, - emacs: &'s Token<'s>, - rust: &'s Document<'s>, -) -> Result<(), Box> { +) -> Result> { let children = emacs.as_list()?; - let first_child = children.first().ok_or("Should have at least one child")?; + let first_child = children.first().ok_or("Should have at least one child.")?; let first_child_text = first_child.as_atom()?; if first_child_text != "org-data" { return Err("Document should correspond to an org-data cell.".into()); } + let mut child_status = Vec::new(); // TODO: compare the children - Ok(()) + // Skipping "org-data" and the first parameter which is often nil + for (i, token) in children.iter().skip(2).enumerate() { + let section_or_headline = token.as_list()?; + let first_cell = section_or_headline + .first() + .ok_or("Should have at least one child.")? + .as_atom()?; + if first_cell == "section" { + if i != 0 { + return Err("Section cannot be after the first child of document.".into()); + } + child_status.push(compare_section( + token, + rust.zeroth_section + .as_ref() + .ok_or("No corresponding zeroth-section")?, + )?); + } else if first_cell == "headline" { + let corresponding_heading = rust + .children + .iter() + .nth(i - rust.zeroth_section.as_ref().map(|_| 1).unwrap_or(0)) + .ok_or("Should have a corresponding heading.")?; + child_status.push(compare_heading(token, rust)?); + } else { + return Err("Document should only contain sections and headlines.".into()); + } + } + + Ok(DiffResult { + status: DiffStatus::Good, + name: "document".to_owned(), + children: child_status, + }) +} + +pub fn compare_section<'s>( + emacs: &'s Token<'s>, + rust: &'s Section<'s>, +) -> Result> { + let children = emacs.as_list()?; + let first_child = children.first().ok_or("Should have at least one child.")?; + let first_child_text = first_child.as_atom()?; + if first_child_text != "section" { + return Err("Section should correspond to a section cell.".into()); + } + let mut child_status = Vec::new(); + + Ok(DiffResult { + status: DiffStatus::Good, + name: "section".to_owned(), + children: child_status, + }) +} + +pub fn compare_heading<'s>( + emacs: &'s Token<'s>, + rust: &'s Document<'s>, +) -> Result> { + let children = emacs.as_list()?; + let first_child = children.first().ok_or("Should have at least one child.")?; + let first_child_text = first_child.as_atom()?; + if first_child_text != "headline" { + return Err("Heading should correspond to a headline cell.".into()); + } + let mut child_status = Vec::new(); + + Ok(DiffResult { + status: DiffStatus::Good, + name: "heading".to_owned(), + children: child_status, + }) } diff --git a/src/org_compare.rs b/src/org_compare.rs index 7459de9..9f1f615 100644 --- a/src/org_compare.rs +++ b/src/org_compare.rs @@ -20,8 +20,10 @@ fn main() -> Result<(), Box> { println!("{:#?}", parsed_sexp); let (_remaining, rust_parsed) = document(org_contents.as_str()).expect("Org Parse failure"); println!("{:#?}", rust_parsed); - compare_document(&parsed_sexp, &rust_parsed)?; + let diff_result = compare_document(&parsed_sexp, &rust_parsed)?; + diff_result.print()?; } + println!("Done."); shutdown_telemetry()?; Ok(()) } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 77672d8..74c00c5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -16,4 +16,5 @@ mod source; mod util; pub use document::document; pub use document::Document; +pub use document::Section; type Context<'r, 's> = &'r parser_context::ContextTree<'r, 's>;