Accept the end condition as a parameter to the plain text parser so it can adapt to the context.

This commit is contained in:
Tom Alexander
2023-09-08 17:45:49 -04:00
parent 0056657b65
commit 669da4073e
3 changed files with 152 additions and 80 deletions

View File

@@ -7,7 +7,6 @@ use nom::combinator::recognize;
use nom::combinator::verify;
use nom::multi::many_till;
use super::object_parser::detect_any_object_except_plain_text;
use super::org_source::OrgSource;
use super::radio_link::RematchObject;
use super::util::exit_matcher_parser;
@@ -17,17 +16,42 @@ use crate::error::Res;
use crate::types::Object;
use crate::types::PlainText;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn plain_text<'b, 'g, 'r, 's>(
pub fn plain_text<F>(
end_condition: F,
) -> impl for<'b, 'g, 'r, 's> Fn(
RefContext<'b, 'g, 'r, 's>,
OrgSource<'s>,
) -> Res<OrgSource<'s>, PlainText<'s>>
where
F: for<'bb, 'gg, 'rr, 'ss> Fn(
RefContext<'bb, 'gg, 'rr, 'ss>,
OrgSource<'ss>,
) -> Res<OrgSource<'ss>, ()>,
{
move |context, input| _plain_text(&end_condition, context, input)
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(ret, level = "debug", skip(end_condition))
)]
fn _plain_text<'b, 'g, 'r, 's, F>(
end_condition: F,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, PlainText<'s>> {
) -> Res<OrgSource<'s>, PlainText<'s>>
where
F: for<'bb, 'gg, 'rr, 'ss> Fn(
RefContext<'bb, 'gg, 'rr, 'ss>,
OrgSource<'ss>,
) -> Res<OrgSource<'ss>, ()>,
{
let (remaining, source) = recognize(verify(
many_till(
anychar,
peek(alt((
parser_with_context!(exit_matcher_parser)(context),
parser_with_context!(plain_text_end)(context),
recognize(parser_with_context!(end_condition)(context)),
))),
),
|(children, _exit_contents)| !children.is_empty(),
@@ -41,16 +65,6 @@ pub fn plain_text<'b, 'g, 'r, 's>(
))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn plain_text_end<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(parser_with_context!(detect_any_object_except_plain_text)(
context,
))(input)
}
impl<'x> RematchObject<'x> for PlainText<'x> {
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn rematch_object<'b, 'g, 'r, 's>(
@@ -75,6 +89,7 @@ mod tests {
use crate::context::ContextElement;
use crate::context::GlobalSettings;
use crate::context::List;
use crate::parser::object_parser::detect_standard_set_object_sans_plain_text;
use crate::types::Source;
#[test]
@@ -83,7 +98,9 @@ mod tests {
let global_settings = GlobalSettings::default();
let initial_context = ContextElement::document_context();
let initial_context = Context::new(&global_settings, List::new(&initial_context));
let plain_text_matcher = parser_with_context!(plain_text)(&initial_context);
let plain_text_matcher = parser_with_context!(plain_text(
detect_standard_set_object_sans_plain_text
))(&initial_context);
let (remaining, result) = map(plain_text_matcher, Object::PlainText)(input).unwrap();
assert_eq!(Into::<&str>::into(remaining), "");
assert_eq!(result.get_source(), Into::<&str>::into(input));