diff options
author | Nora <nora.widdecke@tu-bs.de> | 2019-03-09 17:15:14 +0100 |
---|---|---|
committer | Nora <nora.widdecke@tu-bs.de> | 2019-03-09 17:15:14 +0100 |
commit | 5607b7c2718bdc29b1eaced8821d823f31b4c1be (patch) | |
tree | 990467b3cbaf0a962ea8b40318d2069dbe66e8aa | |
parent | 9490bf527cbfd258d1c6705569d7e3dc395c5d33 (diff) |
working khevent
-rw-r--r-- | src/actions/agenda.rs | 16 | ||||
-rw-r--r-- | src/actions/index/bucketable.rs | 15 | ||||
-rw-r--r-- | src/actions/prettyprint.rs | 2 | ||||
-rw-r--r-- | src/actions/unroll.rs | 3 | ||||
-rw-r--r-- | src/cursorfile.rs | 1 | ||||
-rw-r--r-- | src/icalwrap/icalvevent.rs | 47 | ||||
-rw-r--r-- | src/input.rs | 3 | ||||
-rw-r--r-- | src/khevent.rs | 113 | ||||
-rw-r--r-- | src/khline.rs | 26 | ||||
-rw-r--r-- | src/selectors/cal.rs | 7 | ||||
-rw-r--r-- | src/selectors/grep.rs | 5 | ||||
-rw-r--r-- | src/selectors/mod.rs | 15 | ||||
-rw-r--r-- | src/selectors/prop.rs | 7 |
13 files changed, 170 insertions, 90 deletions
diff --git a/src/actions/agenda.rs b/src/actions/agenda.rs index b56d274..cf0ba4d 100644 --- a/src/actions/agenda.rs +++ b/src/actions/agenda.rs @@ -29,15 +29,15 @@ pub fn show_events(config: &Config, args: &[&str]) -> KhResult<()> { pub fn show_events_cursor( config: &Config, - events: &mut Iterator<Item = IcalVEvent>, + events: &mut Iterator<Item = KhEvent>, cursor: Option<&KhLine>, ) { - let mut not_over_yet: Vec<(usize, IcalVEvent, Option<&CalendarConfig>)> = Vec::new(); + let mut not_over_yet: Vec<(usize, KhEvent, Option<&CalendarConfig>)> = Vec::new(); let mut cals_iter = events .enumerate() .map(|(i, event)| { - let config = event.get_parent().unwrap().get_calendar_name().and_then(|name| config.get_config_for_calendar(&name)); + let config = event.get_calendar_name().and_then(|name| config.get_config_for_calendar(&name)); (i, event, config) }) .peekable(); @@ -61,7 +61,7 @@ pub fn show_events_cursor( maybe_print_date_line_header(&config, cur_day, start_day, &mut last_printed_day); not_over_yet.retain( |(index, event, cal_config)| { - let is_cursor = cursor.map(|c| c.matches(&event)).unwrap_or(false); + let is_cursor = cursor.map(|c| c.matches_khevent(&event)).unwrap_or(false); maybe_print_date_line(&config, cur_day, start_day, &mut last_printed_day); print_event_line(*cal_config, *index, &event, cur_day, is_cursor); event.continues_after(cur_day) @@ -69,7 +69,7 @@ pub fn show_events_cursor( let relevant_events = cals_iter.peeking_take_while(|(_,event,_)| event.starts_on(cur_day)); for (i, event, cal_config) in relevant_events { - let is_cursor = cursor.map(|c| c.matches(&event)).unwrap_or(false); + let is_cursor = cursor.map(|c| c.matches_khevent(&event)).unwrap_or(false); maybe_print_date_line(&config, cur_day, start_day, &mut last_printed_day); print_event_line(cal_config, i, &event, cur_day, is_cursor); if event.continues_after(cur_day) { @@ -112,7 +112,7 @@ fn print_date_line(date: Date<Local>) { fn print_event_line( config: Option<&CalendarConfig>, index: usize, - event: &IcalVEvent, + event: &KhEvent, date: Date<Local>, is_cursor: bool ) { @@ -124,7 +124,7 @@ fn print_event_line( pub fn event_line( config: Option<&CalendarConfig>, - event: &IcalVEvent, + event: &KhEvent, cur_day: Date<Local>, is_cursor: bool ) -> Result<String, String> { @@ -164,7 +164,7 @@ pub fn event_line( } } -impl IcalVEvent { +impl KhEvent { fn starts_on(&self, date: Date<Local>) -> bool { let dtstart: Date<Local> = self.get_start().unwrap().into(); dtstart == date diff --git a/src/actions/index/bucketable.rs b/src/actions/index/bucketable.rs index 299d055..27ab9a6 100644 --- a/src/actions/index/bucketable.rs +++ b/src/actions/index/bucketable.rs @@ -2,7 +2,8 @@ use chrono::{Local, Date, Datelike, Duration}; use std::collections::HashMap; use std::{hash, cmp}; -use crate::icalwrap::{IcalVEvent, IcalVCalendar}; +use crate::icalwrap::IcalVCalendar; +//use crate::icalwrap::IcalVEvent; use crate::utils::misc; use crate::khline::KhLine; use crate::khevent::KhEvent; @@ -22,18 +23,19 @@ pub trait Bucketable { } } -impl Bucketable for IcalVEvent { +impl Bucketable for KhEvent { fn get_buckets(&self) -> Result<HashMap<String, Vec<String>>, String> { let mut result: HashMap<String, Vec<String>> = HashMap::new(); let start_date: Date<Local> = self.get_start().ok_or_else(|| format!("Invalid DTSTART in {}", self.get_uid()))?.into(); - let mut end_date: Date<Local> = self.get_end().map(|date| date.into()).unwrap_or(start_date); + //let mut end_date: Date<Local> = self.get_end().map(|date| date.into()).unwrap_or(start_date); + let mut end_date = self.get_last_relevant_date().map(|date| date.into()).unwrap_or(start_date); // end-dtimes are non-inclusive // so in case of date-only events, the last day of the event is dtend-1 - if self.is_allday() { - end_date = end_date.pred(); - } + //if self.is_allday() { + //end_date = end_date.pred(); + //} let buckets = Self::buckets_for_interval(start_date, end_date); let khline = KhLine::from(self); @@ -62,6 +64,7 @@ impl Bucketable for IcalVCalendar { fn get_buckets(&self) -> Result<HashMap<String, Vec<String>>, String> { let mut result: HashMap<String, Vec<String>> = HashMap::new(); for event in self.events_iter() { + let event = KhEvent::from_event(event); let recur_buckets = event.get_buckets()?; result.merge(recur_buckets); } diff --git a/src/actions/prettyprint.rs b/src/actions/prettyprint.rs index 51a0251..6b7fdad 100644 --- a/src/actions/prettyprint.rs +++ b/src/actions/prettyprint.rs @@ -6,7 +6,7 @@ use crate::KhResult; pub fn prettyprint() -> KhResult<()> { let lines = input::default_input_khlines()?; for line in lines { - let event = line.to_event()?; + let event = line.to_event()?.event; prettyprint_comp(&event, line.get_path()); } Ok(()) diff --git a/src/actions/unroll.rs b/src/actions/unroll.rs index 27f4e10..e3c8a09 100644 --- a/src/actions/unroll.rs +++ b/src/actions/unroll.rs @@ -24,7 +24,8 @@ fn do_unroll(filepath: &Path) -> KhResult<()> { let khline = path.parse::<KhLine>()?; let cal = khline.to_cal()?; - for event in cal.events_iter() { + for ical_event in cal.events_iter() { + let event = KhEvent::from_event(ical_event); if event.is_recur_master() { let recurs = event.get_recur_datetimes(); for datetime in recurs { diff --git a/src/cursorfile.rs b/src/cursorfile.rs index 43c9979..b1b5c64 100644 --- a/src/cursorfile.rs +++ b/src/cursorfile.rs @@ -3,6 +3,7 @@ use std::io; use crate::defaults::*; use crate::khline::KhLine; +use crate::khevent::KhEvent; use crate::utils::fileutil; use crate::KhResult; diff --git a/src/icalwrap/icalvevent.rs b/src/icalwrap/icalvevent.rs index 1494f03..9e9ba9f 100644 --- a/src/icalwrap/icalvevent.rs +++ b/src/icalwrap/icalvevent.rs @@ -32,34 +32,6 @@ impl IcalComponent for IcalVEvent { } } -impl KhEvent for IcalVEvent { - fn get_start(&self) -> Option<IcalTime> { - //TODO: should probably depend on is_recur_master, not the instance timestamp - match self.instance_timestamp { - Some(ref timestamp) => Some(timestamp.clone()), - None => { - self.get_dtstart() - } - } - } - - fn get_end(&self) -> Option<IcalTime> { - //TODO: should probably depend on is_recur_master, not the instance timestamp - match self.instance_timestamp { - Some(ref timestamp) => unsafe { - let icalduration = ical::icalcomponent_get_duration(self.ptr); - let dtend = ical::icaltime_add(**timestamp, icalduration); - Some(IcalTime::from(dtend)) - }, - None => self.get_dtend() - } - } - - fn is_recur_master(&self) -> bool { - self.has_property_rrule() && self.instance_timestamp.is_none() - } -} - impl IcalVEvent { pub fn from_ptr_with_parent( ptr: *mut ical::icalcomponent, @@ -106,14 +78,6 @@ impl IcalVEvent { } } - pub fn get_last_relevant_date(&self) -> Option<IcalTime> { - if self.is_allday() { - self.get_dtend().map(|dtend| dtend.pred()) - } else { - self.get_dtend().map(|dtend| dtend) - } - } - pub fn has_property_rrule(&self) -> bool { !self.get_properties(ical::icalproperty_kind_ICAL_RRULE_PROPERTY).is_empty() } @@ -139,17 +103,6 @@ impl IcalVEvent { result } - pub fn is_recur_valid(&self) -> bool { - if self.is_recur_master() { - true - } else if let Some(ref timestamp) = self.instance_timestamp { - let recur_times = self.get_recur_datetimes(); - recur_times.contains(timestamp) - } else { - self.instance_timestamp.is_none() - } - } - pub fn with_internal_timestamp(&self, datetime: &IcalTime) -> IcalVEvent { IcalVEvent { ptr: self.ptr, diff --git a/src/input.rs b/src/input.rs index 44e3244..3625ad7 100644 --- a/src/input.rs +++ b/src/input.rs @@ -6,8 +6,9 @@ use crate::khline::{KhLine,lines_to_khlines,khlines_to_events}; use crate::utils::stdioutils; use crate::icalwrap::IcalVEvent; use crate::selectors::SelectFilters; +use crate::khevent::KhEvent; -pub fn selection(args: &[&str]) -> Result<Box<dyn Iterator<Item = IcalVEvent>>, String> { +pub fn selection(args: &[&str]) -> Result<Box<dyn Iterator<Item = KhEvent>>, String> { if args.is_empty() { let khlines = default_input_khlines()?; let events = khlines_to_events(khlines); diff --git a/src/khevent.rs b/src/khevent.rs index b3c10a2..0ea4889 100644 --- a/src/khevent.rs +++ b/src/khevent.rs @@ -1,9 +1,114 @@ use crate::icalwrap::IcalTime; +use crate::icalwrap::IcalDuration; +use crate::icalwrap::IcalVEvent; -pub trait KhEvent { - fn get_start(&self) -> Option<IcalTime>; - fn get_end(&self) -> Option<IcalTime>; - fn is_recur_master(&self) -> bool; +pub struct KhEvent { + //TODO event should be private + pub event: IcalVEvent, + instance_timestamp: Option<IcalTime>, } +impl KhEvent { + pub fn get_start(&self) -> Option<IcalTime> { + //TODO: should probably depend on is_recur_master, not the instance timestamp + match self.instance_timestamp { + Some(ref timestamp) => Some(timestamp.clone()), + None => { + self.event.get_dtstart() + } + } + } + + pub fn get_end(&self) -> Option<IcalTime> { + //TODO: should probably depend on is_recur_master, not the instance timestamp + match self.instance_timestamp { + Some(ref timestamp) => unsafe { + let dur = self.get_duration().unwrap(); + let dtend = timestamp.to_owned() + dur; + Some(dtend) + //let icalduration = ical::icalcomponent_get_duration(self.event.ptr); + //let dtend = ical::icaltime_add(**timestamp, icalduration); + //Some(IcalTime::from(dtend)) + }, + None => self.event.get_dtend() + } + } + + pub fn get_calendar_name(&self) -> Option<String> { + self.event.get_parent().and_then(|cal| cal.get_calendar_name()) + } + + pub fn is_allday(&self) -> bool { + self.event.is_allday() + } + + pub fn get_duration(&self) -> Option<IcalDuration> { + self.event.get_duration() + } + + pub fn get_summary(&self) -> Option<String> { + self.event.get_summary() + } + + pub fn get_description(&self) -> Option<String> { + self.event.get_description() + } + + pub fn get_location(&self) -> Option<String> { + self.event.get_location() + } + + pub fn get_uid(&self) -> String { + self.event.get_uid() + } + + pub fn get_last_relevant_date(&self) -> Option<IcalTime> { + //TODO this is still wrong + //events can end at 00:00 + if self.is_allday() { + self.get_end().map(|dtend| dtend.pred()) + } else { + self.get_end().map(|dtend| dtend) + } + } + + pub fn is_recur_master(&self) -> bool { + self.event.has_property_rrule() && self.instance_timestamp.is_none() + } + + pub fn is_recur_valid(&self) -> bool { + if self.is_recur_master() { + true + } else if let Some(ref timestamp) = self.instance_timestamp { + let recur_times = self.event.get_recur_datetimes(); + recur_times.contains(timestamp) + } else { + self.instance_timestamp.is_none() + } + } + + pub fn get_recur_instances(&self) -> impl Iterator<Item = KhEvent> + '_ { + self.event.get_recur_instances().map(|event| KhEvent::from_event(event)) + } + + + pub fn get_recur_datetimes(&self) -> Vec<IcalTime> { + self.event.get_recur_datetimes() + } + + pub fn from_event(event: IcalVEvent) -> Self { + Self { + event, + instance_timestamp: None, + } + } + + pub fn from_event_with_timestamp(event: IcalVEvent, instance_timestamp: Option<IcalTime>) -> Self { + Self { + event, + instance_timestamp, + } + } + +} diff --git a/src/khline.rs b/src/khline.rs index ffb79a3..03a6407 100644 --- a/src/khline.rs +++ b/src/khline.rs @@ -31,19 +31,24 @@ impl KhLine { Ok(calendar) } - pub fn to_event(&self) -> io::Result<IcalVEvent> { + pub fn to_event(&self) -> io::Result<KhEvent> { let calendar = self.to_cal()?; let mut event = calendar.get_first_event(); - if let Some(ref time) = self.time { - event = event.with_internal_timestamp(time); - } - Ok(event) + Ok(KhEvent::from_event_with_timestamp(event, self.time.clone())) + //if let Some(ref time) = self.time { + //event = event.with_internal_timestamp(time); + //} + //Ok(event) } pub fn with_index(self, index: usize) -> Self { Self { path: self.path, time: self.time, index: Some(index) } } + pub fn matches_khevent(&self, event: &KhEvent) -> bool { + self == &KhLine::from(event) + } + pub fn matches(&self, event: &IcalVEvent) -> bool { self == &KhLine::from(event) } @@ -66,6 +71,15 @@ impl KhLine { impl From<&IcalVEvent> for KhLine { fn from(event: &IcalVEvent) -> Self { let path = event.get_parent().unwrap().get_path().unwrap().to_path_buf(); + let time = event.get_dtstart(); + + KhLine{ path, time, index: None } + } +} + +impl From<&KhEvent> for KhLine { + fn from(event: &KhEvent) -> Self { + let path = event.event.get_parent().unwrap().get_path().unwrap().to_path_buf(); let time = event.get_start(); KhLine{ path, time, index: None } @@ -127,7 +141,7 @@ pub fn lines_to_khlines_indexed(lines: impl Iterator<Item = String>) -> impl Ite .flatten() } -pub fn khlines_to_events(lines: impl Iterator<Item = KhLine>) -> impl Iterator<Item = IcalVEvent> { +pub fn khlines_to_events(lines: impl Iterator<Item = KhLine>) -> impl Iterator<Item = KhEvent> { lines.map(|line| line.to_event()).flatten() } diff --git a/src/selectors/cal.rs b/src/selectors/cal.rs index 9567742..aab39b1 100644 --- a/src/selectors/cal.rs +++ b/src/selectors/cal.rs @@ -1,6 +1,7 @@ use super::*; -use crate::icalwrap::IcalVEvent; +//use crate::icalwrap::IcalVEvent; +use crate::khevent::KhEvent; pub struct CalendarFilter { cal_names: Vec<String> @@ -16,8 +17,8 @@ impl SelectFilter for CalendarFilter { !self.cal_names.is_empty() } - fn includes(&self, event: &IcalVEvent) -> bool { - event.get_parent() + fn includes(&self, event: &KhEvent) -> bool { + event.event.get_parent() .and_then(|cal| cal.get_path()) .and_then(|path| path.parent()) .map(|path| path.to_string_lossy().to_lowercase()) diff --git a/src/selectors/grep.rs b/src/selectors/grep.rs index 47ae617..d0dd327 100644 --- a/src/selectors/grep.rs +++ b/src/selectors/grep.rs @@ -1,6 +1,7 @@ use super::*; -use crate::icalwrap::IcalVEvent; +//use crate::icalwrap::IcalVEvent; +use crate::khevent::KhEvent; pub struct GrepFilter { terms: Vec<String> @@ -16,7 +17,7 @@ impl SelectFilter for GrepFilter { !self.terms.is_empty() } - fn includes(&self, event: &IcalVEvent) -> bool { + fn includes(&self, event: &KhEvent) -> bool { for term in &self.terms { if let Some(summary) = event.get_summary() { if summary.to_lowercase().contains(term) { diff --git a/src/selectors/mod.rs b/src/selectors/mod.rs index 940c1b3..7092cd0 100644 --- a/src/selectors/mod.rs +++ b/src/selectors/mod.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use crate::khline::{KhLine,khlines_to_events}; -use crate::icalwrap::IcalVEvent; use crate::khevent::KhEvent; use self::daterange::{SelectFilterFrom,SelectFilterTo}; @@ -28,7 +27,7 @@ pub struct SelectFilters { pub trait SelectFilter { fn add_term(&mut self, it: &mut dyn Iterator<Item = &&str>); fn is_not_empty(&self) -> bool; - fn includes(&self, event: &IcalVEvent) -> bool; + fn includes(&self, event: &KhEvent) -> bool; } impl SelectFilters { @@ -91,13 +90,13 @@ impl SelectFilters { Ok(SelectFilters { from, to, range, others }) } - fn line_is_from(&self, event: &IcalVEvent) -> bool { + fn line_is_from(&self, event: &KhEvent) -> bool { let starts_after = self.from.includes_date(event.get_start().unwrap().into()); let ends_after = self.from.includes_date(event.get_end().unwrap().into()); starts_after || ends_after } - fn line_is_to(&self, event: &IcalVEvent) -> bool { + fn line_is_to(&self, event: &KhEvent) -> bool { self.to.includes_date(event.get_start().unwrap().into()) } @@ -109,22 +108,22 @@ impl SelectFilters { } } - fn others(&self, event: &IcalVEvent) -> bool { + fn others(&self, event: &KhEvent) -> bool { self.others.is_empty() || self.others.iter().any(|filter| filter.includes(event)) } - pub fn is_selected(&self, event: &IcalVEvent) -> bool { + pub fn is_selected(&self, event: &KhEvent) -> bool { self.line_is_from(event) && self.line_is_to(event) && self.others(event) } - pub fn is_selected_index(&self, index: usize, event: &IcalVEvent) -> bool { + pub fn is_selected_index(&self, index: usize, event: &KhEvent) -> bool { self.filter_index(index) && self.line_is_from(event) && self.line_is_to(event) && self.others(event) } pub fn filter_khlines( self, khlines: impl Iterator<Item = KhLine>, - ) -> impl Iterator<Item = IcalVEvent> { + ) -> impl Iterator<Item = KhEvent> { let events = khlines_to_events(khlines); events .enumerate() diff --git a/src/selectors/prop.rs b/src/selectors/prop.rs index 4f644d4..c5188ee 100644 --- a/src/selectors/prop.rs +++ b/src/selectors/prop.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use super::*; -use crate::icalwrap::IcalVEvent; +use crate::khevent::KhEvent; +//use crate::icalwrap::IcalVEvent; use crate::icalwrap::IcalComponent; pub struct PropFilter { @@ -22,9 +23,9 @@ impl SelectFilter for PropFilter { !self.terms.is_empty() } - fn includes(&self, event: &IcalVEvent) -> bool { + fn includes(&self, event: &KhEvent) -> bool { for (term, values) in &self.terms { - for prop in event.get_properties_by_name(term) { + for prop in event.event.get_properties_by_name(term) { let value = prop.get_value().to_lowercase(); if values.iter().any(|x| value.contains(x)) { return true; |