From 0108f5b0b1cce6ea0b50d671864da8da150a9c16 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 11 Dec 2023 12:04:59 -0500 Subject: [PATCH] Implement the new fields for subscript and superscript. --- src/parser/subscript_and_superscript.rs | 47 ++++++++++++++++--------- src/types/object.rs | 20 ++++++++--- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/parser/subscript_and_superscript.rs b/src/parser/subscript_and_superscript.rs index ac627d14..369881f9 100644 --- a/src/parser/subscript_and_superscript.rs +++ b/src/parser/subscript_and_superscript.rs @@ -3,6 +3,7 @@ use nom::bytes::complete::tag; use nom::bytes::complete::take_while; use nom::character::complete::anychar; use nom::character::complete::one_of; +use nom::combinator::consumed; use nom::combinator::map; use nom::combinator::not; use nom::combinator::opt; @@ -54,17 +55,20 @@ pub(crate) fn subscript<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Subscript<'s>> { - // We check for the underscore first before checking the pre-character as a minor optimization to avoid walking up the context tree to find the document root unnecessarily. let (remaining, _) = tag("_")(input)?; pre(input)?; let (remaining, body) = script_body(context, remaining)?; - let (remaining, _trailing_whitespace) = + let (remaining, post_blank) = maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); - let (use_brackets, body) = match body { - ScriptBody::Braceless(text) => (false, vec![Object::PlainText(PlainText { source: text })]), - ScriptBody::WithBraces(body) => (true, body), + let (use_brackets, contents, body) = match body { + ScriptBody::Braceless(text) => ( + false, + text, + vec![Object::PlainText(PlainText { source: text })], + ), + ScriptBody::WithBraces(contents, body) => (true, contents, body), }; Ok(( @@ -72,6 +76,8 @@ pub(crate) fn subscript<'b, 'g, 'r, 's>( Subscript { source: source.into(), use_brackets, + contents, + post_blank: post_blank.map(Into::<&str>::into), children: body, }, )) @@ -89,13 +95,17 @@ pub(crate) fn superscript<'b, 'g, 'r, 's>( let (remaining, _) = tag("^")(input)?; pre(input)?; let (remaining, body) = script_body(context, remaining)?; - let (remaining, _trailing_whitespace) = + let (remaining, post_blank) = maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); - let (use_brackets, body) = match body { - ScriptBody::Braceless(text) => (false, vec![Object::PlainText(PlainText { source: text })]), - ScriptBody::WithBraces(body) => (true, body), + let (use_brackets, contents, body) = match body { + ScriptBody::Braceless(text) => ( + false, + text, + vec![Object::PlainText(PlainText { source: text })], + ), + ScriptBody::WithBraces(contents, body) => (true, contents, body), }; Ok(( @@ -103,6 +113,8 @@ pub(crate) fn superscript<'b, 'g, 'r, 's>( Superscript { source: source.into(), use_brackets, + contents, + post_blank: post_blank.map(Into::<&str>::into), children: body, }, )) @@ -117,7 +129,7 @@ fn pre<'s>(input: OrgSource<'s>) -> Res, ()> { #[derive(Debug)] enum ScriptBody<'s> { Braceless(&'s str), - WithBraces(Vec>), + WithBraces(&'s str, Vec>), } #[cfg_attr( @@ -135,9 +147,10 @@ fn script_body<'b, 'g, 'r, 's>( map(parser_with_context!(script_alphanum)(context), |body| { ScriptBody::Braceless(body.into()) }), - map(parser_with_context!(script_with_braces)(context), |body| { - ScriptBody::WithBraces(body) - }), + map( + parser_with_context!(script_with_braces)(context), + |(contents, body)| ScriptBody::WithBraces(Into::<&str>::into(contents), body), + ), map( parser_with_context!(script_with_parenthesis)(context), |body| ScriptBody::Braceless(body.into()), @@ -195,7 +208,7 @@ fn end_script_alphanum_character<'s>(input: OrgSource<'s>) -> Res, fn script_with_braces<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, Vec>> { +) -> Res, (OrgSource<'s>, Vec>)> { let (remaining, _) = tag("{")(input)?; let exit_with_depth = script_with_braces_end(remaining.get_brace_depth()); let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { @@ -204,13 +217,13 @@ fn script_with_braces<'b, 'g, 'r, 's>( }); let parser_context = context.with_additional_node(&parser_context); - let (remaining, (children, _exit_contents)) = many_till( + let (remaining, (contents, (children, _exit_contents))) = consumed(many_till( parser_with_context!(standard_set_object)(&parser_context), parser_with_context!(exit_matcher_parser)(&parser_context), - )(remaining)?; + ))(remaining)?; let (remaining, _) = tag("}")(remaining)?; - Ok((remaining, children)) + Ok((remaining, (contents, children))) } fn script_with_braces_end(starting_brace_depth: BracketDepth) -> impl ContextMatcher { diff --git a/src/types/object.rs b/src/types/object.rs index 16878546..f9084175 100644 --- a/src/types/object.rs +++ b/src/types/object.rs @@ -264,6 +264,8 @@ pub struct StatisticsCookie<'s> { pub struct Subscript<'s> { pub source: &'s str, pub use_brackets: bool, + pub contents: &'s str, + pub post_blank: Option<&'s str>, pub children: Vec>, } @@ -271,6 +273,8 @@ pub struct Subscript<'s> { pub struct Superscript<'s> { pub source: &'s str, pub use_brackets: bool, + pub contents: &'s str, + pub post_blank: Option<&'s str>, pub children: Vec>, } @@ -883,11 +887,15 @@ impl<'s> StandardProperties<'s> for Subscript<'s> { } fn get_contents<'b>(&'b self) -> Option<&'s str> { - todo!() + Some(self.contents) } fn get_post_blank(&self) -> PostBlank { - todo!() + self.post_blank + .map(|text| text.chars().count()) + .unwrap_or(0) + .try_into() + .expect("Too much post-blank to fit into a PostBlank.") } } @@ -897,11 +905,15 @@ impl<'s> StandardProperties<'s> for Superscript<'s> { } fn get_contents<'b>(&'b self) -> Option<&'s str> { - todo!() + Some(self.contents) } fn get_post_blank(&self) -> PostBlank { - todo!() + self.post_blank + .map(|text| text.chars().count()) + .unwrap_or(0) + .try_into() + .expect("Too much post-blank to fit into a PostBlank.") } }