diff --git a/bin/domain/imag-calendar/Cargo.toml b/bin/domain/imag-calendar/Cargo.toml index 62e21521..7801ac80 100644 --- a/bin/domain/imag-calendar/Cargo.toml +++ b/bin/domain/imag-calendar/Cargo.toml @@ -21,10 +21,11 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" } maintenance = { status = "actively-developed" } [dependencies] -log = "0.4" -failure = "0.1" -walkdir = "2.2.8" -vobject = "0.7" +log = "0.4" +failure = "0.1" +walkdir = "2.2.8" +vobject = "0.7" +handlebars = "2" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } diff --git a/bin/domain/imag-calendar/src/main.rs b/bin/domain/imag-calendar/src/main.rs index f5b9bbdb..a94e2ee2 100644 --- a/bin/domain/imag-calendar/src/main.rs +++ b/bin/domain/imag-calendar/src/main.rs @@ -39,6 +39,7 @@ extern crate clap; extern crate toml_query; extern crate walkdir; +extern crate handlebars; #[macro_use] extern crate libimagrt; extern crate libimagcalendar; @@ -163,7 +164,10 @@ fn import(rt: &Runtime) { fn list(rt: &Runtime) { use util::*; - let scmd = rt.cli().subcommand_matches("list").unwrap(); // safe by clap + let scmd = rt.cli().subcommand_matches("list").unwrap(); // safe by clap + let list_format = get_event_print_format("calendar.list_format", rt, &scmd) + .map_err_trace_exit_unwrap(); + let ref_config = rt.config() .ok_or_else(|| format_err!("No configuration, cannot continue!")) .map_err_trace_exit_unwrap() @@ -173,8 +177,14 @@ fn list(rt: &Runtime) { .ok_or_else(|| format_err!("Configuration missing: {}", libimagentryref::reference::Config::LOCATION)) .map_err_trace_exit_unwrap(); + + debug!("List format: {:?}", list_format); + debug!("Ref config : {:?}", ref_config); + let event_filter = |pefle: &ParsedEventFLE| true; // TODO: impl filtering + let mut listed_events = 0; + rt.store() .all_events() .map_err_trace_exit_unwrap() @@ -186,37 +196,25 @@ fn list(rt: &Runtime) { .map(|ev| ParsedEventFLE::parse(ev, &ref_config)) .trace_unwrap_exit() .filter(|e| event_filter(e)) - .for_each(|parsed_event| { - for event in parsed_event.get_data().events().filter_map(RResult::ok) { - macro_rules! get_data { - ($t:expr, $text:expr) => { - ($t).map(|obj| obj.into_raw()).unwrap_or_else(|| String::from($text)) - } - } + .for_each(|parsed_entry| { + parsed_entry + .get_data() + .events() + .filter_map(RResult::ok) + .filter(event_filter) + .for_each(|event| { + listed_events = listed_events + 1; + let data = build_data_object_for_handlebars(listed_events, &event); - let summary = get_data!(event.summary(), ""); - let uid = get_data!(event.uid(), ""); - let description = get_data!(event.description(), ""); - let dtstart = get_data!(event.dtstart(), ""); - let dtend = get_data!(event.dtend(), ""); - let location = get_data!(event.location(), ""); + let rendered = list_format + .render("format", &data) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); - let summary_underline = std::iter::repeat('-').take(summary.len()).collect::(); + writeln!(rt.stdout(), "{}", rendered).to_exit_code().unwrap_or_exit() + }); - writeln!(rt.stdout(), - "{summary}\n{summary_underline}\n\n{uid}\n{description}\n{dtstart}\n{dtend}\n{location}\n\n", - summary = summary, - summary_underline = summary_underline, - uid = uid, - description = description, - dtstart = dtstart, - dtend = dtend, - location = location) - .to_exit_code() - .unwrap_or_exit(); - } - - rt.report_touched(parsed_event.get_entry().get_location()).unwrap_or_exit(); + rt.report_touched(parsed_entry.get_entry().get_location()).unwrap_or_exit(); }); } @@ -225,3 +223,4 @@ fn is_not_hidden(entry: &DirEntry) -> bool { !entry.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false) } + diff --git a/bin/domain/imag-calendar/src/ui.rs b/bin/domain/imag-calendar/src/ui.rs index 148e2ce7..8386357e 100644 --- a/bin/domain/imag-calendar/src/ui.rs +++ b/bin/domain/imag-calendar/src/ui.rs @@ -60,6 +60,13 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .subcommand(SubCommand::with_name("list") .about("List calendar entries") .version("0.1") + .arg(Arg::with_name("format") + .long("format") + .short("F") + .takes_value(true) + .required(false) + .multiple(false) + .help("Override the format used to list one event")) ) } diff --git a/bin/domain/imag-calendar/src/util.rs b/bin/domain/imag-calendar/src/util.rs index 6c142337..ab9f8eba 100644 --- a/bin/domain/imag-calendar/src/util.rs +++ b/bin/domain/imag-calendar/src/util.rs @@ -17,10 +17,18 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // +use std::collections::BTreeMap; + +use clap::ArgMatches; use vobject::icalendar::ICalendar; +use vobject::icalendar::Event; +use handlebars::Handlebars; use failure::Fallible as Result; use failure::Error; +use failure::err_msg; +use toml_query::read::TomlValueReadTypeExt; +use libimagrt::runtime::Runtime; use libimagstore::store::FileLockEntry; use libimagentryref::reference::fassade::RefFassade; use libimagentryref::reference::Ref; @@ -58,3 +66,54 @@ impl<'a> ParsedEventFLE<'a> { } } +pub fn get_event_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) + -> Result +{ + scmd.value_of("format") + .map(String::from) + .map(Ok) + .unwrap_or_else(|| { + rt.config() + .ok_or_else(|| err_msg("No configuration file"))? + .read_string(config_value_path)? + .ok_or_else(|| err_msg("Configuration 'contact.list_format' does not exist")) + }) + .and_then(|fmt| { + let mut hb = Handlebars::new(); + hb.register_template_string("format", fmt)?; + + hb.register_escape_fn(::handlebars::no_escape); + ::libimaginteraction::format::register_all_color_helpers(&mut hb); + ::libimaginteraction::format::register_all_format_helpers(&mut hb); + + Ok(hb) + }) +} + +pub fn build_data_object_for_handlebars<'a>(i: usize, event: &Event<'a>) + -> BTreeMap<&'static str, String> +{ + macro_rules! process_opt { + ($t:expr, $text:expr) => { + ($t).map(|obj| obj.into_raw()).unwrap_or_else(|| String::from($text)) + } + } + + let mut data = BTreeMap::new(); + + data.insert("i" , format!("{}", i)); + data.insert("dtend" , process_opt!(event.dtend() , "")); + data.insert("dtstart" , process_opt!(event.dtstart() , "")); + data.insert("dtstamp" , process_opt!(event.dtstamp() , "")); + data.insert("uid" , process_opt!(event.uid() , "")); + data.insert("description" , process_opt!(event.description() , "")); + data.insert("summary" , process_opt!(event.summary() , "")); + data.insert("url" , process_opt!(event.url() , "")); + data.insert("location" , process_opt!(event.location() , "")); + data.insert("class" , process_opt!(event.class() , "")); + data.insert("categories" , process_opt!(event.categories() , "")); + data.insert("transp" , process_opt!(event.transp() , "")); + data.insert("rrule" , process_opt!(event.rrule() , "")); + + data +} diff --git a/imagrc.toml b/imagrc.toml index 3b353803..0bd1c291 100644 --- a/imagrc.toml +++ b/imagrc.toml @@ -334,6 +334,21 @@ Email : {{EMAIL}} Address : {{ADR}} """ +[calendar] +list_format = "{{lpad 5 i}} | {{abbrev 5 uid}} | {{summary}} | {{location}}" +show_format = """ +{{i}} - {{uid}} + +Summary : {{summary}} +Start : {{dtstart}} +End : {{dtend}} +Url : {{url}} +Location : {{location}} + +{{description}} + +""" + [log] logs = ["default"] default = "default"