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 })) }