3683 lines
104 KiB
Rust
3683 lines
104 KiB
Rust
use std::borrow::Cow;
|
|
// TODO: Update all to use the macro to assert there are no unexpected keys.
|
|
// TODO: Check all compare funtions for whether they correctly iterate children.
|
|
use std::collections::BTreeSet;
|
|
|
|
use super::compare_field::compare_identity;
|
|
use super::compare_field::compare_noop;
|
|
use super::compare_field::compare_property_always_nil;
|
|
use super::compare_field::compare_property_boolean;
|
|
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_number_lines;
|
|
use super::compare_field::compare_property_numeric;
|
|
use super::compare_field::compare_property_quoted_string;
|
|
use super::compare_field::compare_property_retain_labels;
|
|
use super::compare_field::compare_property_set_of_quoted_string;
|
|
use super::compare_field::compare_property_single_ast_node;
|
|
use super::compare_field::compare_property_unquoted_atom;
|
|
use super::util::affiliated_keywords_names;
|
|
use super::util::assert_no_children;
|
|
use super::util::compare_additional_properties;
|
|
use super::util::compare_affiliated_keywords;
|
|
use super::util::compare_children;
|
|
use super::util::compare_children_iter;
|
|
use super::util::compare_standard_properties;
|
|
use crate::compare::compare_field::ComparePropertiesResult;
|
|
use crate::compare::compare_field::EmacsField;
|
|
use crate::compare::macros::compare_properties;
|
|
use crate::types::AngleLink;
|
|
use crate::types::AstNode;
|
|
use crate::types::BabelCall;
|
|
use crate::types::Bold;
|
|
use crate::types::CenterBlock;
|
|
use crate::types::CheckboxType;
|
|
use crate::types::Citation;
|
|
use crate::types::CitationReference;
|
|
use crate::types::Clock;
|
|
use crate::types::ClockStatus;
|
|
use crate::types::Code;
|
|
use crate::types::Comment;
|
|
use crate::types::CommentBlock;
|
|
use crate::types::Date;
|
|
use crate::types::DayOfMonth;
|
|
use crate::types::DiarySexp;
|
|
use crate::types::Document;
|
|
use crate::types::Drawer;
|
|
use crate::types::DynamicBlock;
|
|
use crate::types::Entity;
|
|
use crate::types::ExampleBlock;
|
|
use crate::types::ExportBlock;
|
|
use crate::types::ExportSnippet;
|
|
use crate::types::FixedWidthArea;
|
|
use crate::types::FootnoteDefinition;
|
|
use crate::types::FootnoteReference;
|
|
use crate::types::FootnoteReferenceType;
|
|
use crate::types::Heading;
|
|
use crate::types::HorizontalRule;
|
|
use crate::types::Hour;
|
|
use crate::types::InlineBabelCall;
|
|
use crate::types::InlineSourceBlock;
|
|
use crate::types::Italic;
|
|
use crate::types::Keyword;
|
|
use crate::types::LatexEnvironment;
|
|
use crate::types::LatexFragment;
|
|
use crate::types::LineBreak;
|
|
use crate::types::LinkType;
|
|
use crate::types::Minute;
|
|
use crate::types::Month;
|
|
use crate::types::NodeProperty;
|
|
use crate::types::OrgMacro;
|
|
use crate::types::Paragraph;
|
|
use crate::types::PlainLink;
|
|
use crate::types::PlainList;
|
|
use crate::types::PlainListItem;
|
|
use crate::types::PlainListType;
|
|
use crate::types::PlainText;
|
|
use crate::types::Planning;
|
|
use crate::types::PropertyDrawer;
|
|
use crate::types::QuoteBlock;
|
|
use crate::types::RadioLink;
|
|
use crate::types::RadioTarget;
|
|
use crate::types::RegularLink;
|
|
use crate::types::RepeaterType;
|
|
use crate::types::Section;
|
|
use crate::types::SpecialBlock;
|
|
use crate::types::SrcBlock;
|
|
use crate::types::StandardProperties;
|
|
use crate::types::StatisticsCookie;
|
|
use crate::types::StrikeThrough;
|
|
use crate::types::Subscript;
|
|
use crate::types::Superscript;
|
|
use crate::types::Table;
|
|
use crate::types::TableCell;
|
|
use crate::types::TableRow;
|
|
use crate::types::TableRowType;
|
|
use crate::types::Target;
|
|
use crate::types::Time;
|
|
use crate::types::TimeUnit;
|
|
use crate::types::Timestamp;
|
|
use crate::types::TimestampRangeType;
|
|
use crate::types::TimestampType;
|
|
use crate::types::TodoKeywordType;
|
|
use crate::types::Underline;
|
|
use crate::types::Verbatim;
|
|
use crate::types::VerseBlock;
|
|
use crate::types::WarningDelayType;
|
|
use crate::types::Year;
|
|
use crate::util::elisp::unquote;
|
|
use crate::util::elisp::Token;
|
|
use crate::util::elisp_fact::ElispFact;
|
|
use crate::util::elisp_fact::GetElispFact;
|
|
use crate::util::terminal::foreground_color;
|
|
use crate::util::terminal::reset_color;
|
|
|
|
#[derive(Debug)]
|
|
pub enum DiffEntry<'b, 's> {
|
|
DiffResult(DiffResult<'b, 's>),
|
|
DiffLayer(DiffLayer<'b, 's>),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct DiffResult<'b, 's> {
|
|
status: DiffStatus,
|
|
name: Cow<'s, str>,
|
|
message: Option<String>,
|
|
children: Vec<DiffEntry<'b, 's>>,
|
|
rust_source: &'s str,
|
|
#[allow(dead_code)]
|
|
emacs_token: &'b Token<'s>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum DiffStatus {
|
|
Good,
|
|
Bad,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct DiffLayer<'b, 's> {
|
|
name: Cow<'s, str>,
|
|
children: Vec<DiffEntry<'b, 's>>,
|
|
}
|
|
|
|
impl<'b, 's> From<DiffResult<'b, 's>> for DiffEntry<'b, 's> {
|
|
fn from(value: DiffResult<'b, 's>) -> Self {
|
|
DiffEntry::DiffResult(value)
|
|
}
|
|
}
|
|
|
|
impl<'b, 's> From<DiffLayer<'b, 's>> for DiffEntry<'b, 's> {
|
|
fn from(value: DiffLayer<'b, 's>) -> Self {
|
|
DiffEntry::DiffLayer(value)
|
|
}
|
|
}
|
|
|
|
impl<'b, 's> DiffEntry<'b, '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) => matches!(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<dyn std::error::Error>> {
|
|
self.print_indented(0, original_document)
|
|
}
|
|
|
|
fn print_indented(
|
|
&self,
|
|
indentation: usize,
|
|
original_document: &str,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
match self {
|
|
DiffEntry::DiffResult(diff) => diff.print_indented(indentation, original_document),
|
|
DiffEntry::DiffLayer(diff) => diff.print_indented(indentation, original_document),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'b, 's> DiffResult<'b, 's> {
|
|
fn print_indented(
|
|
&self,
|
|
indentation: usize,
|
|
original_document: &str,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
let status_text = {
|
|
match self.status {
|
|
DiffStatus::Good => {
|
|
if self.has_bad_children() {
|
|
format!(
|
|
"{color}BADCHILD{reset}",
|
|
color = foreground_color(255, 255, 0),
|
|
reset = reset_color(),
|
|
)
|
|
} else {
|
|
format!(
|
|
"{color}GOOD{reset}",
|
|
color = foreground_color(0, 255, 0),
|
|
reset = reset_color(),
|
|
)
|
|
}
|
|
}
|
|
DiffStatus::Bad => format!(
|
|
"{color}BAD{reset}",
|
|
color = foreground_color(255, 0, 0),
|
|
reset = reset_color(),
|
|
),
|
|
}
|
|
};
|
|
let rust_offset = self.rust_source.as_ptr() as usize - original_document.as_ptr() as usize;
|
|
let preceding_text = &original_document[..rust_offset];
|
|
println!(
|
|
"{indentation}{status_text} {name} char({char_offset}) {message}",
|
|
indentation = " ".repeat(indentation),
|
|
status_text = status_text,
|
|
name = self.name,
|
|
char_offset = preceding_text.chars().count() + 1,
|
|
message = self.message.as_deref().unwrap_or("")
|
|
);
|
|
for child in self.children.iter() {
|
|
child.print_indented(indentation + 1, original_document)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn has_bad_children(&self) -> bool {
|
|
self.children
|
|
.iter()
|
|
.any(|child| child.is_immediately_bad() || child.has_bad_children())
|
|
}
|
|
}
|
|
|
|
impl<'b, 's> DiffLayer<'b, '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<dyn std::error::Error>> {
|
|
let status_text = if self.has_bad_children() {
|
|
format!(
|
|
"{color}BADCHILD{reset}",
|
|
color = foreground_color(255, 255, 0),
|
|
reset = reset_color(),
|
|
)
|
|
} else {
|
|
format!(
|
|
"{color}GOOD{reset}",
|
|
color = foreground_color(0, 255, 0),
|
|
reset = 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(())
|
|
}
|
|
}
|
|
|
|
pub(crate) fn artificial_diff_scope<'b, 's>(
|
|
name: &'s str,
|
|
children: Vec<DiffEntry<'b, 's>>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
Ok(DiffLayer {
|
|
name: name.into(),
|
|
children,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
pub(crate) fn artificial_owned_diff_scope<'b, 's>(
|
|
name: &str,
|
|
children: Vec<DiffEntry<'b, 's>>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
Ok(DiffLayer {
|
|
name: name.to_string().into(),
|
|
children,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
pub(crate) fn compare_ast_node<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: AstNode<'b, 's>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let compare_result: Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> = match rust {
|
|
AstNode::Document(node) => _compare_document(source, emacs, node),
|
|
AstNode::Heading(node) => compare_heading(source, emacs, node),
|
|
AstNode::Section(node) => compare_section(source, emacs, node),
|
|
AstNode::Paragraph(node) => compare_paragraph(source, emacs, node),
|
|
AstNode::PlainList(node) => compare_plain_list(source, emacs, node),
|
|
AstNode::PlainListItem(node) => compare_plain_list_item(source, emacs, node),
|
|
AstNode::CenterBlock(node) => compare_center_block(source, emacs, node),
|
|
AstNode::QuoteBlock(node) => compare_quote_block(source, emacs, node),
|
|
AstNode::SpecialBlock(node) => compare_special_block(source, emacs, node),
|
|
AstNode::DynamicBlock(node) => compare_dynamic_block(source, emacs, node),
|
|
AstNode::FootnoteDefinition(node) => compare_footnote_definition(source, emacs, node),
|
|
AstNode::Comment(node) => compare_comment(source, emacs, node),
|
|
AstNode::Drawer(node) => compare_drawer(source, emacs, node),
|
|
AstNode::PropertyDrawer(node) => compare_property_drawer(source, emacs, node),
|
|
AstNode::NodeProperty(node) => compare_node_property(source, emacs, node),
|
|
AstNode::Table(node) => compare_table(source, emacs, node),
|
|
AstNode::TableRow(node) => compare_table_row(source, emacs, node),
|
|
AstNode::VerseBlock(node) => compare_verse_block(source, emacs, node),
|
|
AstNode::CommentBlock(node) => compare_comment_block(source, emacs, node),
|
|
AstNode::ExampleBlock(node) => compare_example_block(source, emacs, node),
|
|
AstNode::ExportBlock(node) => compare_export_block(source, emacs, node),
|
|
AstNode::SrcBlock(node) => compare_src_block(source, emacs, node),
|
|
AstNode::Clock(node) => compare_clock(source, emacs, node),
|
|
AstNode::DiarySexp(node) => compare_diary_sexp(source, emacs, node),
|
|
AstNode::Planning(node) => compare_planning(source, emacs, node),
|
|
AstNode::FixedWidthArea(node) => compare_fixed_width_area(source, emacs, node),
|
|
AstNode::HorizontalRule(node) => compare_horizontal_rule(source, emacs, node),
|
|
AstNode::Keyword(node) => compare_keyword(source, emacs, node),
|
|
AstNode::BabelCall(node) => compare_babel_call(source, emacs, node),
|
|
AstNode::LatexEnvironment(node) => compare_latex_environment(source, emacs, node),
|
|
AstNode::Bold(node) => compare_bold(source, emacs, node),
|
|
AstNode::Italic(node) => compare_italic(source, emacs, node),
|
|
AstNode::Underline(node) => compare_underline(source, emacs, node),
|
|
AstNode::StrikeThrough(node) => compare_strike_through(source, emacs, node),
|
|
AstNode::Code(node) => compare_code(source, emacs, node),
|
|
AstNode::Verbatim(node) => compare_verbatim(source, emacs, node),
|
|
AstNode::PlainText(node) => compare_plain_text(source, emacs, node),
|
|
AstNode::RegularLink(node) => compare_regular_link(source, emacs, node),
|
|
AstNode::RadioLink(node) => compare_radio_link(source, emacs, node),
|
|
AstNode::RadioTarget(node) => compare_radio_target(source, emacs, node),
|
|
AstNode::PlainLink(node) => compare_plain_link(source, emacs, node),
|
|
AstNode::AngleLink(node) => compare_angle_link(source, emacs, node),
|
|
AstNode::OrgMacro(node) => compare_org_macro(source, emacs, node),
|
|
AstNode::Entity(node) => compare_entity(source, emacs, node),
|
|
AstNode::LatexFragment(node) => compare_latex_fragment(source, emacs, node),
|
|
AstNode::ExportSnippet(node) => compare_export_snippet(source, emacs, node),
|
|
AstNode::FootnoteReference(node) => compare_footnote_reference(source, emacs, node),
|
|
AstNode::Citation(node) => compare_citation(source, emacs, node),
|
|
AstNode::CitationReference(node) => compare_citation_reference(source, emacs, node),
|
|
AstNode::InlineBabelCall(node) => compare_inline_babel_call(source, emacs, node),
|
|
AstNode::InlineSourceBlock(node) => compare_inline_source_block(source, emacs, node),
|
|
AstNode::LineBreak(node) => compare_line_break(source, emacs, node),
|
|
AstNode::Target(node) => compare_target(source, emacs, node),
|
|
AstNode::StatisticsCookie(node) => compare_statistics_cookie(source, emacs, node),
|
|
AstNode::Subscript(node) => compare_subscript(source, emacs, node),
|
|
AstNode::Superscript(node) => compare_superscript(source, emacs, node),
|
|
AstNode::TableCell(node) => compare_table_cell(source, emacs, node),
|
|
AstNode::Timestamp(node) => compare_timestamp(source, emacs, node),
|
|
};
|
|
|
|
let mut compare_result = match compare_result.unwrap_or_else(|e| {
|
|
DiffResult {
|
|
status: DiffStatus::Bad,
|
|
name: rust.get_elisp_fact().get_elisp_name(),
|
|
message: Some(e.to_string()),
|
|
children: Vec::new(),
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into()
|
|
}) {
|
|
DiffEntry::DiffResult(inner) => inner,
|
|
DiffEntry::DiffLayer(_) => {
|
|
unreachable!("Layers are only interior to DiffResults of AST nodes.")
|
|
}
|
|
};
|
|
|
|
// PlainText is a special case because upstream Org-Mode uses relative values for the bounds in plaintext rather than absolute so the below checks do not account for that.
|
|
if let AstNode::PlainText(_) = rust {
|
|
} else if let Err(err) = compare_standard_properties(source, emacs, &rust) {
|
|
compare_result.status = DiffStatus::Bad;
|
|
compare_result.message = Some(err.to_string())
|
|
}
|
|
|
|
Ok(compare_result.into())
|
|
}
|
|
|
|
pub fn compare_document<'b, 's>(
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Document<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
compare_ast_node(rust.source, emacs, rust.into())
|
|
}
|
|
|
|
fn _compare_document<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Document<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
let additional_property_names: Vec<String> = rust
|
|
.get_additional_properties()
|
|
.map(|node_property| format!(":{}", node_property.property_name.to_uppercase()))
|
|
.collect();
|
|
|
|
let additional_properties: Vec<(String, &str)> = rust
|
|
.get_additional_properties()
|
|
.map(|node_property| {
|
|
(
|
|
format!(":{}", node_property.property_name.to_uppercase()),
|
|
node_property.value.unwrap_or(""),
|
|
)
|
|
})
|
|
.collect();
|
|
|
|
compare_additional_properties(emacs, additional_properties.into_iter())?.apply(
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
);
|
|
|
|
compare_children_iter(
|
|
source,
|
|
emacs,
|
|
rust.into_iter(),
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
additional_property_names
|
|
.iter()
|
|
.map(String::as_str)
|
|
.map(EmacsField::Required),
|
|
(
|
|
EmacsField::Required(":path"),
|
|
|r| r.path.as_ref().and_then(|p| p.to_str()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":CATEGORY"),
|
|
|r| r.category.as_ref(),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_section<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Section<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn compare_heading<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Heading<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
let additional_property_names: Vec<String> = rust
|
|
.get_additional_properties()
|
|
.map(|node_property| format!(":{}", node_property.property_name.to_uppercase()))
|
|
.collect();
|
|
|
|
let additional_properties: Vec<(String, &str)> = rust
|
|
.get_additional_properties()
|
|
.map(|node_property| {
|
|
(
|
|
format!(":{}", node_property.property_name.to_uppercase()),
|
|
node_property.value.unwrap_or(""),
|
|
)
|
|
})
|
|
.collect();
|
|
|
|
compare_additional_properties(emacs, additional_properties.into_iter())?.apply(
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
);
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
additional_property_names
|
|
.iter()
|
|
.map(String::as_str)
|
|
.map(EmacsField::Required),
|
|
(
|
|
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::Optional(":scheduled"),
|
|
|r| r.scheduled.as_ref(),
|
|
compare_property_single_ast_node
|
|
),
|
|
(
|
|
EmacsField::Optional(":deadline"),
|
|
|r| r.deadline.as_ref(),
|
|
compare_property_single_ast_node
|
|
),
|
|
(
|
|
EmacsField::Optional(":closed"),
|
|
|r| r.closed.as_ref(),
|
|
compare_property_single_ast_node
|
|
),
|
|
(
|
|
EmacsField::Required(":pre-blank"),
|
|
compare_identity,
|
|
compare_noop
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_paragraph<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Paragraph<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(source, emacs, rust, [],) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_plain_list<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b PlainList<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| Some(match r.list_type {
|
|
PlainListType::Unordered => "unordered",
|
|
PlainListType::Ordered => "ordered",
|
|
PlainListType::Descriptive => "descriptive",
|
|
}),
|
|
compare_property_unquoted_atom
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_plain_list_item<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b PlainListItem<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_center_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b CenterBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(source, emacs, rust, [],) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_quote_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b QuoteBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(source, emacs, rust, [],) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_special_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b SpecialBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| Some(r.block_type),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":parameters"),
|
|
|r| r.parameters,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Optional(":results"),
|
|
compare_identity,
|
|
compare_noop
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_dynamic_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b DynamicBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":block-name"),
|
|
|r| Some(r.block_name),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":arguments"),
|
|
|r| r.parameters,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_footnote_definition<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b FootnoteDefinition<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":label"),
|
|
|r| Some(r.label),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":pre-blank"),
|
|
compare_identity,
|
|
compare_noop
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_comment<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Comment<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.get_value()),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_drawer<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Drawer<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":drawer-name"),
|
|
|r| Some(r.drawer_name),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_property_drawer<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b PropertyDrawer<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_node_property<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b NodeProperty<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":key"),
|
|
|r| Some(r.property_name),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| r.value,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_table<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Table<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":tblfm"),
|
|
|r| if r.formulas.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.formulas.iter().map(|kw| kw.value))
|
|
},
|
|
compare_property_set_of_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|_| Some("org"),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
compare_identity,
|
|
compare_property_always_nil
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_table_row<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b TableRow<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| Some(match r.get_type() {
|
|
TableRowType::Standard => "standard",
|
|
TableRowType::Rule => "rule",
|
|
}),
|
|
compare_property_unquoted_atom
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_table_cell<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b TableCell<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_verse_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b VerseBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(source, emacs, rust, [],) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_comment_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b CommentBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.contents),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_example_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b ExampleBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.get_value()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":switches"),
|
|
|r| r.switches,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":number-lines"),
|
|
|r| r.number_lines.as_ref(),
|
|
compare_property_number_lines
|
|
),
|
|
(
|
|
EmacsField::Required(":preserve-indent"),
|
|
|r| r.preserve_indent,
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":retain-labels"),
|
|
|r| &r.retain_labels,
|
|
compare_property_retain_labels
|
|
),
|
|
(
|
|
EmacsField::Required(":use-labels"),
|
|
|r| r.use_labels,
|
|
compare_property_boolean
|
|
),
|
|
(
|
|
EmacsField::Required(":label-fmt"),
|
|
|r| r.label_format,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_export_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b ExportBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| r.get_export_type(),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.get_value()),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_src_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b SrcBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":language"),
|
|
|r| r.language,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.get_value()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":switches"),
|
|
|r| r.switches,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":parameters"),
|
|
|r| r.parameters,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":number-lines"),
|
|
|r| r.number_lines.as_ref(),
|
|
compare_property_number_lines
|
|
),
|
|
(
|
|
EmacsField::Required(":preserve-indent"),
|
|
|r| r.preserve_indent,
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":retain-labels"),
|
|
|r| &r.retain_labels,
|
|
compare_property_retain_labels
|
|
),
|
|
(
|
|
EmacsField::Required(":use-labels"),
|
|
|r| r.use_labels,
|
|
compare_property_boolean
|
|
),
|
|
(
|
|
EmacsField::Required(":label-fmt"),
|
|
|r| r.label_format,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_clock<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Clock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(&r.timestamp),
|
|
compare_property_single_ast_node
|
|
),
|
|
(
|
|
EmacsField::Required(":duration"),
|
|
|r| r.duration,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":status"),
|
|
|r| Some(match r.status {
|
|
ClockStatus::Running => "running",
|
|
ClockStatus::Closed => "closed",
|
|
}),
|
|
compare_property_unquoted_atom
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_diary_sexp<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b DiarySexp<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_planning<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Planning<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
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
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_fixed_width_area<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b FixedWidthArea<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.get_value()),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_horizontal_rule<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b HorizontalRule<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(source, emacs, rust, [],) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_keyword<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Keyword<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":key"),
|
|
|r| Some(r.key.to_uppercase()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_babel_call<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b BabelCall<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":call"),
|
|
|r| r.call,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":arguments"),
|
|
|r| r.arguments,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":inside-header"),
|
|
|r| r.inside_header,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":end-header"),
|
|
|r| r.end_header,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_latex_environment<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b LatexEnvironment<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
[],
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_plain_text<'b, 's>(
|
|
_source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b PlainText<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut message = None;
|
|
let rust_source = rust.get_source();
|
|
let text = emacs.as_text()?;
|
|
let start_ind: usize = text
|
|
.properties
|
|
.first()
|
|
.expect("Should have start index.")
|
|
.as_atom()?
|
|
.parse()?;
|
|
let end_ind: usize = text
|
|
.properties
|
|
.get(1)
|
|
.expect("Should have end index.")
|
|
.as_atom()?
|
|
.parse()?;
|
|
let emacs_text_length = end_ind - start_ind;
|
|
if rust_source.chars().count() != emacs_text_length {
|
|
this_status = DiffStatus::Bad;
|
|
message = Some(format!(
|
|
"(emacs len != rust len) {:?} != {:?}",
|
|
emacs_text_length,
|
|
rust_source.len()
|
|
));
|
|
}
|
|
let unquoted_text = unquote(text.text)?;
|
|
if unquoted_text != rust_source {
|
|
this_status = DiffStatus::Bad;
|
|
message = Some(format!(
|
|
"(emacs != rust) {:?} != {:?}",
|
|
unquoted_text, rust_source
|
|
));
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: Vec::new(),
|
|
rust_source,
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_bold<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Bold<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_italic<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Italic<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_underline<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Underline<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_verbatim<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Verbatim<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.contents),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_code<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Code<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.contents),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_strike_through<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b StrikeThrough<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_regular_link<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b RegularLink<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| {
|
|
match &r.link_type {
|
|
LinkType::File => Some(Cow::Borrowed("file")),
|
|
LinkType::Protocol(protocol) => Some(protocol.clone()),
|
|
LinkType::Id => Some(Cow::Borrowed("id")),
|
|
LinkType::CustomId => Some(Cow::Borrowed("custom-id")),
|
|
LinkType::CodeRef => Some(Cow::Borrowed("coderef")),
|
|
LinkType::Fuzzy => Some(Cow::Borrowed("fuzzy")),
|
|
}
|
|
},
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":path"),
|
|
|r| Some(r.get_path()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":format"),
|
|
|_| Some("bracket"),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":raw-link"),
|
|
|r| Some(r.get_raw_link()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":application"),
|
|
|r| r.application.as_ref(),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":search-option"),
|
|
|r| r.get_search_option(),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_radio_link<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b RadioLink<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|_| { Some("radio") },
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":path"),
|
|
|r| Some(&r.path),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":format"),
|
|
|_| Some("plain"),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":raw-link"),
|
|
|r| Some(r.get_raw_link()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":application"),
|
|
compare_identity,
|
|
compare_property_always_nil
|
|
),
|
|
(
|
|
EmacsField::Required(":search-option"),
|
|
compare_identity,
|
|
compare_property_always_nil
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_radio_target<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b RadioTarget<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_plain_link<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b PlainLink<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| {
|
|
match &r.link_type {
|
|
LinkType::File => Some(Cow::Borrowed("file")),
|
|
LinkType::Protocol(protocol) => Some(protocol.clone()),
|
|
LinkType::Id => Some(Cow::Borrowed("id")),
|
|
LinkType::CustomId => Some(Cow::Borrowed("custom-id")),
|
|
LinkType::CodeRef => Some(Cow::Borrowed("coderef")),
|
|
LinkType::Fuzzy => Some(Cow::Borrowed("fuzzy")),
|
|
}
|
|
},
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":path"),
|
|
|r| Some(r.path),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":format"),
|
|
|_| Some("plain"),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":raw-link"),
|
|
|r| Some(r.raw_link),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":application"),
|
|
|r| r.application,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":search-option"),
|
|
|r| r.search_option,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_angle_link<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b AngleLink<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| {
|
|
match &r.link_type {
|
|
LinkType::File => Some(Cow::Borrowed("file")),
|
|
LinkType::Protocol(protocol) => Some(protocol.clone()),
|
|
LinkType::Id => Some(Cow::Borrowed("id")),
|
|
LinkType::CustomId => Some(Cow::Borrowed("custom-id")),
|
|
LinkType::CodeRef => Some(Cow::Borrowed("coderef")),
|
|
LinkType::Fuzzy => Some(Cow::Borrowed("fuzzy")),
|
|
}
|
|
},
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":path"),
|
|
|r| Some(r.get_path()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":format"),
|
|
|_| Some("angle"),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":raw-link"),
|
|
|r| Some(r.raw_link),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":application"),
|
|
|r| r.application,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":search-option"),
|
|
|r| r.get_search_option(),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_org_macro<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b OrgMacro<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":key"),
|
|
|r| Some(r.get_key()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":args"),
|
|
|r| if r.args.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.get_args())
|
|
},
|
|
compare_property_list_of_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_entity<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Entity<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":name"),
|
|
|r| Some(r.name),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":latex"),
|
|
|r| Some(r.latex),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":latex-math-p"),
|
|
|r| r.latex_math_mode,
|
|
compare_property_boolean
|
|
),
|
|
(
|
|
EmacsField::Required(":html"),
|
|
|r| Some(r.html),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":ascii"),
|
|
|r| Some(r.ascii),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
// latin1... like I give a shit.
|
|
EmacsField::Required(":latin1"),
|
|
compare_identity,
|
|
compare_noop
|
|
),
|
|
(
|
|
EmacsField::Required(":utf-8"),
|
|
|r| Some(r.utf8),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":use-brackets-p"),
|
|
|r| r.use_brackets,
|
|
compare_property_boolean
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_latex_fragment<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b LatexFragment<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_export_snippet<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b ExportSnippet<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":back-end"),
|
|
|r| Some(r.backend),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| r.contents,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_footnote_reference<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b FootnoteReference<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut child_status = Vec::new();
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.definition,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":label"),
|
|
|r| r.label,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| Some(match r.get_type() {
|
|
FootnoteReferenceType::Standard => "standard",
|
|
FootnoteReferenceType::Inline => "inline",
|
|
}),
|
|
compare_property_unquoted_atom
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_citation<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Citation<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut child_status = Vec::new();
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":style"),
|
|
|r| r.style,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Optional(":prefix"),
|
|
|r| if r.prefix.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.prefix.iter())
|
|
},
|
|
compare_property_list_of_ast_nodes
|
|
),
|
|
(
|
|
EmacsField::Optional(":suffix"),
|
|
|r| if r.suffix.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.suffix.iter())
|
|
},
|
|
compare_property_list_of_ast_nodes
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_citation_reference<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b CitationReference<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":key"),
|
|
|r| Some(r.key),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Optional(":prefix"),
|
|
|r| if r.prefix.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.prefix.iter())
|
|
},
|
|
compare_property_list_of_ast_nodes
|
|
),
|
|
(
|
|
EmacsField::Optional(":suffix"),
|
|
|r| if r.suffix.is_empty() {
|
|
None
|
|
} else {
|
|
Some(r.suffix.iter())
|
|
},
|
|
compare_property_list_of_ast_nodes
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_inline_babel_call<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b InlineBabelCall<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":call"),
|
|
|r| Some(r.call),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":inside-header"),
|
|
|r| r.inside_header,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":arguments"),
|
|
|r| r.arguments,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":end-header"),
|
|
|r| r.end_header,
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_inline_source_block<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b InlineSourceBlock<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":language"),
|
|
|r| Some(r.language),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":parameters"),
|
|
|r| r.parameters,
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_line_break<'b, 's>(
|
|
_source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b LineBreak<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(emacs) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_target<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Target<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_statistics_cookie<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b StatisticsCookie<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":value"),
|
|
|r| Some(r.value),
|
|
compare_property_quoted_string
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_subscript<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Subscript<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":use-brackets-p"),
|
|
|r| r.use_brackets,
|
|
compare_property_boolean
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_superscript<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Superscript<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
compare_children(
|
|
source,
|
|
emacs,
|
|
&rust.children,
|
|
&mut child_status,
|
|
&mut this_status,
|
|
&mut message,
|
|
)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":use-brackets-p"),
|
|
|r| r.use_brackets,
|
|
compare_property_boolean
|
|
)
|
|
) {
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|
|
|
|
fn compare_timestamp<'b, 's>(
|
|
source: &'s str,
|
|
emacs: &'b Token<'s>,
|
|
rust: &'b Timestamp<'s>,
|
|
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error + 's>> {
|
|
let mut this_status = DiffStatus::Good;
|
|
let mut child_status = Vec::new();
|
|
let mut message = None;
|
|
|
|
assert_no_children(emacs, &mut this_status, &mut message)?;
|
|
|
|
for diff in compare_properties!(
|
|
source,
|
|
emacs,
|
|
rust,
|
|
(
|
|
EmacsField::Required(":type"),
|
|
|r| Some(match r.timestamp_type {
|
|
TimestampType::Diary => "diary",
|
|
TimestampType::Active => "active",
|
|
TimestampType::Inactive => "inactive",
|
|
TimestampType::ActiveRange => "active-range",
|
|
TimestampType::InactiveRange => "inactive-range",
|
|
}),
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":range-type"),
|
|
|r| match r.range_type {
|
|
TimestampRangeType::DateRange => Some("daterange"),
|
|
TimestampRangeType::TimeRange => Some("timerange"),
|
|
TimestampRangeType::None => None,
|
|
},
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Required(":raw-value"),
|
|
|r| Some(r.get_raw_value()),
|
|
compare_property_quoted_string
|
|
),
|
|
(
|
|
EmacsField::Required(":year-start"),
|
|
|r| r.start.as_ref().map(Date::get_year).map(Year::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":month-start"),
|
|
|r| r.start.as_ref().map(Date::get_month).map(Month::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":day-start"),
|
|
|r| r
|
|
.start
|
|
.as_ref()
|
|
.map(Date::get_day_of_month)
|
|
.map(DayOfMonth::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":year-end"),
|
|
|r| r.end.as_ref().map(Date::get_year).map(Year::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":month-end"),
|
|
|r| r.end.as_ref().map(Date::get_month).map(Month::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":day-end"),
|
|
|r| r
|
|
.end
|
|
.as_ref()
|
|
.map(Date::get_day_of_month)
|
|
.map(DayOfMonth::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":hour-start"),
|
|
|r| r
|
|
.start_time
|
|
.as_ref()
|
|
.map(Time::get_hour)
|
|
.map(Hour::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":minute-start"),
|
|
|r| r
|
|
.start_time
|
|
.as_ref()
|
|
.map(Time::get_minute)
|
|
.map(Minute::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":hour-end"),
|
|
|r| r.end_time.as_ref().map(Time::get_hour).map(Hour::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Required(":minute-end"),
|
|
|r| r
|
|
.end_time
|
|
.as_ref()
|
|
.map(Time::get_minute)
|
|
.map(Minute::get_value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Optional(":repeater-type"),
|
|
|r| match r.repeater.as_ref().map(|repeater| &repeater.repeater_type) {
|
|
Some(RepeaterType::Cumulative) => Some("cumulate"),
|
|
Some(RepeaterType::CatchUp) => Some("catch-up"),
|
|
Some(RepeaterType::Restart) => Some("restart"),
|
|
None => None,
|
|
},
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Optional(":repeater-unit"),
|
|
|r| match r.repeater.as_ref().map(|repeater| &repeater.unit) {
|
|
Some(TimeUnit::Hour) => Some("hour"),
|
|
Some(TimeUnit::Day) => Some("day"),
|
|
Some(TimeUnit::Week) => Some("week"),
|
|
Some(TimeUnit::Month) => Some("month"),
|
|
Some(TimeUnit::Year) => Some("year"),
|
|
None => None,
|
|
},
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Optional(":repeater-value"),
|
|
|r| r.repeater.as_ref().map(|repeater| repeater.value),
|
|
compare_property_numeric
|
|
),
|
|
(
|
|
EmacsField::Optional(":warning-type"),
|
|
|r| match r
|
|
.warning_delay
|
|
.as_ref()
|
|
.map(|repeater| &repeater.warning_delay_type)
|
|
{
|
|
Some(WarningDelayType::All) => Some("all"),
|
|
Some(WarningDelayType::First) => Some("first"),
|
|
None => None,
|
|
},
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Optional(":warning-unit"),
|
|
|r| match r.warning_delay.as_ref().map(|repeater| &repeater.unit) {
|
|
Some(TimeUnit::Hour) => Some("hour"),
|
|
Some(TimeUnit::Day) => Some("day"),
|
|
Some(TimeUnit::Week) => Some("week"),
|
|
Some(TimeUnit::Month) => Some("month"),
|
|
Some(TimeUnit::Year) => Some("year"),
|
|
None => None,
|
|
},
|
|
compare_property_unquoted_atom
|
|
),
|
|
(
|
|
EmacsField::Optional(":warning-value"),
|
|
|r| r.warning_delay.as_ref().map(|repeater| repeater.value),
|
|
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),
|
|
}
|
|
}
|
|
|
|
Ok(DiffResult {
|
|
status: this_status,
|
|
name: rust.get_elisp_name(),
|
|
message,
|
|
children: child_status,
|
|
rust_source: rust.get_source(),
|
|
emacs_token: emacs,
|
|
}
|
|
.into())
|
|
}
|