Fix handling of search option for plain links when parenthesis are involved.

This commit is contained in:
Tom Alexander 2023-10-08 10:48:34 -04:00
parent b64c1c944b
commit ceb5376b21
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -3,9 +3,11 @@ use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
use nom::bytes::complete::tag_no_case;
use nom::bytes::complete::take;
use nom::bytes::complete::take_until;
use nom::character::complete::anychar;
use nom::character::complete::none_of;
use nom::character::complete::one_of;
use nom::combinator::all_consuming;
use nom::combinator::consumed;
use nom::combinator::eof;
use nom::combinator::flat_map;
@ -127,6 +129,44 @@ pub(crate) fn parse_file_and_application<'s>(
Ok((remaining, application))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn parse_path_and_search_option<'s>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (OrgSource<'s>, Option<OrgSource<'s>>)> {
alt((
all_consuming(parse_path_and_search_option_with_search_option),
all_consuming(parse_path_and_search_option_without_search_option),
))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn parse_path_and_search_option_with_search_option<'s>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (OrgSource<'s>, Option<OrgSource<'s>>)> {
let (remaining, path) = take_until("::")(input)?;
let (remaining, search_option) = opt(map(
tuple((
tag("::"),
verify(is_not(" \t\r\n"), |search_option| {
Into::<&str>::into(search_option)
.chars()
.any(char::is_alphanumeric)
}),
)),
|(_, search_option)| search_option,
))(remaining)?;
// Assert we consumed the entire protocol.
not(anychar)(remaining)?;
Ok((remaining, (path, search_option)))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub(crate) fn parse_path_and_search_option_without_search_option<'s>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (OrgSource<'s>, Option<OrgSource<'s>>)> {
map(rest, |path| (path, None))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn file_path_plain<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
@ -138,30 +178,23 @@ fn file_path_plain<'b, 'g, 'r, 's>(
exit_matcher: &path_plain_end,
});
let parser_context = context.with_additional_node(&parser_context);
let (remaining, (raw_link, (_, application, _, _, path, search_option))) = consumed(tuple((
peek(tag("file")),
map_parser(
parser_with_context!(protocol)(&parser_context),
parse_file_and_application,
),
tag(":"),
opt(flat_map(
peek(map(verify(many1_count(tag("/")), |c| *c >= 3), |c| c - 1)),
take,
)),
parser_with_context!(path_plain)(&parser_context),
opt(map(
tuple((
tag("::"),
verify(is_not(" \t\r\n"), |search_option| {
Into::<&str>::into(search_option)
.chars()
.any(char::is_alphanumeric)
}),
let (remaining, (raw_link, (_, application, _, _, (path, search_option)))) =
consumed(tuple((
peek(tag("file")),
map_parser(
parser_with_context!(protocol)(&parser_context),
parse_file_and_application,
),
tag(":"),
opt(flat_map(
peek(map(verify(many1_count(tag("/")), |c| *c >= 3), |c| c - 1)),
take,
)),
|(_, search_option)| search_option,
)),
)))(input)?;
map_parser(
parser_with_context!(path_plain)(&parser_context),
parse_path_and_search_option,
),
)))(input)?;
Ok((
remaining,
PathPlain {
@ -256,15 +289,9 @@ fn impl_path_plain_end<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
starting_parenthesis_depth: BracketDepth,
enable_search_option: bool,
_enable_search_option: bool,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
if enable_search_option {
let search_option = peek(tag("::"))(input);
if search_option.is_ok() {
return search_option;
}
}
let (remaining, _leading_punctuation) = many0(verify(anychar, |c| {
!" \t\r\n[]<>()/".contains(*c) && c.is_ascii_punctuation()