From e84135985e258c945b07445e51a03a63804090dc Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 6 Oct 2023 17:21:43 -0400 Subject: [PATCH] Parse out the pathreg on regular links. --- .../object/regular_link/code_ref_link.org | 8 ++ src/parser/regular_link.rs | 123 +++++++++++++++--- src/types/mod.rs | 1 + src/types/object.rs | 12 +- 4 files changed, 127 insertions(+), 17 deletions(-) diff --git a/org_mode_samples/object/regular_link/code_ref_link.org b/org_mode_samples/object/regular_link/code_ref_link.org index fcefb14c..6e99b14f 100644 --- a/org_mode_samples/object/regular_link/code_ref_link.org +++ b/org_mode_samples/object/regular_link/code_ref_link.org @@ -1 +1,9 @@ [[(foo)]] + +[[((bar))]] + +[[((baz)]] + +# These become fuzzy +[[(foo) ]] +[[ (foo)]] diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index ba1763c0..414be404 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -3,8 +3,15 @@ use nom::bytes::complete::escaped; use nom::bytes::complete::tag; use nom::bytes::complete::take_till1; use nom::character::complete::anychar; +use nom::combinator::consumed; +use nom::combinator::eof; +use nom::combinator::map_parser; +use nom::combinator::peek; +use nom::combinator::recognize; +use nom::combinator::rest; use nom::combinator::verify; use nom::multi::many_till; +use nom::sequence::tuple; use super::object_parser::regular_link_description_set_object; use super::org_source::OrgSource; @@ -17,6 +24,7 @@ use crate::context::ExitClass; use crate::context::ExitMatcherNode; use crate::context::RefContext; use crate::error::Res; +use crate::types::LinkType; use crate::types::Object; use crate::types::RegularLink; @@ -37,7 +45,7 @@ fn regular_link_without_description<'b, 'g, 'r, 's>( input: OrgSource<'s>, ) -> Res, RegularLink<'s>> { let (remaining, _opening_bracket) = tag("[[")(input)?; - let (remaining, _path) = pathreg(context, remaining)?; + let (remaining, path) = pathreg(context, remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?; let (remaining, _trailing_whitespace) = maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?; @@ -46,9 +54,9 @@ fn regular_link_without_description<'b, 'g, 'r, 's>( remaining, RegularLink { source: source.into(), - link_type: todo!(), - path: todo!(), - raw_link: todo!(), + link_type: path.link_type, + path: path.path, + raw_link: path.raw_link, }, )) } @@ -59,7 +67,7 @@ fn regular_link_with_description<'b, 'g, 'r, 's>( input: OrgSource<'s>, ) -> Res, RegularLink<'s>> { let (remaining, _opening_bracket) = tag("[[")(input)?; - let (remaining, _path) = pathreg(context, remaining)?; + let (remaining, path) = pathreg(context, remaining)?; let (remaining, _closing_bracket) = tag("][")(remaining)?; let (remaining, _description) = description(context, remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?; @@ -70,29 +78,112 @@ fn regular_link_with_description<'b, 'g, 'r, 's>( remaining, RegularLink { source: source.into(), - link_type: todo!(), - path: todo!(), - raw_link: todo!(), + link_type: path.link_type, + path: path.path, + raw_link: path.raw_link, }, )) } +struct PathReg<'s> { + link_type: LinkType<'s>, + path: &'s str, + raw_link: &'s str, +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn pathreg<'b, 'g, 'r, 's>( _context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, OrgSource<'s>> { - let (remaining, path) = escaped( - take_till1(|c| match c { - '\\' | '[' | ']' => true, - _ => false, - }), - '\\', - anychar, +) -> Res, PathReg<'s>> { + let (remaining, path) = map_parser( + escaped( + take_till1(|c| match c { + '\\' | '[' | ']' => true, + _ => false, + }), + '\\', + anychar, + ), + parse_path_reg, )(input)?; Ok((remaining, path)) } +fn parse_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + alt(( + file_path_reg, + id_path_reg, + custom_id_path_reg, + code_ref_path_reg, + fuzzy_path_reg, + ))(input) +} + +fn file_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + let (remaining, (raw_link, (_, path))) = consumed(tuple((tag("file:"), rest)))(input)?; + Ok(( + remaining, + PathReg { + link_type: LinkType::File, + path: path.into(), + raw_link: raw_link.into(), + }, + )) +} + +fn id_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + let (remaining, (raw_link, (_, path))) = consumed(tuple((tag("id:"), rest)))(input)?; + Ok(( + remaining, + PathReg { + link_type: LinkType::Id, + path: path.into(), + raw_link: raw_link.into(), + }, + )) +} + +fn custom_id_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + let (remaining, (raw_link, (_, path))) = consumed(tuple((tag("#"), rest)))(input)?; + Ok(( + remaining, + PathReg { + link_type: LinkType::CustomId, + path: path.into(), + raw_link: raw_link.into(), + }, + )) +} + +fn code_ref_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + let (remaining, (raw_link, (_, path, _))) = consumed(tuple(( + tag("("), + recognize(many_till(anychar, peek(tuple((tag(")"), eof))))), + tag(")"), + )))(input)?; + Ok(( + remaining, + PathReg { + link_type: LinkType::CodeRef, + path: path.into(), + raw_link: raw_link.into(), + }, + )) +} + +fn fuzzy_path_reg<'s>(input: OrgSource<'s>) -> Res, PathReg<'s>> { + let (remaining, body) = rest(input)?; + Ok(( + remaining, + PathReg { + link_type: LinkType::Fuzzy, + path: body.into(), + raw_link: body.into(), + }, + )) +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn description<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, diff --git a/src/types/mod.rs b/src/types/mod.rs index 7abd7105..63eb4ae9 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -75,6 +75,7 @@ pub use object::InlineSourceBlock; pub use object::Italic; pub use object::LatexFragment; pub use object::LineBreak; +pub use object::LinkType; pub use object::Minute; pub use object::MinuteInner; pub use object::Month; diff --git a/src/types/object.rs b/src/types/object.rs index e10df905..bd0af47c 100644 --- a/src/types/object.rs +++ b/src/types/object.rs @@ -77,7 +77,7 @@ pub struct PlainText<'s> { #[derive(Debug, PartialEq)] pub struct RegularLink<'s> { pub source: &'s str, - pub link_type: &'s str, + pub link_type: LinkType<'s>, pub path: &'s str, pub raw_link: &'s str, } @@ -638,3 +638,13 @@ impl<'s> Timestamp<'s> { self.source.trim_end() } } + +#[derive(Debug, PartialEq)] +pub enum LinkType<'s> { + File, + Protocol(&'s str), + Id, + CustomId, + CodeRef, + Fuzzy, +}