Allow text markup at the start of a radio target.

This commit is contained in:
Tom Alexander 2023-10-09 13:44:14 -04:00
parent 5ac12229f4
commit adc5a383c3
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 25 additions and 6 deletions

View File

@ -33,6 +33,11 @@ pub(crate) enum ContextElement<'r, 's> {
/// The value stored is the start of the element after the affiliated keywords. In this way, we can ensure that we do not exit an element immediately after the affiliated keyword had been consumed.
HasAffiliatedKeyword(HasAffiliatedKeywordInner<'r, 's>),
/// Indicate the position that we started parsing a radio target.
///
/// This value is stored because "<<<" is not a valid prefix for text markup UNLESS it is starting a radio target.
StartRadioTarget(OrgSource<'s>),
/// This is just here to use the 's lifetime until I'm sure we can eliminate it from ContextElement.
#[allow(dead_code)]
Placeholder(PhantomData<&'s str>),

View File

@ -103,11 +103,15 @@ pub(crate) fn radio_target<'b, 'g, 'r, 's>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, RadioTarget<'s>> {
let (remaining, _opening) = tag("<<<")(input)?;
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma,
exit_matcher: &radio_target_end,
});
let parser_context = context.with_additional_node(&parser_context);
let contexts = [
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma,
exit_matcher: &radio_target_end,
}),
ContextElement::StartRadioTarget(remaining),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let (remaining, (raw_value, children)) = consumed(verify(
map(

View File

@ -283,7 +283,7 @@ fn _text_markup_string<'b, 'g, 'r, 's, 'c>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn pre<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ()> {
if start_of_line(input).is_ok() {
@ -292,6 +292,16 @@ fn pre<'b, 'g, 'r, 's>(
if preceded_by_whitespace(true)(input).is_ok() {
return Ok((input, ()));
}
let radio_target_start = context
.iter()
.find_map(|c| match c {
ContextElement::StartRadioTarget(text) => Some(text),
_ => None,
})
.map(|text| text.get_byte_offset());
if Some(input.get_byte_offset()) == radio_target_start {
return Ok((input, ()));
}
let preceding_character = input.get_preceding_character();
match preceding_character {
// If None, we are at the start of the file which is technically the beginning of a line.