Implement a new compare_properties implementation of the heading comparison.

This commit is contained in:
Tom Alexander 2023-10-09 21:27:18 -04:00
parent 166e59b922
commit 65615c64d2
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 120 additions and 0 deletions

View File

@ -230,6 +230,45 @@ pub(crate) fn compare_property_boolean<'b, 's, 'x, R, RG: Fn(R) -> bool>(
}
}
pub(crate) fn compare_property_single_ast_node<
'b,
's,
'x: 'b + 's,
R,
RV: std::fmt::Debug,
RG: Fn(R) -> Option<RV>,
>(
source: &'s str,
emacs: &'b Token<'s>,
rust_node: R,
emacs_field: &'x str,
rust_value_getter: RG,
) -> Result<ComparePropertiesResult<'b, 's>, Box<dyn std::error::Error>>
where
AstNode<'b, 's>: From<RV>,
{
let value = get_property(emacs, emacs_field)?;
let rust_value = rust_value_getter(rust_node);
match (value, rust_value) {
(None, None) => {}
(None, rv @ Some(_)) | (Some(_), rv @ None) => {
let this_status = DiffStatus::Bad;
let message = Some(format!(
"{} mismatch (emacs != rust) {:?} != {:?}",
emacs_field, value, rv
));
return Ok(ComparePropertiesResult::SelfChange(this_status, message));
}
(Some(ev), Some(rv)) => {
let child_status: Vec<DiffEntry<'b, 's>> =
vec![compare_ast_node(source, ev, rv.into())?];
let diff_scope = artificial_diff_scope(emacs_field, child_status)?;
return Ok(ComparePropertiesResult::DiffEntry(diff_scope));
}
}
Ok(ComparePropertiesResult::NoChange)
}
pub(crate) fn compare_property_list_of_ast_nodes<
'b,
's,

View File

@ -12,6 +12,7 @@ use super::compare_field::compare_property_list_of_ast_nodes;
use super::compare_field::compare_property_list_of_quoted_string;
use super::compare_field::compare_property_numeric;
use super::compare_field::compare_property_quoted_string;
use super::compare_field::compare_property_single_ast_node;
use super::compare_field::compare_property_unquoted_atom;
use super::elisp_fact::ElispFact;
use super::elisp_fact::GetElispFact;
@ -621,6 +622,86 @@ fn new_compare_heading<'b, 's>(
EmacsField::Required(":level"),
|r| Some(r.level),
compare_property_numeric
),
(
EmacsField::Required(":tags"),
|r| if r.tags.is_empty() {
None
} else {
Some(r.tags.iter())
},
compare_property_list_of_quoted_string
),
(
EmacsField::Required(":todo-keyword"),
|r| r.todo_keyword.as_ref().map(|(_, text)| text),
compare_property_quoted_string
),
(
EmacsField::Required(":todo-type"),
|r| r
.todo_keyword
.as_ref()
.map(|(todo_type, _)| todo_type)
.map(|todo_type| match todo_type {
TodoKeywordType::Todo => "todo",
TodoKeywordType::Done => "done",
}),
compare_property_unquoted_atom
),
(
EmacsField::Required(":title"),
|r| if r.title.is_empty() {
None
} else {
Some(r.title.iter())
},
compare_property_list_of_ast_nodes
),
(
EmacsField::Required(":priority"),
|r| r.priority_cookie,
compare_property_numeric
),
(
EmacsField::Required(":archivedp"),
|r| r.is_archived,
compare_property_boolean
),
(
EmacsField::Required(":commentedp"),
|r| r.is_comment,
compare_property_boolean
),
(
EmacsField::Required(":raw-value"),
|r| Some(r.get_raw_value()),
compare_property_quoted_string
),
(
EmacsField::Required(":footnote-section-p"),
|r| r.is_footnote_section,
compare_property_boolean
),
(
EmacsField::Required(":scheduled"),
|r| r.scheduled.as_ref(),
compare_property_single_ast_node
),
(
EmacsField::Required(":deadline"),
|r| r.deadline.as_ref(),
compare_property_single_ast_node
),
(
EmacsField::Required(":closed"),
|r| r.closed.as_ref(),
compare_property_single_ast_node
),
(
EmacsField::Required(":pre-blank"),
compare_identity,
compare_noop
)
) {
match diff {