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 ;
use nom ::bytes ::complete ::take_while ;
2023-07-13 18:30:18 -04:00
use nom ::character ::complete ::none_of ;
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 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 ;
use crate ::parser ::object ::PlainLink ;
2023-07-13 19:09:44 -04:00
use crate ::parser ::parser_with_context ::parser_with_context ;
use crate ::parser ::util ::get_consumed ;
2023-07-13 18:30:18 -04:00
use crate ::parser ::util ::get_one_before ;
use crate ::parser ::util ::WORD_CONSTITUENT_CHARACTERS ;
2023-07-13 18:18:07 -04:00
#[ tracing::instrument(ret, level = " debug " ) ]
pub fn plain_link < ' r , ' s > ( context : Context < ' r , ' s > , input : & ' s str ) -> Res < & ' s str , 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 {
source ,
link_type : proto ,
path ,
} ,
) )
2023-07-13 18:18:07 -04:00
}
2023-07-13 18:30:18 -04:00
#[ tracing::instrument(ret, level = " debug " ) ]
pub fn pre < ' r , ' s > ( context : Context < ' r , ' s > , input : & ' s str ) -> Res < & ' s str , ( ) > {
let document_root = context . get_document_root ( ) . unwrap ( ) ;
let preceding_character = get_one_before ( document_root , input )
. map ( | slice | slice . chars ( ) . next ( ) )
. flatten ( ) ;
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 (
" Not a valid pre character for plain link. " ,
) ) ) ) ;
}
} ;
Ok ( ( input , ( ) ) )
}
#[ tracing::instrument(ret, level = " debug " ) ]
pub fn post < ' r , ' s > ( context : Context < ' r , ' s > , input : & ' s str ) -> Res < & ' s str , ( ) > {
let ( remaining , _ ) = alt ( ( eof , recognize ( none_of ( WORD_CONSTITUENT_CHARACTERS ) ) ) ) ( input ) ? ;
Ok ( ( remaining , ( ) ) )
}
2023-07-13 19:09:44 -04:00
#[ tracing::instrument(ret, level = " debug " ) ]
pub fn protocol < ' r , ' s > ( context : Context < ' r , ' s > , input : & ' s str ) -> Res < & ' s str , & ' s str > {
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 ) )
}
#[ tracing::instrument(ret, level = " debug " ) ]
pub fn path_plain < ' r , ' s > ( context : Context < ' r , ' s > , input : & ' s str ) -> Res < & ' s str , & ' s str > {
// 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"
take_while ( | c | ! " \t \r \n ()[]<> " . contains ( c ) ) ( input )
// recognize(many1(none_of(" \t\r\n()[]<>")))(input)
}