diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 0692574..08c0e86 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -719,9 +719,58 @@ fn compare_heading<'b, 's>( )); } - // TODO: Compare :pre-blank :scheduled :closed - // - // :scheduled and :closed seem to only appear when the headline has a planning + // 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])?); + } + } + + // TODO: Compare :pre-blank // Compare section let section_status = children @@ -1402,7 +1451,7 @@ fn compare_diary_sexp<'b, 's>( } fn compare_planning<'b, 's>( - _source: &'s str, + source: &'s str, emacs: &'b Token<'s>, rust: &'b Planning<'s>, ) -> Result, Box> { @@ -1422,7 +1471,7 @@ fn compare_planning<'b, 's>( )); } (Some(emacs_child), Some(rust_child)) => { - let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + let result = compare_ast_node(source, emacs_child, rust_child.into())?; child_status.push(artificial_diff_scope("scheduled", vec![result])?); } } @@ -1439,7 +1488,7 @@ fn compare_planning<'b, 's>( )); } (Some(emacs_child), Some(rust_child)) => { - let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + let result = compare_ast_node(source, emacs_child, rust_child.into())?; child_status.push(artificial_diff_scope("deadline", vec![result])?); } } @@ -1456,7 +1505,7 @@ fn compare_planning<'b, 's>( )); } (Some(emacs_child), Some(rust_child)) => { - let result = compare_ast_node(_source, emacs_child, rust_child.into())?; + let result = compare_ast_node(source, emacs_child, rust_child.into())?; child_status.push(artificial_diff_scope("closed", vec![result])?); } } diff --git a/src/parser/headline.rs b/src/parser/headline.rs index 3868362..f59bde2 100644 --- a/src/parser/headline.rs +++ b/src/parser/headline.rs @@ -34,6 +34,7 @@ use crate::error::Res; use crate::parser::object_parser::standard_set_object; use crate::parser::util::blank_line; use crate::types::DocumentElement; +use crate::types::Element; use crate::types::Heading; use crate::types::HeadlineLevel; use crate::types::Object; @@ -55,6 +56,9 @@ fn _heading<'b, 'g, 'r, 's>( input: OrgSource<'s>, parent_star_count: HeadlineLevel, ) -> Res, Heading<'s>> { + let mut scheduled = None; + let mut deadline = None; + let mut closed = None; not(|i| context.check_exit_matcher(i))(input)?; let (remaining, pre_headline) = headline(context, input, parent_star_count)?; let section_matcher = parser_with_context!(section)(context); @@ -65,6 +69,14 @@ fn _heading<'b, 'g, 'r, 's>( let (remaining, mut children) = many0(map(heading_matcher, DocumentElement::Heading))(remaining)?; if let Some(section) = maybe_section { + // If the section has a planning then the timestamp values are copied to the heading. + if let DocumentElement::Section(inner_section) = §ion { + if let Some(Element::Planning(planning)) = inner_section.children.first() { + scheduled = planning.scheduled.clone(); + deadline = planning.deadline.clone(); + closed = planning.closed.clone(); + } + } children.insert(0, section); } let remaining = if children.is_empty() { @@ -94,6 +106,9 @@ fn _heading<'b, 'g, 'r, 's>( is_comment: pre_headline.comment.is_some(), is_archived, is_footnote_section: pre_headline.is_footnote_section, + scheduled, + deadline, + closed, }, )) } diff --git a/src/types/document.rs b/src/types/document.rs index 31f471c..e3aa933 100644 --- a/src/types/document.rs +++ b/src/types/document.rs @@ -4,6 +4,7 @@ use super::Element; use super::GetStandardProperties; use super::Object; use super::StandardProperties; +use super::Timestamp; pub type PriorityCookie = u8; pub type HeadlineLevel = u16; @@ -29,6 +30,9 @@ pub struct Heading<'s> { pub is_comment: bool, pub is_archived: bool, pub is_footnote_section: bool, + pub scheduled: Option>, + pub deadline: Option>, + pub closed: Option>, } #[derive(Debug)] diff --git a/src/types/object.rs b/src/types/object.rs index 3440997..8501365 100644 --- a/src/types/object.rs +++ b/src/types/object.rs @@ -182,7 +182,7 @@ pub struct Superscript<'s> { pub source: &'s str, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Timestamp<'s> { pub source: &'s str, pub timestamp_type: TimestampType, @@ -195,7 +195,7 @@ pub struct Timestamp<'s> { pub warning_delay: Option, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TimestampType { Diary, Active, @@ -204,7 +204,7 @@ pub enum TimestampType { InactiveRange, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TimestampRangeType { None, DateRange,