2023-07-13 18:30:18 -04:00
use nom ::branch ::alt ;
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-07-13 18:30:18 -04:00
use nom ::combinator ::eof ;
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-07-13 22:54:59 -04:00
use nom ::multi ::many_till ;
2023-07-13 18:30:18 -04:00
2023-08-23 00:30:26 -04:00
use super ::org_source ::OrgSource ;
2023-07-13 18:18:07 -04:00
use super ::Context ;
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 ::exiting ::ExitClass ;
2023-07-13 18:18:07 -04:00
use crate ::parser ::object ::PlainLink ;
2023-07-13 22:54:59 -04:00
use crate ::parser ::parser_context ::ContextElement ;
use crate ::parser ::parser_context ::ExitMatcherNode ;
2023-07-13 19:09:44 -04:00
use crate ::parser ::parser_with_context ::parser_with_context ;
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-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-08-23 00:30:26 -04:00
pub fn plain_link < ' r , ' s > (
context : Context < ' r , ' s > ,
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , PlainLink < ' s > > {
2023-07-13 19:09:44 -04:00
let ( remaining , _ ) = pre ( context , input ) ? ;
let ( remaining , proto ) = protocol ( context , remaining ) ? ;
let ( remaining , _separator ) = tag ( " : " ) ( remaining ) ? ;
let ( remaining , path ) = path_plain ( context , remaining ) ? ;
peek ( parser_with_context! ( post ) ( context ) ) ( remaining ) ? ;
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 ( ) ,
link_type : proto . into ( ) ,
path : path . into ( ) ,
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-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-08-24 23:43:41 +00:00
fn pre < ' r , ' s > ( _context : Context < ' 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-08-24 23:43:41 +00:00
fn post < ' r , ' s > ( _context : Context < ' 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-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-08-23 00:30:26 -04:00
pub fn protocol < ' r , ' s > (
2023-08-24 23:43:41 +00:00
_context : Context < ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-13 19:33:38 -04:00
// TODO: This should be defined by org-link-parameters
2023-07-13 19:09:44 -04:00
let ( remaining , proto ) = alt ( (
alt ( (
tag_no_case ( " id " ) ,
tag_no_case ( " eww " ) ,
tag_no_case ( " rmail " ) ,
tag_no_case ( " mhe " ) ,
tag_no_case ( " irc " ) ,
tag_no_case ( " info " ) ,
tag_no_case ( " gnus " ) ,
tag_no_case ( " docview " ) ,
tag_no_case ( " bibtex " ) ,
tag_no_case ( " bbdb " ) ,
tag_no_case ( " w3m " ) ,
) ) ,
alt ( (
tag_no_case ( " doi " ) ,
tag_no_case ( " file+sys " ) ,
tag_no_case ( " file+emacs " ) ,
tag_no_case ( " shell " ) ,
tag_no_case ( " news " ) ,
tag_no_case ( " mailto " ) ,
tag_no_case ( " https " ) ,
tag_no_case ( " http " ) ,
tag_no_case ( " ftp " ) ,
tag_no_case ( " help " ) ,
tag_no_case ( " file " ) ,
tag_no_case ( " elisp " ) ,
) ) ,
) ) ( input ) ? ;
Ok ( ( remaining , proto ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-08-23 00:30:26 -04:00
fn path_plain < ' r , ' s > (
context : Context < ' r , ' s > ,
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-13 19:09:44 -04:00
// TODO: "optionally containing parenthesis-wrapped non-whitespace non-bracket substrings up to a depth of two. The string must end with either a non-punctation non-whitespace character, a forwards slash, or a parenthesis-wrapped substring"
2023-07-13 22:54:59 -04:00
let parser_context =
context . with_additional_node ( ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Beta ,
exit_matcher : & path_plain_end ,
} ) ) ;
let exit_matcher = parser_with_context! ( exit_matcher_parser ) ( & parser_context ) ;
let ( remaining , path ) = recognize ( many_till ( anychar , peek ( exit_matcher ) ) ) ( input ) ? ;
Ok ( ( remaining , path ) )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-08-23 00:30:26 -04:00
fn path_plain_end < ' r , ' s > (
2023-08-24 23:43:41 +00:00
_context : Context < ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-13 22:54:59 -04:00
recognize ( one_of ( " \t \r \n ()[]<> " ) ) ( input )
2023-07-13 19:09:44 -04:00
}