use super::error::Res; use super::footnote_definition::footnote_definition; use super::greater_block::greater_block; use super::greater_element::FootnoteDefinition; use super::greater_element::GreaterBlock; use super::greater_element::PlainList; use super::lesser_element::Paragraph; use super::paragraph::paragraph; use super::plain_list::plain_list; use super::source::Source; use super::Context; use crate::parser::parser_context::ContextElement; use crate::parser::parser_with_context::parser_with_context; use nom::branch::alt; use nom::combinator::map; #[derive(Debug)] pub enum Element<'s> { Paragraph(Paragraph<'s>), PlainList(PlainList<'s>), GreaterBlock(GreaterBlock<'s>), FootnoteDefinition(FootnoteDefinition<'s>), /// The whitespace that follows an element. /// /// This isn't a real org-mode element. Except for items in plain lists, trailing blank lines belong to the preceding element. It is a separate `Element` in this enum to make parsing easier. TrailingWhitespace(&'s str), } impl<'s> Source<'s> for Element<'s> { fn get_source(&'s self) -> &'s str { match self { Element::Paragraph(obj) => obj.source, Element::PlainList(obj) => obj.source, Element::GreaterBlock(obj) => obj.source, Element::TrailingWhitespace(src) => src, Element::FootnoteDefinition(obj) => obj.source, } } } #[tracing::instrument(ret, level = "debug")] pub fn element_with_whitespace<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, Element<'s>> { let parser_context = context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true)); element(&parser_context, input) } #[tracing::instrument(ret, level = "debug")] pub fn element_without_whitespace<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, Element<'s>> { let parser_context = context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false)); element(&parser_context, input) } #[tracing::instrument(ret, level = "debug")] pub fn element<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Element<'s>> { let non_paragraph_matcher = parser_with_context!(non_paragraph_element)(context); let paragraph_matcher = parser_with_context!(paragraph)(context); alt(( non_paragraph_matcher, map(paragraph_matcher, Element::Paragraph), ))(input) } pub fn non_paragraph_element<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, Element<'s>> { let plain_list_matcher = parser_with_context!(plain_list)(context); let greater_block_matcher = parser_with_context!(greater_block)(context); let footnote_definition_matcher = parser_with_context!(footnote_definition)(context); alt(( map(plain_list_matcher, Element::PlainList), map(greater_block_matcher, Element::GreaterBlock), map(footnote_definition_matcher, Element::FootnoteDefinition), ))(input) }