diff --git a/src/parser/timestamp.rs b/src/parser/timestamp.rs index 821933d..33d0122 100644 --- a/src/parser/timestamp.rs +++ b/src/parser/timestamp.rs @@ -82,8 +82,20 @@ fn active_timestamp<'r, 's>( ) -> Res<&'s str, Timestamp<'s>> { let (remaining, _) = tag("<")(input)?; let (remaining, _date) = date(context, remaining)?; - not_yet_implemented()?; - todo!() + let (remaining, _time) = + opt(tuple((space1, parser_with_context!(active_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)?; + + let (remaining, _) = space0(remaining)?; + let source = get_consumed(input, remaining); + + Ok((remaining, Timestamp { source })) } #[tracing::instrument(ret, level = "debug")] @@ -170,3 +182,67 @@ fn dayname_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, c.is_whitespace() || "+-]>0123456789\n".contains(*c) }))(input) } + +#[tracing::instrument(ret, level = "debug")] +fn active_time<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + let (remaining, _hour) = + verify(digit1, |hour: &str| hour.len() >= 1 && hour.len() <= 2)(input)?; + let (remaining, _) = tag(":")(remaining)?; + let (remaining, _minute) = verify(digit1, |minute: &str| minute.len() == 2)(remaining)?; + let (remaining, _time_rest) = opt(parser_with_context!(active_time_rest)(context))(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, source)) +} + +#[tracing::instrument(ret, level = "debug")] +fn active_time_rest<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + let parser_context = + context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &active_time_rest_end, + })); + + 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)) +} + +#[tracing::instrument(ret, level = "debug")] +fn active_time_rest_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + alt(( + recognize(verify(anychar, |c| ">\n".contains(*c))), + parser_with_context!(repeater)(context), + parser_with_context!(warning_delay)(context), + ))(input) +} + +#[tracing::instrument(ret, level = "debug")] +fn repeater<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + // + for cumulative type + // ++ for catch-up type + // .+ for restart type + let (remaining, _mark) = alt((tag("++"), tag("+"), tag(".+")))(input)?; + let (remaining, _value) = digit1(remaining)?; + // 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)) +} + +#[tracing::instrument(ret, level = "debug")] +fn warning_delay<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + // - for all type + // -- for first type + let (remaining, _mark) = alt((tag("--"), tag("-")))(input)?; + let (remaining, _value) = digit1(remaining)?; + // 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)) +}