diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index ecbc6186..d36c260d 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -4,6 +4,7 @@ use nom::bytes::complete::tag_no_case; use nom::bytes::complete::take_while; use nom::character::complete::line_ending; use nom::character::complete::space0; +use nom::combinator::consumed; use nom::combinator::eof; use nom::combinator::not; use nom::combinator::recognize; @@ -70,29 +71,12 @@ where let parser_context = context.with_additional_node(&contexts[0]); let parser_context = parser_context.with_additional_node(&contexts[1]); let parser_context = parser_context.with_additional_node(&contexts[2]); + let (remaining, (contents, children)) = + consumed(parser_with_context!(children)(&parser_context))(remaining)?; - let element_matcher = parser_with_context!(element(true))(&parser_context); - let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); - let (remaining, children) = match tuple(( - not(exit_matcher), - blank_line, - many_till(blank_line, exit_matcher), - ))(remaining) - { - Ok((remain, (_not_immediate_exit, first_line, (_trailing_whitespace, _exit_contents)))) => { - let source = get_consumed(remaining, remain); - let element = Element::Paragraph(Paragraph::of_text(source.into(), first_line.into())); - (remain, vec![element]) - } - Err(_) => { - let (remaining, (children, _exit_contents)) = - many_till(element_matcher, exit_matcher)(remaining)?; - (remaining, children) - } - }; let (remaining, _end) = drawer_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); @@ -106,10 +90,43 @@ where ), drawer_name: drawer_name.into(), children, + contents: Some(contents.into()), + post_blank: post_blank.map(Into::<&str>::into), }, )) } +#[cfg_attr( + feature = "tracing", + tracing::instrument(ret, level = "debug", skip(context)) +)] +fn children<'b, 'g, 'r, 's>( + context: RefContext<'b, 'g, 'r, 's>, + input: OrgSource<'s>, +) -> Res, Vec>> { + let element_matcher = parser_with_context!(element(true))(context); + let exit_matcher = parser_with_context!(exit_matcher_parser)(context); + + let (remaining, children) = match tuple(( + not(exit_matcher), + blank_line, + many_till(blank_line, exit_matcher), + ))(input) + { + Ok((remain, (_not_immediate_exit, first_line, (_trailing_whitespace, _exit_contents)))) => { + let source = get_consumed(input, remain); + let element = Element::Paragraph(Paragraph::of_text(source.into(), first_line.into())); + (remain, vec![element]) + } + Err(_) => { + let (remaining, (children, _exit_contents)) = + many_till(element_matcher, exit_matcher)(input)?; + (remaining, children) + } + }; + Ok((remaining, children)) +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn name<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { take_while(|c| WORD_CONSTITUENT_CHARACTERS.contains(c) || "-_".contains(c))(input) diff --git a/src/types/greater_element.rs b/src/types/greater_element.rs index d16806eb..05606ccd 100644 --- a/src/types/greater_element.rs +++ b/src/types/greater_element.rs @@ -95,6 +95,8 @@ pub struct Drawer<'s> { pub affiliated_keywords: AffiliatedKeywords<'s>, pub drawer_name: &'s str, pub children: Vec>, + pub contents: Option<&'s str>, + pub post_blank: Option<&'s str>, } #[derive(Debug)] @@ -238,11 +240,15 @@ impl<'s> StandardProperties<'s> for Drawer<'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.") } }