2023-07-24 17:54:49 -04:00
use nom ::branch ::alt ;
2023-07-27 18:59:22 -04:00
use nom ::bytes ::complete ::tag ;
use nom ::character ::complete ::anychar ;
2023-09-15 13:12:54 -04:00
use nom ::character ::complete ::digit0 ;
2023-07-27 19:20:28 -04:00
use nom ::character ::complete ::digit1 ;
2023-07-27 18:59:22 -04:00
use nom ::character ::complete ::one_of ;
2023-07-27 19:20:28 -04:00
use nom ::character ::complete ::space1 ;
use nom ::combinator ::opt ;
2023-07-27 18:59:22 -04:00
use nom ::combinator ::recognize ;
use nom ::combinator ::verify ;
use nom ::multi ::many_till ;
2023-07-27 19:20:28 -04:00
use nom ::sequence ::tuple ;
2023-07-24 17:54:49 -04:00
2023-08-23 00:30:26 -04:00
use super ::org_source ::OrgSource ;
2023-09-02 19:28:33 -04:00
use super ::util ::exit_matcher_parser ;
2023-08-31 15:44:44 -04:00
use super ::util ::maybe_consume_object_trailing_whitespace_if_not_exiting ;
2023-09-02 19:28:33 -04:00
use crate ::context ::parser_with_context ;
use crate ::context ::ContextElement ;
use crate ::context ::ExitClass ;
use crate ::context ::ExitMatcherNode ;
use crate ::context ::RefContext ;
2023-07-24 17:34:07 -04:00
use crate ::error ::Res ;
2023-07-27 18:59:22 -04:00
use crate ::parser ::util ::get_consumed ;
2023-09-02 19:28:33 -04:00
use crate ::types ::Timestamp ;
2023-10-02 13:42:46 -04:00
use crate ::types ::TimestampRangeType ;
2023-10-02 13:33:00 -04:00
use crate ::types ::TimestampType ;
2023-07-24 17:34:07 -04:00
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-09-11 13:13:28 -04:00
pub ( crate ) fn timestamp < ' b , ' g , ' r , ' s > (
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 > , Timestamp < ' s > > {
2023-07-24 17:54:49 -04:00
// TODO: This would be more efficient if we didn't throw away the parse result of the first half of an active/inactive date range timestamp if the parse fails (as in, the first thing active_date_range_timestamp parses is a active_timestamp but then we throw that away if it doesn't turn out to be a full active_date_range_timestamp despite the active_timestamp parse being completely valid). I am going with the simplest/cleanest approach for the first implementation.
alt ( (
// Order matters here. If its a date range, we need to parse the entire date range instead of just the first timestamp. If its a time range, we need to make sure thats parsed as a time range instead of as the "rest" portion of a single timestamp.
parser_with_context! ( diary_timestamp ) ( context ) ,
parser_with_context! ( active_time_range_timestamp ) ( context ) ,
parser_with_context! ( inactive_time_range_timestamp ) ( context ) ,
parser_with_context! ( active_date_range_timestamp ) ( context ) ,
parser_with_context! ( inactive_date_range_timestamp ) ( context ) ,
parser_with_context! ( active_timestamp ) ( context ) ,
parser_with_context! ( inactive_timestamp ) ( context ) ,
) ) ( input )
}
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 diary_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 18:59:22 -04:00
let ( remaining , _ ) = tag ( " <%%( " ) ( input ) ? ;
let ( remaining , _body ) = sexp ( context , remaining ) ? ;
let ( remaining , _ ) = tag ( " )> " ) ( remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 18:59:22 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::Diary ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::None ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-27 18:59:22 -04:00
}
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 sexp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-09-02 23:16:02 -04:00
let parser_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & sexp_end ,
} ) ;
let parser_context = context . with_additional_node ( & parser_context ) ;
2023-07-27 18:59:22 -04:00
let ( remaining , body ) = recognize ( verify (
many_till (
anychar ,
parser_with_context! ( exit_matcher_parser ) ( & parser_context ) ,
) ,
| ( body , _end_contents ) | ! body . is_empty ( ) ,
) ) ( input ) ? ;
Ok ( ( remaining , body ) )
}
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 sexp_end < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 18:59:22 -04:00
alt ( ( tag ( " )> " ) , recognize ( one_of ( " > \n " ) ) ) ) ( input )
2023-07-24 17:54:49 -04:00
}
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 active_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 19:20:28 -04:00
let ( remaining , _ ) = tag ( " < " ) ( input ) ? ;
let ( remaining , _date ) = date ( context , remaining ) ? ;
2023-09-02 23:16:02 -04:00
let time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & active_time_rest_end ,
} ) ;
let time_context = context . with_additional_node ( & time_context ) ;
2023-07-27 19:45:57 -04:00
let ( remaining , _time ) =
2023-07-27 19:52:35 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( time ) ( & time_context ) ) ) ) ( remaining ) ? ;
2023-07-27 19:45:57 -04:00
let ( remaining , _repeater ) =
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
let ( remaining , _warning_delay ) = opt ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " > " ) ( remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 19:45:57 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::Active ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::None ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:54:49 -04:00
}
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 inactive_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 19:54:33 -04:00
let ( remaining , _ ) = tag ( " [ " ) ( input ) ? ;
let ( remaining , _date ) = date ( context , remaining ) ? ;
2023-09-02 23:16:02 -04:00
let time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & inactive_time_rest_end ,
} ) ;
let time_context = context . with_additional_node ( & time_context ) ;
2023-07-27 19:54:33 -04:00
let ( remaining , _time ) =
opt ( tuple ( ( space1 , parser_with_context! ( time ) ( & time_context ) ) ) ) ( remaining ) ? ;
let ( remaining , _repeater ) =
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
let ( remaining , _warning_delay ) = opt ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " ] " ) ( remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 19:54:33 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::Inactive ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::None ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:54:49 -04:00
}
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 active_date_range_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 19:59:36 -04:00
let ( remaining , _first_timestamp ) = active_timestamp ( context , input ) ? ;
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
let ( remaining , _separator ) = tag ( " -- " ) ( remaining ) ? ;
let ( remaining , _second_timestamp ) = active_timestamp ( context , remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 19:59:36 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::ActiveRange ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::DateRange ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:54:49 -04:00
}
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 active_time_range_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 20:26:56 -04:00
let ( remaining , _ ) = tag ( " < " ) ( input ) ? ;
let ( remaining , _date ) = date ( context , remaining ) ? ;
2023-09-02 23:16:02 -04:00
let time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & active_time_rest_end ,
} ) ;
let time_context = context . with_additional_node ( & time_context ) ;
let first_time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & time_range_rest_end ,
} ) ;
let first_time_context = time_context . with_additional_node ( & first_time_context ) ;
2023-07-27 20:26:56 -04:00
let ( remaining , _first_time ) =
tuple ( ( space1 , parser_with_context! ( time ) ( & first_time_context ) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
let ( remaining , _second_time ) = parser_with_context! ( time ) ( & time_context ) ( remaining ) ? ;
let ( remaining , _repeater ) =
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
let ( remaining , _warning_delay ) = opt ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " > " ) ( remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 20:26:56 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::Active ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::None ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:54:49 -04:00
}
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 inactive_date_range_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 19:59:36 -04:00
let ( remaining , _first_timestamp ) = inactive_timestamp ( context , input ) ? ;
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
let ( remaining , _separator ) = tag ( " -- " ) ( remaining ) ? ;
let ( remaining , _second_timestamp ) = inactive_timestamp ( context , remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 19:59:36 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::InactiveRange ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::DateRange ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:54:49 -04:00
}
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 inactive_time_range_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , Timestamp < ' s > > {
2023-07-27 20:26:56 -04:00
let ( remaining , _ ) = tag ( " [ " ) ( input ) ? ;
let ( remaining , _date ) = date ( context , remaining ) ? ;
2023-09-02 23:16:02 -04:00
let time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & inactive_time_rest_end ,
} ) ;
let time_context = context . with_additional_node ( & time_context ) ;
let first_time_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & time_range_rest_end ,
} ) ;
let first_time_context = time_context . with_additional_node ( & first_time_context ) ;
2023-07-27 20:26:56 -04:00
let ( remaining , _first_time ) =
tuple ( ( space1 , parser_with_context! ( time ) ( & first_time_context ) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
let ( remaining , _second_time ) = parser_with_context! ( time ) ( & time_context ) ( remaining ) ? ;
let ( remaining , _repeater ) =
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
let ( remaining , _warning_delay ) = opt ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ( remaining ) ? ;
let ( remaining , _ ) = tag ( " ] " ) ( remaining ) ? ;
2023-08-31 15:44:44 -04:00
let ( remaining , _trailing_whitespace ) =
maybe_consume_object_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-07-27 20:26:56 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Timestamp {
source : source . into ( ) ,
2023-10-02 13:33:00 -04:00
timestamp_type : TimestampType ::Inactive ,
2023-10-02 13:42:46 -04:00
range_type : TimestampRangeType ::None ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-07-24 17:34:07 -04:00
}
2023-07-27 19:20:28 -04:00
2023-10-02 15:10:39 -04:00
pub struct Year ( u16 ) ;
pub struct Month ( u8 ) ;
pub struct DayOfMonth ( u8 ) ;
impl Year {
// TODO: Make a real error type instead of a boxed any error.
pub fn new < ' s > ( source : & ' s str ) -> Result < Self , Box < dyn std ::error ::Error > > {
let year = source . parse ::< u16 > ( ) ? ;
Ok ( Year ( year ) )
}
pub fn get_value ( & self ) -> u16 {
self . 0
}
}
impl Month {
// TODO: Make a real error type instead of a boxed any error.
pub fn new < ' s > ( source : & ' s str ) -> Result < Self , Box < dyn std ::error ::Error > > {
let month = source . parse ::< u8 > ( ) ? ;
if month < 1 | | month > 12 {
Err ( " Month exceeds possible range. " ) ? ;
}
Ok ( Month ( month ) )
}
pub fn get_value ( & self ) -> u8 {
self . 0
}
}
impl DayOfMonth {
// TODO: Make a real error type instead of a boxed any error.
pub fn new < ' s > ( source : & ' s str ) -> Result < Self , Box < dyn std ::error ::Error > > {
let day_of_month = source . parse ::< u8 > ( ) ? ;
if day_of_month < 1 | | day_of_month > 31 {
Err ( " Day of month exceeds possible range. " ) ? ;
}
Ok ( DayOfMonth ( day_of_month ) )
}
pub fn get_value ( & self ) -> u8 {
self . 0
}
}
pub struct Date < ' s > {
year : Year ,
month : Month ,
day_of_month : DayOfMonth ,
day_name : & ' s str ,
}
impl < ' s > Date < ' s > {
// TODO: Make a real error type instead of a boxed any error.
pub fn new (
year : Year ,
month : Month ,
day_of_month : DayOfMonth ,
day_name : & ' s str ,
) -> Result < Self , Box < dyn std ::error ::Error > > {
// TODO: Does org-mode support non-gregorian calendars?
// TODO: Do I want to validate leap year?
match ( month . get_value ( ) , day_of_month . get_value ( ) ) {
( 1 , 1 ..= 31 ) = > { }
( 2 , 1 ..= 29 ) = > { }
( 3 , 1 ..= 31 ) = > { }
( 4 , 1 ..= 30 ) = > { }
( 5 , 1 ..= 31 ) = > { }
( 6 , 1 ..= 30 ) = > { }
( 7 , 1 ..= 31 ) = > { }
( 8 , 1 ..= 31 ) = > { }
( 9 , 1 ..= 30 ) = > { }
( 10 , 1 ..= 31 ) = > { }
( 11 , 1 ..= 30 ) = > { }
( 12 , 1 ..= 31 ) = > { }
_ = > Err ( " Invalid day of month for the month. " ) ? ,
} ;
Ok ( Date {
year ,
month ,
day_of_month ,
day_name ,
} )
}
pub fn get_year ( & self ) -> & Year {
& self . year
}
pub fn get_month ( & self ) -> & Month {
& self . month
}
pub fn get_day_of_month ( & self ) -> & DayOfMonth {
& self . day_of_month
}
pub fn get_day_name ( & self ) -> & ' s str {
self . day_name
}
}
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 date < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
let ( remaining , _year ) = verify ( digit1 , | year : & OrgSource < '_ > | year . len ( ) = = 4 ) ( input ) ? ;
2023-07-27 19:20:28 -04:00
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
2023-08-23 00:30:26 -04:00
let ( remaining , _month ) = verify ( digit1 , | month : & OrgSource < '_ > | month . len ( ) = = 2 ) ( remaining ) ? ;
2023-07-27 19:20:28 -04:00
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
2023-08-23 00:30:26 -04:00
let ( remaining , _day_of_month ) = verify ( digit1 , | day_of_month : & OrgSource < '_ > | {
day_of_month . len ( ) = = 2
} ) ( remaining ) ? ;
2023-07-27 19:20:28 -04:00
let ( remaining , _dayname ) =
opt ( tuple ( ( space1 , parser_with_context! ( dayname ) ( context ) ) ) ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
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 dayname < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-09-02 23:16:02 -04:00
let parser_context = ContextElement ::ExitMatcherNode ( ExitMatcherNode {
class : ExitClass ::Gamma ,
exit_matcher : & dayname_end ,
} ) ;
let parser_context = context . with_additional_node ( & parser_context ) ;
2023-07-27 19:20:28 -04:00
let ( remaining , body ) = recognize ( verify (
many_till (
anychar ,
parser_with_context! ( exit_matcher_parser ) ( & parser_context ) ,
) ,
| ( body , _end_contents ) | ! body . is_empty ( ) ,
) ) ( input ) ? ;
Ok ( ( remaining , body ) )
}
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 dayname_end < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:20:28 -04:00
recognize ( verify ( anychar , | c | {
c . is_whitespace ( ) | | " +-]>0123456789 \n " . contains ( * c )
} ) ) ( input )
}
2023-07-27 19:45:57 -04:00
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 time < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
let ( remaining , _hour ) = verify ( digit1 , | hour : & OrgSource < '_ > | {
hour . len ( ) > = 1 & & hour . len ( ) < = 2
} ) ( input ) ? ;
2023-07-27 19:45:57 -04:00
let ( remaining , _ ) = tag ( " : " ) ( remaining ) ? ;
2023-08-23 00:30:26 -04:00
let ( remaining , _minute ) =
verify ( digit1 , | minute : & OrgSource < '_ > | minute . len ( ) = = 2 ) ( remaining ) ? ;
2023-07-27 19:52:35 -04:00
let ( remaining , _time_rest ) = opt ( parser_with_context! ( time_rest ) ( context ) ) ( remaining ) ? ;
2023-07-27 19:45:57 -04:00
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
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 time_rest < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:45:57 -04:00
let ( remaining , body ) = recognize ( verify (
2023-07-27 19:52:35 -04:00
many_till ( anychar , parser_with_context! ( exit_matcher_parser ) ( context ) ) ,
2023-07-27 19:45:57 -04:00
| ( body , _end_contents ) | ! body . is_empty ( ) ,
) ) ( input ) ? ;
Ok ( ( remaining , body ) )
}
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 active_time_rest_end < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:45:57 -04:00
alt ( (
recognize ( verify ( anychar , | c | " > \n " . contains ( * c ) ) ) ,
2023-07-27 20:39:13 -04:00
recognize ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ,
recognize ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ,
2023-07-27 19:45:57 -04:00
) ) ( input )
}
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 inactive_time_rest_end < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:54:33 -04:00
alt ( (
recognize ( verify ( anychar , | c | " ] \n " . contains ( * c ) ) ) ,
2023-07-27 20:39:13 -04:00
recognize ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ,
recognize ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ,
2023-07-27 19:54:33 -04:00
) ) ( input )
}
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 time_range_rest_end < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 20:26:56 -04:00
// We pop off the most recent context element to get a context tree with just the active/inactive_time_rest_end exit matcher (removing this function from the exit matcher chain) because the 2nd time in the range does not end when a "-TIME" pattern is found.
2023-09-02 20:46:17 -04:00
let parent_node = context . get_parent ( ) . expect ( " Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None. " ) ;
2023-07-27 20:26:56 -04:00
let exit_contents =
2023-09-02 20:46:17 -04:00
recognize ( tuple ( ( tag ( " - " ) , parser_with_context! ( time ) ( & parent_node ) ) ) ) ( input ) ;
2023-07-27 20:26:56 -04:00
exit_contents
}
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 repeater < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:45:57 -04:00
// + for cumulative type
// ++ for catch-up type
// .+ for restart type
let ( remaining , _mark ) = alt ( ( tag ( " ++ " ) , tag ( " + " ) , tag ( " .+ " ) ) ) ( input ) ? ;
2023-09-15 13:12:54 -04:00
let ( remaining , _value ) = digit0 ( remaining ) ? ;
2023-07-27 19:45:57 -04:00
// h = hour, d = day, w = week, m = month, y = year
let ( remaining , _unit ) = recognize ( one_of ( " hdwmy " ) ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}
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 warning_delay < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-07-27 19:45:57 -04:00
// - for all type
// -- for first type
let ( remaining , _mark ) = alt ( ( tag ( " -- " ) , tag ( " - " ) ) ) ( input ) ? ;
2023-09-15 13:12:54 -04:00
let ( remaining , _value ) = digit0 ( remaining ) ? ;
2023-07-27 19:45:57 -04:00
// h = hour, d = day, w = week, m = month, y = year
let ( remaining , _unit ) = recognize ( one_of ( " hdwmy " ) ) ( remaining ) ? ;
let source = get_consumed ( input , remaining ) ;
Ok ( ( remaining , source ) )
}