Do not allow time range timestamps with REST on the first TIME.

This commit is contained in:
Tom Alexander 2023-10-02 17:47:09 -04:00
parent 890cd3e4fd
commit 512432c5f0
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 50 additions and 22 deletions

View File

@ -2,13 +2,17 @@
<%%(foo bar baz)> <%%(foo bar baz)>
# active # active
<1970-01-01 Thu 8:15rest +1w -1d> <1970-01-01 Thu 8:15rest +1w -1d>
# Any value for "REST" in the first timestamp makes this a regular timestamp rather than a time range.
<1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d>
# inactive # inactive
[1970-01-01 Thu 8:15rest +1w -1d] [1970-01-01 Thu 8:15rest +1w -1d]
# Any value for "REST" in the first timestamp makes this a regular timestamp rather than a time range.
[1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d]
# active date range # active date range
<1970-01-01 Thu 8:15rest +1w -1d>--<1970-01-01 Thu 8:15rest +1w -1d> <1970-01-01 Thu 8:15rest +1w -1d>--<1970-01-01 Thu 8:15rest +1w -1d>
# active time range # active time range
<1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d> <1970-01-01 Thu 8:15-13:15otherrest +1w -1d>
# inactive date range # inactive date range
[1970-01-01 Thu 8:15rest +1w -1d]--[1970-01-01 Thu 8:15rest +1w -1d] [1970-01-01 Thu 8:15rest +1w -1d]--[1970-01-01 Thu 8:15rest +1w -1d]
# inactive time range # inactive time range
[1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d] [1970-01-01 Thu 8:15-13:15otherrest +1w -1d]

View File

@ -2155,6 +2155,7 @@ fn compare_timestamp<'b, 's>(
let range_type = get_property_unquoted_atom(emacs, ":range-type")?; let range_type = get_property_unquoted_atom(emacs, ":range-type")?;
match (range_type, &rust.range_type) { match (range_type, &rust.range_type) {
(Some("daterange"), TimestampRangeType::DateRange) => {} (Some("daterange"), TimestampRangeType::DateRange) => {}
(Some("timerange"), TimestampRangeType::TimeRange) => {}
(None, TimestampRangeType::None) => {} (None, TimestampRangeType::None) => {}
_ => { _ => {
this_status = DiffStatus::Bad; this_status = DiffStatus::Bad;
@ -2303,7 +2304,7 @@ fn compare_timestamp<'b, 's>(
)); ));
} }
// TODO: Compare :hour-start :minute-start :hour-end :minute-end :repeater-type :repeater-value :repeater-unit :warning-type :warning-value :warning-unit // TODO: Compare :repeater-type :repeater-value :repeater-unit :warning-type :warning-value :warning-unit
// //
// :type unquoted atom either diary, active, inactive, active-range, or inactive-range. // :type unquoted atom either diary, active, inactive, active-range, or inactive-range.
// :range-type unquoted atom either nil, daterange // :range-type unquoted atom either nil, daterange

View File

@ -118,8 +118,10 @@ fn active_timestamp<'b, 'g, 'r, 's>(
exit_matcher: &active_time_rest_end, exit_matcher: &active_time_rest_end,
}); });
let time_context = context.with_additional_node(&time_context); let time_context = context.with_additional_node(&time_context);
let (remaining, time) = let (remaining, time) = opt(tuple((
opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?; space1,
parser_with_context!(time(true))(&time_context),
)))(remaining)?;
let (remaining, _repeater) = let (remaining, _repeater) =
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?; opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
let (remaining, _warning_delay) = opt(tuple(( let (remaining, _warning_delay) = opt(tuple((
@ -158,8 +160,10 @@ fn inactive_timestamp<'b, 'g, 'r, 's>(
exit_matcher: &inactive_time_rest_end, exit_matcher: &inactive_time_rest_end,
}); });
let time_context = context.with_additional_node(&time_context); let time_context = context.with_additional_node(&time_context);
let (remaining, time) = let (remaining, time) = opt(tuple((
opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?; space1,
parser_with_context!(time(true))(&time_context),
)))(remaining)?;
let (remaining, _repeater) = let (remaining, _repeater) =
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?; opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
let (remaining, _warning_delay) = opt(tuple(( let (remaining, _warning_delay) = opt(tuple((
@ -231,10 +235,12 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
exit_matcher: &time_range_rest_end, exit_matcher: &time_range_rest_end,
}); });
let first_time_context = time_context.with_additional_node(&first_time_context); let first_time_context = time_context.with_additional_node(&first_time_context);
let (remaining, (_, first_time)) = let (remaining, (_, first_time)) = tuple((
tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?; space1,
parser_with_context!(time(false))(&first_time_context),
))(remaining)?;
let (remaining, _) = tag("-")(remaining)?; let (remaining, _) = tag("-")(remaining)?;
let (remaining, second_time) = parser_with_context!(time)(&time_context)(remaining)?; let (remaining, second_time) = parser_with_context!(time(true))(&time_context)(remaining)?;
let (remaining, _repeater) = let (remaining, _repeater) =
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?; opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
let (remaining, _warning_delay) = opt(tuple(( let (remaining, _warning_delay) = opt(tuple((
@ -251,8 +257,8 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
remaining, remaining,
Timestamp { Timestamp {
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Active, timestamp_type: TimestampType::ActiveRange,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::TimeRange,
start: Some(start_date.clone()), start: Some(start_date.clone()),
end: Some(start_date), end: Some(start_date),
start_time: Some(first_time), start_time: Some(first_time),
@ -307,10 +313,12 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
exit_matcher: &time_range_rest_end, exit_matcher: &time_range_rest_end,
}); });
let first_time_context = time_context.with_additional_node(&first_time_context); let first_time_context = time_context.with_additional_node(&first_time_context);
let (remaining, (_, first_time)) = let (remaining, (_, first_time)) = tuple((
tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?; space1,
parser_with_context!(time(false))(&first_time_context),
))(remaining)?;
let (remaining, _) = tag("-")(remaining)?; let (remaining, _) = tag("-")(remaining)?;
let (remaining, second_time) = parser_with_context!(time)(&time_context)(remaining)?; let (remaining, second_time) = parser_with_context!(time(true))(&time_context)(remaining)?;
let (remaining, _repeater) = let (remaining, _repeater) =
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?; opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
let (remaining, _warning_delay) = opt(tuple(( let (remaining, _warning_delay) = opt(tuple((
@ -327,8 +335,8 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
remaining, remaining,
Timestamp { Timestamp {
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Inactive, timestamp_type: TimestampType::InactiveRange,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::TimeRange,
start: Some(start_date.clone()), start: Some(start_date.clone()),
end: Some(start_date), end: Some(start_date),
start_time: Some(first_time), start_time: Some(first_time),
@ -402,10 +410,18 @@ fn dayname_end<'b, 'g, 'r, 's>(
}))(input) }))(input)
} }
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)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn time<'b, 'g, 'r, 's>( fn _time<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
allow_rest: bool,
) -> Res<OrgSource<'s>, Time<'s>> { ) -> Res<OrgSource<'s>, Time<'s>> {
let (remaining, hour) = verify(digit1, |hour: &OrgSource<'_>| { let (remaining, hour) = verify(digit1, |hour: &OrgSource<'_>| {
hour.len() >= 1 && hour.len() <= 2 hour.len() >= 1 && hour.len() <= 2
@ -413,13 +429,17 @@ fn time<'b, 'g, 'r, 's>(
let (remaining, _) = tag(":")(remaining)?; let (remaining, _) = tag(":")(remaining)?;
let (remaining, minute) = let (remaining, minute) =
verify(digit1, |minute: &OrgSource<'_>| minute.len() == 2)(remaining)?; verify(digit1, |minute: &OrgSource<'_>| minute.len() == 2)(remaining)?;
let (remaining, _time_rest) = opt(parser_with_context!(time_rest)(context))(remaining)?; let (remaining, time_rest) = if allow_rest {
opt(parser_with_context!(time_rest)(context))(remaining)?
} else {
(remaining, None)
};
let hour = Hour::new(Into::<&str>::into(hour)) let hour = Hour::new(Into::<&str>::into(hour))
.expect("TODO: I should be able to return CustomError from nom parsers."); .expect("TODO: I should be able to return CustomError from nom parsers.");
let minute = Minute::new(Into::<&str>::into(minute)) let minute = Minute::new(Into::<&str>::into(minute))
.expect("TODO: I should be able to return CustomError from nom parsers."); .expect("TODO: I should be able to return CustomError from nom parsers.");
let time = Time::new(hour, minute, _time_rest.map(Into::<&str>::into)) let time = Time::new(hour, minute, time_rest.map(Into::<&str>::into))
.expect("TODO: I should be able to return CustomError from nom parsers."); .expect("TODO: I should be able to return CustomError from nom parsers.");
Ok((remaining, time)) Ok((remaining, time))
@ -475,8 +495,10 @@ fn time_range_rest_end<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
// 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. // 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.
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."); 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.");
let exit_contents = let exit_contents = recognize(tuple((
recognize(tuple((tag("-"), parser_with_context!(time)(&parent_node))))(input); tag("-"),
parser_with_context!(time(true))(&parent_node),
)))(input);
exit_contents exit_contents
} }

View File

@ -206,6 +206,7 @@ pub enum TimestampType {
pub enum TimestampRangeType { pub enum TimestampRangeType {
None, None,
DateRange, DateRange,
TimeRange,
} }
pub type YearInner = u16; pub type YearInner = u16;