Do not consume whitespace in the final plain list item.
This commit is contained in:
parent
56281633f3
commit
7fafbfb6bb
@ -42,18 +42,27 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
|
|||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
exit_matcher: &plain_list_end,
|
exit_matcher: &plain_list_end,
|
||||||
}));
|
}));
|
||||||
|
// children stores tuple of (input string, parsed object) so we can re-parse the final item
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
let mut first_item_indentation: Option<usize> = None;
|
let mut first_item_indentation: Option<usize> = None;
|
||||||
let mut remaining = input;
|
let mut remaining = input;
|
||||||
|
|
||||||
|
// The final list item does not consume trailing blank lines (which instead get consumed by the list). We have three options here:
|
||||||
|
//
|
||||||
|
// 1. Parse all items while consuming trailing whitespace, then edit the final item to remove trailing whitespace.
|
||||||
|
// 2. Parse all items without consuming trailing whitespace, then edit all but the final one to add in the trailing whitespace.
|
||||||
|
// 3. Re-parse the final item with consume trailing whitespace disabled.
|
||||||
|
//
|
||||||
|
// While #3 is the most slow, it also seems to cleanest and involves the least manual mutation of already-parsed objects so I am going with #3 for now, but we should revisit #1 or #2 when the parser is more developed.
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let list_item = parser_with_context!(plain_list_item)(&parser_context)(remaining);
|
let list_item = parser_with_context!(plain_list_item)(&parser_context)(remaining);
|
||||||
match list_item {
|
match list_item {
|
||||||
Ok((remain, item))
|
Ok((remain, item))
|
||||||
if item.indentation == *first_item_indentation.get_or_insert(item.indentation) =>
|
if item.indentation == *first_item_indentation.get_or_insert(item.indentation) =>
|
||||||
{
|
{
|
||||||
|
children.push((remaining, item));
|
||||||
remaining = remain;
|
remaining = remain;
|
||||||
children.push(item);
|
|
||||||
}
|
}
|
||||||
Ok(_) | Err(_) => {
|
Ok(_) | Err(_) => {
|
||||||
break;
|
break;
|
||||||
@ -66,16 +75,31 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if children.is_empty() {
|
let (final_child_start, _final_item_first_parse) = match children.pop() {
|
||||||
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
Some(final_child) => final_child,
|
||||||
"Plain lists require at least one element.",
|
None => {
|
||||||
))));
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
}
|
"Plain lists require at least one element.",
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let final_item_context =
|
||||||
|
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
|
||||||
|
let (remaining, reparsed_final_item) =
|
||||||
|
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
|
||||||
|
children.push((final_child_start, reparsed_final_item));
|
||||||
|
|
||||||
// TODO: trailing whitespace
|
let (remaining, _trailing_ws) =
|
||||||
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
|
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((remaining, PlainList { source, children }))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
PlainList {
|
||||||
|
source,
|
||||||
|
children: children.into_iter().map(|(_start, item)| item).collect(),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@ -109,6 +133,7 @@ pub fn plain_list_item<'r, 's>(
|
|||||||
|
|
||||||
let (remaining, _ws) = space1(remaining)?;
|
let (remaining, _ws) = space1(remaining)?;
|
||||||
let parser_context = context
|
let parser_context = context
|
||||||
|
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
||||||
.with_additional_node(ContextElement::ListItem(indent_level))
|
.with_additional_node(ContextElement::ListItem(indent_level))
|
||||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Beta,
|
class: ExitClass::Beta,
|
||||||
|
Loading…
Reference in New Issue
Block a user