diff --git a/src/parser/text_markup.rs b/src/parser/text_markup.rs index a7a9497..1ea98f6 100644 --- a/src/parser/text_markup.rs +++ b/src/parser/text_markup.rs @@ -12,8 +12,10 @@ use nom::combinator::recognize; use nom::combinator::verify; use nom::multi::many_till; use nom::sequence::terminated; +use nom::sequence::tuple; use tracing::span; +use super::radio_link::RematchObject; use super::Context; use crate::error::CustomError; use crate::error::MyError; @@ -23,6 +25,7 @@ use crate::parser::object_parser::standard_set_object; use crate::parser::parser_context::ContextElement; use crate::parser::parser_context::ExitMatcherNode; use crate::parser::parser_with_context::parser_with_context; +use crate::parser::radio_link::rematch_target; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::get_one_before; @@ -142,7 +145,6 @@ fn _text_markup_object<'r, 's, 'x>( } } - // TODO: Sometimes its plain text, not objects let (remaining, _close) = text_markup_end_specialized(context, remaining)?; let (remaining, _trailing_whitespace) = space0(remaining)?; Ok((remaining, children)) @@ -189,7 +191,6 @@ fn _text_markup_string<'r, 's, 'x>( } } - // TODO: Sometimes its plain text, not objects let (remaining, _close) = text_markup_end_specialized(context, remaining)?; let (remaining, _trailing_whitespace) = space0(remaining)?; Ok((remaining, contents)) @@ -242,3 +243,52 @@ fn _text_markup_end<'r, 's, 'x>( let source = get_consumed(input, remaining); Ok((remaining, source)) } + +impl<'x> RematchObject for Bold<'x> { + fn rematch_object<'r, 's>( + &'r self, + _context: Context<'r, 's>, + input: &'s str, + ) -> Res<&'s str, Object<'s>> { + let (remaining, children) = + _rematch_text_markup_object(_context, input, "*", &self.children)?; + let source = get_consumed(input, remaining); + Ok((remaining, Object::Bold(Bold { source, children }))) + } +} + +#[tracing::instrument(ret, level = "debug")] +fn _rematch_text_markup_object<'r, 's, 'x>( + context: Context<'r, 's>, + input: &'s str, + marker_symbol: &'static str, + original_match_children: &'x Vec>, +) -> Res<&'s str, Vec>> { + let (remaining, _) = pre(context, input)?; + let (remaining, open) = tag(marker_symbol)(remaining)?; + let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; + let text_markup_end_specialized = text_markup_end(open); + let parser_context = + context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &text_markup_end_specialized, + })); + + let (remaining, children) = + // TODO: This doesn't really check the exit matcher between each object. I think it may be possible to construct an org document that parses incorrectly with the current code. + rematch_target(&parser_context, original_match_children, remaining)?; + + { + let span = span!(tracing::Level::DEBUG, "Checking parent exit."); + let _enter = span.enter(); + if exit_matcher_parser(context, remaining).is_ok() { + return Err(nom::Err::Error(CustomError::MyError(MyError( + "Parent exit matcher is triggering.", + )))); + } + } + + let (remaining, _close) = text_markup_end_specialized(context, remaining)?; + let (remaining, _trailing_whitespace) = space0(remaining)?; + Ok((remaining, children)) +}