refator(elements): rewrite Timestamp struct
This commit is contained in:
parent
9023837eb4
commit
8d18fb04c1
|
@ -1,4 +1,4 @@
|
||||||
use crate::elements::{Date, Element, Time, Timestamp};
|
use crate::elements::{Datetime, Element, Timestamp};
|
||||||
use memchr::memchr;
|
use memchr::memchr;
|
||||||
|
|
||||||
/// clock elements
|
/// clock elements
|
||||||
|
@ -10,18 +10,15 @@ use memchr::memchr;
|
||||||
pub enum Clock<'a> {
|
pub enum Clock<'a> {
|
||||||
/// closed Clock
|
/// closed Clock
|
||||||
Closed {
|
Closed {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
end: Datetime<'a>,
|
||||||
end_date: Date<'a>,
|
|
||||||
end_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
duration: &'a str,
|
duration: &'a str,
|
||||||
},
|
},
|
||||||
/// running Clock
|
/// running Clock
|
||||||
Running {
|
Running {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
},
|
},
|
||||||
|
@ -49,50 +46,54 @@ impl Clock<'_> {
|
||||||
|
|
||||||
match timestamp {
|
match timestamp {
|
||||||
Timestamp::InactiveRange {
|
Timestamp::InactiveRange {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
repeater,
|
repeater,
|
||||||
delay,
|
delay,
|
||||||
} if tail.starts_with("=>") => {
|
} => {
|
||||||
let duration = &tail[3..].trim();
|
if tail.starts_with("=>") {
|
||||||
let colon = memchr(b':', duration.as_bytes())?;
|
let duration = &tail[3..].trim();
|
||||||
if duration.as_bytes()[0..colon].iter().all(u8::is_ascii_digit)
|
let colon = memchr(b':', duration.as_bytes())?;
|
||||||
&& colon == duration.len() - 3
|
if duration.as_bytes()[0..colon].iter().all(u8::is_ascii_digit)
|
||||||
&& duration.as_bytes()[colon + 1].is_ascii_digit()
|
&& colon == duration.len() - 3
|
||||||
&& duration.as_bytes()[colon + 2].is_ascii_digit()
|
&& duration.as_bytes()[colon + 1].is_ascii_digit()
|
||||||
{
|
&& duration.as_bytes()[colon + 2].is_ascii_digit()
|
||||||
|
{
|
||||||
|
Some((
|
||||||
|
&text[eol..],
|
||||||
|
Element::Clock(Clock::Closed {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
repeater,
|
||||||
|
delay,
|
||||||
|
duration,
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timestamp::Inactive {
|
||||||
|
start,
|
||||||
|
repeater,
|
||||||
|
delay,
|
||||||
|
} => {
|
||||||
|
if tail.is_empty() {
|
||||||
Some((
|
Some((
|
||||||
&text[eol..],
|
&text[eol..],
|
||||||
Element::Clock(Clock::Closed {
|
Element::Clock(Clock::Running {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
repeater,
|
repeater,
|
||||||
delay,
|
delay,
|
||||||
duration,
|
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Timestamp::Inactive {
|
|
||||||
start_date,
|
|
||||||
start_time,
|
|
||||||
repeater,
|
|
||||||
delay,
|
|
||||||
} if tail.is_empty() => Some((
|
|
||||||
&text[eol..],
|
|
||||||
Element::Clock(Clock::Running {
|
|
||||||
start_date,
|
|
||||||
start_time,
|
|
||||||
repeater,
|
|
||||||
delay,
|
|
||||||
}),
|
|
||||||
)),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,33 +124,27 @@ impl Clock<'_> {
|
||||||
|
|
||||||
/// constructs a new timestamp object from the clock
|
/// constructs a new timestamp object from the clock
|
||||||
pub fn value(&self) -> Timestamp<'_> {
|
pub fn value(&self) -> Timestamp<'_> {
|
||||||
match *self {
|
match &*self {
|
||||||
Clock::Closed {
|
Clock::Closed {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
repeater,
|
repeater,
|
||||||
delay,
|
delay,
|
||||||
..
|
..
|
||||||
} => Timestamp::InactiveRange {
|
} => Timestamp::InactiveRange {
|
||||||
start_date,
|
start: start.clone(),
|
||||||
start_time,
|
end: end.clone(),
|
||||||
end_date,
|
repeater: repeater.clone(),
|
||||||
end_time,
|
delay: delay.clone(),
|
||||||
repeater,
|
|
||||||
delay,
|
|
||||||
},
|
},
|
||||||
Clock::Running {
|
Clock::Running {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
|
||||||
repeater,
|
repeater,
|
||||||
delay,
|
delay,
|
||||||
} => Timestamp::Inactive {
|
} => Timestamp::Inactive {
|
||||||
start_date,
|
start: start.clone(),
|
||||||
start_time,
|
repeater: repeater.clone(),
|
||||||
repeater,
|
delay: delay.clone(),
|
||||||
delay,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,16 +157,14 @@ fn parse() {
|
||||||
Some((
|
Some((
|
||||||
"",
|
"",
|
||||||
Element::Clock(Clock::Running {
|
Element::Clock(Clock::Running {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(9),
|
||||||
|
minute: Some(39)
|
||||||
},
|
},
|
||||||
start_time: Some(Time {
|
|
||||||
hour: 9,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
})
|
})
|
||||||
|
@ -182,26 +175,22 @@ fn parse() {
|
||||||
Some((
|
Some((
|
||||||
"",
|
"",
|
||||||
Element::Clock(Clock::Closed {
|
Element::Clock(Clock::Closed {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(9),
|
||||||
|
minute: Some(39)
|
||||||
},
|
},
|
||||||
start_time: Some(Time {
|
end: Datetime {
|
||||||
hour: 9,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
end_date: Date {
|
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(10),
|
||||||
|
minute: Some(39)
|
||||||
},
|
},
|
||||||
end_time: Some(Time {
|
|
||||||
hour: 10,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
duration: "1:00",
|
duration: "1:00",
|
||||||
|
|
|
@ -22,8 +22,8 @@ mod target;
|
||||||
mod timestamp;
|
mod timestamp;
|
||||||
mod title;
|
mod title;
|
||||||
|
|
||||||
pub(crate) use emphasis::parse as parse_emphasis;
|
|
||||||
pub(crate) use block::Block;
|
pub(crate) use block::Block;
|
||||||
|
pub(crate) use emphasis::parse as parse_emphasis;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
block::{
|
block::{
|
||||||
|
@ -47,7 +47,7 @@ pub use self::{
|
||||||
rule::Rule,
|
rule::Rule,
|
||||||
snippet::Snippet,
|
snippet::Snippet,
|
||||||
target::Target,
|
target::Target,
|
||||||
timestamp::{Date, Time, Timestamp},
|
timestamp::{Datetime, Timestamp},
|
||||||
title::Title,
|
title::Title,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl Planning<'_> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prase() {
|
fn prase() {
|
||||||
use crate::elements::Date;
|
use crate::elements::Datetime;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Planning::parse("SCHEDULED: <2019-04-08 Mon>\n"),
|
Planning::parse("SCHEDULED: <2019-04-08 Mon>\n"),
|
||||||
|
@ -76,13 +76,14 @@ fn prase() {
|
||||||
"",
|
"",
|
||||||
Planning {
|
Planning {
|
||||||
scheduled: Some(Box::new(Timestamp::Active {
|
scheduled: Some(Box::new(Timestamp::Active {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2019,
|
year: 2019,
|
||||||
month: 4,
|
month: 4,
|
||||||
day: 8,
|
day: 8,
|
||||||
dayname: "Mon"
|
dayname: "Mon",
|
||||||
|
hour: None,
|
||||||
|
minute: None
|
||||||
},
|
},
|
||||||
start_time: None,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None
|
delay: None
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{tag, take, take_while_m_n},
|
bytes::complete::{tag, take_while_m_n},
|
||||||
character::complete::space0,
|
character::complete::space0,
|
||||||
combinator::{map, not},
|
error::ErrorKind,
|
||||||
IResult,
|
Err, IResult,
|
||||||
};
|
};
|
||||||
use std::usize;
|
use std::usize;
|
||||||
|
|
||||||
|
@ -17,11 +17,19 @@ impl Rule {
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
let (input, _) = take_while_m_n(5, usize::MAX, |c| c == '-')(input)?;
|
let (input, _) = take_while_m_n(5, usize::MAX, |c| c == '-')(input)?;
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
let (input, _) = alt((tag("\n"), map(not(take(1usize)), |_| "")))(input)?;
|
let (input, _) = alt((tag("\n"), eof))(input)?;
|
||||||
Ok((input, Element::Rule))
|
Ok((input, Element::Rule))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eof(input: &str) -> IResult<&str, &str> {
|
||||||
|
if input.is_empty() {
|
||||||
|
Ok(("", ""))
|
||||||
|
} else {
|
||||||
|
Err(Err::Error(("", ErrorKind::Tag)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse() {
|
fn parse() {
|
||||||
assert_eq!(Rule::parse("-----"), Ok(("", Element::Rule)));
|
assert_eq!(Rule::parse("-----"), Ok(("", Element::Rule)));
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
#[cfg(feature = "chrono")]
|
|
||||||
use chrono::*;
|
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::{tag, take, take_till, take_while, take_while_m_n},
|
bytes::complete::{tag, take, take_till, take_while, take_while_m_n},
|
||||||
character::complete::{space0, space1},
|
character::complete::{space0, space1},
|
||||||
combinator::{map_res, opt},
|
combinator::{map, map_res, opt},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Date
|
/// Datetime
|
||||||
///
|
///
|
||||||
/// # Syntax
|
/// # Syntax
|
||||||
///
|
///
|
||||||
|
@ -17,117 +15,145 @@ use nom::{
|
||||||
///
|
///
|
||||||
#[cfg_attr(test, derive(PartialEq))]
|
#[cfg_attr(test, derive(PartialEq))]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Date<'a> {
|
pub struct Datetime<'a> {
|
||||||
pub year: u16,
|
pub year: u16,
|
||||||
pub month: u8,
|
pub month: u8,
|
||||||
pub day: u8,
|
pub day: u8,
|
||||||
pub dayname: &'a str,
|
pub dayname: &'a str,
|
||||||
|
pub hour: Option<u8>,
|
||||||
|
pub minute: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Date<'_> {
|
fn parse_time(input: &str) -> IResult<&str, (u8, u8)> {
|
||||||
fn parse(input: &str) -> IResult<&str, Date<'_>> {
|
let (input, hour) = map_res(take_while_m_n(1, 2, |c: char| c.is_ascii_digit()), |num| {
|
||||||
let (input, year) = map_res(take(4usize), |num| u16::from_str_radix(num, 10))(input)?;
|
u8::from_str_radix(num, 10)
|
||||||
let (input, _) = tag("-")(input)?;
|
})(input)?;
|
||||||
let (input, month) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
|
let (input, _) = tag(":")(input)?;
|
||||||
let (input, _) = tag("-")(input)?;
|
let (input, minute) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
|
||||||
let (input, day) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
|
Ok((input, (hour, minute)))
|
||||||
let (input, _) = space1(input)?;
|
}
|
||||||
let (input, dayname) = take_while(|c: char| {
|
|
||||||
!c.is_ascii_whitespace()
|
|
||||||
&& !c.is_ascii_digit()
|
|
||||||
&& c != '+'
|
|
||||||
&& c != '-'
|
|
||||||
&& c != ']'
|
|
||||||
&& c != '>'
|
|
||||||
})(input)?;
|
|
||||||
|
|
||||||
Ok((
|
fn parse_datetime(input: &str) -> IResult<&str, Datetime<'_>> {
|
||||||
input,
|
let parse_u8 = |num| u8::from_str_radix(num, 10);
|
||||||
Date {
|
|
||||||
year,
|
let (input, year) = map_res(take(4usize), |num| u16::from_str_radix(num, 10))(input)?;
|
||||||
month,
|
let (input, _) = tag("-")(input)?;
|
||||||
day,
|
let (input, month) = map_res(take(2usize), parse_u8)(input)?;
|
||||||
dayname,
|
let (input, _) = tag("-")(input)?;
|
||||||
},
|
let (input, day) = map_res(take(2usize), parse_u8)(input)?;
|
||||||
))
|
let (input, _) = space1(input)?;
|
||||||
}
|
let (input, dayname) = take_while(|c: char| {
|
||||||
}
|
!c.is_ascii_whitespace()
|
||||||
|
&& !c.is_ascii_digit()
|
||||||
#[cfg_attr(test, derive(PartialEq))]
|
&& c != '+'
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
&& c != '-'
|
||||||
#[derive(Debug, Clone, Copy)]
|
&& c != ']'
|
||||||
pub struct Time {
|
&& c != '>'
|
||||||
pub hour: u8,
|
})(input)?;
|
||||||
pub minute: u8,
|
let (input, (hour, minute)) = map(
|
||||||
}
|
opt(|input| {
|
||||||
|
let (input, _) = space1(input)?;
|
||||||
impl Time {
|
parse_time(input)
|
||||||
fn parse(input: &str) -> IResult<&str, Time> {
|
}),
|
||||||
let (input, hour) = map_res(take_while_m_n(1, 2, |c: char| c.is_ascii_digit()), |num| {
|
|time| (time.map(|t| t.0), time.map(|t| t.1)),
|
||||||
u8::from_str_radix(num, 10)
|
)(input)?;
|
||||||
})(input)?;
|
|
||||||
let (input, _) = tag(":")(input)?;
|
Ok((
|
||||||
let (input, minute) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
|
input,
|
||||||
|
Datetime {
|
||||||
Ok((input, Time { hour, minute }))
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
dayname,
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "chrono")]
|
||||||
|
mod chrono {
|
||||||
|
use super::Datetime;
|
||||||
|
use chrono::*;
|
||||||
|
|
||||||
|
impl Into<NaiveDate> for Datetime<'_> {
|
||||||
|
fn into(self) -> NaiveDate {
|
||||||
|
NaiveDate::from_ymd(self.year.into(), self.month.into(), self.day.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<NaiveTime> for Datetime<'_> {
|
||||||
|
fn into(self) -> NaiveTime {
|
||||||
|
NaiveTime::from_hms(
|
||||||
|
self.hour.unwrap_or_default().into(),
|
||||||
|
self.minute.unwrap_or_default().into(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<NaiveDateTime> for Datetime<'_> {
|
||||||
|
fn into(self) -> NaiveDateTime {
|
||||||
|
NaiveDate::from_ymd(self.year.into(), self.month.into(), self.day.into()).and_hms(
|
||||||
|
self.hour.unwrap_or_default().into(),
|
||||||
|
self.minute.unwrap_or_default().into(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, derive(PartialEq))]
|
#[cfg_attr(test, derive(PartialEq))]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||||
|
#[cfg_attr(feature = "serde", serde(tag = "type", rename_all = "snake_case"))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Timestamp<'a> {
|
pub enum Timestamp<'a> {
|
||||||
Active {
|
Active {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
},
|
},
|
||||||
Inactive {
|
Inactive {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
},
|
},
|
||||||
ActiveRange {
|
ActiveRange {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
end: Datetime<'a>,
|
||||||
end_date: Date<'a>,
|
|
||||||
end_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
},
|
},
|
||||||
InactiveRange {
|
InactiveRange {
|
||||||
start_date: Date<'a>,
|
start: Datetime<'a>,
|
||||||
start_time: Option<Time>,
|
end: Datetime<'a>,
|
||||||
end_date: Date<'a>,
|
|
||||||
end_time: Option<Time>,
|
|
||||||
repeater: Option<&'a str>,
|
repeater: Option<&'a str>,
|
||||||
delay: Option<&'a str>,
|
delay: Option<&'a str>,
|
||||||
},
|
},
|
||||||
Diary(&'a str),
|
Diary {
|
||||||
|
value: &'a str,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timestamp<'_> {
|
impl Timestamp<'_> {
|
||||||
pub(crate) fn parse_active(input: &str) -> IResult<&str, Timestamp<'_>> {
|
pub(crate) fn parse_active(input: &str) -> IResult<&str, Timestamp<'_>> {
|
||||||
let (input, _) = tag("<")(input)?;
|
let (input, _) = tag("<")(input)?;
|
||||||
let (input, start_date) = Date::parse(input)?;
|
let (input, start) = parse_datetime(input)?;
|
||||||
let (input, _) = space0(input)?;
|
|
||||||
let (input, start_time) = opt(Time::parse)(input)?;
|
|
||||||
|
|
||||||
if input.starts_with('-') {
|
if input.starts_with('-') {
|
||||||
let (input, end_time) = opt(Time::parse)(&input[1..])?;
|
let (input, (hour, minute)) = parse_time(&input[1..])?;
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
// TODO: delay-or-repeater
|
// TODO: delay-or-repeater
|
||||||
let (input, _) = tag(">")(input)?;
|
let (input, _) = tag(">")(input)?;
|
||||||
|
let mut end = start.clone();
|
||||||
|
end.hour = Some(hour);
|
||||||
|
end.minute = Some(minute);
|
||||||
return Ok((
|
return Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::ActiveRange {
|
Timestamp::ActiveRange {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date: start_date,
|
|
||||||
end_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -139,19 +165,15 @@ impl Timestamp<'_> {
|
||||||
let (input, _) = tag(">")(input)?;
|
let (input, _) = tag(">")(input)?;
|
||||||
|
|
||||||
if input.starts_with("--<") {
|
if input.starts_with("--<") {
|
||||||
let (input, end_date) = Date::parse(&input["--<".len()..])?;
|
let (input, end) = parse_datetime(&input["--<".len()..])?;
|
||||||
let (input, _) = space0(input)?;
|
|
||||||
let (input, end_time) = opt(Time::parse)(input)?;
|
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
// TODO: delay-or-repeater
|
// TODO: delay-or-repeater
|
||||||
let (input, _) = tag(">")(input)?;
|
let (input, _) = tag(">")(input)?;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::ActiveRange {
|
Timestamp::ActiveRange {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -160,8 +182,7 @@ impl Timestamp<'_> {
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::Active {
|
Timestamp::Active {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -171,22 +192,21 @@ impl Timestamp<'_> {
|
||||||
|
|
||||||
pub(crate) fn parse_inactive(input: &str) -> IResult<&str, Timestamp<'_>> {
|
pub(crate) fn parse_inactive(input: &str) -> IResult<&str, Timestamp<'_>> {
|
||||||
let (input, _) = tag("[")(input)?;
|
let (input, _) = tag("[")(input)?;
|
||||||
let (input, start_date) = Date::parse(input)?;
|
let (input, start) = parse_datetime(input)?;
|
||||||
let (input, _) = space0(input)?;
|
|
||||||
let (input, start_time) = opt(Time::parse)(input)?;
|
|
||||||
|
|
||||||
if input.starts_with('-') {
|
if input.starts_with('-') {
|
||||||
let (input, end_time) = opt(Time::parse)(&input[1..])?;
|
let (input, (hour, minute)) = parse_time(&input[1..])?;
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
// TODO: delay-or-repeater
|
// TODO: delay-or-repeater
|
||||||
let (input, _) = tag("]")(input)?;
|
let (input, _) = tag("]")(input)?;
|
||||||
|
let mut end = start.clone();
|
||||||
|
end.hour = Some(hour);
|
||||||
|
end.minute = Some(minute);
|
||||||
return Ok((
|
return Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::InactiveRange {
|
Timestamp::InactiveRange {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date: start_date,
|
|
||||||
end_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -198,19 +218,15 @@ impl Timestamp<'_> {
|
||||||
let (input, _) = tag("]")(input)?;
|
let (input, _) = tag("]")(input)?;
|
||||||
|
|
||||||
if input.starts_with("--[") {
|
if input.starts_with("--[") {
|
||||||
let (input, end_date) = Date::parse(&input["--[".len()..])?;
|
let (input, end) = parse_datetime(&input["--[".len()..])?;
|
||||||
let (input, _) = space0(input)?;
|
|
||||||
let (input, end_time) = opt(Time::parse)(input)?;
|
|
||||||
let (input, _) = space0(input)?;
|
let (input, _) = space0(input)?;
|
||||||
// TODO: delay-or-repeater
|
// TODO: delay-or-repeater
|
||||||
let (input, _) = tag("]")(input)?;
|
let (input, _) = tag("]")(input)?;
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::InactiveRange {
|
Timestamp::InactiveRange {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
end,
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -219,8 +235,7 @@ impl Timestamp<'_> {
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Timestamp::Inactive {
|
Timestamp::Inactive {
|
||||||
start_date,
|
start,
|
||||||
start_time,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -230,10 +245,10 @@ impl Timestamp<'_> {
|
||||||
|
|
||||||
pub(crate) fn parse_diary(input: &str) -> IResult<&str, Timestamp<'_>> {
|
pub(crate) fn parse_diary(input: &str) -> IResult<&str, Timestamp<'_>> {
|
||||||
let (input, _) = tag("<%%(")(input)?;
|
let (input, _) = tag("<%%(")(input)?;
|
||||||
let (input, sexp) = take_till(|c| c == ')' || c == '>' || c == '\n')(input)?;
|
let (input, value) = take_till(|c| c == ')' || c == '>' || c == '\n')(input)?;
|
||||||
let (input, _) = tag(")>")(input)?;
|
let (input, _) = tag(")>")(input)?;
|
||||||
|
|
||||||
Ok((input, Timestamp::Diary(sexp)))
|
Ok((input, Timestamp::Diary { value }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,13 +306,14 @@ fn parse() {
|
||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
Timestamp::Inactive {
|
Timestamp::Inactive {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: None,
|
||||||
|
minute: None
|
||||||
},
|
},
|
||||||
start_time: None,
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None,
|
delay: None,
|
||||||
},
|
},
|
||||||
|
@ -308,26 +324,22 @@ fn parse() {
|
||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
Timestamp::InactiveRange {
|
Timestamp::InactiveRange {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(9),
|
||||||
|
minute: Some(39)
|
||||||
},
|
},
|
||||||
start_time: Some(Time {
|
end: Datetime {
|
||||||
hour: 9,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
end_date: Date {
|
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(10),
|
||||||
|
minute: Some(39),
|
||||||
},
|
},
|
||||||
end_time: Some(Time {
|
|
||||||
hour: 10,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None
|
delay: None
|
||||||
},
|
},
|
||||||
|
@ -338,26 +350,22 @@ fn parse() {
|
||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
Timestamp::ActiveRange {
|
Timestamp::ActiveRange {
|
||||||
start_date: Date {
|
start: Datetime {
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(9),
|
||||||
|
minute: Some(39),
|
||||||
},
|
},
|
||||||
start_time: Some(Time {
|
end: Datetime {
|
||||||
hour: 9,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
end_date: Date {
|
|
||||||
year: 2003,
|
year: 2003,
|
||||||
month: 9,
|
month: 9,
|
||||||
day: 16,
|
day: 16,
|
||||||
dayname: "Tue"
|
dayname: "Tue",
|
||||||
|
hour: Some(10),
|
||||||
|
minute: Some(39),
|
||||||
},
|
},
|
||||||
end_time: Some(Time {
|
|
||||||
hour: 10,
|
|
||||||
minute: 39
|
|
||||||
}),
|
|
||||||
repeater: None,
|
repeater: None,
|
||||||
delay: None
|
delay: None
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::elements::Element;
|
use crate::elements::{Datetime, Element};
|
||||||
use jetscii::bytes;
|
use jetscii::bytes;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{Error, Write};
|
use std::io::{Error, Write};
|
||||||
|
@ -104,7 +104,7 @@ pub trait HtmlHandler<E: From<Error>> {
|
||||||
Target(_target) => (),
|
Target(_target) => (),
|
||||||
Text { value } => write!(w, "{}", Escape(value))?,
|
Text { value } => write!(w, "{}", Escape(value))?,
|
||||||
Timestamp(timestamp) => {
|
Timestamp(timestamp) => {
|
||||||
use crate::elements::{Date, Time, Timestamp::*};
|
use crate::elements::Timestamp;
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
&mut w,
|
&mut w,
|
||||||
|
@ -114,61 +114,37 @@ pub trait HtmlHandler<E: From<Error>> {
|
||||||
fn write_datetime<W: Write>(
|
fn write_datetime<W: Write>(
|
||||||
mut w: W,
|
mut w: W,
|
||||||
start: &str,
|
start: &str,
|
||||||
date: &Date,
|
datetime: &Datetime,
|
||||||
time: &Option<Time>,
|
|
||||||
end: &str,
|
end: &str,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
write!(w, "{}", start)?;
|
write!(w, "{}", start)?;
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}-{}-{} {}",
|
"{}-{}-{} {}",
|
||||||
date.year,
|
datetime.year, datetime.month, datetime.day, datetime.dayname
|
||||||
date.month,
|
|
||||||
date.day,
|
|
||||||
Escape(date.dayname)
|
|
||||||
)?;
|
)?;
|
||||||
if let Some(time) = time {
|
if let (Some(hour), Some(minute)) = (datetime.hour, datetime.minute) {
|
||||||
write!(w, " {}:{}", time.hour, time.minute)?;
|
write!(w, " {}:{}", hour, minute)?;
|
||||||
}
|
}
|
||||||
write!(w, "{}", end)
|
write!(w, "{}", end)
|
||||||
}
|
}
|
||||||
|
|
||||||
match timestamp {
|
match timestamp {
|
||||||
Active {
|
Timestamp::Active { start, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "<", start, ">")?;
|
||||||
start_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "<", start_date, start_time, ">")?;
|
|
||||||
}
|
}
|
||||||
Inactive {
|
Timestamp::Inactive { start, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "[", start, "]")?;
|
||||||
start_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "[", start_date, start_time, "]")?;
|
|
||||||
}
|
}
|
||||||
ActiveRange {
|
Timestamp::ActiveRange { start, end, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "<", start, ">–")?;
|
||||||
start_time,
|
write_datetime(&mut w, "<", end, ">")?;
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "<", start_date, start_time, ">–")?;
|
|
||||||
write_datetime(&mut w, "<", end_date, end_time, ">")?;
|
|
||||||
}
|
}
|
||||||
InactiveRange {
|
Timestamp::InactiveRange { start, end, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "[", start, "]–")?;
|
||||||
start_time,
|
write_datetime(&mut w, "[", end, "]")?;
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "[", start_date, start_time, "]–")?;
|
|
||||||
write_datetime(&mut w, "[", end_date, end_time, "]")?;
|
|
||||||
}
|
}
|
||||||
Diary(value) => write!(&mut w, "<%%({})>", Escape(value))?,
|
Timestamp::Diary { value } => write!(&mut w, "<%%({})>", Escape(value))?,
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(&mut w, "</span></span>")?;
|
write!(&mut w, "</span></span>")?;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::elements::Element;
|
use crate::elements::{Datetime, Element};
|
||||||
use std::io::{Error, Write};
|
use std::io::{Error, Write};
|
||||||
|
|
||||||
pub trait OrgHandler<E: From<Error>> {
|
pub trait OrgHandler<E: From<Error>> {
|
||||||
|
@ -89,63 +89,42 @@ pub trait OrgHandler<E: From<Error>> {
|
||||||
Target(_target) => (),
|
Target(_target) => (),
|
||||||
Text { value } => write!(w, "{}", value)?,
|
Text { value } => write!(w, "{}", value)?,
|
||||||
Timestamp(timestamp) => {
|
Timestamp(timestamp) => {
|
||||||
use crate::elements::{Date, Time, Timestamp::*};
|
use crate::elements::Timestamp;
|
||||||
|
|
||||||
fn write_datetime<W: Write>(
|
fn write_datetime<W: Write>(
|
||||||
mut w: W,
|
mut w: W,
|
||||||
start: &str,
|
start: &str,
|
||||||
date: &Date,
|
datetime: &Datetime,
|
||||||
time: &Option<Time>,
|
|
||||||
end: &str,
|
end: &str,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
write!(w, "{}", start)?;
|
write!(w, "{}", start)?;
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}-{}-{} {}",
|
"{}-{}-{} {}",
|
||||||
date.year, date.month, date.day, date.dayname
|
datetime.year, datetime.month, datetime.day, datetime.dayname
|
||||||
)?;
|
)?;
|
||||||
if let Some(time) = time {
|
if let (Some(hour), Some(minute)) = (datetime.hour, datetime.minute) {
|
||||||
write!(w, " {}:{}", time.hour, time.minute,)?;
|
write!(w, " {}:{}", hour, minute)?;
|
||||||
}
|
}
|
||||||
write!(w, "{}", end)
|
write!(w, "{}", end)
|
||||||
}
|
}
|
||||||
|
|
||||||
match timestamp {
|
match timestamp {
|
||||||
Active {
|
Timestamp::Active { start, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "<", start, ">")?;
|
||||||
start_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "<", start_date, start_time, ">")?;
|
|
||||||
}
|
}
|
||||||
Inactive {
|
Timestamp::Inactive { start, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "[", start, "]")?;
|
||||||
start_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "[", start_date, start_time, "]")?;
|
|
||||||
}
|
}
|
||||||
ActiveRange {
|
Timestamp::ActiveRange { start, end, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "<", start, ">--")?;
|
||||||
start_time,
|
write_datetime(&mut w, "<", end, ">")?;
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "<", start_date, start_time, ">--")?;
|
|
||||||
write_datetime(&mut w, "<", end_date, end_time, ">")?;
|
|
||||||
}
|
}
|
||||||
InactiveRange {
|
Timestamp::InactiveRange { start, end, .. } => {
|
||||||
start_date,
|
write_datetime(&mut w, "[", start, "]--")?;
|
||||||
start_time,
|
write_datetime(&mut w, "[", end, "]")?;
|
||||||
end_date,
|
|
||||||
end_time,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
write_datetime(&mut w, "[", start_date, start_time, "]--")?;
|
|
||||||
write_datetime(&mut w, "[", end_date, end_time, "]")?;
|
|
||||||
}
|
}
|
||||||
Diary(value) => write!(w, "<%%({})>", value)?,
|
Timestamp::Diary { value } => write!(w, "<%%({})>", value)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Verbatim { value } => write!(w, "={}=", value)?,
|
Verbatim { value } => write!(w, "={}=", value)?,
|
||||||
|
|
Loading…
Reference in a new issue