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

View File

@ -44,6 +44,7 @@ use crate::types::IndentationLevel;
use crate::types::Object;
use crate::types::PlainList;
use crate::types::PlainListItem;
use crate::types::PlainListItemCounter;
use crate::types::PlainListType;
#[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,
)(remaining)?;
let (remaining, _maybe_counter_set) =
let (remaining, maybe_counter_set) =
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)?;
@ -213,6 +215,7 @@ fn plain_list_item<'b, 'g, 'r, 's>(
source: source.into(),
indentation: indent_level,
bullet: bull.into(),
counter: maybe_counter_set,
checkbox: None,
tag: maybe_tag
.map(|(_ws, item_tag)| item_tag)
@ -256,6 +259,7 @@ fn plain_list_item<'b, 'g, 'r, 's>(
source: source.into(),
indentation: indent_level,
bullet: bull.into(),
counter: maybe_counter_set,
checkbox: maybe_checkbox.map(|(_, (checkbox_type, 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"))]
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((
recognize(one_of(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
)),
digit1,
map(
one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
|letter| {
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)
}

View File

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

View File

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