From 58aca53144493747d80be80b1fa76a6bd993f016 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 22:07:23 -0400 Subject: [PATCH 1/4] Move get_property into util. --- src/compare/diff.rs | 23 +++-------------------- src/compare/util.rs | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index f4f9450..f7b631e 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use super::util::assert_bounds; use super::util::assert_name; +use super::util::get_property; use crate::parser::sexp::unquote; use crate::parser::sexp::Token; use crate::parser::AngleLink; @@ -397,6 +398,8 @@ fn compare_heading<'s>( Ok(_) => {} }; + // Compare level + // Compare tags let emacs_tags = get_tags_from_heading(emacs)?; let emacs_tags: HashSet<_> = emacs_tags.iter().map(|val| val.as_str()).collect(); @@ -483,26 +486,6 @@ fn get_tags_from_heading<'s>( Ok(tags) } -fn get_property<'s, 'x>( - emacs: &'s Token<'s>, - key: &'x str, -) -> Result>, Box> { - let children = emacs.as_list()?; - let attributes_child = children - .iter() - .nth(1) - .ok_or("Should have an attributes child.")?; - let attributes_map = attributes_child.as_map()?; - let prop = attributes_map - .get(key) - .ok_or(format!("Missing {} attribute.", key))?; - match prop.as_atom() { - Ok("nil") => return Ok(None), - _ => {} - }; - Ok(Some(*prop)) -} - fn compare_paragraph<'s>( source: &'s str, emacs: &'s Token<'s>, diff --git a/src/compare/util.rs b/src/compare/util.rs index 03c8e9b..7ef432a 100644 --- a/src/compare/util.rs +++ b/src/compare/util.rs @@ -137,3 +137,23 @@ fn maybe_token_to_usize( .flatten() // Outer option is whether or not the param exists, inner option is whether or not it is nil .map_or(Ok(None), |r| r.map(Some))?) } + +pub fn get_property<'s, 'x>( + emacs: &'s Token<'s>, + key: &'x str, +) -> Result>, Box> { + let children = emacs.as_list()?; + let attributes_child = children + .iter() + .nth(1) + .ok_or("Should have an attributes child.")?; + let attributes_map = attributes_child.as_map()?; + let prop = attributes_map + .get(key) + .ok_or(format!("Missing {} attribute.", key))?; + match prop.as_atom() { + Ok("nil") => return Ok(None), + _ => {} + }; + Ok(Some(*prop)) +} From 7944659802237e002c5987ae208baa91ac6b194b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 22:11:56 -0400 Subject: [PATCH 2/4] Compare headline level. --- src/compare/diff.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index f7b631e..d3ca505 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -399,6 +399,16 @@ fn compare_heading<'s>( }; // Compare level + let level = get_property(emacs, ":level")? + .ok_or("Level should not be nil")? + .as_atom()?; + if rust.stars.to_string() != level { + this_status = DiffStatus::Bad; + message = Some(format!( + "Headline level do not much (emacs != rust): {} != {}", + level, rust.stars + )) + } // Compare tags let emacs_tags = get_tags_from_heading(emacs)?; @@ -436,7 +446,7 @@ fn compare_heading<'s>( child_status.push(compare_object(source, emacs_child, rust_child)?); } - // TODO: Compare todo-type, level, priority + // TODO: Compare todo-type, priority, :footnote-section-p, :archivedp, :commentedp // Compare section for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { From 2c5c26c55fa893b05792b5ad7b13964264b43a32 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 22:47:40 -0400 Subject: [PATCH 3/4] Allow diff layers that are not associated with tokens. --- src/compare/diff.rs | 417 ++++++++++++++++++++++++++++---------------- 1 file changed, 271 insertions(+), 146 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index d3ca505..17631d3 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -64,12 +64,18 @@ use crate::parser::Underline; use crate::parser::Verbatim; use crate::parser::VerseBlock; +#[derive(Debug)] +pub enum DiffEntry<'s> { + DiffResult(DiffResult<'s>), + DiffLayer(DiffLayer<'s>), +} + #[derive(Debug)] pub struct DiffResult<'s> { status: DiffStatus, name: String, message: Option, - children: Vec>, + children: Vec>, rust_source: &'s str, #[allow(dead_code)] emacs_token: &'s Token<'s>, @@ -81,11 +87,62 @@ pub enum DiffStatus { Bad, } -impl<'s> DiffResult<'s> { +#[derive(Debug)] +pub struct DiffLayer<'s> { + name: String, + children: Vec>, +} + +impl<'s> From> for DiffEntry<'s> { + fn from(value: DiffResult<'s>) -> Self { + DiffEntry::DiffResult(value) + } +} + +impl<'s> From> for DiffEntry<'s> { + fn from(value: DiffLayer<'s>) -> Self { + DiffEntry::DiffLayer(value) + } +} + +impl<'s> DiffEntry<'s> { + fn has_bad_children(&self) -> bool { + match self { + DiffEntry::DiffResult(diff) => &diff.children, + DiffEntry::DiffLayer(diff) => &diff.children, + } + .iter() + .any(|child| child.is_immediately_bad() || child.has_bad_children()) + } + + fn is_immediately_bad(&self) -> bool { + match self { + DiffEntry::DiffResult(diff) => diff.status == DiffStatus::Bad, + DiffEntry::DiffLayer(_) => false, + } + } + + pub fn is_bad(&self) -> bool { + self.is_immediately_bad() || self.has_bad_children() + } + pub fn print(&self, original_document: &str) -> Result<(), Box> { self.print_indented(0, original_document) } + fn print_indented( + &self, + indentation: usize, + original_document: &str, + ) -> Result<(), Box> { + match self { + DiffEntry::DiffResult(diff) => diff.print_indented(indentation, original_document), + DiffEntry::DiffLayer(diff) => diff.print_indented(indentation, original_document), + } + } +} + +impl<'s> DiffResult<'s> { fn print_indented( &self, indentation: usize, @@ -131,17 +188,10 @@ impl<'s> DiffResult<'s> { Ok(()) } - pub fn has_bad_children(&self) -> bool { + fn has_bad_children(&self) -> bool { self.children .iter() - .any(|child| child.status == DiffStatus::Bad || child.has_bad_children()) - } - - pub fn is_bad(&self) -> bool { - match self.status { - DiffStatus::Good => self.has_bad_children(), - DiffStatus::Bad => true, - } + .any(|child| child.is_immediately_bad() || child.has_bad_children()) } fn foreground_color(red: u8, green: u8, blue: u8) -> String { @@ -184,28 +234,56 @@ impl<'s> DiffResult<'s> { } } +impl<'s> DiffLayer<'s> { + fn has_bad_children(&self) -> bool { + self.children + .iter() + .any(|child| child.is_immediately_bad() || child.has_bad_children()) + } + + fn print_indented( + &self, + indentation: usize, + original_document: &str, + ) -> Result<(), Box> { + let status_text = if self.has_bad_children() { + format!( + "{color}BADCHILD{reset}", + color = DiffResult::foreground_color(255, 255, 0), + reset = DiffResult::reset_color(), + ) + } else { + format!( + "{color}GOOD{reset}", + color = DiffResult::foreground_color(0, 255, 0), + reset = DiffResult::reset_color(), + ) + }; + println!( + "{indentation}{status_text} {name}", + indentation = " ".repeat(indentation), + status_text = status_text, + name = self.name, + ); + for child in self.children.iter() { + child.print_indented(indentation + 1, original_document)?; + } + Ok(()) + } +} + fn artificial_diff_scope<'s>( name: String, - message: Option, - children: Vec>, - emacs_token: &'s Token<'s>, - rust_source: &'s str, -) -> Result, Box> { - Ok(DiffResult { - status: DiffStatus::Good, - name, - message, - children, - rust_source, - emacs_token, - }) + children: Vec>, +) -> Result, Box> { + Ok(DiffLayer { name, children }.into()) } fn compare_element<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Element<'s>, -) -> Result, Box> { +) -> Result, Box> { let compare_result = match rust { Element::Paragraph(obj) => compare_paragraph(source, emacs, obj), Element::PlainList(obj) => compare_plain_list(source, emacs, obj), @@ -238,7 +316,8 @@ fn compare_element<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }), + } + .into()), } } @@ -246,7 +325,7 @@ fn compare_object<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Object<'s>, -) -> Result, Box> { +) -> Result, Box> { let compare_result = match rust { Object::Bold(obj) => compare_bold(source, emacs, obj), Object::Italic(obj) => compare_italic(source, emacs, obj), @@ -285,14 +364,15 @@ fn compare_object<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }), + } + .into()), } } pub fn compare_document<'s>( emacs: &'s Token<'s>, rust: &'s Document<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -338,14 +418,15 @@ pub fn compare_document<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_section<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Section<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut this_status = DiffStatus::Good; let mut child_status = Vec::new(); @@ -373,14 +454,15 @@ fn compare_section<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_heading<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Heading<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -467,7 +549,8 @@ fn compare_heading<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn get_tags_from_heading<'s>( @@ -500,7 +583,7 @@ fn compare_paragraph<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Paragraph<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -529,14 +612,15 @@ fn compare_paragraph<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_plain_list<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s PlainList<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -565,14 +649,15 @@ fn compare_plain_list<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_plain_list_item<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s PlainListItem<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -605,13 +690,7 @@ fn compare_plain_list_item<'s>( .zip(rust.tag.iter()) .map(|(emacs_child, rust_child)| compare_object(source, emacs_child, rust_child)) .collect::, _>>()?; - child_status.push(artificial_diff_scope( - "tag".to_owned(), - None, - tag_status, - tag, - rust.get_source(), - )?); + child_status.push(artificial_diff_scope("tag".to_owned(), tag_status)?); } }; @@ -624,10 +703,7 @@ fn compare_plain_list_item<'s>( .collect::, _>>()?; child_status.push(artificial_diff_scope( "contents".to_owned(), - None, contents_status, - emacs, - rust.get_source(), )?); Ok(DiffResult { @@ -637,14 +713,15 @@ fn compare_plain_list_item<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_greater_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s GreaterBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -677,14 +754,15 @@ fn compare_greater_block<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_dynamic_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s DynamicBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -712,14 +790,15 @@ fn compare_dynamic_block<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_footnote_definition<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s FootnoteDefinition<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -748,14 +827,15 @@ fn compare_footnote_definition<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_comment<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Comment<'s>, -) -> Result, Box> { +) -> Result, Box> { let child_status = Vec::new(); let mut this_status = DiffStatus::Good; let mut message = None; @@ -779,14 +859,15 @@ fn compare_comment<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_drawer<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Drawer<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -815,14 +896,15 @@ fn compare_drawer<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_property_drawer<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s PropertyDrawer<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -852,14 +934,15 @@ fn compare_property_drawer<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_table<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Table<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -888,14 +971,15 @@ fn compare_table<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_table_row<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s TableRow<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -924,14 +1008,15 @@ fn compare_table_row<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_table_cell<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s TableCell<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -958,14 +1043,15 @@ fn compare_table_cell<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_verse_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s VerseBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let children = emacs.as_list()?; let child_status = Vec::new(); let mut this_status = DiffStatus::Good; @@ -992,14 +1078,15 @@ fn compare_verse_block<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_comment_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s CommentBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "comment-block"; @@ -1022,14 +1109,15 @@ fn compare_comment_block<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_example_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s ExampleBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "example-block"; @@ -1052,14 +1140,15 @@ fn compare_example_block<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_export_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s ExportBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "export-block"; @@ -1082,14 +1171,15 @@ fn compare_export_block<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_src_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s SrcBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "src-block"; @@ -1112,14 +1202,15 @@ fn compare_src_block<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_clock<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Clock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "clock"; @@ -1142,14 +1233,15 @@ fn compare_clock<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_diary_sexp<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s DiarySexp<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "diary-sexp"; @@ -1172,14 +1264,15 @@ fn compare_diary_sexp<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_planning<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Planning<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "planning"; @@ -1202,14 +1295,15 @@ fn compare_planning<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_fixed_width_area<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s FixedWidthArea<'s>, -) -> Result, Box> { +) -> Result, Box> { let child_status = Vec::new(); let mut this_status = DiffStatus::Good; let mut message = None; @@ -1233,14 +1327,15 @@ fn compare_fixed_width_area<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_horizontal_rule<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s HorizontalRule<'s>, -) -> Result, Box> { +) -> Result, Box> { let child_status = Vec::new(); let mut this_status = DiffStatus::Good; let mut message = None; @@ -1264,14 +1359,15 @@ fn compare_horizontal_rule<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_keyword<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Keyword<'s>, -) -> Result, Box> { +) -> Result, Box> { let child_status = Vec::new(); let mut this_status = DiffStatus::Good; let mut message = None; @@ -1295,14 +1391,15 @@ fn compare_keyword<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_latex_environment<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s LatexEnvironment<'s>, -) -> Result, Box> { +) -> Result, Box> { let child_status = Vec::new(); let mut this_status = DiffStatus::Good; let mut message = None; @@ -1326,14 +1423,15 @@ fn compare_latex_environment<'s>( children: child_status, rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_plain_text<'s>( _source: &'s str, emacs: &'s Token<'s>, rust: &'s PlainText<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let rust_source = rust.get_source(); @@ -1375,14 +1473,15 @@ fn compare_plain_text<'s>( children: Vec::new(), rust_source, emacs_token: emacs, - }) + } + .into()) } fn compare_bold<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Bold<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "bold"; @@ -1405,14 +1504,15 @@ fn compare_bold<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_italic<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Italic<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "italic"; @@ -1435,14 +1535,15 @@ fn compare_italic<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_underline<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Underline<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "underline"; @@ -1465,14 +1566,15 @@ fn compare_underline<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_verbatim<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Verbatim<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "verbatim"; @@ -1495,14 +1597,15 @@ fn compare_verbatim<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_code<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Code<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "code"; @@ -1525,14 +1628,15 @@ fn compare_code<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_strike_through<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s StrikeThrough<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "strike-through"; @@ -1555,14 +1659,15 @@ fn compare_strike_through<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_regular_link<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s RegularLink<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "link"; @@ -1585,14 +1690,15 @@ fn compare_regular_link<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_radio_link<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s RadioLink<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "link"; @@ -1615,14 +1721,15 @@ fn compare_radio_link<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_radio_target<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s RadioTarget<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "radio-target"; @@ -1645,14 +1752,15 @@ fn compare_radio_target<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_plain_link<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s PlainLink<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "link"; @@ -1675,14 +1783,15 @@ fn compare_plain_link<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_angle_link<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s AngleLink<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "link"; @@ -1705,14 +1814,15 @@ fn compare_angle_link<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_org_macro<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s OrgMacro<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "macro"; @@ -1735,14 +1845,15 @@ fn compare_org_macro<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_entity<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Entity<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "entity"; @@ -1765,14 +1876,15 @@ fn compare_entity<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_latex_fragment<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s LatexFragment<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "latex-fragment"; @@ -1795,14 +1907,15 @@ fn compare_latex_fragment<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_export_snippet<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s ExportSnippet<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "export-snippet"; @@ -1825,14 +1938,15 @@ fn compare_export_snippet<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_footnote_reference<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s FootnoteReference<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "footnote-reference"; @@ -1855,14 +1969,15 @@ fn compare_footnote_reference<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_citation<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Citation<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "citation"; @@ -1885,14 +2000,15 @@ fn compare_citation<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_citation_reference<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s CitationReference<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "citation-reference"; @@ -1915,14 +2031,15 @@ fn compare_citation_reference<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_inline_babel_call<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s InlineBabelCall<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "inline-babel-call"; @@ -1945,14 +2062,15 @@ fn compare_inline_babel_call<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_inline_source_block<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s InlineSourceBlock<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "inline-src-block"; @@ -1975,14 +2093,15 @@ fn compare_inline_source_block<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_line_break<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s LineBreak<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "line-break"; @@ -2005,14 +2124,15 @@ fn compare_line_break<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_target<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Target<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "target"; @@ -2035,14 +2155,15 @@ fn compare_target<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_statistics_cookie<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s StatisticsCookie<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "statistics-cookie"; @@ -2065,14 +2186,15 @@ fn compare_statistics_cookie<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_subscript<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Subscript<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "subscript"; @@ -2095,14 +2217,15 @@ fn compare_subscript<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_superscript<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Superscript<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "superscript"; @@ -2125,14 +2248,15 @@ fn compare_superscript<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } fn compare_timestamp<'s>( source: &'s str, emacs: &'s Token<'s>, rust: &'s Timestamp<'s>, -) -> Result, Box> { +) -> Result, Box> { let mut this_status = DiffStatus::Good; let mut message = None; let emacs_name = "timestamp"; @@ -2155,5 +2279,6 @@ fn compare_timestamp<'s>( children: Vec::new(), rust_source: rust.get_source(), emacs_token: emacs, - }) + } + .into()) } From d471f7178b4829f01ff0615a11bdde621cf1767c Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 22:57:08 -0400 Subject: [PATCH 4/4] Wrap the components of headlines in diff layers. --- src/compare/diff.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 17631d3..6e1386d 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -524,23 +524,31 @@ fn compare_heading<'s>( // Compare title let title = get_property(emacs, ":title")?.ok_or("Missing :title attribute.")?; - for (emacs_child, rust_child) in title.as_list()?.iter().zip(rust.title.iter()) { - child_status.push(compare_object(source, emacs_child, rust_child)?); - } + let title_status = title + .as_list()? + .iter() + .zip(rust.title.iter()) + .map(|(emacs_child, rust_child)| compare_object(source, emacs_child, rust_child)) + .collect::, _>>()?; + child_status.push(artificial_diff_scope("title".to_owned(), title_status)?); // TODO: Compare todo-type, priority, :footnote-section-p, :archivedp, :commentedp // Compare section - for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { - match rust_child { + let section_status = children + .iter() + .skip(2) + .zip(rust.children.iter()) + .map(|(emacs_child, rust_child)| match rust_child { DocumentElement::Heading(rust_heading) => { - child_status.push(compare_heading(source, emacs_child, rust_heading)?); + compare_heading(source, emacs_child, rust_heading) } DocumentElement::Section(rust_section) => { - child_status.push(compare_section(source, emacs_child, rust_section)?); + compare_section(source, emacs_child, rust_section) } - }; - } + }) + .collect::, _>>()?; + child_status.push(artificial_diff_scope("section".to_owned(), section_status)?); Ok(DiffResult { status: this_status,