summaryrefslogtreecommitdiffstats
path: root/lib/etc/libimaginteraction/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-08-13 21:48:17 +0000
committerMatthias Beyer <mail@beyermatthias.de>2017-08-27 15:12:09 +0200
commit59a3662ac47b0c657781bd1db34bbf9a5a692326 (patch)
tree709f72c44c8d978a5a76abb9036c6f08744a4aa2 /lib/etc/libimaginteraction/src
parent31254071e5a4bf2f5db9067c5cdb22c25579ac67 (diff)
Reorganize code in subdirs
Diffstat (limited to 'lib/etc/libimaginteraction/src')
-rw-r--r--lib/etc/libimaginteraction/src/ask.rs350
-rw-r--r--lib/etc/libimaginteraction/src/error.rs39
-rw-r--r--lib/etc/libimaginteraction/src/filter.rs20
-rw-r--r--lib/etc/libimaginteraction/src/lib.rs53
-rw-r--r--lib/etc/libimaginteraction/src/readline.rs129
-rw-r--r--lib/etc/libimaginteraction/src/result.rs24
-rw-r--r--lib/etc/libimaginteraction/src/ui.rs83
7 files changed, 698 insertions, 0 deletions
diff --git a/lib/etc/libimaginteraction/src/ask.rs b/lib/etc/libimaginteraction/src/ask.rs
new file mode 100644
index 00000000..2a393d0e
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/ask.rs
@@ -0,0 +1,350 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+// functions to ask the user for data, with crate:spinner
+
+use std::io::stdin;
+use std::io::BufRead;
+use std::io::BufReader;
+use std::result::Result as RResult;
+
+use error::InteractionError;
+use error::InteractionErrorKind;
+use result::Result;
+
+use regex::Regex;
+use ansi_term::Colour::*;
+use interactor::*;
+
+/// Ask the user for a Yes/No answer. Optionally provide a default value. If none is provided, this
+/// keeps loop{}ing
+pub fn ask_bool(s: &str, default: Option<bool>) -> bool {
+ ask_bool_(s, default, &mut BufReader::new(stdin()))
+}
+
+fn ask_bool_<R: BufRead>(s: &str, default: Option<bool>, input: &mut R) -> bool {
+ lazy_static! {
+ static ref R_YES: Regex = Regex::new(r"^[Yy](\n?)$").unwrap();
+ static ref R_NO: Regex = Regex::new(r"^[Nn](\n?)$").unwrap();
+ }
+
+ loop {
+ ask_question(s, false);
+ if match default { Some(s) => s, _ => true } {
+ println!(" [Yn]: ");
+ } else {
+ println!(" [yN]: ");
+ }
+
+ let mut s = String::new();
+ let _ = input.read_line(&mut s);
+
+ if R_YES.is_match(&s[..]) {
+ return true
+ } else if R_NO.is_match(&s[..]) {
+ return false
+ } else if default.is_some() {
+ return default.unwrap();
+ }
+ // else again...
+ }
+}
+
+/// Ask the user for an unsigned number. Optionally provide a default value. If none is provided,
+/// this keeps loop{}ing
+pub fn ask_uint(s: &str, default: Option<u64>) -> u64 {
+ ask_uint_(s, default, &mut BufReader::new(stdin()))
+}
+
+fn ask_uint_<R: BufRead>(s: &str, default: Option<u64>, input: &mut R) -> u64 {
+ use std::str::FromStr;
+
+ loop {
+ ask_question(s, false);
+
+ let mut s = String::new();
+ let _ = input.read_line(&mut s);
+
+ let u : RResult<u64, _> = FromStr::from_str(&s[..]);
+ match u {
+ Ok(u) => { return u; },
+ Err(_) => {
+ if default.is_some() {
+ return default.unwrap();
+ } // else keep looping
+ }
+ }
+ }
+}
+
+/// Ask the user for a String.
+///
+/// If `permit_empty` is set to false, the default value will be returned if the user inserts an
+/// empty string.
+///
+/// If the `permit_empty` value is true, the `default` value is never returned.
+///
+/// If the `permit_multiline` is set to true, the `prompt` will be displayed before each input line.
+///
+/// If the `eof` parameter is `None`, the input ends as soon as there is an empty line input from
+/// the user. If the parameter is `Some(text)`, the input ends if the input line is equal to `text`.
+pub fn ask_string(s: &str,
+ default: Option<String>,
+ permit_empty: bool,
+ permit_multiline: bool,
+ eof: Option<&str>,
+ prompt: &str)
+ -> String
+{
+ ask_string_(s,
+ default,
+ permit_empty,
+ permit_multiline,
+ eof,
+ prompt,
+ &mut BufReader::new(stdin()))
+}
+
+fn ask_string_<R: BufRead>(s: &str,
+ default: Option<String>,
+ permit_empty: bool,
+ permit_multiline: bool,
+ eof: Option<&str>,
+ prompt: &str,
+ input: &mut R)
+ -> String
+{
+ let mut v = vec![];
+ loop {
+ ask_question(s, true);
+ print!("{}", prompt);
+
+ let mut s = String::new();
+ let _ = input.read_line(&mut s);
+
+ if permit_multiline {
+ if permit_multiline && eof.map_or(false, |e| e == s) {
+ return v.join("\n");
+ }
+
+ if permit_empty || !v.is_empty() {
+ v.push(s);
+ }
+ print!("{}", prompt);
+ } else if s.is_empty() && permit_empty {
+ return s;
+ } else if s.is_empty() && !permit_empty {
+ if default.is_some() {
+ return default.unwrap();
+ } else {
+ continue;
+ }
+ } else {
+ return s;
+ }
+ }
+}
+
+pub fn ask_select_from_list(list: &[&str]) -> Result<String> {
+ pick_from_list(default_menu_cmd().as_mut(), list, "Selection: ")
+ .map_err(|e| InteractionError::new(InteractionErrorKind::Unknown, Some(Box::new(e))))
+}
+
+/// Helper function to print a imag question string. The `question` argument may not contain a
+/// trailing questionmark.
+///
+/// The `nl` parameter can be used to configure whether a newline character should be printed
+pub fn ask_question(question: &str, nl: bool) {
+ if nl {
+ println!("[imag]: {}?", Yellow.paint(question));
+ } else {
+ print!("[imag]: {}?", Yellow.paint(question));
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use std::io::BufReader;
+
+ use super::ask_bool_;
+ use super::ask_uint_;
+
+ #[test]
+ fn test_ask_bool_nodefault_yes() {
+ let question = "Is this true";
+ let default = None;
+ let answers = "\n\n\n\n\ny";
+
+ assert!(ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_nodefault_yes_nl() {
+ let question = "Is this true";
+ let default = None;
+ let answers = "\n\n\n\n\ny\n";
+
+ assert!(ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_nodefault_no() {
+ let question = "Is this true";
+ let default = None;
+ let answers = "n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_nodefault_no_nl() {
+ let question = "Is this true";
+ let default = None;
+ let answers = "n\n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_no() {
+ let question = "Is this true";
+ let default = Some(false);
+ let answers = "n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_no_nl() {
+ let question = "Is this true";
+ let default = Some(false);
+ let answers = "n\n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_yes() {
+ let question = "Is this true";
+ let default = Some(true);
+ let answers = "y";
+
+ assert!(true == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_yes_nl() {
+ let question = "Is this true";
+ let default = Some(true);
+ let answers = "y\n";
+
+ assert!(true == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_yes_answer_no() {
+ let question = "Is this true";
+ let default = Some(true);
+ let answers = "n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_no_answer_yes() {
+ let question = "Is this true";
+ let default = Some(false);
+ let answers = "y";
+
+ assert!(true == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_no_without_answer() {
+ let question = "Is this true";
+ let default = Some(false);
+ let answers = "\n";
+
+ assert!(false == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_bool_default_yes_without_answer() {
+ let question = "Is this true";
+ let default = Some(true);
+ let answers = "\n";
+
+ assert!(true == ask_bool_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_nodefault() {
+ let question = "Is this 1";
+ let default = None;
+ let answers = "1";
+
+ assert!(1 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_default() {
+ let question = "Is this 1";
+ let default = Some(1);
+ let answers = "1";
+
+ assert!(1 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_default_2_input_1() {
+ let question = "Is this 1";
+ let default = Some(2);
+ let answers = "1";
+
+ assert!(1 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_default_2_noinput() {
+ let question = "Is this 1";
+ let default = Some(2);
+ let answers = "\n";
+
+ assert!(2 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_default_2_several_noinput() {
+ let question = "Is this 1";
+ let default = Some(2);
+ let answers = "\n\n\n\n";
+
+ assert!(2 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+ #[test]
+ fn test_ask_uint_default_2_wrong_input() {
+ let question = "Is this 1";
+ let default = Some(2);
+ let answers = "\n\n\nasfb\nsakjf\naskjf\n-2";
+
+ assert!(2 == ask_uint_(question, default, &mut BufReader::new(answers.as_bytes())));
+ }
+
+}
diff --git a/lib/etc/libimaginteraction/src/error.rs b/lib/etc/libimaginteraction/src/error.rs
new file mode 100644
index 00000000..1a4be7df
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/error.rs
@@ -0,0 +1,39 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+generate_error_module!(
+ generate_error_types!(InteractionError, InteractionErrorKind,
+ Unknown => "Unknown Error",
+ CLIError => "Error on commandline",
+ IdMissingError => "Commandline: ID missing",
+ StoreIdParsingError => "Error while parsing StoreId",
+ IdSelectingError => "Error while selecting id",
+ ConfigError => "Configuration error",
+ ConfigMissingError => "Configuration missing",
+ ConfigTypeError => "Config Type Error",
+ NoConfigError => "No configuration",
+ ReadlineHistoryFileCreationError => "Could not create history file for readline",
+ ReadlineError => "Readline error"
+ );
+);
+
+pub use self::error::InteractionError;
+pub use self::error::InteractionErrorKind;
+pub use self::error::MapErrInto;
+
diff --git a/lib/etc/libimaginteraction/src/filter.rs b/lib/etc/libimaginteraction/src/filter.rs
new file mode 100644
index 00000000..5869a529
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/filter.rs
@@ -0,0 +1,20 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+// A filter which uses crate:interactor to filter entries
diff --git a/lib/etc/libimaginteraction/src/lib.rs b/lib/etc/libimaginteraction/src/lib.rs
new file mode 100644
index 00000000..67c61cf4
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/lib.rs
@@ -0,0 +1,53 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![deny(
+ non_camel_case_types,
+ non_snake_case,
+ path_statements,
+ trivial_numeric_casts,
+ unstable_features,
+ unused_allocation,
+ unused_import_braces,
+ unused_imports,
+ unused_mut,
+ unused_qualifications,
+ while_true,
+)]
+
+extern crate spinner;
+extern crate interactor;
+extern crate ansi_term;
+#[macro_use] extern crate lazy_static;
+extern crate regex;
+extern crate clap;
+extern crate toml;
+extern crate rustyline;
+
+extern crate libimagentryfilter;
+extern crate libimagstore;
+extern crate libimagutil;
+#[macro_use] extern crate libimagerror;
+
+pub mod ask;
+pub mod error;
+pub mod filter;
+pub mod result;
+pub mod ui;
+
diff --git a/lib/etc/libimaginteraction/src/readline.rs b/lib/etc/libimaginteraction/src/readline.rs
new file mode 100644
index 00000000..7b998dd0
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/readline.rs
@@ -0,0 +1,129 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+use error::InteractionErrorKind as IEK;
+use error::MapErrInto;
+
+use toml::Value;
+
+use rustyline::{Config, Editor};
+
+pub struct Readline {
+ editor: Editor,
+ history_file: PathBuf,
+ prompt: String,
+}
+
+impl Readline {
+
+ pub fn new(rt: &Runtime) -> Result<Readline> {
+ let cfg = try!(rt.config().ok_or(IEK::NoConfigError));
+
+ let c = cfg.config();
+ let histfile = try!(c.lookup("ui.cli.readline_history_file").ok_or(IEK::ConfigError));
+ let histsize = try!(c.lookup("ui.cli.readline_history_size").ok_or(IEK::ConfigError));
+ let histigndups = try!(c.lookup("ui.cli.readline_history_ignore_dups").ok_or(IEK::ConfigError));
+ let histignspace = try!(c.lookup("ui.cli.readline_history_ignore_space").ok_or(IEK::ConfigError));
+ let prompt = try!(c.lookup("ui.cli.readline_prompt").ok_or(IEK::ConfigError));
+
+ let histfile = try!(match histfile {
+ Value::String(s) => PathBuf::from(s),
+ _ => Err(IEK::ConfigTypeError.into_error())
+ .map_err_into(IEK::ConfigError)
+ .map_err_into(IEK::ReadlineError)
+ });
+
+ let histsize = try!(match histsize {
+ Value::Integer(i) => i,
+ _ => Err(IEK::ConfigTypeError.into_error())
+ .map_err_into(IEK::ConfigError)
+ .map_err_into(IEK::ReadlineError)
+ });
+
+ let histigndups = try!(match histigndups {
+ Value::Boolean(b) => b,
+ _ => Err(IEK::ConfigTypeError.into_error())
+ .map_err_into(IEK::ConfigError)
+ .map_err_into(IEK::ReadlineError)
+ });
+
+ let histignspace = try!(match histignspace {
+ Value::Boolean(b) => b,
+ _ => Err(IEK::ConfigTypeError.into_error())
+ .map_err_into(IEK::ConfigError)
+ .map_err_into(IEK::ReadlineError)
+ });
+
+ let prompt = try!(match prompt {
+ Value::String(s) => s,
+ _ => Err(IEK::ConfigTypeError.into_error())
+ .map_err_into(IEK::ConfigError)
+ .map_err_into(IEK::ReadlineError)
+ });
+
+ let config = Config::builder().
+ .max_history_size(histsize)
+ .history_ignore_dups(histigndups)
+ .history_ignore_space(histignspace)
+ .build();
+
+ let mut editor = Editor::new(config);
+
+ if !histfile.exists() {
+ let _ = try!(File::create(histfile.clone())
+ .map_err_into(IEK::ReadlineHistoryFileCreationError));
+ }
+
+ let _ = try!(editor.load_history(&histfile).map_err_into(ReadlineError));
+
+ Ok(Readline {
+ editor: editor,
+ history_file: histfile,
+ prompt: prompt,
+ })
+ }
+
+ pub fn read_line(&mut self) -> Result<Option<String>> {
+ use rustyline::ReadlineError;
+ use libimagutil::warn_result::*;
+
+ match self.editor.readline(&self.prompt) {
+ Ok(line) => {
+ self.editor.add_history_line(&line);
+ self.editor
+ .save_history(&self.history_file)
+ .map_warn_err_str(|e| format!("Could not save history file {} -> {:?}",
+ self.history_file.display(), e));
+ return line;
+ },
+ Err(ReadlineError::Interrupted) => {
+ info!("CTRL-C");
+ Ok(None)
+ },
+ Err(ReadlineError::Eof) => {
+ info!("CTRL-D");
+ Ok(None)
+ },
+ Err(err) => Err(err).map_err_into(ReadlineError),
+
+ }
+ }
+
+}
+
diff --git a/lib/etc/libimaginteraction/src/result.rs b/lib/etc/libimaginteraction/src/result.rs
new file mode 100644
index 00000000..8eeaf47b
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/result.rs
@@ -0,0 +1,24 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+use std::result::Result as RResult;
+
+use error::InteractionError;
+
+pub type Result<T> = RResult<T, InteractionError>;
diff --git a/lib/etc/libimaginteraction/src/ui.rs b/lib/etc/libimaginteraction/src/ui.rs
new file mode 100644
index 00000000..49c4619d
--- /dev/null
+++ b/lib/etc/libimaginteraction/src/ui.rs
@@ -0,0 +1,83 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+use std::path::PathBuf;
+
+use clap::{Arg, ArgMatches};
+
+use libimagstore::storeid::StoreId;
+use libimagerror::into::IntoError;
+
+use result::Result;
+use error::MapErrInto;
+use error::InteractionErrorKind as IEK;
+
+pub fn id_argument<'a, 'b>() -> Arg<'a, 'b> {
+ Arg::with_name(id_argument_name())
+ .short(id_argument_short())
+ .long(id_argument_long())
+ .takes_value(true)
+ .multiple(true)
+ .help("Specify the Store-Id")
+}
+
+pub fn id_argument_name() -> &'static str {
+ "id-argument"
+}
+
+pub fn id_argument_short() -> &'static str {
+ "i"
+}
+
+pub fn id_argument_long() -> &'static str {
+ "id"
+}
+
+pub fn get_id(matches: &ArgMatches) -> Result<Vec<StoreId>> {
+ matches
+ .values_of(id_argument_name())
+ .ok_or(IEK::IdMissingError.into_error())
+ .map_err_into(IEK::CLIError)
+ .and_then(|vals| {
+ vals.into_iter()
+ .fold(Ok(vec![]), |acc, elem| {
+ acc.and_then(|mut v| {
+ let elem = StoreId::new_baseless(PathBuf::from(String::from(elem)));
+ let elem = try!(elem.map_err_into(IEK::StoreIdParsingError));
+ v.push(elem);
+ Ok(v)
+ })
+ })
+ })
+}
+
+pub fn get_or_select_id(matches: &ArgMatches, store_path: &PathBuf) -> Result<Vec<StoreId>> {
+ use interactor::{pick_file, default_menu_cmd};
+
+ match get_id(matches).map_err_into(IEK::IdSelectingError) {
+ Ok(v) => Ok(v),
+ Err(_) => {
+ let path = store_path.clone();
+ let p = try!(pick_file(default_menu_cmd, path).map_err_into(IEK::IdSelectingError));
+ let id = try!(StoreId::new_baseless(p).map_err_into(IEK::StoreIdParsingError));
+ Ok(vec![id])
+ },
+ }
+}
+