2023-04-24 18:02:37 -04:00
use nom ::branch ::alt ;
2023-09-14 04:00:34 -04:00
use nom ::bytes ::complete ::is_not ;
2023-09-14 04:04:21 -04:00
use nom ::bytes ::complete ::tag_no_case ;
2023-04-24 18:02:37 -04:00
use nom ::character ::complete ::anychar ;
2023-09-14 04:00:34 -04:00
use nom ::character ::complete ::line_ending ;
use nom ::character ::complete ::one_of ;
2023-09-19 23:25:49 -04:00
use nom ::combinator ::eof ;
2023-04-24 18:02:37 -04:00
use nom ::combinator ::peek ;
2023-04-22 19:46:27 -04:00
use nom ::combinator ::recognize ;
2023-04-24 18:02:37 -04:00
use nom ::combinator ::verify ;
2023-09-14 04:00:34 -04:00
use nom ::multi ::many1 ;
2023-04-24 18:02:37 -04:00
use nom ::multi ::many_till ;
2023-09-19 23:25:49 -04:00
use nom ::sequence ::tuple ;
2023-04-22 19:46:27 -04:00
2023-08-23 00:30:26 -04:00
use super ::org_source ::OrgSource ;
2023-04-24 20:32:59 -04:00
use super ::radio_link ::RematchObject ;
2023-09-03 12:23:18 -04:00
use super ::util ::exit_matcher_parser ;
2023-09-14 04:00:34 -04:00
use super ::util ::get_consumed ;
use super ::util ::org_space_or_line_ending ;
2023-09-03 12:23:18 -04:00
use crate ::context ::parser_with_context ;
use crate ::context ::RefContext ;
2023-09-14 04:00:34 -04:00
use crate ::error ::CustomError ;
use crate ::error ::MyError ;
2023-04-21 18:36:01 -04:00
use crate ::error ::Res ;
2023-09-03 12:23:18 -04:00
use crate ::types ::Object ;
use crate ::types ::PlainText ;
2023-03-25 12:53:57 -04:00
2023-09-11 13:13:28 -04:00
pub ( crate ) fn plain_text < F > (
2023-09-08 17:45:49 -04:00
end_condition : F ,
) -> impl for < ' b , ' g , ' r , ' s > Fn (
RefContext < ' b , ' g , ' r , ' s > ,
OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , PlainText < ' s > >
where
F : for < ' bb , ' gg , ' rr , ' ss > Fn (
RefContext < ' bb , ' gg , ' rr , ' ss > ,
OrgSource < ' ss > ,
) -> Res < OrgSource < ' ss > , ( ) > ,
{
move | context , input | _plain_text ( & end_condition , context , input )
}
#[ cfg_attr(
feature = " tracing " ,
tracing ::instrument ( ret , level = " debug " , skip ( end_condition ) )
) ]
fn _plain_text < ' b , ' g , ' r , ' s , F > (
end_condition : F ,
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 > ,
2023-09-08 17:45:49 -04:00
) -> Res < OrgSource < ' s > , PlainText < ' s > >
where
F : for < ' bb , ' gg , ' rr , ' ss > Fn (
RefContext < ' bb , ' gg , ' rr , ' ss > ,
OrgSource < ' ss > ,
) -> Res < OrgSource < ' ss > , ( ) > ,
{
2023-04-24 18:02:37 -04:00
let ( remaining , source ) = recognize ( verify (
many_till (
anychar ,
peek ( alt ( (
parser_with_context! ( exit_matcher_parser ) ( context ) ,
2023-09-08 17:45:49 -04:00
recognize ( parser_with_context! ( end_condition ) ( context ) ) ,
2023-04-24 18:02:37 -04:00
) ) ) ,
) ,
| ( children , _exit_contents ) | ! children . is_empty ( ) ,
) ) ( input ) ? ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
PlainText {
source : source . into ( ) ,
} ,
) )
2023-03-25 12:53:57 -04:00
}
2023-07-14 18:04:01 -04:00
impl < ' x > RematchObject < ' x > for PlainText < ' x > {
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 rematch_object < ' b , ' g , ' r , ' s > (
2023-07-14 18:04:01 -04:00
& ' x self ,
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 > , Object < ' s > > {
2023-09-14 04:00:34 -04:00
let mut remaining = input ;
let mut goal = self . source ;
loop {
if goal . is_empty ( ) {
break ;
}
let is_not_whitespace = is_not ::< & str , & str , CustomError < _ > > ( " \t \r \n " ) ( goal ) ;
match is_not_whitespace {
Ok ( ( new_goal , payload ) ) = > {
2023-09-19 23:25:49 -04:00
let ( new_remaining , _ ) = tuple ( (
tag_no_case ( payload ) ,
// TODO: Test to see what the REAL condition is. Checking for not-alphabetic works fine for now, but the real criteria might be something like the plain text exit matcher.
peek ( alt ( (
recognize ( verify ( anychar , | c | ! c . is_alphanumeric ( ) ) ) ,
eof ,
) ) ) ,
) ) ( remaining ) ? ;
2023-09-14 04:00:34 -04:00
remaining = new_remaining ;
goal = new_goal ;
continue ;
}
Err ( _ ) = > { }
} ;
let is_whitespace = recognize ( many1 ( alt ( (
recognize ( one_of ::< & str , & str , CustomError < _ > > ( " \t " ) ) ,
line_ending ,
) ) ) ) ( goal ) ;
match is_whitespace {
Ok ( ( new_goal , _ ) ) = > {
let ( new_remaining , _ ) = many1 ( org_space_or_line_ending ) ( remaining ) ? ;
remaining = new_remaining ;
goal = new_goal ;
continue ;
}
Err ( _ ) = > { }
} ;
return Err ( nom ::Err ::Error ( CustomError ::MyError ( MyError (
" Target does not match. " . into ( ) ,
) ) ) ) ;
}
let source = get_consumed ( input , remaining ) ;
Ok ( (
remaining ,
2023-08-23 00:30:26 -04:00
Object ::PlainText ( PlainText {
2023-09-14 04:00:34 -04:00
source : Into ::< & str > ::into ( source ) ,
} ) ,
) )
2023-04-24 20:32:59 -04:00
}
}
2023-03-25 12:53:57 -04:00
#[ cfg(test) ]
mod tests {
use nom ::combinator ::map ;
2023-04-22 19:46:27 -04:00
use super ::* ;
2023-09-03 12:23:18 -04:00
use crate ::context ::Context ;
use crate ::context ::ContextElement ;
use crate ::context ::GlobalSettings ;
use crate ::context ::List ;
2023-09-08 17:45:49 -04:00
use crate ::parser ::object_parser ::detect_standard_set_object_sans_plain_text ;
2023-09-23 19:13:01 -04:00
use crate ::types ::GetStandardProperties ;
2023-03-25 12:53:57 -04:00
#[ test ]
fn plain_text_simple ( ) {
2023-08-24 17:15:24 -04:00
let input = OrgSource ::new ( " foobarbaz " ) ;
2023-09-03 12:23:18 -04:00
let global_settings = GlobalSettings ::default ( ) ;
let initial_context = ContextElement ::document_context ( ) ;
let initial_context = Context ::new ( & global_settings , List ::new ( & initial_context ) ) ;
2023-09-08 17:45:49 -04:00
let plain_text_matcher = parser_with_context! ( plain_text (
detect_standard_set_object_sans_plain_text
) ) ( & initial_context ) ;
2023-03-25 12:53:57 -04:00
let ( remaining , result ) = map ( plain_text_matcher , Object ::PlainText ) ( input ) . unwrap ( ) ;
2023-08-24 17:15:24 -04:00
assert_eq! ( Into ::< & str > ::into ( remaining ) , " " ) ;
2023-09-23 19:13:01 -04:00
assert_eq! (
result . get_standard_properties ( ) . get_source ( ) ,
Into ::< & str > ::into ( input )
) ;
2023-03-25 12:53:57 -04:00
}
}