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-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 ;
2023-10-02 18:58:30 -04:00
use nom ::combinator ::map ;
2023-07-27 19:20:28 -04:00
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-10-02 15:49:51 -04:00
use crate ::types ::Date ;
use crate ::types ::DayOfMonth ;
2023-10-02 16:37:23 -04:00
use crate ::types ::Hour ;
use crate ::types ::Minute ;
2023-10-02 15:49:51 -04:00
use crate ::types ::Month ;
2023-10-02 18:58:30 -04:00
use crate ::types ::Repeater ;
use crate ::types ::RepeaterType ;
2023-10-02 16:37:23 -04:00
use crate ::types ::Time ;
2023-10-02 18:58:30 -04:00
use crate ::types ::TimeUnit ;
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-10-02 18:58:30 -04:00
use crate ::types ::WarningDelay ;
use crate ::types ::WarningDelayType ;
2023-10-02 15:49:51 -04:00
use crate ::types ::Year ;
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-10-02 15:49:51 -04:00
start : None ,
end : None ,
2023-10-02 18:58:30 -04:00
start_time : None ,
end_time : None ,
repeater : None ,
warning_delay : 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 ) ? ;
2023-10-02 15:49:51 -04:00
let ( remaining , start ) = 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-10-02 17:47:09 -04:00
let ( remaining , time ) = opt ( tuple ( (
space1 ,
parser_with_context! ( time ( true ) ) ( & time_context ) ,
) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , repeater ) =
2023-07-27 19:45:57 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , warning_delay ) = opt ( tuple ( (
2023-07-27 19:45:57 -04:00
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-10-02 15:59:06 -04:00
start : Some ( start . clone ( ) ) ,
end : Some ( start ) ,
2023-10-02 16:37:23 -04:00
start_time : time . as_ref ( ) . map ( | ( _ , time ) | time . clone ( ) ) ,
end_time : time . map ( | ( _ , time ) | time ) ,
2023-10-02 18:58:30 -04:00
repeater : repeater . map ( | ( _ , repeater ) | repeater ) ,
warning_delay : warning_delay . map ( | ( _ , warning_delay ) | warning_delay ) ,
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 ) ? ;
2023-10-02 15:49:51 -04:00
let ( remaining , start ) = 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-10-02 17:47:09 -04:00
let ( remaining , time ) = opt ( tuple ( (
space1 ,
parser_with_context! ( time ( true ) ) ( & time_context ) ,
) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , repeater ) =
2023-07-27 19:54:33 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , warning_delay ) = opt ( tuple ( (
2023-07-27 19:54:33 -04:00
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-10-02 15:59:06 -04:00
start : Some ( start . clone ( ) ) ,
end : Some ( start ) ,
2023-10-02 16:37:23 -04:00
start_time : time . as_ref ( ) . map ( | ( _ , time ) | time . clone ( ) ) ,
end_time : time . map ( | ( _ , time ) | time ) ,
2023-10-02 18:58:30 -04:00
repeater : repeater . map ( | ( _ , repeater ) | repeater ) ,
warning_delay : warning_delay . map ( | ( _ , warning_delay ) | warning_delay ) ,
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-10-02 15:59:06 -04:00
let ( remaining , first_timestamp ) = active_timestamp ( context , input ) ? ;
2023-07-27 19:59:36 -04:00
// 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 ) ? ;
2023-10-02 15:59:06 -04:00
let ( remaining , second_timestamp ) = active_timestamp ( context , remaining ) ? ;
2023-07-27 19:59:36 -04:00
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-10-02 15:59:06 -04:00
start : first_timestamp . start ,
end : second_timestamp . end ,
2023-10-02 16:37:23 -04:00
start_time : first_timestamp . start_time ,
end_time : second_timestamp . end_time ,
2023-10-02 18:58:30 -04:00
repeater : first_timestamp . repeater . or ( second_timestamp . repeater ) ,
warning_delay : first_timestamp
. warning_delay
. or ( second_timestamp . warning_delay ) ,
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 ) ? ;
2023-10-02 15:59:06 -04:00
let ( remaining , start_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-10-02 17:47:09 -04:00
let ( remaining , ( _ , first_time ) ) = tuple ( (
space1 ,
parser_with_context! ( time ( false ) ) ( & first_time_context ) ,
) ) ( remaining ) ? ;
2023-07-27 20:26:56 -04:00
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
2023-10-02 17:47:09 -04:00
let ( remaining , second_time ) = parser_with_context! ( time ( true ) ) ( & time_context ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , repeater ) =
2023-07-27 20:26:56 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , warning_delay ) = opt ( tuple ( (
2023-07-27 20:26:56 -04:00
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 17:47:09 -04:00
timestamp_type : TimestampType ::ActiveRange ,
range_type : TimestampRangeType ::TimeRange ,
2023-10-02 15:59:06 -04:00
start : Some ( start_date . clone ( ) ) ,
end : Some ( start_date ) ,
2023-10-02 16:37:23 -04:00
start_time : Some ( first_time ) ,
end_time : Some ( second_time ) ,
2023-10-02 18:58:30 -04:00
repeater : repeater . map ( | ( _ , repeater ) | repeater ) ,
warning_delay : warning_delay . map ( | ( _ , warning_delay ) | warning_delay ) ,
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-10-02 15:59:06 -04:00
let ( remaining , first_timestamp ) = inactive_timestamp ( context , input ) ? ;
2023-07-27 19:59:36 -04:00
// 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 ) ? ;
2023-10-02 15:59:06 -04:00
let ( remaining , second_timestamp ) = inactive_timestamp ( context , remaining ) ? ;
2023-07-27 19:59:36 -04:00
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-10-02 15:59:06 -04:00
start : first_timestamp . start ,
end : second_timestamp . end ,
2023-10-02 16:37:23 -04:00
start_time : first_timestamp . start_time ,
end_time : second_timestamp . end_time ,
2023-10-02 18:58:30 -04:00
repeater : first_timestamp . repeater . or ( second_timestamp . repeater ) ,
warning_delay : first_timestamp
. warning_delay
. or ( second_timestamp . warning_delay ) ,
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 ) ? ;
2023-10-02 15:59:06 -04:00
let ( remaining , start_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-10-02 17:47:09 -04:00
let ( remaining , ( _ , first_time ) ) = tuple ( (
space1 ,
parser_with_context! ( time ( false ) ) ( & first_time_context ) ,
) ) ( remaining ) ? ;
2023-07-27 20:26:56 -04:00
let ( remaining , _ ) = tag ( " - " ) ( remaining ) ? ;
2023-10-02 17:47:09 -04:00
let ( remaining , second_time ) = parser_with_context! ( time ( true ) ) ( & time_context ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , repeater ) =
2023-07-27 20:26:56 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ( remaining ) ? ;
2023-10-02 18:58:30 -04:00
let ( remaining , warning_delay ) = opt ( tuple ( (
2023-07-27 20:26:56 -04:00
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 17:47:09 -04:00
timestamp_type : TimestampType ::InactiveRange ,
range_type : TimestampRangeType ::TimeRange ,
2023-10-02 15:59:06 -04:00
start : Some ( start_date . clone ( ) ) ,
end : Some ( start_date ) ,
2023-10-02 16:37:23 -04:00
start_time : Some ( first_time ) ,
end_time : Some ( second_time ) ,
2023-10-02 18:58:30 -04:00
repeater : repeater . map ( | ( _ , repeater ) | repeater ) ,
warning_delay : warning_delay . map ( | ( _ , warning_delay ) | warning_delay ) ,
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-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 > ,
2023-10-02 15:49:51 -04:00
) -> Res < OrgSource < ' s > , Date < ' 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-10-02 15:49:51 -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-10-02 15:49:51 -04:00
let ( remaining , day_of_month ) = verify ( digit1 , | day_of_month : & OrgSource < '_ > | {
2023-08-23 00:30:26 -04:00
day_of_month . len ( ) = = 2
} ) ( remaining ) ? ;
2023-10-02 15:49:51 -04:00
let ( remaining , day_name ) =
2023-07-27 19:20:28 -04:00
opt ( tuple ( ( space1 , parser_with_context! ( dayname ) ( context ) ) ) ) ( remaining ) ? ;
2023-10-02 15:49:51 -04:00
let year = Year ::new ( Into ::< & str > ::into ( year ) )
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
let month = Month ::new ( Into ::< & str > ::into ( month ) )
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
let day_of_month = DayOfMonth ::new ( Into ::< & str > ::into ( day_of_month ) )
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
let date = Date ::new (
year ,
month ,
day_of_month ,
day_name . map ( | ( _ , day_name ) | Into ::< & str > ::into ( day_name ) ) ,
)
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
Ok ( ( remaining , date ) )
2023-07-27 19:20:28 -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 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-10-02 17:47:09 -04:00
const fn time < ' c > (
allow_rest : bool ,
) -> impl for < ' b , ' g , ' r , ' s > Fn ( RefContext < ' b , ' g , ' r , ' s > , OrgSource < ' s > ) -> Res < OrgSource < ' s > , Time < ' s > >
{
move | context , input | _time ( context , input , allow_rest )
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-10-02 17:47:09 -04:00
fn _time < ' 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 > ,
2023-10-02 17:47:09 -04:00
allow_rest : bool ,
2023-10-02 16:37:23 -04:00
) -> Res < OrgSource < ' s > , Time < ' s > > {
let ( remaining , hour ) = verify ( digit1 , | hour : & OrgSource < '_ > | {
2023-08-23 00:30:26 -04:00
hour . len ( ) > = 1 & & hour . len ( ) < = 2
} ) ( input ) ? ;
2023-07-27 19:45:57 -04:00
let ( remaining , _ ) = tag ( " : " ) ( remaining ) ? ;
2023-10-02 16:37:23 -04:00
let ( remaining , minute ) =
2023-08-23 00:30:26 -04:00
verify ( digit1 , | minute : & OrgSource < '_ > | minute . len ( ) = = 2 ) ( remaining ) ? ;
2023-10-02 17:47:09 -04:00
let ( remaining , time_rest ) = if allow_rest {
opt ( parser_with_context! ( time_rest ) ( context ) ) ( remaining ) ?
} else {
( remaining , None )
} ;
2023-10-02 16:37:23 -04:00
let hour = Hour ::new ( Into ::< & str > ::into ( hour ) )
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
let minute = Minute ::new ( Into ::< & str > ::into ( minute ) )
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
2023-10-02 17:47:09 -04:00
let time = Time ::new ( hour , minute , time_rest . map ( Into ::< & str > ::into ) )
2023-10-02 16:37:23 -04:00
. expect ( " TODO: I should be able to return CustomError from nom parsers. " ) ;
Ok ( ( remaining , time ) )
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_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 > (
2023-10-02 19:09:20 -04:00
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-10-02 19:09:20 -04:00
alt ( (
recognize ( verify ( anychar , | c | " > \n " . contains ( * c ) ) ) ,
recognize ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ,
recognize ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ,
) ) ( 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 inactive_time_rest_end < ' b , ' g , ' r , ' s > (
2023-10-02 19:09:20 -04:00
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
2023-10-02 19:09:20 -04:00
alt ( (
recognize ( verify ( anychar , | c | " ] \n " . contains ( * c ) ) ) ,
recognize ( tuple ( ( space1 , parser_with_context! ( repeater ) ( context ) ) ) ) ,
recognize ( tuple ( (
space1 ,
parser_with_context! ( warning_delay ) ( context ) ,
) ) ) ,
) ) ( input )
2023-07-27 19:54:33 -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_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-10-02 17:47:09 -04:00
let exit_contents = recognize ( tuple ( (
tag ( " - " ) ,
parser_with_context! ( time ( true ) ) ( & 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 > ,
2023-10-02 18:58:30 -04:00
) -> Res < OrgSource < ' s > , Repeater > {
2023-07-27 19:45:57 -04:00
// + for cumulative type
// ++ for catch-up type
// .+ for restart type
2023-10-02 18:58:30 -04:00
let ( remaining , repeater_type ) = alt ( (
map ( tag ( " ++ " ) , | _ | RepeaterType ::Cumulative ) ,
map ( tag ( " + " ) , | _ | RepeaterType ::CatchUp ) ,
map ( tag ( " .+ " ) , | _ | RepeaterType ::Restart ) ,
) ) ( input ) ? ;
let ( remaining , value ) = digit1 ( remaining ) ? ;
let value = Into ::< & str > ::into ( value )
. parse ( )
. expect ( " digit1 ensures this will parse as a number. " ) ;
2023-07-27 19:45:57 -04:00
// h = hour, d = day, w = week, m = month, y = year
2023-10-02 18:58:30 -04:00
let ( remaining , unit ) = alt ( (
map ( tag ( " h " ) , | _ | TimeUnit ::Hour ) ,
map ( tag ( " d " ) , | _ | TimeUnit ::Day ) ,
map ( tag ( " w " ) , | _ | TimeUnit ::Week ) ,
map ( tag ( " m " ) , | _ | TimeUnit ::Month ) ,
map ( tag ( " y " ) , | _ | TimeUnit ::Year ) ,
) ) ( remaining ) ? ;
Ok ( (
remaining ,
Repeater {
repeater_type ,
value ,
unit ,
} ,
) )
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 warning_delay < ' b , ' g , ' r , ' s > (
_context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
2023-10-02 18:58:30 -04:00
) -> Res < OrgSource < ' s > , WarningDelay > {
2023-07-27 19:45:57 -04:00
// - for all type
// -- for first type
2023-10-02 18:58:30 -04:00
let ( remaining , warning_delay_type ) = alt ( (
map ( tag ( " -- " ) , | _ | WarningDelayType ::First ) ,
map ( tag ( " - " ) , | _ | WarningDelayType ::All ) ,
) ) ( input ) ? ;
let ( remaining , value ) = digit1 ( remaining ) ? ;
let value = Into ::< & str > ::into ( value )
. parse ( )
. expect ( " digit1 ensures this will parse as a number. " ) ;
2023-07-27 19:45:57 -04:00
// h = hour, d = day, w = week, m = month, y = year
2023-10-02 18:58:30 -04:00
let ( remaining , unit ) = alt ( (
map ( tag ( " h " ) , | _ | TimeUnit ::Hour ) ,
map ( tag ( " d " ) , | _ | TimeUnit ::Day ) ,
map ( tag ( " w " ) , | _ | TimeUnit ::Week ) ,
map ( tag ( " m " ) , | _ | TimeUnit ::Month ) ,
map ( tag ( " y " ) , | _ | TimeUnit ::Year ) ,
) ) ( remaining ) ? ;
Ok ( (
remaining ,
WarningDelay {
warning_delay_type ,
value ,
unit ,
} ,
) )
2023-07-27 19:45:57 -04:00
}