Enhance listing functionality with handlebars templating
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
8dbb2f1590
commit
14dc03f40f
5 changed files with 114 additions and 33 deletions
|
@ -21,10 +21,11 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" }
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
walkdir = "2.2.8"
|
walkdir = "2.2.8"
|
||||||
vobject = "0.7"
|
vobject = "0.7"
|
||||||
|
handlebars = "2"
|
||||||
|
|
||||||
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
|
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
|
||||||
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
|
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate toml_query;
|
extern crate toml_query;
|
||||||
extern crate walkdir;
|
extern crate walkdir;
|
||||||
|
extern crate handlebars;
|
||||||
|
|
||||||
#[macro_use] extern crate libimagrt;
|
#[macro_use] extern crate libimagrt;
|
||||||
extern crate libimagcalendar;
|
extern crate libimagcalendar;
|
||||||
|
@ -163,7 +164,10 @@ fn import(rt: &Runtime) {
|
||||||
fn list(rt: &Runtime) {
|
fn list(rt: &Runtime) {
|
||||||
use util::*;
|
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()
|
let ref_config = rt.config()
|
||||||
.ok_or_else(|| format_err!("No configuration, cannot continue!"))
|
.ok_or_else(|| format_err!("No configuration, cannot continue!"))
|
||||||
.map_err_trace_exit_unwrap()
|
.map_err_trace_exit_unwrap()
|
||||||
|
@ -173,8 +177,14 @@ fn list(rt: &Runtime) {
|
||||||
.ok_or_else(|| format_err!("Configuration missing: {}", libimagentryref::reference::Config::LOCATION))
|
.ok_or_else(|| format_err!("Configuration missing: {}", libimagentryref::reference::Config::LOCATION))
|
||||||
.map_err_trace_exit_unwrap();
|
.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 event_filter = |pefle: &ParsedEventFLE| true; // TODO: impl filtering
|
||||||
|
|
||||||
|
let mut listed_events = 0;
|
||||||
|
|
||||||
rt.store()
|
rt.store()
|
||||||
.all_events()
|
.all_events()
|
||||||
.map_err_trace_exit_unwrap()
|
.map_err_trace_exit_unwrap()
|
||||||
|
@ -186,37 +196,25 @@ fn list(rt: &Runtime) {
|
||||||
.map(|ev| ParsedEventFLE::parse(ev, &ref_config))
|
.map(|ev| ParsedEventFLE::parse(ev, &ref_config))
|
||||||
.trace_unwrap_exit()
|
.trace_unwrap_exit()
|
||||||
.filter(|e| event_filter(e))
|
.filter(|e| event_filter(e))
|
||||||
.for_each(|parsed_event| {
|
.for_each(|parsed_entry| {
|
||||||
for event in parsed_event.get_data().events().filter_map(RResult::ok) {
|
parsed_entry
|
||||||
macro_rules! get_data {
|
.get_data()
|
||||||
($t:expr, $text:expr) => {
|
.events()
|
||||||
($t).map(|obj| obj.into_raw()).unwrap_or_else(|| String::from($text))
|
.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(), "<no summary>");
|
let rendered = list_format
|
||||||
let uid = get_data!(event.uid(), "<no uid>");
|
.render("format", &data)
|
||||||
let description = get_data!(event.description(), "<no description>");
|
.map_err(Error::from)
|
||||||
let dtstart = get_data!(event.dtstart(), "<no start date>");
|
.map_err_trace_exit_unwrap();
|
||||||
let dtend = get_data!(event.dtend(), "<no end date>");
|
|
||||||
let location = get_data!(event.location(), "<no location>");
|
|
||||||
|
|
||||||
let summary_underline = std::iter::repeat('-').take(summary.len()).collect::<String>();
|
writeln!(rt.stdout(), "{}", rendered).to_exit_code().unwrap_or_exit()
|
||||||
|
});
|
||||||
|
|
||||||
writeln!(rt.stdout(),
|
rt.report_touched(parsed_entry.get_entry().get_location()).unwrap_or_exit();
|
||||||
"{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();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,3 +223,4 @@ fn is_not_hidden(entry: &DirEntry) -> bool {
|
||||||
!entry.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
|
!entry.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,13 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||||
.subcommand(SubCommand::with_name("list")
|
.subcommand(SubCommand::with_name("list")
|
||||||
.about("List calendar entries")
|
.about("List calendar entries")
|
||||||
.version("0.1")
|
.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"))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,18 @@
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// 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::ICalendar;
|
||||||
|
use vobject::icalendar::Event;
|
||||||
|
use handlebars::Handlebars;
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use failure::err_msg;
|
||||||
|
use toml_query::read::TomlValueReadTypeExt;
|
||||||
|
|
||||||
|
use libimagrt::runtime::Runtime;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
use libimagentryref::reference::fassade::RefFassade;
|
use libimagentryref::reference::fassade::RefFassade;
|
||||||
use libimagentryref::reference::Ref;
|
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<Handlebars>
|
||||||
|
{
|
||||||
|
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() , "<no dtend>"));
|
||||||
|
data.insert("dtstart" , process_opt!(event.dtstart() , "<no dtstart>"));
|
||||||
|
data.insert("dtstamp" , process_opt!(event.dtstamp() , "<no dtstamp>"));
|
||||||
|
data.insert("uid" , process_opt!(event.uid() , "<no uid>"));
|
||||||
|
data.insert("description" , process_opt!(event.description() , "<no description>"));
|
||||||
|
data.insert("summary" , process_opt!(event.summary() , "<no summary>"));
|
||||||
|
data.insert("url" , process_opt!(event.url() , "<no url>"));
|
||||||
|
data.insert("location" , process_opt!(event.location() , "<no location>"));
|
||||||
|
data.insert("class" , process_opt!(event.class() , "<no class>"));
|
||||||
|
data.insert("categories" , process_opt!(event.categories() , "<no categories>"));
|
||||||
|
data.insert("transp" , process_opt!(event.transp() , "<no transp>"));
|
||||||
|
data.insert("rrule" , process_opt!(event.rrule() , "<no rrule>"));
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
15
imagrc.toml
15
imagrc.toml
|
@ -334,6 +334,21 @@ Email : {{EMAIL}}
|
||||||
Address : {{ADR}}
|
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]
|
[log]
|
||||||
logs = ["default"]
|
logs = ["default"]
|
||||||
default = "default"
|
default = "default"
|
||||||
|
|
Loading…
Reference in a new issue