From d7f0a02bb89d1a1d0bdbd7b80c3a75dab0dcd7ab Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 3 Apr 2023 19:30:17 -0400 Subject: [PATCH] Fix plain list ending with another element. --- src/parser/plain_list.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index a320cdc..02cf02e 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -26,20 +26,29 @@ use nom::combinator::verify; use nom::multi::many_till; use nom::sequence::tuple; -#[tracing::instrument(ret, level = "debug")] pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, PlainList<'s>> { - let (remaining, first_item) = plain_list_item(context, input)?; + let (mut remaining, first_item) = plain_list_item(context, input)?; + let first_item_indentation = first_item.indentation; let plain_list_item_matcher = parser_with_context!(plain_list_item)(context); let exit_matcher = parser_with_context!(exit_matcher_parser)(context); - // TODO: The problem is this expects the list to be followed by something that matches the exit matcher, but after we have the first plain list item, really anything that is not a plain list item is a good exit condition. - let (remaining, (mut children, _exit_contents)) = many_till( - verify(plain_list_item_matcher, |pli| { - pli.indentation == first_item.indentation - }), - exit_matcher, - )(remaining)?; + let mut children = Vec::new(); + children.push(first_item); + loop { + let exit_contents = exit_matcher(remaining); + if exit_contents.is_ok() { + break; + } + + let next_list_item = plain_list_item_matcher(remaining); + match next_list_item { + Ok((remain, next_child)) if next_child.indentation == first_item_indentation => { + children.push(next_child); + remaining = remain; + } + Ok(_) | Err(_) => break, + }; + } let source = get_consumed(input, remaining); - children.insert(0, first_item); Ok((remaining, PlainList { source, children })) }