Add an exit matcher to plain text.

Tom Alexander 11 months ago
parent 9a3bde0d80
commit a4cce121c0
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

@ -1,4 +1,5 @@
imports_granularity = "Item"
group_imports = "StdExternalCrate"
# In rustfmt 2.0 I will want to adjust these settings.

@ -43,3 +43,17 @@ pub fn minimal_set_object<'r, 's>(
map(parser_with_context!(plain_text)(context), Object::PlainText),
#[tracing::instrument(ret, level = "debug")]
pub fn any_object_except_plain_text<'r, 's>(
context: Context<'r, 's>,
input: &'s str,
) -> Res<&'s str, Object<'s>> {
// TODO: add entities, LaTeX fragments, export snippets, footnote references, citations (NOT citation references), inline babel calls, inline source blocks, line breaks, links, macros, targets and radio targets, statistics cookies, subscript and superscript, timestamps, and text markup.
not(|i| context.check_exit_matcher(i))(input)?;

@ -1,9 +1,16 @@
use nom::combinator::not;
use nom::combinator::recognize;
use super::object::PlainText;
use super::Context;
use crate::error::CustomError;
use crate::error::MyError;
use crate::error::Res;
use nom::combinator::not;
use crate::parser::exiting::ExitClass;
use crate::parser::object_parser::any_object_except_plain_text;
use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ExitMatcherNode;
use crate::parser::parser_with_context::parser_with_context;
#[tracing::instrument(ret, level = "debug")]
pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, PlainText<'s>> {
@ -12,12 +19,17 @@ pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
"Zero input length to plain_text.",
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
exit_matcher: &plain_text_end,
let mut current_input = input.char_indices();
loop {
match {
Some((offset, _char)) => {
let remaining = &input[offset..];
let exit_matcher_status = not(|i| context.check_exit_matcher(i))(remaining);
let exit_matcher_status = not(|i| parser_context.check_exit_matcher(i))(remaining);
if exit_matcher_status.is_err() {
if offset == 0 {
// If we're at the start of the input, then nothing is plain text, so fire an error for zero-length match.
@ -40,18 +52,22 @@ pub fn plain_text<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
#[tracing::instrument(ret, level = "debug")]
fn plain_text_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> {
mod tests {
use nom::combinator::map;
use super::*;
use crate::parser::object::Object;
use crate::parser::parser_context::ContextElement;
use crate::parser::parser_context::ContextTree;
use crate::parser::parser_with_context::parser_with_context;
use crate::parser::source::Source;
use super::*;
fn plain_text_simple() {
let input = "foobarbaz";