organic/src/compare/diff.rs

2473 lines
68 KiB
Rust
Raw Normal View History

2023-08-25 06:46:00 -04:00
use std::collections::HashSet;
2023-04-19 15:29:46 -04:00
use super::util::assert_bounds;
use super::util::assert_name;
2023-08-29 22:07:23 -04:00
use super::util::get_property;
use crate::parser::sexp::unquote;
use crate::parser::sexp::Token;
2023-09-03 12:52:09 -04:00
use crate::types::AngleLink;
use crate::types::Bold;
use crate::types::Citation;
use crate::types::CitationReference;
use crate::types::Clock;
use crate::types::Code;
use crate::types::Comment;
use crate::types::CommentBlock;
use crate::types::DiarySexp;
use crate::types::Document;
use crate::types::DocumentElement;
use crate::types::Drawer;
use crate::types::DynamicBlock;
use crate::types::Element;
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::GreaterBlock;
use crate::types::Heading;
use crate::types::HorizontalRule;
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;
2023-09-06 18:49:59 -04:00
use crate::types::NodeProperty;
2023-09-03 12:52:09 -04:00
use crate::types::Object;
use crate::types::OrgMacro;
use crate::types::Paragraph;
use crate::types::PlainLink;
use crate::types::PlainList;
use crate::types::PlainListItem;
use crate::types::PlainText;
use crate::types::Planning;
use crate::types::PriorityCookie;
2023-09-03 12:52:09 -04:00
use crate::types::PropertyDrawer;
use crate::types::RadioLink;
use crate::types::RadioTarget;
use crate::types::RegularLink;
use crate::types::Section;
use crate::types::Source;
use crate::types::SrcBlock;
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::Target;
use crate::types::Timestamp;
2023-09-06 12:39:03 -04:00
use crate::types::TodoKeywordType;
2023-09-03 12:52:09 -04:00
use crate::types::Underline;
use crate::types::Verbatim;
use crate::types::VerseBlock;
#[derive(Debug)]
pub enum DiffEntry<'s> {
DiffResult(DiffResult<'s>),
DiffLayer(DiffLayer<'s>),
}
#[derive(Debug)]
pub struct DiffResult<'s> {
status: DiffStatus,
name: String,
message: Option<String>,
children: Vec<DiffEntry<'s>>,
rust_source: &'s str,
#[allow(dead_code)]
emacs_token: &'s Token<'s>,
}
2023-04-11 19:22:42 -04:00
#[derive(Debug, PartialEq)]
pub enum DiffStatus {
Good,
Bad,
}
#[derive(Debug)]
pub struct DiffLayer<'s> {
name: String,
children: Vec<DiffEntry<'s>>,
}
impl<'s> From<DiffResult<'s>> for DiffEntry<'s> {
fn from(value: DiffResult<'s>) -> Self {
DiffEntry::DiffResult(value)
}
}
impl<'s> From<DiffLayer<'s>> for DiffEntry<'s> {
fn from(value: DiffLayer<'s>) -> Self {
DiffEntry::DiffLayer(value)
}
}
impl<'s> DiffEntry<'s> {
fn has_bad_children(&self) -> bool {
match self {
DiffEntry::DiffResult(diff) => &diff.children,
DiffEntry::DiffLayer(diff) => &diff.children,
}
.iter()
.any(|child| child.is_immediately_bad() || child.has_bad_children())
}
fn is_immediately_bad(&self) -> bool {
match self {
DiffEntry::DiffResult(diff) => diff.status == DiffStatus::Bad,
DiffEntry::DiffLayer(_) => false,
}
}
pub fn is_bad(&self) -> bool {
self.is_immediately_bad() || self.has_bad_children()
}
pub fn print(&self, original_document: &str) -> Result<(), Box<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<'s> DiffResult<'s> {
fn print_indented(
&self,
indentation: usize,
original_document: &str,
) -> Result<(), Box<dyn std::error::Error>> {
2023-04-11 19:22:42 -04:00
let status_text = {
match self.status {
DiffStatus::Good => {
if self.has_bad_children() {
2023-08-25 04:09:52 -04:00
format!(
"{color}BADCHILD{reset}",
color = DiffResult::foreground_color(255, 255, 0),
reset = DiffResult::reset_color(),
)
2023-04-11 19:22:42 -04:00
} else {
2023-08-25 04:09:52 -04:00
format!(
"{color}GOOD{reset}",
color = DiffResult::foreground_color(0, 255, 0),
reset = DiffResult::reset_color(),
)
2023-04-11 19:22:42 -04:00
}
2023-04-12 11:35:02 -04:00
}
2023-08-25 04:09:52 -04:00
DiffStatus::Bad => format!(
"{color}BAD{reset}",
color = DiffResult::foreground_color(255, 0, 0),
reset = DiffResult::reset_color(),
),
2023-04-11 19:22:42 -04:00
}
};
let rust_offset = self.rust_source.as_ptr() as usize - original_document.as_ptr() as usize;
2023-08-29 21:49:16 -04:00
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,
2023-08-29 21:49:16 -04:00
char_offset = preceding_text.chars().count() + 1,
message = self.message.as_ref().map(|m| m.as_str()).unwrap_or("")
);
for child in self.children.iter() {
child.print_indented(indentation + 1, original_document)?;
}
Ok(())
}
2023-04-11 19:22:42 -04:00
fn has_bad_children(&self) -> bool {
2023-04-12 11:35:02 -04:00
self.children
.iter()
.any(|child| child.is_immediately_bad() || child.has_bad_children())
}
2023-08-25 04:09:52 -04:00
fn foreground_color(red: u8, green: u8, blue: u8) -> String {
if DiffResult::should_use_color() {
format!(
"\x1b[38;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
} else {
String::new()
}
2023-08-25 04:09:52 -04:00
}
#[allow(dead_code)]
fn background_color(red: u8, green: u8, blue: u8) -> String {
if DiffResult::should_use_color() {
format!(
"\x1b[48;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
} else {
String::new()
}
2023-08-25 04:09:52 -04:00
}
fn reset_color() -> &'static str {
if DiffResult::should_use_color() {
"\x1b[0m"
} else {
""
}
}
fn should_use_color() -> bool {
!std::env::var("NO_COLOR").is_ok_and(|val| !val.is_empty())
2023-08-25 04:09:52 -04:00
}
}
impl<'s> DiffLayer<'s> {
fn has_bad_children(&self) -> bool {
self.children
.iter()
.any(|child| child.is_immediately_bad() || child.has_bad_children())
}
fn print_indented(
&self,
indentation: usize,
original_document: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let status_text = if self.has_bad_children() {
format!(
"{color}BADCHILD{reset}",
color = DiffResult::foreground_color(255, 255, 0),
reset = DiffResult::reset_color(),
)
} else {
format!(
"{color}GOOD{reset}",
color = DiffResult::foreground_color(0, 255, 0),
reset = DiffResult::reset_color(),
)
};
println!(
"{indentation}{status_text} {name}",
indentation = " ".repeat(indentation),
status_text = status_text,
name = self.name,
);
for child in self.children.iter() {
child.print_indented(indentation + 1, original_document)?;
}
Ok(())
}
}
fn artificial_diff_scope<'s>(
name: String,
children: Vec<DiffEntry<'s>>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
Ok(DiffLayer { name, children }.into())
}
fn compare_element<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Element<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-08-29 14:17:47 -04:00
let compare_result = match rust {
Element::Paragraph(obj) => compare_paragraph(source, emacs, obj),
Element::PlainList(obj) => compare_plain_list(source, emacs, obj),
Element::GreaterBlock(obj) => compare_greater_block(source, emacs, obj),
Element::DynamicBlock(obj) => compare_dynamic_block(source, emacs, obj),
Element::FootnoteDefinition(obj) => compare_footnote_definition(source, emacs, obj),
Element::Comment(obj) => compare_comment(source, emacs, obj),
Element::Drawer(obj) => compare_drawer(source, emacs, obj),
Element::PropertyDrawer(obj) => compare_property_drawer(source, emacs, obj),
Element::Table(obj) => compare_table(source, emacs, obj),
Element::VerseBlock(obj) => compare_verse_block(source, emacs, obj),
Element::CommentBlock(obj) => compare_comment_block(source, emacs, obj),
Element::ExampleBlock(obj) => compare_example_block(source, emacs, obj),
Element::ExportBlock(obj) => compare_export_block(source, emacs, obj),
Element::SrcBlock(obj) => compare_src_block(source, emacs, obj),
Element::Clock(obj) => compare_clock(source, emacs, obj),
Element::DiarySexp(obj) => compare_diary_sexp(source, emacs, obj),
Element::Planning(obj) => compare_planning(source, emacs, obj),
Element::FixedWidthArea(obj) => compare_fixed_width_area(source, emacs, obj),
Element::HorizontalRule(obj) => compare_horizontal_rule(source, emacs, obj),
Element::Keyword(obj) => compare_keyword(source, emacs, obj),
2023-09-06 18:04:53 -04:00
Element::BabelCall(obj) => compare_babel_call(source, emacs, obj),
Element::LatexEnvironment(obj) => compare_latex_environment(source, emacs, obj),
2023-08-29 14:17:47 -04:00
};
match compare_result {
Ok(_) => compare_result,
Err(ref e) => Ok(DiffResult {
status: DiffStatus::Bad,
name: "error!".to_owned(),
message: Some(e.to_string()),
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into()),
}
}
fn compare_object<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Object<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-08-29 14:17:47 -04:00
let compare_result = match rust {
Object::Bold(obj) => compare_bold(source, emacs, obj),
Object::Italic(obj) => compare_italic(source, emacs, obj),
Object::Underline(obj) => compare_underline(source, emacs, obj),
Object::Verbatim(obj) => compare_verbatim(source, emacs, obj),
Object::Code(obj) => compare_code(source, emacs, obj),
Object::StrikeThrough(obj) => compare_strike_through(source, emacs, obj),
Object::PlainText(obj) => compare_plain_text(source, emacs, obj),
Object::RegularLink(obj) => compare_regular_link(source, emacs, obj),
Object::RadioLink(obj) => compare_radio_link(source, emacs, obj),
Object::RadioTarget(obj) => compare_radio_target(source, emacs, obj),
2023-07-13 18:18:07 -04:00
Object::PlainLink(obj) => compare_plain_link(source, emacs, obj),
2023-07-13 22:42:42 -04:00
Object::AngleLink(obj) => compare_angle_link(source, emacs, obj),
2023-07-13 23:26:51 -04:00
Object::OrgMacro(obj) => compare_org_macro(source, emacs, obj),
2023-07-18 20:05:39 -04:00
Object::Entity(obj) => compare_entity(source, emacs, obj),
2023-07-18 20:51:06 -04:00
Object::LatexFragment(obj) => compare_latex_fragment(source, emacs, obj),
2023-07-19 00:09:16 -04:00
Object::ExportSnippet(obj) => compare_export_snippet(source, emacs, obj),
Object::FootnoteReference(obj) => compare_footnote_reference(source, emacs, obj),
2023-07-20 00:38:16 -04:00
Object::Citation(obj) => compare_citation(source, emacs, obj),
Object::CitationReference(obj) => compare_citation_reference(source, emacs, obj),
Object::InlineBabelCall(obj) => compare_inline_babel_call(source, emacs, obj),
Object::InlineSourceBlock(obj) => compare_inline_source_block(source, emacs, obj),
2023-07-21 23:48:37 -04:00
Object::LineBreak(obj) => compare_line_break(source, emacs, obj),
2023-07-22 01:15:04 -04:00
Object::Target(obj) => compare_target(source, emacs, obj),
Object::StatisticsCookie(obj) => compare_statistics_cookie(source, emacs, obj),
Object::Subscript(obj) => compare_subscript(source, emacs, obj),
Object::Superscript(obj) => compare_superscript(source, emacs, obj),
2023-07-24 17:34:07 -04:00
Object::Timestamp(obj) => compare_timestamp(source, emacs, obj),
2023-08-29 14:17:47 -04:00
};
match compare_result {
Ok(_) => compare_result,
Err(ref e) => Ok(DiffResult {
status: DiffStatus::Bad,
name: "error!".to_owned(),
message: Some(e.to_string()),
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into()),
}
}
pub fn compare_document<'s>(
emacs: &'s Token<'s>,
rust: &'s Document<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let emacs_name = "org-data";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
// Skipping "org-data" and the first parameter which is often nil
for (i, token) in children.iter().skip(2).enumerate() {
let section_or_headline = token.as_list()?;
let first_cell = section_or_headline
.first()
.ok_or("Should have at least one child.")?
.as_atom()?;
if first_cell == "section" {
if i != 0 {
return Err("Section cannot be after the first child of document.".into());
}
child_status.push(compare_section(
rust.source,
token,
rust.zeroth_section
.as_ref()
.ok_or("No corresponding zeroth-section")?,
)?);
} else if first_cell == "headline" {
let corresponding_heading = rust
.children
.iter()
.nth(i - rust.zeroth_section.as_ref().map(|_| 1).unwrap_or(0))
.ok_or("Should have a corresponding heading.")?;
child_status.push(compare_heading(rust.source, token, corresponding_heading)?);
} else {
return Err("Document should only contain sections and headlines.".into());
}
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message: None,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-12 13:16:25 -04:00
fn compare_section<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Section<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let mut message = None;
let emacs_name = "section";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-12 11:46:49 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-12 13:16:25 -04:00
fn compare_heading<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Heading<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
2023-08-25 06:46:00 -04:00
let mut message = None;
let emacs_name = "headline";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-08-29 22:07:23 -04:00
// Compare level
2023-08-29 22:11:56 -04:00
let level = get_property(emacs, ":level")?
.ok_or("Level should not be nil")?
.as_atom()?;
if rust.stars.to_string() != level {
this_status = DiffStatus::Bad;
message = Some(format!(
"Headline level do not much (emacs != rust): {} != {}",
level, rust.stars
))
}
2023-08-29 22:07:23 -04:00
// Compare tags
let emacs_tags = get_tags_from_heading(emacs)?;
let emacs_tags: HashSet<_> = emacs_tags.iter().map(|val| val.as_str()).collect();
let rust_tags: HashSet<&str> = rust.tags.iter().map(|val| *val).collect();
let difference: Vec<&str> = emacs_tags
.symmetric_difference(&rust_tags)
.map(|val| *val)
.collect();
if !difference.is_empty() {
this_status = DiffStatus::Bad;
message = Some(format!("Mismatched tags: {}", difference.join(", ")));
}
// Compare todo-keyword
let todo_keyword = get_property(emacs, ":todo-keyword")?
.map(Token::as_atom)
.map_or(Ok(None), |r| r.map(Some))?
.unwrap_or("nil");
2023-09-06 12:39:03 -04:00
match (todo_keyword, &rust.todo_keyword, unquote(todo_keyword)) {
("nil", None, _) => {}
2023-09-06 12:39:03 -04:00
(_, Some((_rust_todo_type, rust_todo)), Ok(emacs_todo)) if emacs_todo == *rust_todo => {}
(emacs_todo, rust_todo, _) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"(emacs != rust) {:?} != {:?}",
emacs_todo, rust_todo
));
}
};
2023-09-06 12:39:03 -04:00
// Compare todo-type
let todo_type = get_property(emacs, ":todo-type")?
.map(Token::as_atom)
.map_or(Ok(None), |r| r.map(Some))?
.unwrap_or("nil");
// todo-type is an unquoted string either todo, done, or nil
match (todo_type, &rust.todo_keyword) {
("nil", None) => {}
("todo", Some((TodoKeywordType::Todo, _))) => {}
("done", Some((TodoKeywordType::Done, _))) => {}
(emacs_todo, rust_todo) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"(emacs != rust) {:?} != {:?}",
emacs_todo, rust_todo
));
}
};
// Compare title
let title = get_property(emacs, ":title")?.ok_or("Missing :title attribute.")?;
let title_status = title
.as_list()?
.iter()
.zip(rust.title.iter())
.map(|(emacs_child, rust_child)| compare_object(source, emacs_child, rust_child))
.collect::<Result<Vec<_>, _>>()?;
child_status.push(artificial_diff_scope("title".to_owned(), title_status)?);
// Compare priority
let priority = get_property(emacs, ":priority")?;
match (priority, rust.priority_cookie) {
(None, None) => {}
(None, Some(_)) | (Some(_), None) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Priority cookie mismatch (emacs != rust) {:?} != {:?}",
priority, rust.priority_cookie
));
}
(Some(emacs_priority_cookie), Some(rust_priority_cookie)) => {
let emacs_priority_cookie =
emacs_priority_cookie.as_atom()?.parse::<PriorityCookie>()?;
if emacs_priority_cookie != rust_priority_cookie {
this_status = DiffStatus::Bad;
message = Some(format!(
"Priority cookie mismatch (emacs != rust) {:?} != {:?}",
emacs_priority_cookie, rust_priority_cookie
));
}
}
}
// Compare archived
let archived = get_property(emacs, ":archivedp")?;
match (archived, rust.is_archived) {
(None, true) | (Some(_), false) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"archived mismatch (emacs != rust) {:?} != {:?}",
archived, rust.is_archived
));
}
(None, false) | (Some(_), true) => {}
}
// Compare commented
let commented = get_property(emacs, ":commentedp")?;
match (commented, rust.is_comment) {
(None, true) | (Some(_), false) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"commented mismatch (emacs != rust) {:?} != {:?}",
commented, rust.is_comment
));
}
(None, false) | (Some(_), true) => {}
}
// TODO: Compare :footnote-section-p
// Compare section
let section_status = children
.iter()
.skip(2)
.zip(rust.children.iter())
.map(|(emacs_child, rust_child)| match rust_child {
2023-04-12 11:35:02 -04:00
DocumentElement::Heading(rust_heading) => {
compare_heading(source, emacs_child, rust_heading)
2023-04-12 13:16:25 -04:00
}
2023-04-12 11:35:02 -04:00
DocumentElement::Section(rust_section) => {
compare_section(source, emacs_child, rust_section)
2023-04-12 13:16:25 -04:00
}
})
.collect::<Result<Vec<_>, _>>()?;
child_status.push(artificial_diff_scope("section".to_owned(), section_status)?);
2023-04-12 11:35:02 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
2023-08-25 06:46:00 -04:00
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-12 11:46:49 -04:00
2023-08-25 06:46:00 -04:00
fn get_tags_from_heading<'s>(
emacs: &'s Token<'s>,
) -> Result<HashSet<String>, Box<dyn std::error::Error>> {
let tags = match get_property(emacs, ":tags")? {
Some(prop) => prop,
None => return Ok(HashSet::new()),
};
2023-08-25 06:46:00 -04:00
match tags.as_atom() {
Ok(val) => panic!("Unexpected value for tags: {:?}", val),
Err(_) => {}
};
let tags = {
let tags = tags.as_list()?;
let strings = tags
.iter()
.map(Token::as_atom)
.collect::<Result<Vec<&str>, _>>()?;
strings
.into_iter()
.map(unquote)
.collect::<Result<HashSet<String>, _>>()?
2023-08-25 06:46:00 -04:00
};
Ok(tags)
}
2023-04-12 13:16:25 -04:00
fn compare_paragraph<'s>(
2023-04-12 11:46:49 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Paragraph<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-12 11:46:49 -04:00
let children = emacs.as_list()?;
let mut child_status = Vec::new();
2023-04-12 11:46:49 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "paragraph";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
2023-04-12 11:46:49 -04:00
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-12 11:46:49 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_object(source, emacs_child, rust_child)?);
}
2023-04-12 11:46:49 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-12 11:46:49 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-12 11:46:49 -04:00
}
2023-04-12 13:16:25 -04:00
fn compare_plain_list<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s PlainList<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-12 13:16:25 -04:00
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "plain-list";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
2023-04-12 13:16:25 -04:00
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-12 13:16:25 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_plain_list_item(source, emacs_child, rust_child)?);
}
2023-04-12 13:16:25 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-12 13:16:25 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-12 13:16:25 -04:00
}
fn compare_plain_list_item<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s PlainListItem<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "item";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
// Compare tag
let tag = get_property(emacs, ":tag")?;
match (tag, rust.tag.is_empty()) {
(None, true) => {}
(None, false) | (Some(_), true) => {
this_status = DiffStatus::Bad;
message = Some("Mismatched tags".to_owned());
}
(Some(tag), false) => {
let tag_status = tag
.as_list()?
.iter()
.zip(rust.tag.iter())
.map(|(emacs_child, rust_child)| compare_object(source, emacs_child, rust_child))
.collect::<Result<Vec<_>, _>>()?;
child_status.push(artificial_diff_scope("tag".to_owned(), tag_status)?);
}
};
// Compare contents
let contents_status = children
.iter()
.skip(2)
.zip(rust.children.iter())
.map(|(emacs_child, rust_child)| compare_element(source, emacs_child, rust_child))
.collect::<Result<Vec<_>, _>>()?;
child_status.push(artificial_diff_scope(
"contents".to_owned(),
contents_status,
)?);
// TODO: compare :bullet :checkbox :counter :pre-blank
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_greater_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s GreaterBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = match rust.name.to_lowercase().as_str() {
"center" => "center-block",
"quote" => "quote-block",
2023-08-31 19:04:44 -04:00
_ => "special-block",
};
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-19 13:59:17 -04:00
}
fn compare_dynamic_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s DynamicBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-19 13:59:17 -04:00
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
if assert_name(emacs, "dynamic-block").is_err() {
this_status = DiffStatus::Bad;
}
2023-04-19 13:59:17 -04:00
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-19 13:59:17 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: "dynamic-block".to_owned(),
message,
2023-04-19 13:59:17 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_footnote_definition<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s FootnoteDefinition<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "footnote-definition";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-15 16:53:58 -04:00
fn compare_comment<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Comment<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let child_status = Vec::new();
2023-04-15 16:53:58 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "comment";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
2023-04-15 16:53:58 -04:00
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-15 16:53:58 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-15 16:53:58 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-15 16:53:58 -04:00
}
2023-04-15 18:00:34 -04:00
fn compare_drawer<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Drawer<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-15 18:00:34 -04:00
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "drawer";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
2023-04-15 18:00:34 -04:00
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-15 18:00:34 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-15 18:00:34 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-15 18:00:34 -04:00
}
fn compare_property_drawer<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s PropertyDrawer<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
2023-09-06 18:49:59 -04:00
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "property-drawer";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-09-06 18:49:59 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_node_property(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-19 20:59:58 -04:00
2023-09-06 18:49:59 -04:00
fn compare_node_property<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s NodeProperty<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "node-property";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
// TODO: Compare :key :value
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-19 20:59:58 -04:00
fn compare_table<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Table<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-19 20:59:58 -04:00
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-19 20:59:58 -04:00
let emacs_name = "table";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-19 20:59:58 -04:00
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_table_row(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_table_row<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s TableRow<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "table-row";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_table_cell(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_table_cell<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s TableCell<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "table-cell";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
for (_emacs_child, _rust_child) in children.iter().skip(2).zip(rust.children.iter()) {}
2023-04-19 20:59:58 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-19 20:59:58 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-19 20:59:58 -04:00
}
fn compare_verse_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s VerseBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 18:05:40 -04:00
let children = emacs.as_list()?;
let child_status = Vec::new();
2023-04-21 18:05:40 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 18:05:40 -04:00
let emacs_name = "verse-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 18:05:40 -04:00
for (_emacs_child, _rust_child) in children.iter().skip(2).zip(rust.children.iter()) {}
2023-04-21 18:05:40 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 18:05:40 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_comment_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s CommentBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 18:05:40 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 18:05:40 -04:00
let emacs_name = "comment-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 18:05:40 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 18:05:40 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_example_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s ExampleBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 18:05:40 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 18:05:40 -04:00
let emacs_name = "example-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 18:05:40 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 18:05:40 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_export_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s ExportBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 18:05:40 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 18:05:40 -04:00
let emacs_name = "export-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 18:05:40 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 18:05:40 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_src_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s SrcBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 18:05:40 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 18:05:40 -04:00
let emacs_name = "src-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 18:05:40 -04:00
2023-09-06 18:11:57 -04:00
// TODO: Compare :language :switches :parameters :number-lines :preserve-indent :retain-labels :use-labels :label-fmt :value
2023-04-21 18:05:40 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 18:05:40 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_clock<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Clock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "clock";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-04-21 20:22:31 -04:00
fn compare_diary_sexp<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s DiarySexp<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 20:22:31 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 20:22:31 -04:00
let emacs_name = "diary-sexp";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 20:22:31 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 20:22:31 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-21 20:22:31 -04:00
}
2023-04-21 21:33:23 -04:00
fn compare_planning<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Planning<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 21:33:23 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 21:33:23 -04:00
let emacs_name = "planning";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 21:33:23 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 21:33:23 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-21 21:33:23 -04:00
}
2023-04-21 22:04:22 -04:00
fn compare_fixed_width_area<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s FixedWidthArea<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 22:04:22 -04:00
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 22:04:22 -04:00
let emacs_name = "fixed-width";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 22:04:22 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 22:04:22 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-21 22:04:22 -04:00
}
2023-04-21 22:23:59 -04:00
fn compare_horizontal_rule<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s HorizontalRule<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 22:23:59 -04:00
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 22:23:59 -04:00
let emacs_name = "horizontal-rule";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 22:23:59 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 22:23:59 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-21 22:23:59 -04:00
}
2023-04-21 22:33:10 -04:00
fn compare_keyword<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Keyword<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-21 22:33:10 -04:00
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-21 22:33:10 -04:00
let emacs_name = "keyword";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-21 22:33:10 -04:00
2023-09-06 12:08:06 -04:00
let key = unquote(
get_property(emacs, ":key")?
.ok_or("Emacs keywords should have a :key")?
.as_atom()?,
)?;
if key != rust.key.to_uppercase() {
this_status = DiffStatus::Bad;
message = Some(format!(
"Mismatchs keyword keys (emacs != rust) {:?} != {:?}",
key, rust.key
))
}
let value = unquote(
get_property(emacs, ":value")?
.ok_or("Emacs keywords should have a :value")?
.as_atom()?,
)?;
if value != rust.value {
this_status = DiffStatus::Bad;
message = Some(format!(
"Mismatchs keyword values (emacs != rust) {:?} != {:?}",
value, rust.value
))
}
2023-09-06 18:04:53 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_babel_call<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Keyword<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "babel-call";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
// TODO: compare :call :inside-header :arguments :end-header
let value = unquote(
get_property(emacs, ":value")?
.ok_or("Emacs keywords should have a :value")?
.as_atom()?,
)?;
if value != rust.value {
this_status = DiffStatus::Bad;
message = Some(format!(
"Mismatchs keyword values (emacs != rust) {:?} != {:?}",
value, rust.value
))
}
2023-04-21 22:33:10 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-21 22:33:10 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-21 22:33:10 -04:00
}
2023-04-22 16:56:36 -04:00
fn compare_latex_environment<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s LatexEnvironment<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 16:56:36 -04:00
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 16:56:36 -04:00
let emacs_name = "latex-environment";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 16:56:36 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-04-22 16:56:36 -04:00
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-04-22 16:56:36 -04:00
}
fn compare_plain_text<'s>(
_source: &'s str,
emacs: &'s Token<'s>,
rust: &'s PlainText<'s>,
) -> Result<DiffEntry<'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
.get(0)
.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()
));
}
2023-08-25 06:46:00 -04:00
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: "plain-text".to_owned(),
message,
children: Vec::new(),
rust_source,
emacs_token: emacs,
}
.into())
}
fn compare_bold<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Bold<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "bold";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_italic<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Italic<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "italic";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_underline<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Underline<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "underline";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_verbatim<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Verbatim<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "verbatim";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_code<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Code<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "code";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_strike_through<'s>(
2023-04-22 20:48:01 -04:00
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s StrikeThrough<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-04-22 20:48:01 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-04-22 20:48:01 -04:00
let emacs_name = "strike-through";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-04-22 20:48:01 -04:00
Ok(DiffResult {
2023-04-22 20:48:01 -04:00
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_regular_link<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s RegularLink<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "link";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_radio_link<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s RadioLink<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "link";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_radio_target<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s RadioTarget<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "radio-target";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-07-13 18:18:07 -04:00
fn compare_plain_link<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s PlainLink<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-13 18:18:07 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-13 18:18:07 -04:00
let emacs_name = "link";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-13 18:18:07 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-13 18:18:07 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-13 18:18:07 -04:00
}
2023-07-13 22:42:42 -04:00
fn compare_angle_link<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s AngleLink<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-13 22:42:42 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-13 22:42:42 -04:00
let emacs_name = "link";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-13 22:42:42 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-13 22:42:42 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-13 22:42:42 -04:00
}
2023-07-13 23:26:51 -04:00
fn compare_org_macro<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s OrgMacro<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-13 23:26:51 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-13 23:26:51 -04:00
let emacs_name = "macro";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-13 23:26:51 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-13 23:26:51 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-13 23:26:51 -04:00
}
2023-07-18 20:05:39 -04:00
fn compare_entity<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Entity<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-18 20:05:39 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-18 20:05:39 -04:00
let emacs_name = "entity";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-18 20:05:39 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-18 20:05:39 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-18 20:05:39 -04:00
}
2023-07-18 20:51:06 -04:00
fn compare_latex_fragment<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s LatexFragment<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-18 20:51:06 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-18 20:51:06 -04:00
let emacs_name = "latex-fragment";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-18 20:51:06 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-18 20:51:06 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-18 20:51:06 -04:00
}
2023-07-19 00:09:16 -04:00
fn compare_export_snippet<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s ExportSnippet<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-19 00:09:16 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-19 00:09:16 -04:00
let emacs_name = "export-snippet";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-19 00:09:16 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-19 00:09:16 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-19 00:09:16 -04:00
}
fn compare_footnote_reference<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s FootnoteReference<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "footnote-reference";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-07-20 00:38:16 -04:00
fn compare_citation<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Citation<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-20 00:38:16 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-20 00:38:16 -04:00
let emacs_name = "citation";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-20 00:38:16 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-20 00:38:16 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-20 00:38:16 -04:00
}
fn compare_citation_reference<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s CitationReference<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-20 00:38:16 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-20 00:38:16 -04:00
let emacs_name = "citation-reference";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-20 00:38:16 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-20 00:38:16 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-20 00:38:16 -04:00
}
fn compare_inline_babel_call<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s InlineBabelCall<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "inline-babel-call";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_inline_source_block<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s InlineSourceBlock<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "inline-src-block";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-07-21 23:48:37 -04:00
fn compare_line_break<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s LineBreak<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-21 23:48:37 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-21 23:48:37 -04:00
let emacs_name = "line-break";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-21 23:48:37 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-21 23:48:37 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-21 23:48:37 -04:00
}
2023-07-22 01:15:04 -04:00
fn compare_target<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Target<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-22 01:15:04 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-22 01:15:04 -04:00
let emacs_name = "target";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-22 01:15:04 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-22 01:15:04 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-22 01:15:04 -04:00
}
fn compare_statistics_cookie<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s StatisticsCookie<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "statistics-cookie";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_subscript<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Subscript<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "subscript";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_superscript<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Superscript<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "superscript";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
2023-07-24 17:34:07 -04:00
fn compare_timestamp<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Timestamp<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
2023-07-24 17:34:07 -04:00
let mut this_status = DiffStatus::Good;
let mut message = None;
2023-07-24 17:34:07 -04:00
let emacs_name = "timestamp";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
2023-07-24 17:34:07 -04:00
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
2023-07-24 17:34:07 -04:00
children: Vec::new(),
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
2023-07-24 17:34:07 -04:00
}