Add "find" command

This patch adds a "find" command to imag-contact which can either list
or show the found contacts (defaults to "list").
This commit is contained in:
Matthias Beyer 2018-03-12 15:23:37 +01:00
parent 252046583a
commit cbe30fa9c2
2 changed files with 110 additions and 0 deletions

View File

@ -98,6 +98,7 @@ fn main() {
"list" => list(&rt),
"import" => import(&rt),
"show" => show(&rt),
"find" => find(&rt),
"create" => create(&rt),
_ => {
error!("Unknown command"); // More error handling
@ -214,6 +215,82 @@ fn show(rt: &Runtime) {
let _ = writeln!(::std::io::stdout(), "{}", s).to_exit_code().unwrap_or_exit();
}
fn find(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("find").unwrap();
let grepstring = scmd
.values_of("string")
.unwrap() // safed by clap
.map(String::from)
.collect::<Vec<String>>();
// We don't know yet which we need, but we pay that price for simplicity of the codebase
let show_format = get_contact_print_format("contact.show_format", rt, &scmd);
let list_format = get_contact_print_format("contact.list_format", rt, &scmd);
rt.store()
.all_contacts()
.map_err_trace_exit_unwrap(1)
.into_get_iter(rt.store())
.map(|el| {
el.map_err_trace_exit_unwrap(1)
.ok_or_else(|| {
error!("Could not get StoreId from Store::all_contacts(). This is a BUG!");
::std::process::exit(1)
})
.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
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));
if take {
// optimization so we don't have to parse again in the next step
Some((cont, card))
} else {
None
}
})
.enumerate()
.for_each(|(i, (fle, card))| {
let fmt = if scmd.is_present("find-show") {
&show_format
} else if scmd.is_present("find-list") {
&list_format
} else { // default: find-list
&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 s = fmt
.render("format", &data)
.err_from_str()
.map_err(CE::from)
.map_err_trace_exit_unwrap(1);
let _ = writeln!(rt.stdout(), "{}", s)
.to_exit_code()
.unwrap_or_exit();
});
}
fn get_contact_print_format(config_value_path: &'static str, rt: &Runtime, scmd: &ArgMatches) -> Handlebars {
let fmt = scmd
.value_of("format")

View File

@ -71,6 +71,39 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
.help("Format to format the contact when printing it"))
)
.subcommand(SubCommand::with_name("find")
.about("Find contact by grepping for a string (no regex yet)")
.version("0.1")
.arg(Arg::with_name("string")
.index(1)
.takes_value(true)
.required(true)
.multiple(true)
.value_name("grepstring")
.help("Find the contact by grepping for this string"))
.arg(Arg::with_name("find-show")
.long("show")
.short("s")
.takes_value(false)
.required(false)
.multiple(false)
.help("Show the result")
.conflicts_with("find-list")
)
.arg(Arg::with_name("find-list")
.long("list")
.short("l")
.takes_value(false)
.required(false)
.multiple(false)
.help("List the result")
.conflicts_with("find-show")
)
)
.subcommand(SubCommand::with_name("create")
.about("Create a contact file (.vcf) and track it in imag.")
.version("0.1")