Compare plain list item counter.

This commit is contained in:
Tom Alexander 2023-09-29 18:45:38 -04:00
parent 967e74c147
commit 7727b5ef47
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 57 additions and 8 deletions

View File

@ -52,6 +52,7 @@ use crate::types::Paragraph;
use crate::types::PlainLink; use crate::types::PlainLink;
use crate::types::PlainList; use crate::types::PlainList;
use crate::types::PlainListItem; use crate::types::PlainListItem;
use crate::types::PlainListItemCounter;
use crate::types::PlainListType; use crate::types::PlainListType;
use crate::types::PlainText; use crate::types::PlainText;
use crate::types::Planning; use crate::types::Planning;
@ -754,6 +755,7 @@ fn compare_plain_list<'s>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
// Compare type
// :type is an unquoted atom of either descriptive, ordered, or unordered // :type is an unquoted atom of either descriptive, ordered, or unordered
let list_type = get_property_unquoted_atom(emacs, ":type")?; let list_type = get_property_unquoted_atom(emacs, ":type")?;
match (list_type, &rust.list_type) { match (list_type, &rust.list_type) {
@ -831,17 +833,41 @@ fn compare_plain_list_item<'s>(
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
child_status.push(artificial_diff_scope("contents", contents_status)?); child_status.push(artificial_diff_scope("contents", contents_status)?);
// TODO: Compare :counter :pre-blank // Compare bullet
let bullet = get_property_quoted_string(emacs, ":bullet")? let bullet = get_property_quoted_string(emacs, ":bullet")?
.ok_or("Plain list items must have a :bullet.")?; .ok_or("Plain list items must have a :bullet.")?;
if bullet != rust.bullet { if bullet != rust.bullet {
this_status = DiffStatus::Bad; this_status = DiffStatus::Bad;
message = Some(format!( message = Some(format!(
"Plain list item bullet mismatch (emacs != rust) {:?} != {:?}", "Bullet mismatch (emacs != rust) {:?} != {:?}",
bullet, rust.bullet bullet, rust.bullet
)); ));
} }
// Compare counter
let counter = get_property_unquoted_atom(emacs, ":counter")?;
let counter: Option<PlainListItemCounter> = counter
.map(|val| val.parse())
.map_or(Ok(None), |r| r.map(Some))?;
match (counter, rust.counter) {
(None, None) => {}
(None, Some(_)) | (Some(_), None) => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Counter mismatch (emacs != rust) {:?} != {:?}",
counter, rust.counter
));
}
(Some(e), Some(r)) if e != r => {
this_status = DiffStatus::Bad;
message = Some(format!(
"Counter mismatch (emacs != rust) {:?} != {:?}",
counter, rust.counter
));
}
(Some(_), Some(_)) => {}
};
// Compare checkbox // Compare checkbox
let checkbox = get_property(emacs, ":checkbox")? let checkbox = get_property(emacs, ":checkbox")?
.map(Token::as_atom) .map(Token::as_atom)
@ -861,6 +887,8 @@ fn compare_plain_list_item<'s>(
} }
}; };
// TODO: Compare :pre-blank
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),

View File

@ -44,6 +44,7 @@ use crate::types::IndentationLevel;
use crate::types::Object; use crate::types::Object;
use crate::types::PlainList; use crate::types::PlainList;
use crate::types::PlainListItem; use crate::types::PlainListItem;
use crate::types::PlainListItemCounter;
use crate::types::PlainListType; use crate::types::PlainListType;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -166,8 +167,9 @@ fn plain_list_item<'b, 'g, 'r, 's>(
|(_bullet_type, bull)| !Into::<&str>::into(bull).starts_with("*") || indent_level > 0, |(_bullet_type, bull)| !Into::<&str>::into(bull).starts_with("*") || indent_level > 0,
)(remaining)?; )(remaining)?;
let (remaining, _maybe_counter_set) = let (remaining, maybe_counter_set) =
opt(tuple((space1, tag("[@"), counter_set_value, tag("]"))))(remaining)?; opt(tuple((space1, tag("[@"), counter_set_value, tag("]"))))(remaining)?;
let maybe_counter_set = maybe_counter_set.map(|(_, _, val, _)| val);
let (remaining, maybe_checkbox) = opt(tuple((space1, item_checkbox)))(remaining)?; let (remaining, maybe_checkbox) = opt(tuple((space1, item_checkbox)))(remaining)?;
@ -213,6 +215,7 @@ fn plain_list_item<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
indentation: indent_level, indentation: indent_level,
bullet: bull.into(), bullet: bull.into(),
counter: maybe_counter_set,
checkbox: None, checkbox: None,
tag: maybe_tag tag: maybe_tag
.map(|(_ws, item_tag)| item_tag) .map(|(_ws, item_tag)| item_tag)
@ -256,6 +259,7 @@ fn plain_list_item<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
indentation: indent_level, indentation: indent_level,
bullet: bull.into(), bullet: bull.into(),
counter: maybe_counter_set,
checkbox: maybe_checkbox.map(|(_, (checkbox_type, source))| { checkbox: maybe_checkbox.map(|(_, (checkbox_type, source))| {
(checkbox_type, Into::<&str>::into(source)) (checkbox_type, Into::<&str>::into(source))
}), }),
@ -316,12 +320,25 @@ fn counter<'b, 'g, 'r, 's>(
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn counter_set_value<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { fn counter_set_value<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, PlainListItemCounter> {
alt(( alt((
recognize(one_of( map(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
)), |letter| {
digit1, let num = match letter {
'a'..='z' => (letter as u32) - ('a' as u32) + 1,
'A'..='Z' => (letter as u32) - ('A' as u32) + 1,
_ => unreachable!(),
};
PlainListItemCounter::try_from(num)
.expect("Counter set value should be between 1 and 26 inclusive.")
},
),
map(digit1, |num: OrgSource<'_>| {
Into::<&str>::into(num)
.parse()
.expect("digit1 must parse to a number.")
}),
))(input) ))(input)
} }

View File

@ -26,11 +26,14 @@ pub struct PlainListItem<'s> {
pub source: &'s str, pub source: &'s str,
pub indentation: IndentationLevel, pub indentation: IndentationLevel,
pub bullet: &'s str, pub bullet: &'s str,
pub counter: Option<PlainListItemCounter>,
pub checkbox: Option<(CheckboxType, &'s str)>, pub checkbox: Option<(CheckboxType, &'s str)>,
pub tag: Vec<Object<'s>>, pub tag: Vec<Object<'s>>,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
} }
pub type PlainListItemCounter = u16;
#[derive(Debug)] #[derive(Debug)]
pub enum CheckboxType { pub enum CheckboxType {
On, On,

View File

@ -24,6 +24,7 @@ pub use greater_element::IndentationLevel;
pub use greater_element::NodeProperty; pub use greater_element::NodeProperty;
pub use greater_element::PlainList; pub use greater_element::PlainList;
pub use greater_element::PlainListItem; pub use greater_element::PlainListItem;
pub use greater_element::PlainListItemCounter;
pub use greater_element::PlainListType; pub use greater_element::PlainListType;
pub use greater_element::PropertyDrawer; pub use greater_element::PropertyDrawer;
pub use greater_element::Table; pub use greater_element::Table;