2023-07-13 18:30:18 -04:00
|
|
|
use nom::branch::alt;
|
2023-10-07 02:22:36 -04:00
|
|
|
use nom::bytes::complete::is_not;
|
2023-07-13 19:09:44 -04:00
|
|
|
use nom::bytes::complete::tag;
|
|
|
|
use nom::bytes::complete::tag_no_case;
|
2023-07-13 22:54:59 -04:00
|
|
|
use nom::character::complete::anychar;
|
2023-07-13 18:30:18 -04:00
|
|
|
use nom::character::complete::none_of;
|
2023-07-13 22:54:59 -04:00
|
|
|
use nom::character::complete::one_of;
|
2023-10-07 02:22:36 -04:00
|
|
|
use nom::combinator::consumed;
|
2023-07-13 18:30:18 -04:00
|
|
|
use nom::combinator::eof;
|
2023-10-07 02:22:36 -04:00
|
|
|
use nom::combinator::map;
|
2023-10-07 03:00:40 -04:00
|
|
|
use nom::combinator::map_parser;
|
2023-09-21 18:34:32 -04:00
|
|
|
use nom::combinator::not;
|
2023-10-07 02:22:36 -04:00
|
|
|
use nom::combinator::opt;
|
2023-07-13 19:09:44 -04:00
|
|
|
use nom::combinator::peek;
|
2023-07-13 18:30:18 -04:00
|
|
|
use nom::combinator::recognize;
|
2023-10-07 03:00:40 -04:00
|
|
|
use nom::combinator::rest;
|
2023-08-29 15:44:04 -04:00
|
|
|
use nom::combinator::verify;
|
2023-09-21 18:34:32 -04:00
|
|
|
use nom::multi::many0;
|
|
|
|
use nom::multi::many1;
|
2023-07-13 22:54:59 -04:00
|
|
|
use nom::multi::many_till;
|
2023-09-21 18:34:32 -04:00
|
|
|
use nom::sequence::tuple;
|
2023-07-13 18:30:18 -04:00
|
|
|
|
2023-09-21 16:34:24 -04:00
|
|
|
use super::org_source::BracketDepth;
|
2023-08-23 00:30:26 -04:00
|
|
|
use super::org_source::OrgSource;
|
2023-09-06 14:25:49 -04:00
|
|
|
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
|
2023-09-03 11:05:34 -04:00
|
|
|
use crate::context::parser_with_context;
|
|
|
|
use crate::context::ContextElement;
|
2023-09-21 16:34:24 -04:00
|
|
|
use crate::context::ContextMatcher;
|
2023-09-03 11:05:34 -04:00
|
|
|
use crate::context::ExitClass;
|
|
|
|
use crate::context::ExitMatcherNode;
|
2023-09-21 18:34:32 -04:00
|
|
|
use crate::context::Matcher;
|
2023-09-03 11:05:34 -04:00
|
|
|
use crate::context::RefContext;
|
2023-07-13 18:30:18 -04:00
|
|
|
use crate::error::CustomError;
|
|
|
|
use crate::error::MyError;
|
2023-07-13 18:18:07 -04:00
|
|
|
use crate::error::Res;
|
2023-07-13 22:54:59 -04:00
|
|
|
use crate::parser::util::exit_matcher_parser;
|
2023-07-13 19:09:44 -04:00
|
|
|
use crate::parser::util::get_consumed;
|
2023-07-13 18:30:18 -04:00
|
|
|
use crate::parser::util::WORD_CONSTITUENT_CHARACTERS;
|
2023-10-07 02:22:36 -04:00
|
|
|
use crate::types::LinkType;
|
2023-09-03 11:05:34 -04:00
|
|
|
use crate::types::PlainLink;
|
2023-07-13 18:18:07 -04:00
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-11 13:13:28 -04:00
|
|
|
pub(crate) fn plain_link<'b, 'g, 'r, 's>(
|
2023-09-03 15:44:18 -04:00
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
2023-08-23 00:30:26 -04:00
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, PlainLink<'s>> {
|
2023-07-13 19:09:44 -04:00
|
|
|
let (remaining, _) = pre(context, input)?;
|
2023-10-07 02:22:36 -04:00
|
|
|
let (remaining, path_plain) = parse_path_plain(context, remaining)?;
|
2023-07-13 19:09:44 -04:00
|
|
|
peek(parser_with_context!(post)(context))(remaining)?;
|
2023-09-06 14:25:49 -04:00
|
|
|
let (remaining, _trailing_whitespace) =
|
|
|
|
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
2023-07-13 19:09:44 -04:00
|
|
|
let source = get_consumed(input, remaining);
|
2023-07-13 23:22:10 +00:00
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
PlainLink {
|
2023-08-23 00:30:26 -04:00
|
|
|
source: source.into(),
|
2023-10-07 02:22:36 -04:00
|
|
|
link_type: path_plain.link_type,
|
|
|
|
path: path_plain.path,
|
|
|
|
raw_link: path_plain.raw_link,
|
|
|
|
search_option: path_plain.search_option,
|
2023-10-07 03:00:40 -04:00
|
|
|
application: path_plain.application,
|
2023-07-13 23:22:10 +00:00
|
|
|
},
|
|
|
|
))
|
2023-07-13 18:18:07 -04:00
|
|
|
}
|
2023-07-13 18:30:18 -04:00
|
|
|
|
2023-10-07 02:22:36 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct PathPlain<'s> {
|
|
|
|
link_type: LinkType<'s>,
|
|
|
|
path: &'s str,
|
|
|
|
raw_link: &'s str,
|
|
|
|
search_option: Option<&'s str>,
|
2023-10-07 03:00:40 -04:00
|
|
|
application: Option<&'s str>,
|
2023-10-07 02:22:36 -04:00
|
|
|
}
|
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-03 15:44:18 -04:00
|
|
|
fn pre<'b, 'g, 'r, 's>(
|
|
|
|
_context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, ()> {
|
2023-08-24 16:55:56 -04:00
|
|
|
let preceding_character = input.get_preceding_character();
|
2023-07-13 18:30:18 -04:00
|
|
|
match preceding_character {
|
|
|
|
// If None, we are at the start of the file which is fine
|
|
|
|
None => {}
|
|
|
|
Some(x) if !WORD_CONSTITUENT_CHARACTERS.contains(x) => {}
|
|
|
|
Some(_) => {
|
|
|
|
// Not at start of line, cannot be a heading
|
|
|
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
2023-08-23 00:30:26 -04:00
|
|
|
"Not a valid pre character for plain link.".into(),
|
2023-07-13 18:30:18 -04:00
|
|
|
))));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok((input, ()))
|
|
|
|
}
|
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-03 15:44:18 -04:00
|
|
|
fn post<'b, 'g, 'r, 's>(
|
|
|
|
_context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, ()> {
|
2023-07-13 18:30:18 -04:00
|
|
|
let (remaining, _) = alt((eof, recognize(none_of(WORD_CONSTITUENT_CHARACTERS))))(input)?;
|
|
|
|
Ok((remaining, ()))
|
|
|
|
}
|
2023-07-13 19:09:44 -04:00
|
|
|
|
2023-10-08 09:28:09 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-10-07 02:22:36 -04:00
|
|
|
fn parse_path_plain<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, PathPlain<'s>> {
|
|
|
|
alt((
|
|
|
|
parser_with_context!(file_path_plain)(context),
|
|
|
|
parser_with_context!(protocol_path_plain)(context),
|
|
|
|
))(input)
|
|
|
|
}
|
|
|
|
|
2023-10-08 09:28:09 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-10-07 03:14:16 -04:00
|
|
|
pub(crate) fn parse_file_and_application<'s>(
|
2023-10-07 03:00:40 -04:00
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
|
|
|
|
let (remaining, _) = tag("file")(input)?;
|
|
|
|
let (remaining, application) =
|
|
|
|
opt(map(tuple((tag("+"), rest)), |(_, application)| application))(remaining)?;
|
|
|
|
// Assert we consumed the entire protocol.
|
|
|
|
not(anychar)(remaining)?;
|
|
|
|
Ok((remaining, application))
|
|
|
|
}
|
|
|
|
|
2023-10-08 09:28:09 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-10-07 02:22:36 -04:00
|
|
|
fn file_path_plain<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, PathPlain<'s>> {
|
2023-10-07 02:42:07 -04:00
|
|
|
let path_plain_end = path_plain_end(input.get_parenthesis_depth(), true);
|
|
|
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
|
|
class: ExitClass::Gamma,
|
|
|
|
exit_matcher: &path_plain_end,
|
|
|
|
});
|
|
|
|
let parser_context = context.with_additional_node(&parser_context);
|
2023-10-08 09:28:09 -04:00
|
|
|
let (remaining, (raw_link, (_, application, _, path, search_option))) = consumed(tuple((
|
2023-10-08 09:16:48 -04:00
|
|
|
peek(tag("file")),
|
2023-10-07 03:00:40 -04:00
|
|
|
map_parser(
|
|
|
|
parser_with_context!(protocol)(&parser_context),
|
|
|
|
parse_file_and_application,
|
|
|
|
),
|
|
|
|
tag(":"),
|
2023-10-08 09:28:09 -04:00
|
|
|
recognize(opt(parser_with_context!(path_plain)(&parser_context))),
|
2023-10-07 02:22:36 -04:00
|
|
|
opt(map(
|
2023-10-07 03:25:01 -04:00
|
|
|
tuple((
|
|
|
|
tag("::"),
|
|
|
|
verify(is_not(" \t\r\n"), |search_option| {
|
|
|
|
Into::<&str>::into(search_option)
|
|
|
|
.chars()
|
|
|
|
.any(char::is_alphanumeric)
|
|
|
|
}),
|
|
|
|
)),
|
2023-10-07 02:22:36 -04:00
|
|
|
|(_, search_option)| search_option,
|
|
|
|
)),
|
|
|
|
)))(input)?;
|
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
PathPlain {
|
|
|
|
link_type: LinkType::File,
|
|
|
|
path: path.into(),
|
|
|
|
raw_link: raw_link.into(),
|
|
|
|
search_option: search_option.map(Into::<&str>::into),
|
2023-10-07 03:00:40 -04:00
|
|
|
application: application.map(Into::<&str>::into),
|
2023-10-07 02:22:36 -04:00
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2023-10-08 09:28:09 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-10-07 02:22:36 -04:00
|
|
|
fn protocol_path_plain<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, PathPlain<'s>> {
|
2023-10-07 02:42:07 -04:00
|
|
|
let path_plain_end = path_plain_end(input.get_parenthesis_depth(), false);
|
|
|
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
|
|
class: ExitClass::Gamma,
|
|
|
|
exit_matcher: &path_plain_end,
|
|
|
|
});
|
|
|
|
let parser_context = context.with_additional_node(&parser_context);
|
2023-10-07 02:22:36 -04:00
|
|
|
let (remaining, (raw_link, (protocol, _, path))) = consumed(tuple((
|
2023-10-07 02:42:07 -04:00
|
|
|
parser_with_context!(protocol)(&parser_context),
|
2023-10-07 02:22:36 -04:00
|
|
|
tag(":"),
|
2023-10-07 02:42:07 -04:00
|
|
|
parser_with_context!(path_plain)(&parser_context),
|
2023-10-07 02:22:36 -04:00
|
|
|
)))(input)?;
|
|
|
|
Ok((
|
|
|
|
remaining,
|
|
|
|
PathPlain {
|
|
|
|
link_type: LinkType::Protocol(protocol.into()),
|
|
|
|
path: path.into(),
|
|
|
|
raw_link: raw_link.into(),
|
|
|
|
search_option: None,
|
2023-10-07 03:00:40 -04:00
|
|
|
application: None,
|
2023-10-07 02:22:36 -04:00
|
|
|
},
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-11 13:13:28 -04:00
|
|
|
pub(crate) fn protocol<'b, 'g, 'r, 's>(
|
2023-10-06 19:18:58 -04:00
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
2023-08-23 00:30:26 -04:00
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
2023-10-06 19:18:58 -04:00
|
|
|
for link_parameter in context.get_global_settings().link_parameters {
|
|
|
|
let result = tag_no_case::<_, _, CustomError<_>>(*link_parameter)(input);
|
2023-08-29 15:44:04 -04:00
|
|
|
match result {
|
|
|
|
Ok((remaining, ent)) => {
|
|
|
|
return Ok((remaining, ent));
|
|
|
|
}
|
|
|
|
Err(_) => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(nom::Err::Error(CustomError::MyError(MyError(
|
|
|
|
"NoLinkProtocol".into(),
|
|
|
|
))))
|
2023-07-13 19:09:44 -04:00
|
|
|
}
|
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-03 15:44:18 -04:00
|
|
|
fn path_plain<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
2023-08-23 00:30:26 -04:00
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
2023-10-07 02:42:07 -04:00
|
|
|
// The caller needs to put an instance of path_plain_end on the context before calling this.
|
2023-09-21 18:34:32 -04:00
|
|
|
let (remaining, _components) = many1(alt((
|
2023-10-07 02:42:07 -04:00
|
|
|
parser_with_context!(path_plain_no_parenthesis)(context),
|
|
|
|
parser_with_context!(path_plain_parenthesis)(context),
|
2023-09-21 18:34:32 -04:00
|
|
|
)))(input)?;
|
2023-07-13 22:54:59 -04:00
|
|
|
|
2023-09-21 18:34:32 -04:00
|
|
|
let source = get_consumed(input, remaining);
|
|
|
|
Ok((remaining, source))
|
|
|
|
}
|
|
|
|
|
2023-10-07 02:42:07 -04:00
|
|
|
fn path_plain_end(
|
|
|
|
starting_parenthesis_depth: BracketDepth,
|
|
|
|
enable_search_option: bool,
|
|
|
|
) -> impl ContextMatcher {
|
|
|
|
move |context, input: OrgSource<'_>| {
|
2023-10-08 09:10:47 -04:00
|
|
|
impl_path_plain_end(
|
2023-10-07 02:42:07 -04:00
|
|
|
context,
|
|
|
|
input,
|
|
|
|
starting_parenthesis_depth,
|
|
|
|
enable_search_option,
|
|
|
|
)
|
|
|
|
}
|
2023-09-21 18:34:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-10-08 09:10:47 -04:00
|
|
|
fn impl_path_plain_end<'b, 'g, 'r, 's>(
|
2023-09-21 18:34:32 -04:00
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
starting_parenthesis_depth: BracketDepth,
|
2023-10-07 02:42:07 -04:00
|
|
|
enable_search_option: bool,
|
2023-09-21 18:34:32 -04:00
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
2023-10-07 02:42:07 -04:00
|
|
|
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
|
|
|
|
if enable_search_option && current_depth == 0 {
|
|
|
|
let search_option = peek(tag("::"))(input);
|
|
|
|
if search_option.is_ok() {
|
|
|
|
return search_option;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-21 18:34:32 -04:00
|
|
|
let (remaining, _leading_punctuation) = many0(verify(anychar, |c| {
|
|
|
|
!" \t\r\n[]<>()/".contains(*c) && c.is_ascii_punctuation()
|
|
|
|
}))(input)?;
|
|
|
|
|
|
|
|
let disallowed_character = recognize(one_of(" \t\r\n[]<>"))(remaining);
|
|
|
|
if disallowed_character.is_ok() {
|
|
|
|
return disallowed_character;
|
|
|
|
}
|
|
|
|
|
|
|
|
if current_depth == 0 {
|
|
|
|
let close_parenthesis =
|
|
|
|
tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>(")")(remaining);
|
|
|
|
if close_parenthesis.is_ok() {
|
|
|
|
return close_parenthesis;
|
|
|
|
}
|
|
|
|
|
|
|
|
let open_parenthesis_without_match = recognize(tuple((
|
|
|
|
peek(tag("(")),
|
|
|
|
not(parser_with_context!(path_plain_parenthesis)(context)),
|
|
|
|
)))(remaining);
|
|
|
|
if open_parenthesis_without_match.is_ok() {
|
|
|
|
return open_parenthesis_without_match;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(nom::Err::Error(CustomError::MyError(MyError(
|
|
|
|
"No path plain end".into(),
|
|
|
|
))))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
|
|
fn path_plain_no_parenthesis<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
2023-08-29 15:44:04 -04:00
|
|
|
let (remaining, path) = recognize(verify(
|
2023-09-21 18:34:32 -04:00
|
|
|
many_till(
|
|
|
|
anychar,
|
|
|
|
alt((
|
|
|
|
peek(path_plain_no_parenthesis_disallowed_character),
|
|
|
|
parser_with_context!(exit_matcher_parser)(context),
|
|
|
|
)),
|
|
|
|
),
|
2023-08-29 15:44:04 -04:00
|
|
|
|(children, _exit_contents)| !children.is_empty(),
|
|
|
|
))(input)?;
|
2023-08-29 17:35:04 -04:00
|
|
|
|
2023-07-13 22:54:59 -04:00
|
|
|
Ok((remaining, path))
|
|
|
|
}
|
|
|
|
|
2023-08-10 20:04:59 -04:00
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
2023-09-21 18:34:32 -04:00
|
|
|
fn path_plain_no_parenthesis_disallowed_character<'s>(
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
|
|
recognize(verify(anychar, |c| {
|
|
|
|
c.is_whitespace() || "()[]<>".contains(*c)
|
|
|
|
}))(input)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
|
|
fn path_plain_parenthesis<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
2023-08-23 00:30:26 -04:00
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
2023-09-21 18:34:32 -04:00
|
|
|
let (remaining, _opening) = tag("(")(input)?;
|
|
|
|
let starting_depth = remaining.get_parenthesis_depth();
|
|
|
|
|
|
|
|
let (remaining, _path) = recognize(verify(
|
|
|
|
many_till(
|
|
|
|
anychar,
|
|
|
|
alt((
|
|
|
|
peek(path_plain_parenthesis_end(starting_depth)),
|
|
|
|
parser_with_context!(exit_matcher_parser)(context),
|
|
|
|
)),
|
|
|
|
),
|
|
|
|
|(children, _exit_contents)| !children.is_empty(),
|
|
|
|
))(remaining)?;
|
|
|
|
let (remaining, _opening) = tag(")")(remaining)?;
|
|
|
|
let source = get_consumed(input, remaining);
|
|
|
|
|
|
|
|
Ok((remaining, source))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_plain_parenthesis_end(starting_parenthesis_depth: BracketDepth) -> impl Matcher {
|
|
|
|
move |input: OrgSource<'_>| _path_plain_parenthesis_end(input, starting_parenthesis_depth)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
|
|
fn _path_plain_parenthesis_end<'s>(
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
starting_parenthesis_depth: BracketDepth,
|
|
|
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
|
|
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
|
|
|
|
if current_depth < 0 {
|
|
|
|
// This shouldn't be possible because if depth is 0 then a closing parenthesis should end the link.
|
|
|
|
unreachable!("Exceeded plain link parenthesis depth.")
|
|
|
|
}
|
|
|
|
if current_depth == 0 {
|
|
|
|
let close_parenthesis = tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>(")")(input);
|
|
|
|
if close_parenthesis.is_ok() {
|
|
|
|
return close_parenthesis;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if current_depth == 1 {
|
|
|
|
let open_parenthesis = tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>("(")(input);
|
|
|
|
if open_parenthesis.is_ok() {
|
|
|
|
return open_parenthesis;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(nom::Err::Error(CustomError::MyError(MyError(
|
|
|
|
"No closing parenthesis".into(),
|
|
|
|
))))
|
2023-07-13 19:09:44 -04:00
|
|
|
}
|