diff --git a/src/parser/dynamic_block.rs b/src/parser/dynamic_block.rs index e1eb68b..1f59f9d 100644 --- a/src/parser/dynamic_block.rs +++ b/src/parser/dynamic_block.rs @@ -6,20 +6,20 @@ use nom::character::complete::anychar; use nom::character::complete::line_ending; use nom::character::complete::space0; use nom::character::complete::space1; -use nom::combinator::consumed; use nom::combinator::eof; use nom::combinator::not; use nom::combinator::opt; use nom::combinator::peek; use nom::combinator::recognize; -use nom::multi::many0; use nom::multi::many_till; -use nom::sequence::preceded; use nom::sequence::tuple; use super::affiliated_keyword::parse_affiliated_keywords; +use super::greater_block::leading_blank_lines_end; use super::org_source::OrgSource; +use super::paragraph::empty_paragraph; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; +use crate::context::bind_context; use crate::context::parser_with_context; use crate::context::ContextElement; use crate::context::ExitClass; @@ -28,7 +28,6 @@ use crate::context::RefContext; use crate::error::CustomError; use crate::error::Res; use crate::parser::element_parser::element; -use crate::parser::util::blank_line; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::immediate_in_section; @@ -36,7 +35,6 @@ use crate::parser::util::start_of_line; use crate::types::DynamicBlock; use crate::types::Element; use crate::types::Keyword; -use crate::types::Paragraph; #[cfg_attr( feature = "tracing", @@ -81,23 +79,25 @@ where let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); not(exit_matcher)(remaining)?; - let (remaining, leading_blank_lines) = opt(consumed(tuple(( - blank_line, - many0(preceded(not(exit_matcher), blank_line)), - ))))(remaining)?; - let leading_blank_lines = - leading_blank_lines.map(|(source, (first_line, _remaining_lines))| { - Element::Paragraph(Paragraph::of_text(source.into(), first_line.into())) - }); + let contents_begin = remaining; + let blank_line_context = ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Alpha, + exit_matcher: &leading_blank_lines_end, + }); + let blank_line_context = parser_context.with_additional_node(&blank_line_context); + + let (remaining, leading_blank_lines) = + opt(bind_context!(empty_paragraph, &blank_line_context))(remaining)?; let (remaining, (mut children, _exit_contents)) = many_till(element_matcher, exit_matcher)(remaining)?; if let Some(lines) = leading_blank_lines { - children.insert(0, lines); + children.insert(0, Element::Paragraph(lines)); } + let contents = get_consumed(contents_begin, remaining); let (remaining, _end) = dynamic_block_end(&parser_context, remaining)?; - let (remaining, _trailing_ws) = + let (remaining, post_blank) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); Ok(( @@ -111,6 +111,12 @@ where block_name: name.into(), parameters: parameters.map(|val| val.into()), children, + contents: if contents.len() > 0 { + Some(Into::<&str>::into(contents)) + } else { + None + }, + post_blank: post_blank.map(Into::<&str>::into), }, )) } diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index 65f0747..c1b52c9 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -339,7 +339,7 @@ fn _greater_block_end<'b, 'g, 'r, 's, 'c>( feature = "tracing", tracing::instrument(ret, level = "debug", skip(_context)) )] -fn leading_blank_lines_end<'b, 'g, 'r, 's, 'c>( +pub(crate) fn leading_blank_lines_end<'b, 'g, 'r, 's, 'c>( _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { diff --git a/src/types/greater_element.rs b/src/types/greater_element.rs index bbb7ccd..7b5b8bf 100644 --- a/src/types/greater_element.rs +++ b/src/types/greater_element.rs @@ -87,6 +87,8 @@ pub struct DynamicBlock<'s> { pub block_name: &'s str, pub parameters: Option<&'s str>, pub children: Vec>, + pub contents: Option<&'s str>, + pub post_blank: Option<&'s str>, } #[derive(Debug)] @@ -243,11 +245,15 @@ impl<'s> StandardProperties<'s> for DynamicBlock<'s> { } fn get_contents<'b>(&'b self) -> Option<&'s str> { - todo!() + self.contents } fn get_post_blank(&self) -> PostBlank { - todo!() + self.post_blank + .map(|text| text.lines().count()) + .unwrap_or(0) + .try_into() + .expect("Too much post-blank to fit into a PostBlank.") } }