diff --git a/bin/domain/imag-contact/src/edit.rs b/bin/domain/imag-contact/src/edit.rs index a775fefb..bcb89900 100644 --- a/bin/domain/imag-contact/src/edit.rs +++ b/bin/domain/imag-contact/src/edit.rs @@ -33,16 +33,21 @@ )] use std::process::exit; +use std::io::Read; +use std::io::Write; use failure::Error; use failure::err_msg; +use failure::Fallible as Result; use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; +use libimagstore::store::FileLockEntry; use libimagcontact::store::ContactStore; use libimagentryref::reference::fassade::RefFassade; use libimagentryref::hasher::default::DefaultHasher; use libimagentryref::reference::Ref; +use libimagentryref::reference::Config as RefConfig; pub fn edit(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("edit").unwrap(); @@ -50,40 +55,66 @@ pub fn edit(rt: &Runtime) { let ref_config = libimagentryref::util::get_ref_config(&rt, "imag-contact").map_err_trace_exit_unwrap(); let hash = scmd.value_of("hash").map(String::from).unwrap(); // safed by clap let force_override = true; // when editing, we want to override, right? + let retry = !scmd.is_present("fail-on-parse-error"); if rt.output_is_pipe() { error!("Cannot spawn editor if output is a pipe!"); exit(1); } + let mut output = rt.stdout(); + let mut input = rt.stdin().unwrap_or_else(|| { + error!("No input stream. Cannot ask for permission."); + exit(1) + }); + ::util::find_contact_by_hash(rt, hash) .for_each(|contact| { - let filepath = contact - .as_ref_with_hasher::() - .get_path(&ref_config) - .map_err_trace_exit_unwrap(); - - let success = rt.editor() - .map_err_trace_exit_unwrap() - .ok_or_else(|| { - err_msg("I have no editor configured. Cannot continue!") - }) - .map_err_trace_exit_unwrap() - .arg(&filepath) - .status() - .map_err(Error::from) - .map_err_trace_exit_unwrap() - .success(); - - if !success { - error!("Editor failed!"); - exit(1); + loop { + let res = edit_contact(&rt, &contact, &ref_config, collection_name, force_override); + if !retry { + let _ = res.map_err_trace_exit_unwrap(); + } else { + if ask_continue(&mut input, &mut output) { + continue; + } else { + exit(1) + } + } } - - let _ = rt - .store() - .retrieve_from_path(&filepath, &ref_config, &collection_name, force_override) - .map_err_trace_exit_unwrap(); }); } +fn edit_contact<'a>(rt: &Runtime, contact: &FileLockEntry<'a>, ref_config: &RefConfig, collection_name: &str, force_override: bool) -> Result<()> { + let filepath = contact + .as_ref_with_hasher::() + .get_path(ref_config) + .map_err_trace_exit_unwrap(); + + let success = rt.editor() + .map_err_trace_exit_unwrap() + .ok_or_else(|| { + err_msg("I have no editor configured. Cannot continue!") + }) + .map_err_trace_exit_unwrap() + .arg(&filepath) + .status() + .map_err(Error::from) + .map_err_trace_exit_unwrap() + .success(); + + if !success { + error!("Editor failed!"); + exit(1); + } + + rt.store() + .retrieve_from_path(&filepath, &ref_config, &collection_name, force_override) + .map(|_| ()) +} + +fn ask_continue(inputstream: &mut Read, outputstream: &mut Write) -> bool { + ::libimaginteraction::ask::ask_bool("Edit vcard", Some(true), inputstream, outputstream) + .map_err_trace_exit_unwrap() +} + diff --git a/bin/domain/imag-contact/src/ui.rs b/bin/domain/imag-contact/src/ui.rs index e4cf657c..f60fd17d 100644 --- a/bin/domain/imag-contact/src/ui.rs +++ b/bin/domain/imag-contact/src/ui.rs @@ -102,6 +102,12 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .multiple(true) .value_name("HASH") .help("Edit the contact pointed to by this reference hash(es)")) + .arg(Arg::with_name("fail-on-parse-error") + .long("no-retry") + .takes_value(false) + .required(false) + .multiple(false) + .help("Fail immediately if vcard cannot be parsed after editing.")) ) .subcommand(SubCommand::with_name("find")