From a6d742a536f1e5b21049130779d0a2863249fbf2 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 29 Aug 2023 20:11:23 -0400 Subject: [PATCH] Fix handling line breaks after divider in description lists. --- .../plain_list/description_eof.org | 2 ++ .../plain_list/description_list.org | 3 ++ src/parser/plain_list.rs | 33 +++++++++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 org_mode_samples/greater_element/plain_list/description_eof.org diff --git a/org_mode_samples/greater_element/plain_list/description_eof.org b/org_mode_samples/greater_element/plain_list/description_eof.org new file mode 100644 index 0000000..0f72e5d --- /dev/null +++ b/org_mode_samples/greater_element/plain_list/description_eof.org @@ -0,0 +1,2 @@ +- foo :: + diff --git a/org_mode_samples/greater_element/plain_list/description_list.org b/org_mode_samples/greater_element/plain_list/description_list.org index ef014f7..5bbcedf 100644 --- a/org_mode_samples/greater_element/plain_list/description_list.org +++ b/org_mode_samples/greater_element/plain_list/description_list.org @@ -6,3 +6,6 @@ - lorem :: ipsum - dolar *bold* foo :: ipsum +- big gap :: + + stuff diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 8386796..75bdbd0 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -6,9 +6,12 @@ use nom::character::complete::one_of; use nom::character::complete::space0; use nom::character::complete::space1; use nom::combinator::eof; +use nom::combinator::not; use nom::combinator::opt; +use nom::combinator::peek; use nom::combinator::recognize; use nom::combinator::verify; +use nom::multi::many0; use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; @@ -163,7 +166,7 @@ pub fn plain_list_item<'r, 's>( parser_with_context!(item_tag)(context), tag(" ::"), )))(remaining)?; - let (remaining, _ws) = alt((space1, line_ending))(remaining)?; + let (remaining, _ws) = item_tag_post_gap(context, remaining)?; let exit_matcher = plain_list_item_end(indent_level); let parser_context = context .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) @@ -174,7 +177,10 @@ pub fn plain_list_item<'r, 's>( let (remaining, (children, _exit_contents)) = many_till( parser_with_context!(element(true))(&parser_context), - parser_with_context!(exit_matcher_parser)(&parser_context), + alt(( + peek(recognize(tuple((start_of_line, many0(blank_line), eof)))), + parser_with_context!(exit_matcher_parser)(&parser_context), + )), )(remaining)?; let (remaining, _trailing_ws) = @@ -189,7 +195,7 @@ pub fn plain_list_item<'r, 's>( bullet: bull.into(), tag: maybe_tag .map(|(_ws, item_tag, _divider)| item_tag) - .unwrap_or(Vec::new()), // TODO + .unwrap_or(Vec::new()), children, }, )); @@ -305,6 +311,27 @@ fn item_tag_end<'r, 's>( )))(input) } +#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] +fn item_tag_post_gap<'r, 's>( + context: Context<'r, 's>, + input: OrgSource<'s>, +) -> Res, OrgSource<'s>> { + verify( + recognize(tuple(( + alt((blank_line, space0)), + many_till( + blank_line, + alt(( + peek(recognize(not(blank_line))), + peek(recognize(tuple((many0(blank_line), eof)))), + parser_with_context!(exit_matcher_parser)(context), + )), + ), + ))), + |gap| gap.len() > 0, + )(input) +} + #[cfg(test)] mod tests { use super::*;