From 2e1a946ac96aaf3960ed1bbf8023df7055498d90 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 2 Oct 2023 20:25:08 -0400 Subject: [PATCH] Compare scheduled, deadline, and closed. --- src/compare/diff.rs | 58 ++++++++++++++++++++++++++++++++++--- src/parser/planning.rs | 48 ++++++++++++++++++++++++------ src/types/lesser_element.rs | 4 +++ 3 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 7138fa1..0692574 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -1406,16 +1406,66 @@ fn compare_planning<'b, 's>( emacs: &'b Token<'s>, rust: &'b Planning<'s>, ) -> Result, Box> { - let this_status = DiffStatus::Good; - let message = None; + let mut child_status = Vec::new(); + let mut this_status = DiffStatus::Good; + let mut message = None; - // TODO: Compare :closed :deadline :scheduled + // Compare scheduled + let scheduled = get_property(emacs, ":scheduled")?; + match (scheduled, &rust.scheduled) { + (None, None) => {} + (None, Some(_)) | (Some(_), None) => { + this_status = DiffStatus::Bad; + message = Some(format!( + "Scheduled mismatch (emacs != rust) {:?} != {:?}", + scheduled, rust.scheduled + )); + } + (Some(emacs_child), Some(rust_child)) => { + let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + child_status.push(artificial_diff_scope("scheduled", vec![result])?); + } + } + + // Compare deadline + let deadline = get_property(emacs, ":deadline")?; + match (deadline, &rust.deadline) { + (None, None) => {} + (None, Some(_)) | (Some(_), None) => { + this_status = DiffStatus::Bad; + message = Some(format!( + "Deadline mismatch (emacs != rust) {:?} != {:?}", + deadline, rust.deadline + )); + } + (Some(emacs_child), Some(rust_child)) => { + let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + child_status.push(artificial_diff_scope("deadline", vec![result])?); + } + } + + // Compare closed + let closed = get_property(emacs, ":closed")?; + match (closed, &rust.closed) { + (None, None) => {} + (None, Some(_)) | (Some(_), None) => { + this_status = DiffStatus::Bad; + message = Some(format!( + "Closed mismatch (emacs != rust) {:?} != {:?}", + closed, rust.closed + )); + } + (Some(emacs_child), Some(rust_child)) => { + let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + child_status.push(artificial_diff_scope("closed", vec![result])?); + } + } Ok(DiffResult { status: this_status, name: rust.get_elisp_name(), message, - children: Vec::new(), + children: child_status, rust_source: rust.get_source(), emacs_token: emacs, } diff --git a/src/parser/planning.rs b/src/parser/planning.rs index b50a9ea..d7fe70e 100644 --- a/src/parser/planning.rs +++ b/src/parser/planning.rs @@ -3,6 +3,7 @@ use nom::bytes::complete::tag; use nom::bytes::complete::tag_no_case; use nom::character::complete::space0; use nom::character::complete::space1; +use nom::combinator::map; use nom::multi::many1; use nom::sequence::tuple; @@ -16,6 +17,7 @@ use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::start_of_line; use crate::types::Planning; +use crate::types::Timestamp; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub(crate) fn planning<'b, 'g, 'r, 's>( @@ -24,7 +26,7 @@ pub(crate) fn planning<'b, 'g, 'r, 's>( ) -> Res, Planning<'s>> { start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; - let (remaining, _planning_parameters) = + let (remaining, planning_parameters) = many1(parser_with_context!(planning_parameter)(context))(remaining)?; let (remaining, _trailing_ws) = tuple((space0, org_line_ending))(remaining)?; @@ -32,26 +34,54 @@ pub(crate) fn planning<'b, 'g, 'r, 's>( maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); + let mut scheduled = None; + let mut deadline = None; + let mut closed = None; + + for (timestamp_type, timestamp) in planning_parameters.into_iter() { + match timestamp_type { + PlanningTimestampType::Scheduled => { + scheduled = Some(timestamp); + } + PlanningTimestampType::Deadline => { + deadline = Some(timestamp); + } + PlanningTimestampType::Closed => { + closed = Some(timestamp); + } + } + } + Ok(( remaining, Planning { source: source.into(), + scheduled, + deadline, + closed, }, )) } +enum PlanningTimestampType { + Scheduled, + Deadline, + Closed, +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn planning_parameter<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, -) -> Res, OrgSource<'s>> { - let (remaining, _planning_type) = alt(( - tag_no_case("DEADLINE"), - tag_no_case("SCHEDULED"), - tag_no_case("CLOSED"), +) -> Res, (PlanningTimestampType, Timestamp<'s>)> { + let (remaining, planning_type) = alt(( + map(tag_no_case("DEADLINE"), |_| PlanningTimestampType::Deadline), + map(tag_no_case("SCHEDULED"), |_| { + PlanningTimestampType::Scheduled + }), + map(tag_no_case("CLOSED"), |_| PlanningTimestampType::Closed), ))(input)?; let (remaining, _gap) = tuple((tag(":"), space1))(remaining)?; - let (remaining, _timestamp) = timestamp(context, remaining)?; - let source = get_consumed(input, remaining); - Ok((remaining, source)) + let (remaining, timestamp) = timestamp(context, remaining)?; + Ok((remaining, (planning_type, timestamp))) } diff --git a/src/types/lesser_element.rs b/src/types/lesser_element.rs index 1061139..e0e9762 100644 --- a/src/types/lesser_element.rs +++ b/src/types/lesser_element.rs @@ -1,6 +1,7 @@ use super::object::Object; use super::PlainText; use super::StandardProperties; +use super::Timestamp; #[derive(Debug)] pub struct Paragraph<'s> { @@ -72,6 +73,9 @@ pub struct DiarySexp<'s> { #[derive(Debug)] pub struct Planning<'s> { pub source: &'s str, + pub scheduled: Option>, + pub deadline: Option>, + pub closed: Option>, } #[derive(Debug)]