diff --git a/org_mode_samples/lesser_element/lesser_block/src_with_space_after_end.org b/org_mode_samples/lesser_element/lesser_block/src_with_space_after_end.org new file mode 100644 index 00000000..11b6b6f3 --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/src_with_space_after_end.org @@ -0,0 +1,4 @@ +# There are trailing spaces after the begin and end src lines +#+begin_src + echo "this is a source block." +#+end_src diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index 4325cdda..4f323d95 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -7,6 +7,7 @@ use nom::character::complete::space1; use nom::combinator::consumed; use nom::combinator::eof; use nom::combinator::opt; +use nom::combinator::recognize; use nom::combinator::verify; use nom::multi::many_till; use nom::sequence::tuple; @@ -40,7 +41,7 @@ pub fn verse_block<'b, 'g, 'r, 's>( ) -> Res, VerseBlock<'s>> { let (remaining, name) = lesser_block_begin("verse")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; - let (remaining, _nl) = line_ending(remaining)?; + let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let lesser_block_end_specialized = lesser_block_end("verse"); let contexts = [ ContextElement::ConsumeTrailingWhitespace(true), @@ -95,7 +96,7 @@ pub fn comment_block<'b, 'g, 'r, 's>( ) -> Res, CommentBlock<'s>> { let (remaining, name) = lesser_block_begin("comment")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; - let (remaining, _nl) = line_ending(remaining)?; + let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let lesser_block_end_specialized = lesser_block_end("comment"); let contexts = [ ContextElement::ConsumeTrailingWhitespace(true), @@ -135,7 +136,7 @@ pub fn example_block<'b, 'g, 'r, 's>( ) -> Res, ExampleBlock<'s>> { let (remaining, _name) = lesser_block_begin("example")(context, input)?; let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; - let (remaining, _nl) = line_ending(remaining)?; + let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let lesser_block_end_specialized = lesser_block_end("example"); let contexts = [ ContextElement::ConsumeTrailingWhitespace(true), @@ -176,7 +177,7 @@ pub fn export_block<'b, 'g, 'r, 's>( let (remaining, name) = lesser_block_begin("export")(context, input)?; // https://orgmode.org/worg/org-syntax.html#Blocks claims that export blocks must have a single word for data but testing shows no data and multi-word data still parses as an export block. let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; - let (remaining, _nl) = line_ending(remaining)?; + let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let lesser_block_end_specialized = lesser_block_end("export"); let contexts = [ ContextElement::ConsumeTrailingWhitespace(true), @@ -217,7 +218,7 @@ pub fn src_block<'b, 'g, 'r, 's>( let (remaining, name) = lesser_block_begin("src")(context, input)?; // https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block. let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?; - let (remaining, _nl) = line_ending(remaining)?; + let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?; let lesser_block_end_specialized = lesser_block_end("src"); let contexts = [ ContextElement::ConsumeTrailingWhitespace(true), @@ -275,9 +276,10 @@ fn _lesser_block_end<'b, 'g, 'r, 's, 'c>( ) -> Res, OrgSource<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; - let (remaining, (_begin, _name, _ws)) = tuple(( + let (remaining, (_begin, _name, _ws, _ending)) = tuple(( tag_no_case("#+end_"), tag_no_case(current_name_lower), + space0, alt((eof, line_ending)), ))(remaining)?; let source = get_consumed(input, remaining);