diff --git a/org_mode_samples/greater_element/plain_list/checkbox.org b/org_mode_samples/greater_element/plain_list/checkbox.org new file mode 100644 index 00000000..e987168d --- /dev/null +++ b/org_mode_samples/greater_element/plain_list/checkbox.org @@ -0,0 +1,3 @@ +- [ ] Foo +- [-] Bar +- [X] Baz diff --git a/src/compare/diff.rs b/src/compare/diff.rs index f37c5963..0a58bb77 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -83,8 +83,6 @@ use crate::types::Paragraph; use crate::types::PlainLink; use crate::types::PlainList; use crate::types::PlainListItem; -use crate::types::PlainListItemCounter; -use crate::types::PlainListItemPreBlank; use crate::types::PlainListType; use crate::types::PlainText; use crate::types::Planning; @@ -1121,108 +1119,70 @@ fn compare_plain_list_item<'b, 's>( source: &'s str, emacs: &'b Token<'s>, rust: &'b PlainListItem<'s>, -) -> Result, Box> { - let children = emacs.as_list()?; - let mut child_status = Vec::new(); +) -> Result, Box> { let mut this_status = DiffStatus::Good; + let mut child_status = Vec::new(); let mut message = None; - // Compare tag - let tag = get_property(emacs, ":tag")?; - match (tag, rust.tag.is_empty()) { - (None, true) => {} - (None, false) | (Some(_), true) => { - this_status = DiffStatus::Bad; - message = Some("Mismatched tags".to_owned()); - } - (Some(tag), false) => { - let tag_status = tag - .as_list()? - .iter() - .zip(rust.tag.iter()) - .map(|(emacs_child, rust_child)| { - compare_ast_node(source, emacs_child, rust_child.into()) - }) - .collect::, _>>()?; - child_status.push(artificial_diff_scope("tag", tag_status)?); - } - }; + compare_children( + source, + emacs, + &rust.children, + &mut child_status, + &mut this_status, + &mut message, + )?; - // Compare contents - let contents_status = children - .iter() - .skip(2) - .zip(rust.children.iter()) - .map(|(emacs_child, rust_child)| compare_ast_node(source, emacs_child, rust_child.into())) - .collect::, _>>()?; - child_status.push(artificial_diff_scope("contents", contents_status)?); - - // Compare bullet - let bullet = get_property_quoted_string(emacs, ":bullet")? - .ok_or("Plain list items must have a :bullet.")?; - if bullet != rust.bullet { - this_status = DiffStatus::Bad; - message = Some(format!( - "Bullet mismatch (emacs != rust) {:?} != {:?}", - bullet, rust.bullet - )); - } - - // Compare counter - let counter = get_property_unquoted_atom(emacs, ":counter")?; - let counter: Option = counter - .map(|val| val.parse()) - .map_or(Ok(None), |r| r.map(Some))?; - match (counter, rust.counter) { - (None, None) => {} - (None, Some(_)) | (Some(_), None) => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Counter mismatch (emacs != rust) {:?} != {:?}", - counter, rust.counter - )); + for diff in compare_properties!( + source, + emacs, + rust, + ( + EmacsField::Required(":tag"), + |r| if r.tag.is_empty() { + None + } else { + Some(r.tag.iter()) + }, + compare_property_list_of_ast_nodes + ), + ( + EmacsField::Required(":bullet"), + |r| Some(r.bullet), + compare_property_quoted_string + ), + ( + EmacsField::Required(":counter"), + |r| r.counter, + compare_property_numeric + ), + ( + EmacsField::Required(":checkbox"), + |r| r + .checkbox + .as_ref() + .map(|(checkbox_type, _)| checkbox_type) + .map(|checkbox_type| match checkbox_type { + CheckboxType::On => "on", + CheckboxType::Trans => "trans", + CheckboxType::Off => "off", + }), + compare_property_unquoted_atom + ), + ( + EmacsField::Required(":pre-blank"), + |r| Some(r.pre_blank), + compare_property_numeric + ) + ) { + match diff { + ComparePropertiesResult::NoChange => {} + ComparePropertiesResult::SelfChange(new_status, new_message) => { + this_status = new_status; + message = new_message + } + ComparePropertiesResult::DiffEntry(diff_entry) => child_status.push(diff_entry), } - (Some(e), Some(r)) if e != r => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Counter mismatch (emacs != rust) {:?} != {:?}", - counter, rust.counter - )); - } - (Some(_), Some(_)) => {} - }; - - // Compare checkbox - let checkbox = get_property(emacs, ":checkbox")? - .map(Token::as_atom) - .map_or(Ok(None), |r| r.map(Some))? - .unwrap_or("nil"); - match (checkbox, &rust.checkbox) { - ("nil", None) => {} - ("off", Some((CheckboxType::Off, _))) => {} - ("trans", Some((CheckboxType::Trans, _))) => {} - ("on", Some((CheckboxType::On, _))) => {} - _ => { - this_status = DiffStatus::Bad; - message = Some(format!( - "Checkbox mismatch (emacs != rust) {:?} != {:?}", - checkbox, rust.checkbox - )); - } - }; - - // Compare pre-blank - // :pre-blank appears to count the line breaks between "::" and the contents in a descriptive list. Oddly enough it does not count the spaces so I'm not quite sure what the value is. - let pre_blank = get_property_unquoted_atom(emacs, ":pre-blank")?; - let pre_blank: Option = pre_blank - .map(|val| val.parse()) - .map_or(Ok(None), |r| r.map(Some))?; - if pre_blank.unwrap_or(0) != rust.pre_blank { - this_status = DiffStatus::Bad; - message = Some(format!( - "Pre-blank mismatch (emacs != rust) {:?} != {:?}", - pre_blank, rust.pre_blank - )); } Ok(DiffResult {