2023-04-21 19:14:41 -04:00
use nom ::branch ::alt ;
2023-04-21 19:21:42 -04:00
use nom ::bytes ::complete ::tag ;
2023-04-21 19:14:41 -04:00
use nom ::bytes ::complete ::tag_no_case ;
2023-04-21 19:21:42 -04:00
use nom ::character ::complete ::digit1 ;
2023-04-21 19:14:41 -04:00
use nom ::character ::complete ::space0 ;
use nom ::character ::complete ::space1 ;
2023-10-05 03:19:17 -04:00
use nom ::combinator ::map ;
use nom ::combinator ::opt ;
2023-04-21 19:21:42 -04:00
use nom ::combinator ::recognize ;
use nom ::sequence ::tuple ;
2023-04-21 19:14:41 -04:00
2023-08-23 00:30:26 -04:00
use super ::org_source ::OrgSource ;
2023-10-05 03:19:17 -04:00
use super ::timestamp ::inactive_date_range_timestamp ;
use super ::timestamp ::inactive_time_range_timestamp ;
use super ::timestamp ::inactive_timestamp ;
2023-10-06 11:45:15 -04:00
use super ::util ::maybe_consume_trailing_whitespace_if_not_exiting ;
2023-10-05 03:19:17 -04:00
use super ::util ::org_line_ending ;
2023-09-03 12:23:18 -04:00
use crate ::context ::parser_with_context ;
use crate ::context ::RefContext ;
2023-04-21 19:02:16 -04:00
use crate ::error ::Res ;
2023-04-21 19:14:41 -04:00
use crate ::parser ::util ::get_consumed ;
use crate ::parser ::util ::start_of_line ;
2023-09-03 12:23:18 -04:00
use crate ::types ::Clock ;
2023-10-05 03:19:17 -04:00
use crate ::types ::ClockStatus ;
use crate ::types ::Timestamp ;
2023-04-21 19:02:16 -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 clock < ' 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 > , Clock < ' s > > {
2023-08-24 19:29:00 -04:00
start_of_line ( input ) ? ;
2023-04-21 19:14:41 -04:00
let ( remaining , _leading_whitespace ) = space0 ( input ) ? ;
let ( remaining , _clock ) = tag_no_case ( " clock: " ) ( remaining ) ? ;
let ( remaining , _gap_whitespace ) = space1 ( remaining ) ? ;
2023-10-05 03:19:17 -04:00
let ( remaining , ( timestamp , duration ) ) = clock_timestamp ( context , remaining ) ? ;
let ( remaining , _ ) = tuple ( ( space0 , org_line_ending ) ) ( remaining ) ? ;
2023-04-21 19:14:41 -04:00
2023-10-06 11:45:15 -04:00
let ( remaining , _trailing_ws ) =
maybe_consume_trailing_whitespace_if_not_exiting ( context , remaining ) ? ;
2023-04-21 19:14:41 -04:00
let source = get_consumed ( input , remaining ) ;
2023-08-23 00:30:26 -04:00
Ok ( (
remaining ,
Clock {
source : source . into ( ) ,
2023-10-05 03:19:17 -04:00
timestamp ,
duration ,
status : if duration . is_some ( ) {
ClockStatus ::Closed
} else {
ClockStatus ::Running
} ,
2023-08-23 00:30:26 -04:00
} ,
) )
2023-04-21 19:14:41 -04:00
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-10-05 03:19:17 -04:00
fn clock_timestamp < ' b , ' g , ' r , ' s > (
context : RefContext < ' b , ' g , ' r , ' s > ,
2023-08-23 00:30:26 -04:00
input : OrgSource < ' s > ,
2023-10-05 03:19:17 -04:00
) -> Res < OrgSource < ' s > , ( Timestamp < ' s > , Option < & ' s str > ) > {
// 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.
map (
parser_with_context! ( inactive_time_range_timestamp ) ( context ) ,
| timestamp | ( timestamp , None ) ,
) ,
map (
tuple ( (
parser_with_context! ( inactive_date_range_timestamp ) ( context ) ,
opt ( duration ) ,
) ) ,
| ( timestamp , duration ) | ( timestamp , duration . map ( Into ::< & str > ::into ) ) ,
) ,
map (
parser_with_context! ( inactive_timestamp ) ( context ) ,
| timestamp | ( timestamp , None ) ,
) ,
) ) ( input )
2023-04-21 19:14:41 -04:00
}
2023-08-10 20:04:59 -04:00
#[ cfg_attr(feature = " tracing " , tracing::instrument(ret, level = " debug " )) ]
2023-10-05 03:19:17 -04:00
fn duration < ' s > ( input : OrgSource < ' s > ) -> Res < OrgSource < ' s > , OrgSource < ' s > > {
let ( remaining , _ ) = tuple ( ( tag ( " => " ) , space1 ) ) ( input ) ? ;
let ( remaining , duration ) = recognize ( tuple ( ( digit1 , tag ( " : " ) , digit1 ) ) ) ( remaining ) ? ;
Ok ( ( remaining , duration ) )
2023-04-21 19:02:16 -04:00
}