Reimplement imag-contact
This commit is contained in:
parent
a83d10fb1e
commit
d6f8751f6e
3 changed files with 108 additions and 167 deletions
|
@ -44,14 +44,13 @@ use toml_query::read::TomlValueReadExt;
|
|||
use toml::Value;
|
||||
use uuid::Uuid;
|
||||
|
||||
use libimagcontact::store::ContactStore;
|
||||
use libimagcontact::error::ContactError as CE;
|
||||
use libimagcontact::store::UniqueContactPathGenerator;
|
||||
use libimagrt::runtime::Runtime;
|
||||
use libimagerror::str::ErrFromStr;
|
||||
use libimagerror::trace::MapErrTrace;
|
||||
use libimagerror::trace::trace_error;
|
||||
use libimagutil::warn_result::WarnResult;
|
||||
use libimagentryref::refstore::RefStore;
|
||||
|
||||
const TEMPLATE : &'static str = include_str!("../static/new-contact-template.toml");
|
||||
|
||||
|
@ -158,7 +157,8 @@ pub fn create(rt: &Runtime) {
|
|||
|
||||
if let Some(location) = location {
|
||||
if !scmd.is_present("dont-track") {
|
||||
RefStore::create_ref::<UniqueContactPathGenerator, _>(rt.store(), location)
|
||||
rt.store()
|
||||
.create_from_path(&location)
|
||||
.map_err_trace_exit_unwrap(1);
|
||||
|
||||
info!("Created entry in store");
|
||||
|
|
|
@ -48,7 +48,6 @@ extern crate libimagstore;
|
|||
extern crate libimagerror;
|
||||
extern crate libimagutil;
|
||||
extern crate libimaginteraction;
|
||||
extern crate libimagentryref;
|
||||
extern crate libimagentryedit;
|
||||
|
||||
use std::process::exit;
|
||||
|
@ -57,7 +56,6 @@ use std::io::Write;
|
|||
|
||||
use handlebars::Handlebars;
|
||||
use clap::ArgMatches;
|
||||
use vobject::vcard::Vcard;
|
||||
use toml_query::read::TomlValueReadTypeExt;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
|
@ -67,14 +65,12 @@ use libimagerror::str::ErrFromStr;
|
|||
use libimagerror::trace::MapErrTrace;
|
||||
use libimagerror::io::ToExitCode;
|
||||
use libimagerror::exit::ExitUnwrap;
|
||||
use libimagerror::iter::TraceIterator;
|
||||
use libimagcontact::store::ContactStore;
|
||||
use libimagcontact::store::UniqueContactPathGenerator;
|
||||
use libimagcontact::error::ContactError as CE;
|
||||
use libimagcontact::contact::Contact;
|
||||
use libimagcontact::deser::DeserVcard;
|
||||
use libimagstore::iter::get::StoreIdGetIteratorExtension;
|
||||
use libimagentryref::reference::Ref;
|
||||
use libimagentryref::refstore::RefStore;
|
||||
|
||||
mod ui;
|
||||
mod util;
|
||||
|
@ -128,24 +124,13 @@ fn list(rt: &Runtime) {
|
|||
.ok_or_else(|| CE::from("StoreId not found".to_owned()))
|
||||
.map_err_trace_exit_unwrap(1);
|
||||
|
||||
fle
|
||||
.get_contact_data()
|
||||
.map(|cd| (fle, cd))
|
||||
.map(|(fle, cd)| (fle, cd.into_inner()))
|
||||
.map(|(fle, cd)| {
|
||||
let card = Vcard::from_component(cd).unwrap_or_else(|e| {
|
||||
error!("Element is not a VCARD object: {:?}", e);
|
||||
exit(1)
|
||||
});
|
||||
(fle, card)
|
||||
})
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
fle.deser().map_err_trace_exit_unwrap(1)
|
||||
})
|
||||
.enumerate();
|
||||
|
||||
if scmd.is_present("json") {
|
||||
let v : Vec<DeserVcard> = iterator
|
||||
.map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect();
|
||||
let v : Vec<DeserVcard> = iterator.map(|tpl| tpl.1).collect();
|
||||
|
||||
match ::serde_json::to_string(&v) {
|
||||
Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
|
||||
Err(e) => {
|
||||
|
@ -155,9 +140,8 @@ fn list(rt: &Runtime) {
|
|||
}
|
||||
} 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);
|
||||
.map(|(i, deservcard)| {
|
||||
let data = build_data_object_for_handlebars(i, &deservcard);
|
||||
|
||||
list_format.render("format", &data)
|
||||
.err_from_str()
|
||||
|
@ -219,30 +203,45 @@ fn import(rt: &Runtime) {
|
|||
fn show(rt: &Runtime) {
|
||||
let scmd = rt.cli().subcommand_matches("show").unwrap();
|
||||
let hash = scmd.value_of("hash").map(String::from).unwrap(); // safed by clap
|
||||
|
||||
let contact_data = rt.store()
|
||||
.get_ref::<UniqueContactPathGenerator, _>(hash.clone())
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
.ok_or(CE::from(format!("No entry for hash {}", hash)))
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
.get_contact_data()
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
.into_inner();
|
||||
let vcard = Vcard::from_component(contact_data)
|
||||
.unwrap_or_else(|e| {
|
||||
error!("Element is not a VCARD object: {:?}", e);
|
||||
exit(1)
|
||||
});
|
||||
|
||||
let show_format = get_contact_print_format("contact.show_format", rt, &scmd);
|
||||
let data = build_data_object_for_handlebars(0, hash, &vcard);
|
||||
let out = rt.stdout();
|
||||
let mut outlock = out.lock();
|
||||
|
||||
rt.store()
|
||||
.all_contacts()
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
.into_get_iter(rt.store())
|
||||
.trace_unwrap_exit(1)
|
||||
.map(|o| o.unwrap_or_else(|| {
|
||||
error!("Failed to get entry");
|
||||
exit(1)
|
||||
}))
|
||||
.filter_map(|entry| {
|
||||
let deser = entry.deser().map_err_trace_exit_unwrap(1);
|
||||
|
||||
if deser.uid()
|
||||
.ok_or_else(|| {
|
||||
error!("Could not get StoreId from Store::all_contacts(). This is a BUG!");
|
||||
::std::process::exit(1)
|
||||
})
|
||||
.unwrap() // exited above
|
||||
.starts_with(&hash)
|
||||
{
|
||||
Some(deser)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.for_each(|elem| {
|
||||
let data = build_data_object_for_handlebars(0, &elem);
|
||||
|
||||
let s = show_format
|
||||
.render("format", &data)
|
||||
.err_from_str()
|
||||
.map_err(CE::from)
|
||||
.map_err_trace_exit_unwrap(1);
|
||||
let _ = writeln!(::std::io::stdout(), "{}", s).to_exit_code().unwrap_or_exit();
|
||||
let _ = writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit();
|
||||
});
|
||||
}
|
||||
|
||||
fn find(rt: &Runtime) {
|
||||
|
@ -270,30 +269,20 @@ fn find(rt: &Runtime) {
|
|||
})
|
||||
.unwrap() // safed above
|
||||
})
|
||||
.filter_map(|cont| {
|
||||
let comp = cont
|
||||
.get_contact_data()
|
||||
.map_err_trace_exit_unwrap(1)
|
||||
.into_inner();
|
||||
|
||||
let card = Vcard::from_component(comp)
|
||||
.map_err(|_| {
|
||||
error!("Could not build Vcard from {:?}", cont.get_location());
|
||||
::std::process::exit(1)
|
||||
})
|
||||
.unwrap(); // safed above
|
||||
.filter_map(|entry| {
|
||||
let card = entry.deser().map_err_trace_exit_unwrap(1);
|
||||
|
||||
let str_contains_any = |s: &String, v: &Vec<String>| {
|
||||
v.iter().any(|i| s.contains(i))
|
||||
};
|
||||
|
||||
let take = card.adr().iter().any(|a| str_contains_any(a.raw(), &grepstring))
|
||||
|| card.email().iter().any(|a| str_contains_any(a.raw(), &grepstring))
|
||||
|| card.fullname().iter().any(|a| str_contains_any(a.raw(), &grepstring));
|
||||
let take = card.adr().iter().any(|a| str_contains_any(a, &grepstring))
|
||||
|| card.email().iter().any(|a| str_contains_any(a, &grepstring))
|
||||
|| card.fullname().iter().any(|a| str_contains_any(a, &grepstring));
|
||||
|
||||
if take {
|
||||
// optimization so we don't have to parse again in the next step
|
||||
Some((cont, card))
|
||||
Some((entry, card))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -301,8 +290,8 @@ fn find(rt: &Runtime) {
|
|||
.enumerate();
|
||||
|
||||
if scmd.is_present("json") {
|
||||
let v : Vec<DeserVcard> = iterator
|
||||
.map(|(_, (_, vcard))| DeserVcard::from(vcard)).collect();
|
||||
let v : Vec<DeserVcard> = iterator.map(|(_, tlp)| tlp.1).collect();
|
||||
|
||||
match ::serde_json::to_string(&v) {
|
||||
Ok(s) => writeln!(rt.stdout(), "{}", s).to_exit_code().unwrap_or_exit(),
|
||||
Err(e) => {
|
||||
|
@ -312,22 +301,22 @@ fn find(rt: &Runtime) {
|
|||
}
|
||||
} else if scmd.is_present("find-id") {
|
||||
iterator
|
||||
.for_each(|(_i, (fle, _card))| {
|
||||
writeln!(rt.stdout(), "{}", fle.get_location())
|
||||
.for_each(|(_i, (entry, _))| {
|
||||
writeln!(rt.stdout(), "{}", entry.get_location())
|
||||
.to_exit_code()
|
||||
.unwrap_or_exit();
|
||||
})
|
||||
} else if scmd.is_present("find-full-id") {
|
||||
let storepath = rt.store().path().display();
|
||||
iterator
|
||||
.for_each(|(_i, (fle, _card))| {
|
||||
writeln!(rt.stdout(), "{}/{}", storepath, fle.get_location())
|
||||
.for_each(|(_i, (entry, _))| {
|
||||
writeln!(rt.stdout(), "{}/{}", storepath, entry.get_location())
|
||||
.to_exit_code()
|
||||
.unwrap_or_exit();
|
||||
})
|
||||
} else {
|
||||
iterator
|
||||
.for_each(|(i, (fle, card))| {
|
||||
.for_each(|(i, (_, card))| {
|
||||
let fmt = if scmd.is_present("find-show") {
|
||||
&show_format
|
||||
} else if scmd.is_present("find-list") {
|
||||
|
@ -336,8 +325,7 @@ fn find(rt: &Runtime) {
|
|||
&list_format
|
||||
};
|
||||
|
||||
let hash = fle.get_hash().map(String::from).map_err_trace_exit_unwrap(1);
|
||||
let data = build_data_object_for_handlebars(i, hash, &card);
|
||||
let data = build_data_object_for_handlebars(i, &card);
|
||||
let s = fmt
|
||||
.render("format", &data)
|
||||
.err_from_str()
|
||||
|
|
|
@ -18,105 +18,58 @@
|
|||
//
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use vobject::vcard::Vcard;
|
||||
|
||||
pub fn build_data_object_for_handlebars<'a>(i: usize, hash: String, vcard: &Vcard) -> BTreeMap<&'static str, String> {
|
||||
use libimagcontact::deser::DeserVcard;
|
||||
|
||||
pub fn build_data_object_for_handlebars<'a>(i: usize, vcard: &DeserVcard) -> BTreeMap<&'static str, String> {
|
||||
let mut data = BTreeMap::new();
|
||||
|
||||
let process_list = |list: &Vec<String>| {
|
||||
list.iter()
|
||||
.map(String::clone)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
};
|
||||
|
||||
let process_opt = |opt: Option<&String>| {
|
||||
opt.map(String::clone).unwrap_or_else(String::new)
|
||||
};
|
||||
|
||||
{
|
||||
data.insert("i" , format!("{}", i));
|
||||
|
||||
// The hash (as in libimagentryref) of the contact
|
||||
data.insert("id" , hash);
|
||||
|
||||
data.insert("ADR" , vcard.adr()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("ANNIVERSARY" , vcard.anniversary()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("BDAY" , vcard.bday()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("CATEGORIES" , vcard.categories()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("CLIENTPIDMAP" , vcard.clientpidmap()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("EMAIL" , vcard.email()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("FN" , vcard.fullname()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("GENDER" , vcard.gender()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("GEO" , vcard.geo()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("IMPP" , vcard.impp()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("KEY" , vcard.key()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("LANG" , vcard.lang()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("LOGO" , vcard.logo()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("MEMBER" , vcard.member()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("N" , vcard.name()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("NICKNAME" , vcard.nickname()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("NOTE" , vcard.note()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("ORG" , vcard.org()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("PHOTO" , vcard.photo()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("PRIOD" , vcard.proid()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("RELATED" , vcard.related()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("REV" , vcard.rev()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("ROLE" , vcard.role()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("SOUND" , vcard.sound()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("TEL" , vcard.tel()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("TITLE" , vcard.title()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("TZ" , vcard.tz()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("UID" , vcard.uid()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
|
||||
data.insert("URL" , vcard.url()
|
||||
.into_iter().map(|c| c.raw().clone()).collect::<Vec<_>>().join(", "));
|
||||
|
||||
data.insert("VERSION" , vcard.version()
|
||||
.map(|c| c.raw().clone()).unwrap_or(String::new()));
|
||||
data.insert("id" , process_opt(vcard.uid()));
|
||||
data.insert("ADR" , process_list(vcard.adr()));
|
||||
data.insert("ANNIVERSARY" , process_opt(vcard.anniversary()));
|
||||
data.insert("BDAY" , process_opt(vcard.bday()));
|
||||
data.insert("CATEGORIES" , process_list(vcard.categories()));
|
||||
data.insert("CLIENTPIDMAP" , process_opt(vcard.clientpidmap()));
|
||||
data.insert("EMAIL" , process_list(vcard.email()));
|
||||
data.insert("FN" , process_list(vcard.fullname()));
|
||||
data.insert("GENDER" , process_opt(vcard.gender()));
|
||||
data.insert("GEO" , process_list(vcard.geo()));
|
||||
data.insert("IMPP" , process_list(vcard.impp()));
|
||||
data.insert("KEY" , process_list(vcard.key()));
|
||||
data.insert("LANG" , process_list(vcard.lang()));
|
||||
data.insert("LOGO" , process_list(vcard.logo()));
|
||||
data.insert("MEMBER" , process_list(vcard.member()));
|
||||
data.insert("N" , process_opt(vcard.name()));
|
||||
data.insert("NICKNAME" , process_list(vcard.nickname()));
|
||||
data.insert("NOTE" , process_list(vcard.note()));
|
||||
data.insert("ORG" , process_list(vcard.org()));
|
||||
data.insert("PHOTO" , process_list(vcard.photo()));
|
||||
data.insert("PRIOD" , process_opt(vcard.proid()));
|
||||
data.insert("RELATED" , process_list(vcard.related()));
|
||||
data.insert("REV" , process_opt(vcard.rev()));
|
||||
data.insert("ROLE" , process_list(vcard.role()));
|
||||
data.insert("SOUND" , process_list(vcard.sound()));
|
||||
data.insert("TEL" , process_list(vcard.tel()));
|
||||
data.insert("TITLE" , process_list(vcard.title()));
|
||||
data.insert("TZ" , process_list(vcard.tz()));
|
||||
data.insert("UID" , process_opt(vcard.uid()));
|
||||
data.insert("URL" , process_list(vcard.url()));
|
||||
data.insert("VERSION" , process_opt(vcard.version()));
|
||||
}
|
||||
|
||||
data
|
||||
|
|
Loading…
Reference in a new issue