From bfc9e7f58d1785cf0fba175445fd174c551dcdec Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 31 Aug 2023 17:08:21 -0400 Subject: [PATCH] When re-parsing last item in list, only disable white space consumption for last element in item. --- .../plain_list/trailing_whitespace_eof.org | 2 ++ src/parser/plain_list.rs | 36 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 org_mode_samples/greater_element/plain_list/trailing_whitespace_eof.org diff --git a/org_mode_samples/greater_element/plain_list/trailing_whitespace_eof.org b/org_mode_samples/greater_element/plain_list/trailing_whitespace_eof.org new file mode 100644 index 00000000..4ca3d0e4 --- /dev/null +++ b/org_mode_samples/greater_element/plain_list/trailing_whitespace_eof.org @@ -0,0 +1,2 @@ +- foo + diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 75bdbd00..ea4d54f6 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -69,6 +69,7 @@ pub fn plain_list<'r, 's>( ) -> Res, PlainList<'s>> { let parser_context = context .with_additional_node(ContextElement::Context("plain list")) + .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, exit_matcher: &plain_list_end, @@ -175,14 +176,23 @@ pub fn plain_list_item<'r, 's>( exit_matcher: &exit_matcher, })); - let (remaining, (children, _exit_contents)) = many_till( - parser_with_context!(element(true))(&parser_context), - alt(( - peek(recognize(tuple((start_of_line, many0(blank_line), eof)))), - parser_with_context!(exit_matcher_parser)(&parser_context), - )), + let (mut remaining, (mut children, _exit_contents)) = many_till( + include_input(parser_with_context!(element(true))(&parser_context)), + parser_with_context!(exit_matcher_parser)(&parser_context), )(remaining)?; + if !children.is_empty() && !context.should_consume_trailing_whitespace() { + let final_item_context = + parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); + let (final_child_start, _original_final_child) = children.pop().expect("if-statement already checked that children was non-empty."); + let (remain, reparsed_final_element) = + include_input(parser_with_context!(element(true))(&final_item_context))( + final_child_start, + )?; + remaining = remain; + children.push(reparsed_final_element); + } + let (remaining, _trailing_ws) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; @@ -196,11 +206,23 @@ pub fn plain_list_item<'r, 's>( tag: maybe_tag .map(|(_ws, item_tag, _divider)| item_tag) .unwrap_or(Vec::new()), - children, + children: children.into_iter().map(|(_start, item)| item).collect(), }, )); } +fn include_input<'s, F, O>( + mut inner: F, +) -> impl FnMut(OrgSource<'s>) -> Res, (OrgSource<'s>, O)> +where + F: FnMut(OrgSource<'s>) -> Res, O>, +{ + move |input: OrgSource<'_>| { + let (remaining, output) = inner(input)?; + Ok((remaining, (input, output))) + } +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn bullet<'s>(i: OrgSource<'s>) -> Res, OrgSource<'s>> { alt((