Compare date start/end.

This commit is contained in:
Tom Alexander 2023-10-02 15:59:06 -04:00
parent c55fae86f8
commit a8a34e2d9c
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 115 additions and 46 deletions

View File

@ -24,6 +24,9 @@ use crate::types::Clock;
use crate::types::Code; use crate::types::Code;
use crate::types::Comment; use crate::types::Comment;
use crate::types::CommentBlock; use crate::types::CommentBlock;
use crate::types::Date;
use crate::types::DayOfMonth;
use crate::types::DayOfMonthInner;
use crate::types::DiarySexp; use crate::types::DiarySexp;
use crate::types::Document; use crate::types::Document;
use crate::types::DocumentElement; use crate::types::DocumentElement;
@ -47,6 +50,8 @@ use crate::types::Keyword;
use crate::types::LatexEnvironment; use crate::types::LatexEnvironment;
use crate::types::LatexFragment; use crate::types::LatexFragment;
use crate::types::LineBreak; use crate::types::LineBreak;
use crate::types::Month;
use crate::types::MonthInner;
use crate::types::NodeProperty; use crate::types::NodeProperty;
use crate::types::OrgMacro; use crate::types::OrgMacro;
use crate::types::Paragraph; use crate::types::Paragraph;
@ -81,6 +86,8 @@ use crate::types::TodoKeywordType;
use crate::types::Underline; use crate::types::Underline;
use crate::types::Verbatim; use crate::types::Verbatim;
use crate::types::VerseBlock; use crate::types::VerseBlock;
use crate::types::Year;
use crate::types::YearInner;
#[derive(Debug)] #[derive(Debug)]
pub enum DiffEntry<'b, 's> { pub enum DiffEntry<'b, 's> {
@ -2165,21 +2172,76 @@ fn compare_timestamp<'b, 's>(
} }
// Compare start // Compare start
let year_start: Option<u16> = get_property_unquoted_atom(emacs, ":year-start")? let year_start: Option<YearInner> = get_property_numeric(emacs, ":year-start")?;
.map(|val| val.parse()) let month_start: Option<MonthInner> = get_property_numeric(emacs, ":month-start")?;
.map_or(Ok(None), |r| r.map(Some))?; let day_of_month_start: Option<DayOfMonthInner> = get_property_numeric(emacs, ":day-start")?;
let month_start: Option<u8> = get_property_unquoted_atom(emacs, ":month-start")? let rust_year_start = rust.start.as_ref().map(Date::get_year).map(Year::get_value);
.map(|val| val.parse()) let rust_month_start = rust
.map_or(Ok(None), |r| r.map(Some))?; .start
let day_of_month_start: Option<u8> = get_property_unquoted_atom(emacs, ":day-start")? .as_ref()
.map(|val| val.parse()) .map(Date::get_month)
.map_or(Ok(None), |r| r.map(Some))?; .map(Month::get_value);
let rust_day_of_month_start = rust
let year_end = get_property_numeric::<u16>(emacs, ":year-end")?; .start
.as_ref()
.map(Date::get_day_of_month)
.map(DayOfMonth::get_value);
if year_start != rust_year_start {
this_status = DiffStatus::Bad;
message = Some(format!(
"year start mismatch (emacs != rust) {:?} != {:?}",
year_start, rust_year_start
));
}
if month_start != rust_month_start {
this_status = DiffStatus::Bad;
message = Some(format!(
"month start mismatch (emacs != rust) {:?} != {:?}",
month_start, rust_month_start
));
}
if day_of_month_start != rust_day_of_month_start {
this_status = DiffStatus::Bad;
message = Some(format!(
"day of month start mismatch (emacs != rust) {:?} != {:?}",
day_of_month_start, rust_day_of_month_start
));
}
// Compare end // Compare end
let year_end: Option<YearInner> = get_property_numeric(emacs, ":year-end")?;
let month_end: Option<MonthInner> = get_property_numeric(emacs, ":month-end")?;
let day_of_month_end: Option<DayOfMonthInner> = get_property_numeric(emacs, ":day-end")?;
let rust_year_end = rust.end.as_ref().map(Date::get_year).map(Year::get_value);
let rust_month_end = rust.end.as_ref().map(Date::get_month).map(Month::get_value);
let rust_day_of_month_end = rust
.end
.as_ref()
.map(Date::get_day_of_month)
.map(DayOfMonth::get_value);
if year_end != rust_year_end {
this_status = DiffStatus::Bad;
message = Some(format!(
"year end mismatch (emacs != rust) {:?} != {:?}",
year_end, rust_year_end
));
}
if month_end != rust_month_end {
this_status = DiffStatus::Bad;
message = Some(format!(
"month end mismatch (emacs != rust) {:?} != {:?}",
month_end, rust_month_end
));
}
if day_of_month_end != rust_day_of_month_end {
this_status = DiffStatus::Bad;
message = Some(format!(
"day of month end mismatch (emacs != rust) {:?} != {:?}",
day_of_month_end, rust_day_of_month_end
));
}
// TODO: Compare :year-start :month-start :day-start :hour-start :minute-start :year-end :month-end :day-end :hour-end :minute-end :repeater-type :repeater-value :repeater-unit :warning-type :warning-value :warning-unit // TODO: Compare :hour-start :minute-start :hour-end :minute-end :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

@ -248,11 +248,11 @@ where
<N as FromStr>::Err: std::error::Error, <N as FromStr>::Err: std::error::Error,
<N as FromStr>::Err: 's, <N as FromStr>::Err: 's,
{ {
let foo = get_property(emacs, key)? let unparsed_string = get_property(emacs, key)?
.map(Token::as_atom) .map(Token::as_atom)
.map_or(Ok(None), |r| r.map(Some))?; .map_or(Ok(None), |r| r.map(Some))?;
let bar = foo let parsed_number = unparsed_string
.map(|val| val.parse::<N>()) .map(|val| val.parse::<N>())
.map_or(Ok(None), |r| r.map(Some))?; .map_or(Ok(None), |r| r.map(Some))?;
Ok(bar) Ok(parsed_number)
} }

View File

@ -133,8 +133,8 @@ fn active_timestamp<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Active, timestamp_type: TimestampType::Active,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::None,
start: Some(start), start: Some(start.clone()),
end: None, end: Some(start),
}, },
)) ))
} }
@ -171,8 +171,8 @@ fn inactive_timestamp<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Inactive, timestamp_type: TimestampType::Inactive,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::None,
start: Some(start), start: Some(start.clone()),
end: None, end: Some(start),
}, },
)) ))
} }
@ -182,10 +182,10 @@ fn active_date_range_timestamp<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Timestamp<'s>> { ) -> Res<OrgSource<'s>, Timestamp<'s>> {
let (remaining, _first_timestamp) = active_timestamp(context, input)?; let (remaining, first_timestamp) = active_timestamp(context, input)?;
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace // TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
let (remaining, _separator) = tag("--")(remaining)?; let (remaining, _separator) = tag("--")(remaining)?;
let (remaining, _second_timestamp) = active_timestamp(context, remaining)?; let (remaining, second_timestamp) = active_timestamp(context, remaining)?;
let (remaining, _trailing_whitespace) = let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?; maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
@ -197,8 +197,8 @@ fn active_date_range_timestamp<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
timestamp_type: TimestampType::ActiveRange, timestamp_type: TimestampType::ActiveRange,
range_type: TimestampRangeType::DateRange, range_type: TimestampRangeType::DateRange,
start: None, // TODO start: first_timestamp.start,
end: None, // TODO end: second_timestamp.end,
}, },
)) ))
} }
@ -209,7 +209,7 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Timestamp<'s>> { ) -> Res<OrgSource<'s>, Timestamp<'s>> {
let (remaining, _) = tag("<")(input)?; let (remaining, _) = tag("<")(input)?;
let (remaining, _date) = date(context, remaining)?; let (remaining, start_date) = date(context, remaining)?;
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma, class: ExitClass::Gamma,
exit_matcher: &active_time_rest_end, exit_matcher: &active_time_rest_end,
@ -242,8 +242,8 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Active, timestamp_type: TimestampType::Active,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::None,
start: None, // TODO start: Some(start_date.clone()),
end: None, // TODO end: Some(start_date),
}, },
)) ))
} }
@ -253,10 +253,10 @@ fn inactive_date_range_timestamp<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Timestamp<'s>> { ) -> Res<OrgSource<'s>, Timestamp<'s>> {
let (remaining, _first_timestamp) = inactive_timestamp(context, input)?; let (remaining, first_timestamp) = inactive_timestamp(context, input)?;
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace // TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
let (remaining, _separator) = tag("--")(remaining)?; let (remaining, _separator) = tag("--")(remaining)?;
let (remaining, _second_timestamp) = inactive_timestamp(context, remaining)?; let (remaining, second_timestamp) = inactive_timestamp(context, remaining)?;
let (remaining, _trailing_whitespace) = let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?; maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
@ -269,8 +269,8 @@ fn inactive_date_range_timestamp<'b, 'g, 'r, 's>(
timestamp_type: TimestampType::InactiveRange, timestamp_type: TimestampType::InactiveRange,
range_type: TimestampRangeType::DateRange, range_type: TimestampRangeType::DateRange,
start: None, // TODO start: first_timestamp.start,
end: None, // TODO end: second_timestamp.end,
}, },
)) ))
} }
@ -281,7 +281,7 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Timestamp<'s>> { ) -> Res<OrgSource<'s>, Timestamp<'s>> {
let (remaining, _) = tag("[")(input)?; let (remaining, _) = tag("[")(input)?;
let (remaining, _date) = date(context, remaining)?; let (remaining, start_date) = date(context, remaining)?;
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode { let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma, class: ExitClass::Gamma,
exit_matcher: &inactive_time_rest_end, exit_matcher: &inactive_time_rest_end,
@ -314,8 +314,8 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
source: source.into(), source: source.into(),
timestamp_type: TimestampType::Inactive, timestamp_type: TimestampType::Inactive,
range_type: TimestampRangeType::None, range_type: TimestampRangeType::None,
start: None, // TODO start: Some(start_date.clone()),
end: None, // TODO end: Some(start_date),
}, },
)) ))
} }

View File

@ -56,6 +56,7 @@ pub use object::CitationReference;
pub use object::Code; pub use object::Code;
pub use object::Date; pub use object::Date;
pub use object::DayOfMonth; pub use object::DayOfMonth;
pub use object::DayOfMonthInner;
pub use object::Entity; pub use object::Entity;
pub use object::ExportSnippet; pub use object::ExportSnippet;
pub use object::FootnoteReference; pub use object::FootnoteReference;
@ -65,6 +66,7 @@ pub use object::Italic;
pub use object::LatexFragment; pub use object::LatexFragment;
pub use object::LineBreak; pub use object::LineBreak;
pub use object::Month; pub use object::Month;
pub use object::MonthInner;
pub use object::Object; pub use object::Object;
pub use object::OrgMacro; pub use object::OrgMacro;
pub use object::PlainLink; pub use object::PlainLink;
@ -83,5 +85,6 @@ pub use object::TimestampType;
pub use object::Underline; pub use object::Underline;
pub use object::Verbatim; pub use object::Verbatim;
pub use object::Year; pub use object::Year;
pub use object::YearInner;
pub(crate) use source::SetSource; pub(crate) use source::SetSource;
pub use standard_properties::StandardProperties; pub use standard_properties::StandardProperties;

View File

@ -206,23 +206,27 @@ pub enum TimestampRangeType {
DateRange, DateRange,
} }
#[derive(Debug, PartialEq)] pub type YearInner = u16;
pub struct Year(u16); pub type MonthInner = u8;
pub type DayOfMonthInner = u8;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone)]
pub struct Month(u8); pub struct Year(YearInner);
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone)]
pub struct DayOfMonth(u8); pub struct Month(MonthInner);
#[derive(Debug, PartialEq, Clone)]
pub struct DayOfMonth(DayOfMonthInner);
impl Year { impl Year {
// TODO: Make a real error type instead of a boxed any error. // TODO: Make a real error type instead of a boxed any error.
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> { pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
let year = source.parse::<u16>()?; let year = source.parse::<YearInner>()?;
Ok(Year(year)) Ok(Year(year))
} }
pub fn get_value(&self) -> u16 { pub fn get_value(&self) -> YearInner {
self.0 self.0
} }
} }
@ -230,14 +234,14 @@ impl Year {
impl Month { impl Month {
// TODO: Make a real error type instead of a boxed any error. // TODO: Make a real error type instead of a boxed any error.
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> { pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
let month = source.parse::<u8>()?; let month = source.parse::<MonthInner>()?;
if month < 1 || month > 12 { if month < 1 || month > 12 {
Err("Month exceeds possible range.")?; Err("Month exceeds possible range.")?;
} }
Ok(Month(month)) Ok(Month(month))
} }
pub fn get_value(&self) -> u8 { pub fn get_value(&self) -> MonthInner {
self.0 self.0
} }
} }
@ -245,19 +249,19 @@ impl Month {
impl DayOfMonth { impl DayOfMonth {
// TODO: Make a real error type instead of a boxed any error. // TODO: Make a real error type instead of a boxed any error.
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> { pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
let day_of_month = source.parse::<u8>()?; let day_of_month = source.parse::<DayOfMonthInner>()?;
if day_of_month < 1 || day_of_month > 31 { if day_of_month < 1 || day_of_month > 31 {
Err("Day of month exceeds possible range.")?; Err("Day of month exceeds possible range.")?;
} }
Ok(DayOfMonth(day_of_month)) Ok(DayOfMonth(day_of_month))
} }
pub fn get_value(&self) -> u8 { pub fn get_value(&self) -> DayOfMonthInner {
self.0 self.0
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone)]
pub struct Date<'s> { pub struct Date<'s> {
year: Year, year: Year,
month: Month, month: Month,