Add JSON output support

This commit is contained in:
Matthias Beyer 2018-03-12 17:46:06 +01:00
parent e8ae2fb73e
commit e755bfd9de
3 changed files with 79 additions and 22 deletions

View file

@ -29,16 +29,22 @@ handlebars = "0.29"
vobject = "0.4" vobject = "0.4"
walkdir = "1" walkdir = "1"
uuid = { version = "0.6", features = ["v4"] } uuid = { version = "0.6", features = ["v4"] }
serde_json = "1"
libimagrt = { version = "0.7.0", path = "../../../lib/core/libimagrt" } libimagrt = { version = "0.7.0", path = "../../../lib/core/libimagrt" }
libimagstore = { version = "0.7.0", path = "../../../lib/core/libimagstore" } libimagstore = { version = "0.7.0", path = "../../../lib/core/libimagstore" }
libimagerror = { version = "0.7.0", path = "../../../lib/core/libimagerror" } libimagerror = { version = "0.7.0", path = "../../../lib/core/libimagerror" }
libimagcontact = { version = "0.7.0", path = "../../../lib/domain/libimagcontact" }
libimagutil = { version = "0.7.0", path = "../../../lib/etc/libimagutil" } libimagutil = { version = "0.7.0", path = "../../../lib/etc/libimagutil" }
libimagentryref = { version = "0.7.0", path = "../../../lib/entry/libimagentryref" } libimagentryref = { version = "0.7.0", path = "../../../lib/entry/libimagentryref" }
libimagentryedit = { version = "0.7.0", path = "../../../lib/entry/libimagentryedit" } libimagentryedit = { version = "0.7.0", path = "../../../lib/entry/libimagentryedit" }
libimaginteraction = { version = "0.7.0", path = "../../../lib/etc/libimaginteraction" } libimaginteraction = { version = "0.7.0", path = "../../../lib/etc/libimaginteraction" }
[dependencies.libimagcontact]
version = "0.7.0"
path = "../../../lib/domain/libimagcontact"
default-features = false
features = ["deser"]
[dependencies.clap] [dependencies.clap]
version = ">=2.29" version = ">=2.29"
default-features = false default-features = false

View file

@ -40,6 +40,7 @@ extern crate toml_query;
extern crate handlebars; extern crate handlebars;
extern crate walkdir; extern crate walkdir;
extern crate uuid; extern crate uuid;
extern crate serde_json;
extern crate libimagcontact; extern crate libimagcontact;
extern crate libimagstore; extern crate libimagstore;
@ -70,6 +71,7 @@ use libimagcontact::store::ContactStore;
use libimagcontact::store::UniqueContactPathGenerator; use libimagcontact::store::UniqueContactPathGenerator;
use libimagcontact::error::ContactError as CE; use libimagcontact::error::ContactError as CE;
use libimagcontact::contact::Contact; use libimagcontact::contact::Contact;
use libimagcontact::deser::DeserVcard;
use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagentryref::reference::Ref; use libimagentryref::reference::Ref;
use libimagentryref::refstore::RefStore; use libimagentryref::refstore::RefStore;
@ -111,7 +113,7 @@ fn list(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("list").unwrap(); let scmd = rt.cli().subcommand_matches("list").unwrap();
let list_format = get_contact_print_format("contact.list_format", rt, &scmd); let list_format = get_contact_print_format("contact.list_format", rt, &scmd);
let _ = rt let iterator = rt
.store() .store()
.all_contacts() .all_contacts()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
@ -126,27 +128,46 @@ fn list(rt: &Runtime) {
.get_contact_data() .get_contact_data()
.map(|cd| (fle, cd)) .map(|cd| (fle, cd))
.map(|(fle, cd)| (fle, cd.into_inner())) .map(|(fle, cd)| (fle, cd.into_inner()))
.map(|(fle, cd)| (fle, Vcard::from_component(cd))) .map(|(fle, cd)| {
.map_err_trace_exit_unwrap(1) let card = Vcard::from_component(cd).unwrap_or_else(|e| {
})
.enumerate()
.map(|(i, (fle, vcard))| {
let hash = String::from(fle.get_hash().map_err_trace_exit_unwrap(1));
let vcard = vcard.unwrap_or_else(|e| {
error!("Element is not a VCARD object: {:?}", e); error!("Element is not a VCARD object: {:?}", e);
exit(1) exit(1)
}); });
(fle, card)
})
.map_err_trace_exit_unwrap(1)
})
.enumerate();
if scmd.is_present("json") {
let v : Vec<DeserVcard> = iterator
.map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect();
match ::serde_json::to_string(&v) {
Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
Err(e) => {
error!("Error generating JSON: {:?}", e);
::std::process::exit(1)
}
}
} else {
iterator
.map(|(i, (fle, vcard))| {
let hash = String::from(fle.get_hash().map_err_trace_exit_unwrap(1));
let data = build_data_object_for_handlebars(i, hash, &vcard); let data = build_data_object_for_handlebars(i, hash, &vcard);
let s = list_format.render("format", &data) list_format.render("format", &data)
.err_from_str() .err_from_str()
.map_err(CE::from) .map_err(CE::from)
.map_err_trace_exit_unwrap(1); .map_err_trace_exit_unwrap(1)
writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit()
}) })
.collect::<Vec<_>>();
// collect, so that we can have rendered all the things and printing is faster.
.collect::<Vec<String>>()
.into_iter()
.for_each(|s| {
writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit()
});
}
} }
fn import(rt: &Runtime) { fn import(rt: &Runtime) {
@ -227,7 +248,8 @@ fn find(rt: &Runtime) {
let show_format = get_contact_print_format("contact.show_format", rt, &scmd); let show_format = get_contact_print_format("contact.show_format", rt, &scmd);
let list_format = get_contact_print_format("contact.list_format", rt, &scmd); let list_format = get_contact_print_format("contact.list_format", rt, &scmd);
rt.store() let iterator = rt
.store()
.all_contacts() .all_contacts()
.map_err_trace_exit_unwrap(1) .map_err_trace_exit_unwrap(1)
.into_get_iter(rt.store()) .into_get_iter(rt.store())
@ -267,7 +289,20 @@ fn find(rt: &Runtime) {
None None
} }
}) })
.enumerate() .enumerate();
if scmd.is_present("json") {
let v : Vec<DeserVcard> = iterator
.map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect();
match ::serde_json::to_string(&v) {
Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
Err(e) => {
error!("Error generating JSON: {:?}", e);
::std::process::exit(1)
}
}
} else {
iterator
.for_each(|(i, (fle, card))| { .for_each(|(i, (fle, card))| {
let fmt = if scmd.is_present("find-show") { let fmt = if scmd.is_present("find-show") {
&show_format &show_format
@ -290,6 +325,7 @@ fn find(rt: &Runtime) {
.unwrap_or_exit(); .unwrap_or_exit();
}); });
} }
}
fn get_contact_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) -> Handlebars { fn get_contact_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) -> Handlebars {
let fmt = scmd let fmt = scmd

View file

@ -38,6 +38,12 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
.multiple(false) .multiple(false)
.value_name("FORMAT") .value_name("FORMAT")
.help("Format to format the listing")) .help("Format to format the listing"))
.arg(Arg::with_name("json")
.long("json")
.takes_value(false)
.required(false)
.multiple(false)
.help("Print output as JSON"))
) )
.subcommand(SubCommand::with_name("import") .subcommand(SubCommand::with_name("import")
@ -102,6 +108,15 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
.conflicts_with("find-show") .conflicts_with("find-show")
) )
.arg(Arg::with_name("json")
.long("json")
.takes_value(false)
.required(false)
.multiple(false)
.help("Print output as JSON")
.conflicts_with("find-show")
.conflicts_with("find-list"))
) )
.subcommand(SubCommand::with_name("create") .subcommand(SubCommand::with_name("create")