diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 69e83247..bf4fd598 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -3,6 +3,8 @@ use crate::compare::util::get_offsets; use crate::parser::Document; use crate::parser::DocumentElement; use crate::parser::Element; +use crate::parser::FootnoteDefinition; +use crate::parser::GreaterBlock; use crate::parser::Heading; use crate::parser::Paragraph; use crate::parser::PlainList; @@ -204,8 +206,8 @@ fn compare_element<'s>( match rust { Element::Paragraph(obj) => compare_paragraph(source, emacs, obj), Element::PlainList(obj) => compare_plain_list(source, emacs, obj), - Element::GreaterBlock(_) => todo!(), - Element::FootnoteDefinition(_) => todo!(), + Element::GreaterBlock(obj) => compare_greater_block(source, emacs, obj), + Element::FootnoteDefinition(obj) => compare_footnote_definition(source, emacs, obj), } } @@ -295,4 +297,99 @@ fn compare_plain_list<'s>( }) } -//plain-list +fn compare_greater_block<'s>( + source: &'s str, + emacs: &'s Token<'s>, + rust: &'s GreaterBlock<'s>, +) -> Result> { + let children = emacs.as_list()?; + let first_child = children + .first() + .ok_or("Should have at least one child.")? + .as_atom()?; + match rust.name.to_lowercase().as_str() { + "center" => { + if first_child != "center-block" { + return Err( + "Center greater blocks should correspond to a center-block cell.".into(), + ); + } + } + _ => todo!(), + } + let mut child_status = Vec::new(); + let mut this_status = DiffStatus::Good; + + let attributes_child = children + .iter() + .nth(1) + .ok_or("Should have an attributes child.")?; + let attributes_map = attributes_child.as_map()?; + let begin = attributes_map + .get(":begin") + .ok_or("Missing :begin attribute.")? + .as_atom()?; + let end = attributes_map + .get(":end") + .ok_or("Missing :end attribute.")? + .as_atom()?; + let (rust_begin, rust_end) = get_offsets(source, rust); + if (rust_begin + 1).to_string() != begin || (rust_end + 1).to_string() != end { + this_status = DiffStatus::Bad; + } + + for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { + child_status.push(compare_element(source, emacs_child, rust_child)?); + } + + Ok(DiffResult { + status: this_status, + name: "greater-block".to_owned(), + children: child_status, + }) +} + +fn compare_footnote_definition<'s>( + source: &'s str, + emacs: &'s Token<'s>, + rust: &'s FootnoteDefinition<'s>, +) -> Result> { + let children = emacs.as_list()?; + let first_child = children + .first() + .ok_or("Should have at least one child.")? + .as_atom()?; + if first_child != "footnote-definition" { + return Err("Paragraph should correspond to a paragraph cell.".into()); + } + let mut child_status = Vec::new(); + let mut this_status = DiffStatus::Good; + + let attributes_child = children + .iter() + .nth(1) + .ok_or("Should have an attributes child.")?; + let attributes_map = attributes_child.as_map()?; + let begin = attributes_map + .get(":begin") + .ok_or("Missing :begin attribute.")? + .as_atom()?; + let end = attributes_map + .get(":end") + .ok_or("Missing :end attribute.")? + .as_atom()?; + let (rust_begin, rust_end) = get_offsets(source, rust); + if (rust_begin + 1).to_string() != begin || (rust_end + 1).to_string() != end { + this_status = DiffStatus::Bad; + } + + for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { + child_status.push(compare_element(source, emacs_child, rust_child)?); + } + + Ok(DiffResult { + status: this_status, + name: "footnote-definition".to_owned(), + children: child_status, + }) +} diff --git a/src/parser/element.rs b/src/parser/element.rs index 4c6760c8..a6f009d3 100644 --- a/src/parser/element.rs +++ b/src/parser/element.rs @@ -44,6 +44,18 @@ impl<'s> Source<'s> for PlainList<'s> { } } +impl<'s> Source<'s> for GreaterBlock<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} + +impl<'s> Source<'s> for FootnoteDefinition<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} + #[tracing::instrument(ret, level = "debug")] pub fn element<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Element<'s>> { let non_paragraph_matcher = parser_with_context!(non_paragraph_element)(context); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 4863def2..d4fd9603 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -20,6 +20,8 @@ pub use document::DocumentElement; pub use document::Heading; pub use document::Section; pub use element::Element; +pub use greater_element::FootnoteDefinition; +pub use greater_element::GreaterBlock; pub use greater_element::PlainList; pub use lesser_element::Paragraph; pub use source::Source;