diff --git a/src/parser/plain_link.rs b/src/parser/plain_link.rs index ac205dc..ae90402 100644 --- a/src/parser/plain_link.rs +++ b/src/parser/plain_link.rs @@ -111,9 +111,15 @@ fn file_path_plain<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PathPlain<'s>> { + 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); let (remaining, (raw_link, (_, path, search_option))) = consumed(tuple(( tag("file:"), - parser_with_context!(path_plain)(context), + parser_with_context!(path_plain)(&parser_context), opt(map( tuple((tag("::"), is_not(" \t\r\n"))), |(_, search_option)| search_option, @@ -134,10 +140,16 @@ fn protocol_path_plain<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PathPlain<'s>> { + 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); let (remaining, (raw_link, (protocol, _, path))) = consumed(tuple(( - parser_with_context!(protocol)(context), + parser_with_context!(protocol)(&parser_context), tag(":"), - parser_with_context!(path_plain)(context), + parser_with_context!(path_plain)(&parser_context), )))(input)?; Ok(( remaining, @@ -175,24 +187,28 @@ fn path_plain<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, OrgSource<'s>> { - let path_plain_end = path_plain_end(input.get_parenthesis_depth()); - let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { - class: ExitClass::Gamma, - exit_matcher: &path_plain_end, - }); - let parser_context = context.with_additional_node(&parser_context); - + // The caller needs to put an instance of path_plain_end on the context before calling this. let (remaining, _components) = many1(alt(( - parser_with_context!(path_plain_no_parenthesis)(&parser_context), - parser_with_context!(path_plain_parenthesis)(&parser_context), + parser_with_context!(path_plain_no_parenthesis)(context), + parser_with_context!(path_plain_parenthesis)(context), )))(input)?; let source = get_consumed(input, remaining); Ok((remaining, source)) } -fn path_plain_end(starting_parenthesis_depth: BracketDepth) -> impl ContextMatcher { - move |context, input: OrgSource<'_>| _path_plain_end(context, input, starting_parenthesis_depth) +fn path_plain_end( + starting_parenthesis_depth: BracketDepth, + enable_search_option: bool, +) -> impl ContextMatcher { + move |context, input: OrgSource<'_>| { + _path_plain_end( + context, + input, + starting_parenthesis_depth, + enable_search_option, + ) + } } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] @@ -200,7 +216,16 @@ fn _path_plain_end<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, starting_parenthesis_depth: BracketDepth, + enable_search_option: bool, ) -> Res, OrgSource<'s>> { + 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; + } + } + let (remaining, _leading_punctuation) = many0(verify(anychar, |c| { !" \t\r\n[]<>()/".contains(*c) && c.is_ascii_punctuation() }))(input)?; @@ -210,7 +235,6 @@ fn _path_plain_end<'b, 'g, 'r, 's>( return disallowed_character; } - let current_depth = remaining.get_parenthesis_depth() - starting_parenthesis_depth; if current_depth == 0 { let close_parenthesis = tag::<&str, OrgSource<'_>, CustomError>>(")")(remaining); @@ -227,7 +251,6 @@ fn _path_plain_end<'b, 'g, 'r, 's>( } } - // many0 punctuation Err(nom::Err::Error(CustomError::MyError(MyError( "No path plain end".into(), ))))