Implement the new fields for subscript and superscript.
clippy Build clippy has failed Details
rust-foreign-document-test Build rust-foreign-document-test has failed Details
rust-build Build rust-build has succeeded Details
rust-test Build rust-test has failed Details

This commit is contained in:
Tom Alexander 2023-12-11 12:04:59 -05:00
parent 50145c6cf2
commit 0108f5b0b1
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 46 additions and 21 deletions

View File

@ -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<OrgSource<'s>, 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<OrgSource<'s>, ()> {
#[derive(Debug)]
enum ScriptBody<'s> {
Braceless(&'s str),
WithBraces(Vec<Object<'s>>),
WithBraces(&'s str, Vec<Object<'s>>),
}
#[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<OrgSource<'s>,
fn script_with_braces<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
) -> Res<OrgSource<'s>, (OrgSource<'s>, Vec<Object<'s>>)> {
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 {

View File

@ -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<Object<'s>>,
}
@ -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<Object<'s>>,
}
@ -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.")
}
}