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, | ||||
|             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 first_item_indentation: Option<usize> = None; | ||||
|     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 { | ||||
|         let list_item = parser_with_context!(plain_list_item)(&parser_context)(remaining); | ||||
|         match list_item { | ||||
|             Ok((remain, item)) | ||||
|                 if item.indentation == *first_item_indentation.get_or_insert(item.indentation) => | ||||
|             { | ||||
|                 children.push((remaining, item)); | ||||
|                 remaining = remain; | ||||
|                 children.push(item); | ||||
|             } | ||||
|             Ok(_) | Err(_) => { | ||||
|                 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() { | ||||
|         return Err(nom::Err::Error(CustomError::MyError(MyError( | ||||
|             "Plain lists require at least one element.", | ||||
|         )))); | ||||
|     } | ||||
|     let (final_child_start, _final_item_first_parse) = match children.pop() { | ||||
|         Some(final_child) => final_child, | ||||
|         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); | ||||
|     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"))] | ||||
| @ -109,6 +133,7 @@ pub fn plain_list_item<'r, 's>( | ||||
| 
 | ||||
|     let (remaining, _ws) = space1(remaining)?; | ||||
|     let parser_context = context | ||||
|         .with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)) | ||||
|         .with_additional_node(ContextElement::ListItem(indent_level)) | ||||
|         .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { | ||||
|             class: ExitClass::Beta, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander