From 7a37c472634cfd76ee6b2a3d097fafc6c0c252b8 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:18:14 +0200 Subject: [PATCH 01/35] Add ImagApplication trait for CLI completion + single-binary support To re-add the imag-binary CLI completion, as well as to enable building a single imag containing all of the subcommands, this commit introduces an ImagApplication trait to be implemented by all imag binary crates. The binary crates will be converted to libraries, with an additional binary target. This enables standalone and single binary builds. On its own, this commit doesn't do much, but rather it paves the way to dynamically interacting with the imag uis/clis using a library-crate interface. Signed-off-by: Leon Schuermann --- lib/core/libimagrt/src/application.rs | 70 +++++++++++++++++++++++++++ lib/core/libimagrt/src/lib.rs | 1 + 2 files changed, 71 insertions(+) create mode 100644 lib/core/libimagrt/src/application.rs diff --git a/lib/core/libimagrt/src/application.rs b/lib/core/libimagrt/src/application.rs new file mode 100644 index 00000000..74ad4b68 --- /dev/null +++ b/lib/core/libimagrt/src/application.rs @@ -0,0 +1,70 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 runtime::Runtime; +use clap::App; +use failure::Fallible as Result; + +pub trait ImagApplication { + fn run(rt: Runtime) -> Result<()>; + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a>; + fn name() -> &'static str; + fn version() -> &'static str; + fn description() -> &'static str; +} + + +#[macro_export] +macro_rules! simple_imag_application_binary { + ($application_library:ident, $application_implementor:ident) => { + extern crate libimagerror; + extern crate failure; + extern crate $application_library; + + use failure::{Error, Fallible as Result}; + + fn main() { + use libimagerror::trace::MapErrTrace; + use libimagrt::application::ImagApplication; + use libimagrt::setup::generate_runtime_setup; + use $application_library::$application_implementor; + + let version = make_imag_version!(); + let rt = generate_runtime_setup($application_implementor::name(), + &version, + $application_implementor::description(), + $application_implementor::build_cli); + + // The error context must have a 'static lifetime + // Therefore, the easiest, safe, but hacky way to achieve this + // is to allocate a string, which is then forgotten to + // leak memory and return it's contents as a &'static str + // Because this is the very end of the application and only + // happens once, it should have no impact whatsoever + let error_context: &'static str = Box::leak( + format!("Failed to run {}", $application_implementor::name()) + .into_boxed_str() + ); + $application_implementor::run(rt) + .map_err(|e| e.context(error_context)) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + } + }; +} diff --git a/lib/core/libimagrt/src/lib.rs b/lib/core/libimagrt/src/lib.rs index ebe8f4fc..f9d349c0 100644 --- a/lib/core/libimagrt/src/lib.rs +++ b/lib/core/libimagrt/src/lib.rs @@ -55,6 +55,7 @@ extern crate libimagutil; extern crate libimagerror; extern crate libimaginteraction; +pub mod application; pub mod configuration; pub mod logger; pub mod io; From ec75892516f143d4eebfadde1016c82cf91ff04d Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:26:16 +0200 Subject: [PATCH 02/35] imag-annotate: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-annotate/Cargo.toml | 7 +++ bin/core/imag-annotate/src/bin.rs | 39 ++++++++++++ .../imag-annotate/src/{main.rs => lib.rs} | 59 ++++++++++++------- 3 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 bin/core/imag-annotate/src/bin.rs rename bin/core/imag-annotate/src/{main.rs => lib.rs} (87%) diff --git a/bin/core/imag-annotate/Cargo.toml b/bin/core/imag-annotate/Cargo.toml index 1d3d9ce0..63cdc07c 100644 --- a/bin/core/imag-annotate/Cargo.toml +++ b/bin/core/imag-annotate/Cargo.toml @@ -39,3 +39,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagannotatecmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-annotate" +path = "src/bin.rs" diff --git a/bin/core/imag-annotate/src/bin.rs b/bin/core/imag-annotate/src/bin.rs new file mode 100644 index 00000000..cae358af --- /dev/null +++ b/bin/core/imag-annotate/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagannotatecmd, ImagAnnotate); diff --git a/bin/core/imag-annotate/src/main.rs b/bin/core/imag-annotate/src/lib.rs similarity index 87% rename from bin/core/imag-annotate/src/main.rs rename to bin/core/imag-annotate/src/lib.rs index d1d269bd..e2501985 100644 --- a/bin/core/imag-annotate/src/main.rs +++ b/bin/core/imag-annotate/src/lib.rs @@ -44,7 +44,7 @@ extern crate toml_query; extern crate libimagentryannotation; extern crate libimagentryedit; extern crate libimagerror; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagutil; extern crate libimagentrylink; @@ -52,7 +52,9 @@ extern crate libimagentrylink; use std::io::Write; use failure::Error; +use failure::Fallible as Result; use toml_query::read::TomlValueReadTypeExt; +use clap::App; use libimagentryannotation::annotateable::*; use libimagentryannotation::annotation_fetcher::*; @@ -63,33 +65,48 @@ use libimagerror::io::ToExitCode; use libimagerror::errors::ErrorMsg as EM; use libimagerror::iter::TraceIterator; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagstore::store::FileLockEntry; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagentrylink::linkable::Linkable; mod ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-annotation", - &version, - "Add annotations to entries", - ui::build_ui); - - if let Some(name) = rt.cli().subcommand_name() { - match name { - "add" => add(&rt), - "remove" => remove(&rt), - "list" => list(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-annotation", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +pub enum ImagAnnotate {} +impl ImagApplication for ImagAnnotate { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + match name { + "add" => add(&rt), + "remove" => remove(&rt), + "list" => list(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-annotation", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Add annotations to entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 79cfa8d9d8189fafcdb268b8d8afa54b24323fdd Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:26:50 +0200 Subject: [PATCH 03/35] imag-category: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-category/Cargo.toml | 7 ++ bin/core/imag-category/src/bin.rs | 39 ++++++++++ .../imag-category/src/{main.rs => lib.rs} | 71 ++++++++++++------- 3 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 bin/core/imag-category/src/bin.rs rename bin/core/imag-category/src/{main.rs => lib.rs} (79%) diff --git a/bin/core/imag-category/Cargo.toml b/bin/core/imag-category/Cargo.toml index 6294a3c6..afc09fbb 100644 --- a/bin/core/imag-category/Cargo.toml +++ b/bin/core/imag-category/Cargo.toml @@ -36,3 +36,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagcategorycmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-category" +path = "src/bin.rs" diff --git a/bin/core/imag-category/src/bin.rs b/bin/core/imag-category/src/bin.rs new file mode 100644 index 00000000..e3120cae --- /dev/null +++ b/bin/core/imag-category/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagcategorycmd, ImagCategory); diff --git a/bin/core/imag-category/src/main.rs b/bin/core/imag-category/src/lib.rs similarity index 79% rename from bin/core/imag-category/src/main.rs rename to bin/core/imag-category/src/lib.rs index 44a87c12..a40bd632 100644 --- a/bin/core/imag-category/src/main.rs +++ b/bin/core/imag-category/src/lib.rs @@ -42,15 +42,18 @@ extern crate failure; extern crate libimagentrycategory; extern crate libimagerror; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimaginteraction; +use failure::Fallible as Result; +use clap::App; + use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; mod ui; @@ -63,32 +66,52 @@ use libimagerror::iter::TraceIterator; use libimagentrycategory::entry::EntryCategory; use libimagentrycategory::category::Category; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-category", - &version, - "Add a category to entries and manage categories", - ui::build_ui); - - if let Some(name) = rt.cli().subcommand_name() { - match name { - "set" => set(&rt), - "get" => get(&rt), - "list-category" => list_category(&rt), - "create-category" => create_category(&rt), - "delete-category" => delete_category(&rt), - "list-categories" => list_categories(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-category", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagCategory {} +impl ImagApplication for ImagCategory { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + match name { + "set" => set(&rt), + "get" => get(&rt), + "list-category" => list_category(&rt), + "create-category" => create_category(&rt), + "delete-category" => delete_category(&rt), + "list-categories" => list_categories(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-category", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Add a category to entries and manage categories" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } + fn set(rt: &Runtime) { let scmd = rt.cli().subcommand_matches("set").unwrap(); // safed by main() let name = scmd.value_of("set-name").map(String::from).unwrap(); // safed by clap From a34450a37e5c48e527b22ab0f73e7997082eda5b Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:28:39 +0200 Subject: [PATCH 04/35] imag-diagnostics: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-diagnostics/Cargo.toml | 7 + bin/core/imag-diagnostics/src/bin.rs | 39 ++++ bin/core/imag-diagnostics/src/lib.rs | 288 ++++++++++++++++++++++++++ bin/core/imag-diagnostics/src/main.rs | 269 ------------------------ 4 files changed, 334 insertions(+), 269 deletions(-) create mode 100644 bin/core/imag-diagnostics/src/bin.rs create mode 100644 bin/core/imag-diagnostics/src/lib.rs delete mode 100644 bin/core/imag-diagnostics/src/main.rs diff --git a/bin/core/imag-diagnostics/Cargo.toml b/bin/core/imag-diagnostics/Cargo.toml index 97ec6047..d0c1b102 100644 --- a/bin/core/imag-diagnostics/Cargo.toml +++ b/bin/core/imag-diagnostics/Cargo.toml @@ -30,3 +30,10 @@ version = "2.33.0" default-features = false features = ["suggestions", "color", "wrap_help"] +[lib] +name = "libimagdiagnosticscmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-diagnostics" +path = "src/bin.rs" diff --git a/bin/core/imag-diagnostics/src/bin.rs b/bin/core/imag-diagnostics/src/bin.rs new file mode 100644 index 00000000..351163f6 --- /dev/null +++ b/bin/core/imag-diagnostics/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagdiagnosticscmd, ImagDiagnostics); diff --git a/bin/core/imag-diagnostics/src/lib.rs b/bin/core/imag-diagnostics/src/lib.rs new file mode 100644 index 00000000..1118630f --- /dev/null +++ b/bin/core/imag-diagnostics/src/lib.rs @@ -0,0 +1,288 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +extern crate toml; +extern crate toml_query; +extern crate indicatif; +extern crate failure; +#[macro_use] extern crate log; + +extern crate libimagrt; +extern crate libimagerror; +extern crate libimagentrylink; +extern crate libimagstore; + +use std::io::Write; + +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; +use libimagerror::io::ToExitCode; +use libimagerror::exit::ExitUnwrap; +use libimagstore::store::FileLockEntry; +use libimagstore::storeid::StoreId; +use libimagentrylink::linkable::Linkable; + +use toml::Value; +use toml_query::read::TomlValueReadExt; +use indicatif::{ProgressBar, ProgressStyle}; +use failure::Fallible as Result; +use failure::Error; +use failure::err_msg; +use clap::App; + +use std::collections::BTreeMap; + +mod ui; + +#[derive(Debug)] +struct Diagnostic { + pub id: StoreId, + pub entry_store_version: String, + pub header_sections: usize, + pub bytecount_content: usize, + pub overall_byte_size: usize, + pub verified: bool, + pub num_links: usize, +} + +impl Diagnostic { + + fn for_entry<'a>(entry: &FileLockEntry<'a>) -> Result { + Ok(Diagnostic { + id: entry.get_location().clone(), + entry_store_version: entry + .get_header() + .read("imag.version") + .map(|opt| match opt { + Some(&Value::String(ref s)) => s.clone(), + Some(_) => "Non-String type in 'imag.version'".to_owned(), + None => "No version".to_owned(), + }) + .unwrap_or("Error reading version".to_owned()), + header_sections: match entry.get_header() { + &Value::Table(ref map) => map.keys().count(), + _ => 0 + }, + bytecount_content: entry.get_content().as_str().len(), + overall_byte_size: entry.to_str()?.as_str().len(), + verified: entry.verify().is_ok(), + num_links: entry.links().map(Iterator::count).unwrap_or(0), + }) + } +} + +macro_rules! do_write { + ($dest:ident, $pattern:tt) => { + let _ = writeln!($dest, $pattern) + .to_exit_code() + .unwrap_or_exit(); + }; + + ($dest:ident, $pattern:tt, $( $args:expr ),*) => { + let _ = writeln!($dest, $pattern, $( $args ),*) + .to_exit_code() + .unwrap_or_exit(); + } +} + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagDiagnostics {} +impl ImagApplication for ImagDiagnostics { + fn run(rt: Runtime) -> Result<()> { + let template = get_config(&rt, "rt.progressbar_style"); + let tick_chars = get_config(&rt, "rt.progressticker_chars"); + let verbose = rt.cli().is_present("more-output"); + + let style = if let Some(tick_chars) = tick_chars { + ProgressStyle::default_spinner().tick_chars(&tick_chars) + } else { + ProgressStyle::default_spinner() + }; + + let spinner = ProgressBar::new_spinner(); + spinner.enable_steady_tick(100); + spinner.set_style(style); + spinner.set_message("Accumulating data"); + + let diags = rt.store() + .entries() + .map_err_trace_exit_unwrap() + .into_get_iter() + .map(|e| { + e.map_err_trace_exit_unwrap() + .ok_or_else(|| Error::from(err_msg("Unable to get entry".to_owned()))) + .map_err_trace_exit_unwrap() + }) + .map(|e| { + let diag = Diagnostic::for_entry(&e); + debug!("Diagnostic for '{:?}' = {:?}", e.get_location(), diag); + drop(e); + diag + }) + .collect::>>() + .map_err_trace_exit_unwrap(); + + spinner.finish(); + let n = diags.len(); + let progress = ProgressBar::new(n as u64); + let style = if let Some(template) = template { + ProgressStyle::default_bar().template(&template) + } else { + ProgressStyle::default_bar() + }; + progress.set_style(style); + progress.set_message("Calculating stats"); + + let mut version_counts : BTreeMap = BTreeMap::new(); + let mut sum_header_sections = 0; + let mut sum_bytecount_content = 0; + let mut sum_overall_byte_size = 0; + let mut max_overall_byte_size : Option<(usize, StoreId)> = None; + let mut verified_count = 0; + let mut unverified_count = 0; + let mut unverified_entries = vec![]; + let mut num_links = 0; + let mut max_links : Option<(usize, StoreId)> = None; + + for diag in diags.iter() { + sum_header_sections += diag.header_sections; + sum_bytecount_content += diag.bytecount_content; + sum_overall_byte_size += diag.overall_byte_size; + match max_overall_byte_size { + None => max_overall_byte_size = Some((diag.num_links, diag.id.clone())), + Some((num, _)) => if num < diag.overall_byte_size { + max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone())); + } + } + + let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0); + version_counts.insert(diag.entry_store_version.clone(), n+1); + + if diag.verified { + verified_count += 1; + } else { + unverified_count += 1; + if verbose { + unverified_entries.push(diag.id.clone()); + } + } + + num_links += diag.num_links; + match max_links { + None => max_links = Some((diag.num_links, diag.id.clone())), + Some((num, _)) => if num < diag.num_links { + max_links = Some((diag.num_links, diag.id.clone())); + } + } + + progress.inc(1); + } + + progress.finish(); + + let mut out = rt.stdout(); + + do_write!(out, "imag version {}", { env!("CARGO_PKG_VERSION") }); + do_write!(out, ""); + do_write!(out, "{} entries", n); + + for (k, v) in version_counts { + do_write!(out, "{} entries with store version '{}'", v, k); + } + if n != 0 { + do_write!(out, "{} header sections in the average entry", sum_header_sections / n); + do_write!(out, "{} average content bytecount", sum_bytecount_content / n); + do_write!(out, "{} average overall bytecount", sum_overall_byte_size / n); + + if let Some((num, path)) = max_overall_byte_size { + do_write!(out, "Largest Entry ({} bytes): {}", num, path.local_display_string()); + } + + do_write!(out, "{} average internal link count per entry", num_links / n); + + if let Some((num, path)) = max_links { + do_write!(out, "Entry with most internal links ({}): {}", + num, + path.local_display_string()); + } + do_write!(out, "{} verified entries", verified_count); + do_write!(out, "{} unverified entries", unverified_count); + if verbose { + for unve in unverified_entries.iter() { + do_write!(out, "Unverified: {}", unve); + } + } + } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Print diagnostics about imag and the imag store" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} + +fn get_config(rt: &Runtime, s: &'static str) -> Option { + rt.config().and_then(|cfg| { + cfg.read(s) + .map_err(Error::from) + .map_err_trace_exit_unwrap() + .map(|opt| match opt { + &Value::String(ref s) => s.to_owned(), + _ => { + error!("Config type wrong: 'rt.progressbar_style' should be a string"); + ::std::process::exit(1) + } + }) + }) +} diff --git a/bin/core/imag-diagnostics/src/main.rs b/bin/core/imag-diagnostics/src/main.rs deleted file mode 100644 index 3a1f6806..00000000 --- a/bin/core/imag-diagnostics/src/main.rs +++ /dev/null @@ -1,269 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -extern crate toml; -extern crate toml_query; -extern crate indicatif; -extern crate failure; -#[macro_use] extern crate log; - -#[macro_use] extern crate libimagrt; -extern crate libimagerror; -extern crate libimagentrylink; -extern crate libimagstore; - -use std::io::Write; - -use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; -use libimagerror::trace::MapErrTrace; -use libimagerror::io::ToExitCode; -use libimagerror::exit::ExitUnwrap; -use libimagstore::store::FileLockEntry; -use libimagstore::storeid::StoreId; -use libimagentrylink::linkable::Linkable; - -use toml::Value; -use toml_query::read::TomlValueReadExt; -use indicatif::{ProgressBar, ProgressStyle}; -use failure::Fallible as Result; -use failure::Error; -use failure::err_msg; - -use std::collections::BTreeMap; - -mod ui; - -#[derive(Debug)] -struct Diagnostic { - pub id: StoreId, - pub entry_store_version: String, - pub header_sections: usize, - pub bytecount_content: usize, - pub overall_byte_size: usize, - pub verified: bool, - pub num_links: usize, -} - -impl Diagnostic { - - fn for_entry<'a>(entry: &FileLockEntry<'a>) -> Result { - Ok(Diagnostic { - id: entry.get_location().clone(), - entry_store_version: entry - .get_header() - .read("imag.version") - .map(|opt| match opt { - Some(&Value::String(ref s)) => s.clone(), - Some(_) => "Non-String type in 'imag.version'".to_owned(), - None => "No version".to_owned(), - }) - .unwrap_or_else(|_| "Error reading version".to_owned()), - header_sections: match entry.get_header() { - Value::Table(ref map) => map.keys().count(), - _ => 0 - }, - bytecount_content: entry.get_content().as_str().len(), - overall_byte_size: entry.to_str()?.as_str().len(), - verified: entry.verify().is_ok(), - num_links: entry.links().map(Iterator::count).unwrap_or(0), - }) - } -} - -macro_rules! do_write { - ($dest:ident, $pattern:tt) => { - let _ = writeln!($dest, $pattern) - .to_exit_code() - .unwrap_or_exit(); - }; - - ($dest:ident, $pattern:tt, $( $args:expr ),*) => { - let _ = writeln!($dest, $pattern, $( $args ),*) - .to_exit_code() - .unwrap_or_exit(); - } -} - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-diagnostics", - &version, - "Print diagnostics about imag and the imag store", - ui::build_ui); - - let template = get_config(&rt, "rt.progressbar_style"); - let tick_chars = get_config(&rt, "rt.progressticker_chars"); - let verbose = rt.cli().is_present("more-output"); - - let style = if let Some(tick_chars) = tick_chars { - ProgressStyle::default_spinner().tick_chars(&tick_chars) - } else { - ProgressStyle::default_spinner() - }; - - let spinner = ProgressBar::new_spinner(); - spinner.enable_steady_tick(100); - spinner.set_style(style); - spinner.set_message("Accumulating data"); - - let diags = rt.store() - .entries() - .map_err_trace_exit_unwrap() - .into_get_iter() - .map(|e| { - e.map_err_trace_exit_unwrap() - .ok_or_else(|| err_msg("Unable to get entry".to_owned())) - .map_err_trace_exit_unwrap() - }) - .map(|e| { - let diag = Diagnostic::for_entry(&e); - debug!("Diagnostic for '{:?}' = {:?}", e.get_location(), diag); - drop(e); - diag - }) - .collect::>>() - .map_err_trace_exit_unwrap(); - - spinner.finish(); - let n = diags.len(); - let progress = ProgressBar::new(n as u64); - let style = if let Some(template) = template { - ProgressStyle::default_bar().template(&template) - } else { - ProgressStyle::default_bar() - }; - progress.set_style(style); - progress.set_message("Calculating stats"); - - let mut version_counts : BTreeMap = BTreeMap::new(); - let mut sum_header_sections = 0; - let mut sum_bytecount_content = 0; - let mut sum_overall_byte_size = 0; - let mut max_overall_byte_size : Option<(usize, StoreId)> = None; - let mut verified_count = 0; - let mut unverified_count = 0; - let mut unverified_entries = vec![]; - let mut num_links = 0; - let mut max_links : Option<(usize, StoreId)> = None; - - for diag in diags.iter() { - sum_header_sections += diag.header_sections; - sum_bytecount_content += diag.bytecount_content; - sum_overall_byte_size += diag.overall_byte_size; - match max_overall_byte_size { - None => max_overall_byte_size = Some((diag.num_links, diag.id.clone())), - Some((num, _)) => if num < diag.overall_byte_size { - max_overall_byte_size = Some((diag.overall_byte_size, diag.id.clone())); - } - } - - let n = version_counts.get(&diag.entry_store_version).map(Clone::clone).unwrap_or(0); - version_counts.insert(diag.entry_store_version.clone(), n+1); - - if diag.verified { - verified_count += 1; - } else { - unverified_count += 1; - if verbose { - unverified_entries.push(diag.id.clone()); - } - } - - num_links += diag.num_links; - match max_links { - None => max_links = Some((diag.num_links, diag.id.clone())), - Some((num, _)) => if num < diag.num_links { - max_links = Some((diag.num_links, diag.id.clone())); - } - } - - progress.inc(1); - } - - progress.finish(); - - let mut out = rt.stdout(); - - do_write!(out, "imag version {}", { env!("CARGO_PKG_VERSION") }); - do_write!(out, ""); - do_write!(out, "{} entries", n); - - for (k, v) in version_counts { - do_write!(out, "{} entries with store version '{}'", v, k); - } - if n != 0 { - do_write!(out, "{} header sections in the average entry", sum_header_sections / n); - do_write!(out, "{} average content bytecount", sum_bytecount_content / n); - do_write!(out, "{} average overall bytecount", sum_overall_byte_size / n); - - if let Some((num, path)) = max_overall_byte_size { - do_write!(out, "Largest Entry ({} bytes): {}", num, path.local_display_string()); - } - - do_write!(out, "{} average internal link count per entry", num_links / n); - - if let Some((num, path)) = max_links { - do_write!(out, "Entry with most internal links ({}): {}", - num, - path.local_display_string()); - } - do_write!(out, "{} verified entries", verified_count); - do_write!(out, "{} unverified entries", unverified_count); - if verbose { - for unve in unverified_entries.iter() { - do_write!(out, "Unverified: {}", unve); - } - } - } -} - -fn get_config(rt: &Runtime, s: &'static str) -> Option { - rt.config().and_then(|cfg| { - cfg.read(s) - .map_err(Error::from) - .map_err_trace_exit_unwrap() - .map(|opt| match opt { - Value::String(ref s) => s.to_owned(), - _ => { - error!("Config type wrong: 'rt.progressbar_style' should be a string"); - ::std::process::exit(1) - } - }) - }) -} - From 861af28724506b8f60f2dcf3a0b2d96023b3798f Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:29:37 +0200 Subject: [PATCH 05/35] imag-edit: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-edit/Cargo.toml | 7 ++ bin/core/imag-edit/src/bin.rs | 39 +++++++++++ bin/core/imag-edit/src/lib.rs | 121 +++++++++++++++++++++++++++++++++ bin/core/imag-edit/src/main.rs | 99 --------------------------- 4 files changed, 167 insertions(+), 99 deletions(-) create mode 100644 bin/core/imag-edit/src/bin.rs create mode 100644 bin/core/imag-edit/src/lib.rs delete mode 100644 bin/core/imag-edit/src/main.rs diff --git a/bin/core/imag-edit/Cargo.toml b/bin/core/imag-edit/Cargo.toml index b329e17f..6dc9a67d 100644 --- a/bin/core/imag-edit/Cargo.toml +++ b/bin/core/imag-edit/Cargo.toml @@ -49,3 +49,10 @@ path = "../../../lib/core/libimagrt" default-features = false features = ["testing"] +[lib] +name = "libimageditcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-edit" +path = "src/bin.rs" diff --git a/bin/core/imag-edit/src/bin.rs b/bin/core/imag-edit/src/bin.rs new file mode 100644 index 00000000..b0002164 --- /dev/null +++ b/bin/core/imag-edit/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimageditcmd, ImagEdit); diff --git a/bin/core/imag-edit/src/lib.rs b/bin/core/imag-edit/src/lib.rs new file mode 100644 index 00000000..7d515c6d --- /dev/null +++ b/bin/core/imag-edit/src/lib.rs @@ -0,0 +1,121 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] extern crate log; +extern crate failure; + +extern crate libimagentryedit; +extern crate libimagerror; +extern crate libimagrt; +extern crate libimagstore; +extern crate libimagutil; + +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagentryedit::edit::Edit; +use libimagentryedit::edit::EditHeader; +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagstore::storeid::StoreIdIterator; +use libimagstore::iter::get::StoreIdGetIteratorExtension; + +use failure::Fallible as Result; +use clap::App; + +mod ui; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagEdit {} +impl ImagApplication for ImagEdit { + fn run(rt: Runtime) -> Result<()> { + let edit_header = rt.cli().is_present("edit-header"); + let edit_header_only = rt.cli().is_present("edit-header-only"); + + let sids = rt + .ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter(); + + StoreIdIterator::new(Box::new(sids.into_iter().map(Ok))) + .into_get_iter(rt.store()) + .trace_unwrap_exit() + .map(|o| o.unwrap_or_else(|| { + error!("Did not find one entry"); + ::std::process::exit(1) + })) + .for_each(|mut entry| { + if edit_header { + let _ = entry + .edit_header_and_content(&rt) + .map_err_trace_exit_unwrap(); + } else if edit_header_only { + let _ = entry + .edit_header(&rt) + .map_err_trace_exit_unwrap(); + } else { + let _ = entry + .edit_content(&rt) + .map_err_trace_exit_unwrap(); + } + }); + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Edit store entries with $EDITOR" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} diff --git a/bin/core/imag-edit/src/main.rs b/bin/core/imag-edit/src/main.rs deleted file mode 100644 index 3e758d7c..00000000 --- a/bin/core/imag-edit/src/main.rs +++ /dev/null @@ -1,99 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -#[macro_use] extern crate log; -extern crate failure; - -extern crate libimagentryedit; -extern crate libimagerror; -#[macro_use] extern crate libimagrt; -extern crate libimagstore; -extern crate libimagutil; - -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagentryedit::edit::Edit; -use libimagentryedit::edit::EditHeader; -use libimagrt::setup::generate_runtime_setup; -use libimagstore::storeid::StoreIdIterator; -use libimagstore::iter::get::StoreIdGetIteratorExtension; - -mod ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-edit", - &version, - "Edit store entries with $EDITOR", - ui::build_ui); - - let edit_header = rt.cli().is_present("edit-header"); - let edit_header_only = rt.cli().is_present("edit-header-only"); - - let sids = rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter(); - - StoreIdIterator::new(Box::new(sids.map(Ok))) - .into_get_iter(rt.store()) - .trace_unwrap_exit() - .map(|o| o.unwrap_or_else(|| { - error!("Did not find one entry"); - ::std::process::exit(1) - })) - .for_each(|mut entry| { - if edit_header { - entry - .edit_header_and_content(&rt) - .map_err_trace_exit_unwrap(); - } else if edit_header_only { - entry - .edit_header(&rt) - .map_err_trace_exit_unwrap(); - } else { - entry - .edit_content(&rt) - .map_err_trace_exit_unwrap(); - } - }); -} - From bfe15c9157281ef3957001cbe5d54dce9d3ff7fe Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:30:15 +0200 Subject: [PATCH 06/35] imag-git: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-git/Cargo.toml | 8 ++ bin/core/imag-git/src/bin.rs | 39 +++++++ bin/core/imag-git/src/lib.rs | 197 ++++++++++++++++++++++++++++++++++ bin/core/imag-git/src/main.rs | 171 ----------------------------- 4 files changed, 244 insertions(+), 171 deletions(-) create mode 100644 bin/core/imag-git/src/bin.rs create mode 100644 bin/core/imag-git/src/lib.rs delete mode 100644 bin/core/imag-git/src/main.rs diff --git a/bin/core/imag-git/Cargo.toml b/bin/core/imag-git/Cargo.toml index 278b387b..168e04ce 100644 --- a/bin/core/imag-git/Cargo.toml +++ b/bin/core/imag-git/Cargo.toml @@ -23,6 +23,7 @@ maintenance = { status = "actively-developed" } log = "0.4.6" toml = "0.5.1" toml-query = "0.9.2" +failure = "0.1.5" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } @@ -32,3 +33,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimaggitcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-git" +path = "src/bin.rs" diff --git a/bin/core/imag-git/src/bin.rs b/bin/core/imag-git/src/bin.rs new file mode 100644 index 00000000..759a3a3a --- /dev/null +++ b/bin/core/imag-git/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaggitcmd, ImagGit); diff --git a/bin/core/imag-git/src/lib.rs b/bin/core/imag-git/src/lib.rs new file mode 100644 index 00000000..b5b7d5e7 --- /dev/null +++ b/bin/core/imag-git/src/lib.rs @@ -0,0 +1,197 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] extern crate log; +extern crate toml; +extern crate toml_query; +extern crate failure; + +extern crate libimagrt; +extern crate libimagerror; + +use std::io::Write; +use std::io::ErrorKind; +use std::process::Command; + +use toml::Value; +use toml_query::read::TomlValueReadExt; +use clap::App; +use failure::Fallible as Result; + +use libimagerror::exit::ExitUnwrap; +use libimagerror::io::ToExitCode; +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; + +mod ui; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagGit {} +impl ImagApplication for ImagGit { + fn run(rt: Runtime) -> Result<()> { + let execute_in_store = rt + .config() + .unwrap_or_else(|| { + error!("No configuration. Please use git yourself, not via imag-git"); + error!("Won't continue without configuration."); + ::std::process::exit(1); + }) + .read("git.execute_in_store") + .unwrap_or_else(|e| { + error!("Failed to read config setting 'git.execute_in_store'"); + error!("-> {:?}", e); + ::std::process::exit(1) + }) + .unwrap_or_else(|| { + error!("Missing config setting 'git.execute_in_store'"); + ::std::process::exit(1) + }); + + let execute_in_store = match *execute_in_store { + Value::Boolean(b) => b, + _ => { + error!("Type error: 'git.execute_in_store' is not a boolean!"); + ::std::process::exit(1) + } + }; + + let execpath = if execute_in_store { + rt.store().path().to_str() + } else { + rt.rtp().to_str() + } + .map(String::from) + .unwrap_or_else(|| { + error!("Cannot parse to string: {:?}", rt.store().path()); + ::std::process::exit(1) + }); + + + let mut command = Command::new("git"); + command + .stdin(::std::process::Stdio::inherit()) + .stdout(::std::process::Stdio::inherit()) + .stderr(::std::process::Stdio::inherit()) + .arg("-C").arg(&execpath); + + let args = rt + .cli() + .values_of("") + .map(|vs| vs.map(String::from).collect()) + .unwrap_or_else(|| vec![]); + + debug!("Adding args = {:?}", args); + command.args(&args); + + match rt.cli().subcommand() { + (external, Some(ext_m)) => { + command.arg(external); + let args = ext_m + .values_of("") + .map(|vs| vs.map(String::from).collect()) + .unwrap_or_else(|| vec![]); + + debug!("Adding subcommand '{}' and args = {:?}", external, args); + command.args(&args); + }, + _ => {}, + } + + let mut out = rt.stdout(); + + debug!("Calling: {:?}", command); + + match command.spawn().and_then(|mut c| c.wait()) { + Ok(exit_status) => { + if !exit_status.success() { + debug!("git exited with non-zero exit code: {:?}", exit_status); + let mut err = rt.stderr(); + writeln!(err, "git exited with non-zero exit code") + .to_exit_code() + .unwrap_or_exit(); + ::std::process::exit(exit_status.code().unwrap_or(1)); + } + debug!("Successful exit!"); + }, + + Err(e) => { + debug!("Error calling git"); + match e.kind() { + ErrorKind::NotFound => { + let _ = writeln!(out, "Cannot find 'git' executable") + .to_exit_code() + .unwrap_or_exit(); + ::std::process::exit(1); + }, + ErrorKind::PermissionDenied => { + let _ = writeln!(out, "No permission to execute: 'git'") + .to_exit_code() + .unwrap_or_exit(); + ::std::process::exit(1); + }, + _ => { + let _ = writeln!(out, "Error spawning: {:?}", e) + .to_exit_code() + .unwrap_or_exit(); + ::std::process::exit(1); + } + } + } + } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Helper to call git in the store" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} diff --git a/bin/core/imag-git/src/main.rs b/bin/core/imag-git/src/main.rs deleted file mode 100644 index d1370ab1..00000000 --- a/bin/core/imag-git/src/main.rs +++ /dev/null @@ -1,171 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -#[macro_use] extern crate log; -extern crate toml; -extern crate toml_query; - -#[macro_use] extern crate libimagrt; -extern crate libimagerror; - -use std::io::Write; -use std::io::ErrorKind; -use std::process::Command; - -use toml::Value; -use toml_query::read::TomlValueReadExt; - -use libimagerror::exit::ExitUnwrap; -use libimagerror::io::ToExitCode; -use libimagrt::setup::generate_runtime_setup; - -mod ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-git", - &version, - "Helper to call git in the store", - ui::build_ui); - - let execute_in_store = rt - .config() - .unwrap_or_else(|| { - error!("No configuration. Please use git yourself, not via imag-git"); - error!("Won't continue without configuration."); - ::std::process::exit(1); - }) - .read("git.execute_in_store") - .unwrap_or_else(|e| { - error!("Failed to read config setting 'git.execute_in_store'"); - error!("-> {:?}", e); - ::std::process::exit(1) - }) - .unwrap_or_else(|| { - error!("Missing config setting 'git.execute_in_store'"); - ::std::process::exit(1) - }); - - let execute_in_store = match *execute_in_store { - Value::Boolean(b) => b, - _ => { - error!("Type error: 'git.execute_in_store' is not a boolean!"); - ::std::process::exit(1) - } - }; - - let execpath = if execute_in_store { - rt.store().path().to_str() - } else { - rt.rtp().to_str() - } - .map(String::from) - .unwrap_or_else(|| { - error!("Cannot parse to string: {:?}", rt.store().path()); - ::std::process::exit(1) - }); - - - let mut command = Command::new("git"); - command - .stdin(::std::process::Stdio::inherit()) - .stdout(::std::process::Stdio::inherit()) - .stderr(::std::process::Stdio::inherit()) - .arg("-C").arg(&execpath); - - let args = rt - .cli() - .values_of("") - .map(|vs| vs.map(String::from).collect()) - .unwrap_or_else(|| vec![]); - - debug!("Adding args = {:?}", args); - command.args(&args); - - if let (external, Some(ext_m)) = rt.cli().subcommand() { - command.arg(external); - let args = ext_m - .values_of("") - .map(|vs| vs.map(String::from).collect()) - .unwrap_or_else(|| vec![]); - - debug!("Adding subcommand '{}' and args = {:?}", external, args); - command.args(&args); - } - let mut out = rt.stdout(); - - debug!("Calling: {:?}", command); - - match command.spawn().and_then(|mut c| c.wait()) { - Ok(exit_status) => { - if !exit_status.success() { - debug!("git exited with non-zero exit code: {:?}", exit_status); - let mut err = rt.stderr(); - writeln!(err, "git exited with non-zero exit code") - .to_exit_code() - .unwrap_or_exit(); - ::std::process::exit(exit_status.code().unwrap_or(1)); - } - debug!("Successful exit!"); - }, - - Err(e) => { - debug!("Error calling git"); - match e.kind() { - ErrorKind::NotFound => { - writeln!(out, "Cannot find 'git' executable") - .to_exit_code() - .unwrap_or_exit(); - ::std::process::exit(1); - }, - ErrorKind::PermissionDenied => { - writeln!(out, "No permission to execute: 'git'") - .to_exit_code() - .unwrap_or_exit(); - ::std::process::exit(1); - }, - _ => { - writeln!(out, "Error spawning: {:?}", e) - .to_exit_code() - .unwrap_or_exit(); - ::std::process::exit(1); - } - } - } - } -} - From 58ac2caf203e66d2b431ca3e0633fd407fd38a1c Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:39:02 +0200 Subject: [PATCH 07/35] imag-gps: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-gps/Cargo.toml | 7 +++ bin/core/imag-gps/src/bin.rs | 39 +++++++++++++++ bin/core/imag-gps/src/{main.rs => lib.rs} | 61 +++++++++++++++-------- 3 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 bin/core/imag-gps/src/bin.rs rename bin/core/imag-gps/src/{main.rs => lib.rs} (82%) diff --git a/bin/core/imag-gps/Cargo.toml b/bin/core/imag-gps/Cargo.toml index cb7247fc..5c197e7d 100644 --- a/bin/core/imag-gps/Cargo.toml +++ b/bin/core/imag-gps/Cargo.toml @@ -43,3 +43,10 @@ path = "../../../lib/etc/libimagutil" default-features = false features = ["testing"] +[lib] +name = "libimaggpscmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-gps" +path = "src/bin.rs" diff --git a/bin/core/imag-gps/src/bin.rs b/bin/core/imag-gps/src/bin.rs new file mode 100644 index 00000000..60be43b2 --- /dev/null +++ b/bin/core/imag-gps/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaggpscmd, ImagGps); diff --git a/bin/core/imag-gps/src/main.rs b/bin/core/imag-gps/src/lib.rs similarity index 82% rename from bin/core/imag-gps/src/main.rs rename to bin/core/imag-gps/src/lib.rs index 80ef51b8..6b5ae542 100644 --- a/bin/core/imag-gps/src/main.rs +++ b/bin/core/imag-gps/src/lib.rs @@ -39,7 +39,7 @@ extern crate clap; #[macro_use] extern crate failure; extern crate libimagentrygps; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagutil; extern crate libimagerror; extern crate libimagstore; @@ -50,11 +50,13 @@ use std::str::FromStr; use failure::err_msg; +use failure::Fallible as Result; +use clap::App; use libimagstore::storeid::StoreId; use libimagentrygps::types::*; use libimagentrygps::entry::*; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; @@ -62,26 +64,45 @@ use libimagerror::io::ToExitCode; mod ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-gps", - &version, - "Add GPS coordinates to entries", - ui::build_ui); - - if let Some(name) = rt.cli().subcommand_name() { - match name { - "add" => add(&rt), - "remove" => remove(&rt), - "get" => get(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-gps", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagGps {} +impl ImagApplication for ImagGps { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + match name { + "add" => add(&rt), + "remove" => remove(&rt), + "get" => get(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-gps", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + } } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Add GPS coordinates to entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From a7d55930d7303cbced9f9d53b355672b0415d900 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:41:21 +0200 Subject: [PATCH 08/35] imag-grep: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-grep/Cargo.toml | 8 ++ bin/core/imag-grep/src/bin.rs | 39 ++++++++ bin/core/imag-grep/src/{main.rs => lib.rs} | 110 ++++++++++++--------- 3 files changed, 113 insertions(+), 44 deletions(-) create mode 100644 bin/core/imag-grep/src/bin.rs rename bin/core/imag-grep/src/{main.rs => lib.rs} (53%) diff --git a/bin/core/imag-grep/Cargo.toml b/bin/core/imag-grep/Cargo.toml index c95c85b4..a923a902 100644 --- a/bin/core/imag-grep/Cargo.toml +++ b/bin/core/imag-grep/Cargo.toml @@ -22,6 +22,7 @@ maintenance = { status = "actively-developed" } [dependencies] log = "0.4.6" regex = "1.1.7" +failure = "0.1.5" libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" } libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } @@ -32,3 +33,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimaggrepcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-grep" +path = "src/bin.rs" diff --git a/bin/core/imag-grep/src/bin.rs b/bin/core/imag-grep/src/bin.rs new file mode 100644 index 00000000..aacc4628 --- /dev/null +++ b/bin/core/imag-grep/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaggrepcmd, ImagGrep); diff --git a/bin/core/imag-grep/src/main.rs b/bin/core/imag-grep/src/lib.rs similarity index 53% rename from bin/core/imag-grep/src/main.rs rename to bin/core/imag-grep/src/lib.rs index a7b1a1f3..f7a4a2d1 100644 --- a/bin/core/imag-grep/src/main.rs +++ b/bin/core/imag-grep/src/lib.rs @@ -37,17 +37,20 @@ #[macro_use] extern crate log; extern crate clap; extern crate regex; +extern crate failure; extern crate libimagstore; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; use std::io::Write; use regex::Regex; +use failure::Fallible as Result; +use clap::App; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagstore::store::Entry; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; @@ -60,53 +63,72 @@ struct Options { count: bool, } -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-grep", - &version, - "grep through entries text", - ui::build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagGrep {} +impl ImagApplication for ImagGrep { + fn run(rt: Runtime) -> Result<()> { + let opts = Options { + files_with_matches : rt.cli().is_present("files-with-matches"), + count : rt.cli().is_present("count"), + }; - let opts = Options { - files_with_matches : rt.cli().is_present("files-with-matches"), - count : rt.cli().is_present("count"), - }; + let mut count : usize = 0; - let mut count : usize = 0; + let pattern = rt + .cli() + .value_of("pattern") + .map(Regex::new) + .unwrap() // ensured by clap + .unwrap_or_else(|e| { + error!("Regex building error: {:?}", e); + ::std::process::exit(1) + }); - let pattern = rt - .cli() - .value_of("pattern") - .map(Regex::new) - .unwrap() // ensured by clap - .unwrap_or_else(|e| { - error!("Regex building error: {:?}", e); - ::std::process::exit(1) - }); + let overall_count = rt + .store() + .entries() + .map_err_trace_exit_unwrap() + .into_get_iter() + .filter_map(|res| res.map_err_trace_exit_unwrap()) + .filter_map(|entry| if pattern.is_match(entry.get_content()) { + show(&rt, &entry, &pattern, &opts, &mut count); + Some(()) + } else { + None + }) + .count(); - let overall_count = rt - .store() - .entries() - .map_err_trace_exit_unwrap() - .into_get_iter() - .filter_map(|res| res.map_err_trace_exit_unwrap()) - .filter_map(|entry| if pattern.is_match(entry.get_content()) { - show(&rt, &entry, &pattern, &opts, &mut count); - Some(()) - } else { - None - }) - .count(); + if opts.count { + writeln!(rt.stdout(), "{}", count).to_exit_code().unwrap_or_exit(); + } else if !opts.files_with_matches { + writeln!(rt.stdout(), "Processed {} files, {} matches, {} nonmatches", + overall_count, + count, + overall_count - count) + .to_exit_code() + .unwrap_or_exit(); + } - if opts.count { - writeln!(rt.stdout(), "{}", count).to_exit_code().unwrap_or_exit(); - } else if !opts.files_with_matches { - writeln!(rt.stdout(), "Processed {} files, {} matches, {} nonmatches", - overall_count, - count, - overall_count - count) - .to_exit_code() - .unwrap_or_exit(); + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "grep through entries text" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 97c46da599bfb0b2afd392c44f44c0b7fc73997f Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:41:51 +0200 Subject: [PATCH 09/35] imag-header: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-header/Cargo.toml | 7 ++ bin/core/imag-header/src/bin.rs | 39 +++++++ bin/core/imag-header/src/{main.rs => lib.rs} | 106 +++++++++++-------- 3 files changed, 108 insertions(+), 44 deletions(-) create mode 100644 bin/core/imag-header/src/bin.rs rename bin/core/imag-header/src/{main.rs => lib.rs} (81%) diff --git a/bin/core/imag-header/Cargo.toml b/bin/core/imag-header/Cargo.toml index e36c05ac..7caf2292 100644 --- a/bin/core/imag-header/Cargo.toml +++ b/bin/core/imag-header/Cargo.toml @@ -45,3 +45,10 @@ path = "../../../lib/core/libimagrt" default-features = false features = ["testing"] +[lib] +name = "libimagheadercmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-header" +path = "src/bin.rs" diff --git a/bin/core/imag-header/src/bin.rs b/bin/core/imag-header/src/bin.rs new file mode 100644 index 00000000..532520e6 --- /dev/null +++ b/bin/core/imag-header/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagheadercmd, ImagHeader); diff --git a/bin/core/imag-header/src/main.rs b/bin/core/imag-header/src/lib.rs similarity index 81% rename from bin/core/imag-header/src/main.rs rename to bin/core/imag-header/src/lib.rs index 1366726c..a8918fe8 100644 --- a/bin/core/imag-header/src/main.rs +++ b/bin/core/imag-header/src/lib.rs @@ -41,7 +41,7 @@ extern crate failure; extern crate libimagentryedit; extern crate libimagerror; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagutil; @@ -49,10 +49,10 @@ use std::io::Write; use std::str::FromStr; use std::string::ToString; -use clap::ArgMatches; +use clap::{App, ArgMatches}; use filters::filter::Filter; -use failure::Error; use toml::Value; +use failure::{Fallible as Result, Error}; use libimagerror::exit::ExitCode; use libimagerror::exit::ExitUnwrap; @@ -60,7 +60,7 @@ use libimagerror::io::ToExitCode; use libimagerror::iter::TraceIterator; use libimagerror::trace::MapErrTrace; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreIdIterator; @@ -68,55 +68,73 @@ use libimagstore::storeid::StoreIdIterator; use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadTypeExt; - mod ui; const EPS_CMP: f64 = 1e-10; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-header", - &version, - "Plumbing tool for reading/writing structured data in entries", - ui::build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagHeader {} +impl ImagApplication for ImagHeader { + fn run(rt: Runtime) -> Result<()> { + let list_output_with_ids = rt.cli().is_present("list-id"); + let list_output_with_ids_fmt = rt.cli().value_of("list-id-format"); - let list_output_with_ids = rt.cli().is_present("list-id"); - let list_output_with_ids_fmt = rt.cli().value_of("list-id-format"); + trace!("list_output_with_ids = {:?}", list_output_with_ids ); + trace!("list_output_with_ids_fmt = {:?}", list_output_with_ids_fmt); - trace!("list_output_with_ids = {:?}", list_output_with_ids ); - trace!("list_output_with_ids_fmt = {:?}", list_output_with_ids_fmt); + let sids = rt + .ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter(); - let sids = rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter(); + let iter = StoreIdIterator::new(Box::new(sids.map(Ok))) + .into_get_iter(rt.store()) + .trace_unwrap_exit() + .filter_map(|x| x); - let iter = StoreIdIterator::new(Box::new(sids.map(Ok))) - .into_get_iter(rt.store()) - .trace_unwrap_exit() - .filter_map(|x| x); + match rt.cli().subcommand() { + ("read", Some(mtch)) => ::std::process::exit(read(&rt, mtch, iter)), + ("has", Some(mtch)) => has(&rt, mtch, iter), + ("hasnt", Some(mtch)) => hasnt(&rt, mtch, iter), + ("int", Some(mtch)) => int(&rt, mtch, iter), + ("float", Some(mtch)) => float(&rt, mtch, iter), + ("string", Some(mtch)) => string(&rt, mtch, iter), + ("bool", Some(mtch)) => boolean(&rt, mtch, iter), + (other, _mtchs) => { + debug!("Unknown command"); + ::std::process::exit({ + rt.handle_unknown_subcommand("imag-header", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .unwrap_or(1) + }); + }, + }; - match rt.cli().subcommand() { - ("read", Some(mtch)) => ::std::process::exit(read(&rt, mtch, iter)), - ("has", Some(mtch)) => has(&rt, mtch, iter), - ("hasnt", Some(mtch)) => hasnt(&rt, mtch, iter), - ("int", Some(mtch)) => int(&rt, mtch, iter), - ("float", Some(mtch)) => float(&rt, mtch, iter), - ("string", Some(mtch)) => string(&rt, mtch, iter), - ("bool", Some(mtch)) => boolean(&rt, mtch, iter), - (other, _mtchs) => { - debug!("Unknown command"); - ::std::process::exit({ - rt.handle_unknown_subcommand("imag-header", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .unwrap_or(1) - }); - }, + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Plumbing tool for reading/writing structured data in entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 0739fed6662154f484eb615c92373d37ce2977fe Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:43:27 +0200 Subject: [PATCH 10/35] imag-ids: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-ids/Cargo.toml | 7 ++ bin/core/imag-ids/src/bin.rs | 39 ++++++++++ bin/core/imag-ids/src/lib.rs | 134 ++++++++++++++++++++++++++++++++++ bin/core/imag-ids/src/main.rs | 113 ---------------------------- 4 files changed, 180 insertions(+), 113 deletions(-) create mode 100644 bin/core/imag-ids/src/bin.rs create mode 100644 bin/core/imag-ids/src/lib.rs delete mode 100644 bin/core/imag-ids/src/main.rs diff --git a/bin/core/imag-ids/Cargo.toml b/bin/core/imag-ids/Cargo.toml index 3282c375..8f6afe96 100644 --- a/bin/core/imag-ids/Cargo.toml +++ b/bin/core/imag-ids/Cargo.toml @@ -37,3 +37,10 @@ features = ["color", "suggestions", "wrap_help"] [dev-dependencies] env_logger = "0.7" +[lib] +name = "libimagidscmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-ids" +path = "src/bin.rs" diff --git a/bin/core/imag-ids/src/bin.rs b/bin/core/imag-ids/src/bin.rs new file mode 100644 index 00000000..ca472b77 --- /dev/null +++ b/bin/core/imag-ids/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagidscmd, ImagIds); diff --git a/bin/core/imag-ids/src/lib.rs b/bin/core/imag-ids/src/lib.rs new file mode 100644 index 00000000..bb0e08a8 --- /dev/null +++ b/bin/core/imag-ids/src/lib.rs @@ -0,0 +1,134 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] extern crate log; +extern crate toml; +extern crate toml_query; +#[macro_use] extern crate failure; + +#[cfg(test)] +extern crate env_logger; + +extern crate libimagerror; +extern crate libimagstore; +extern crate libimagrt; + +use std::io::Write; +use std::result::Result as RResult; + +use failure::Fallible as Result; +use clap::App; + +use libimagstore::storeid::StoreId; +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagerror::exit::ExitUnwrap; +use libimagerror::io::ToExitCode; + +mod ui; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagIds {} +impl ImagApplication for ImagIds { + fn run(rt: Runtime) -> Result<()> { + let print_storepath = rt.cli().is_present("print-storepath"); + + let iterator = if rt.ids_from_stdin() { + debug!("Fetching IDs from stdin..."); + let ids = rt + .ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }); + Box::new(ids.into_iter().map(Ok)) + as Box>> + } else { + Box::new(rt.store().entries().map_err_trace_exit_unwrap()) + as Box>> + } + .trace_unwrap_exit() + .map(|id| if print_storepath { + (Some(rt.store().path()), id) + } else { + (None, id) + }); + + let mut stdout = rt.stdout(); + trace!("Got output: {:?}", stdout); + + iterator.for_each(|(storepath, id)| { + rt.report_touched(&id).unwrap_or_exit(); + if !rt.output_is_pipe() { + let id = id.to_str().map_err_trace_exit_unwrap(); + trace!("Writing to {:?}", stdout); + + let result = if let Some(store) = storepath { + writeln!(stdout, "{}/{}", store.display(), id) + } else { + writeln!(stdout, "{}", id) + }; + + result.to_exit_code().unwrap_or_exit(); + } + }); + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "print all ids" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} diff --git a/bin/core/imag-ids/src/main.rs b/bin/core/imag-ids/src/main.rs deleted file mode 100644 index 8c8222bd..00000000 --- a/bin/core/imag-ids/src/main.rs +++ /dev/null @@ -1,113 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -#[macro_use] extern crate log; -extern crate toml; -extern crate toml_query; -#[macro_use] extern crate failure; - -#[cfg(test)] -extern crate env_logger; - -extern crate libimagerror; -extern crate libimagstore; -#[macro_use] extern crate libimagrt; - -use std::io::Write; - -use libimagstore::storeid::StoreId; -use libimagrt::setup::generate_runtime_setup; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::exit::ExitUnwrap; -use libimagerror::io::ToExitCode; - -mod ui; - -use crate::ui::build_ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-ids", - &version, - "print all ids", - build_ui); - - let print_storepath = rt.cli().is_present("print-storepath"); - - let iterator = if rt.ids_from_stdin() { - debug!("Fetching IDs from stdin..."); - let ids = rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }); - Box::new(ids.into_iter().map(Ok)) - as Box>> - } else { - Box::new(rt.store().entries().map_err_trace_exit_unwrap()) - as Box>> - } - .trace_unwrap_exit() - .map(|id| if print_storepath { - (Some(rt.store().path()), id) - } else { - (None, id) - }); - - let mut stdout = rt.stdout(); - trace!("Got output: {:?}", stdout); - - iterator.for_each(|(storepath, id)| { - rt.report_touched(&id).unwrap_or_exit(); - if !rt.output_is_pipe() { - let id = id.to_str().map_err_trace_exit_unwrap(); - trace!("Writing to {:?}", stdout); - - let result = if let Some(store) = storepath { - writeln!(stdout, "{}/{}", store.display(), id) - } else { - writeln!(stdout, "{}", id) - }; - - result.to_exit_code().unwrap_or_exit(); - } - }) -} - From 208d6e62e60f4d80658629c2c13280c4bdab448c Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:44:01 +0200 Subject: [PATCH 11/35] imag-init: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-init/Cargo.toml | 9 +++++ bin/core/imag-init/src/bin.rs | 46 ++++++++++++++++++++++ bin/core/imag-init/src/{main.rs => lib.rs} | 35 +++++++++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 bin/core/imag-init/src/bin.rs rename bin/core/imag-init/src/{main.rs => lib.rs} (91%) diff --git a/bin/core/imag-init/Cargo.toml b/bin/core/imag-init/Cargo.toml index 9701794c..cf68ef8c 100644 --- a/bin/core/imag-init/Cargo.toml +++ b/bin/core/imag-init/Cargo.toml @@ -20,6 +20,8 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" } maintenance = { status = "actively-developed" } [dependencies] +failure = "0.1.5" + libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } @@ -31,3 +33,10 @@ features = ["color", "suggestions", "wrap_help"] [dev-dependencies] toml = "0.5.1" +[lib] +name = "libimaginitcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-init" +path = "src/bin.rs" diff --git a/bin/core/imag-init/src/bin.rs b/bin/core/imag-init/src/bin.rs new file mode 100644 index 00000000..aea6ebc3 --- /dev/null +++ b/bin/core/imag-init/src/bin.rs @@ -0,0 +1,46 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate failure; +use failure::Fallible as Result; + +extern crate libimaginitcmd; + + +fn main() -> Result<()> { + libimaginitcmd::imag_init(); + Ok(()) +} diff --git a/bin/core/imag-init/src/main.rs b/bin/core/imag-init/src/lib.rs similarity index 91% rename from bin/core/imag-init/src/main.rs rename to bin/core/imag-init/src/lib.rs index 5935a812..e2033e3d 100644 --- a/bin/core/imag-init/src/main.rs +++ b/bin/core/imag-init/src/lib.rs @@ -35,7 +35,7 @@ )] extern crate clap; - +extern crate failure; #[cfg(test)] extern crate toml; @@ -53,6 +53,10 @@ use std::process::Command; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; + +use failure::Fallible as Result; +use clap::App; const CONFIGURATION_STR : &str = include_str!("../imagrc.toml"); @@ -69,7 +73,34 @@ const GITIGNORE_STR : &str = r#" imagrc.toml "#; -fn main() { +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagInit {} +impl ImagApplication for ImagInit { + fn run(_rt: Runtime) -> Result<()> { + panic!("imag-init needs to be run as a seperate binary, or we'll need to figure something out here!"); + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Intialize the imag store" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} + +pub fn imag_init() { let version = make_imag_version!(); let app = ui::build_ui(Runtime::get_default_cli_builder( "imag-init", From aa851a87f5fb8ddf98edd98561980a562319b05e Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:44:20 +0200 Subject: [PATCH 12/35] imag-link: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-link/Cargo.toml | 6 ++ bin/core/imag-link/src/bin.rs | 39 +++++++ bin/core/imag-link/src/{main.rs => lib.rs} | 112 ++++++++++++--------- 3 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 bin/core/imag-link/src/bin.rs rename bin/core/imag-link/src/{main.rs => lib.rs} (89%) diff --git a/bin/core/imag-link/Cargo.toml b/bin/core/imag-link/Cargo.toml index 5b98906e..50ef9d95 100644 --- a/bin/core/imag-link/Cargo.toml +++ b/bin/core/imag-link/Cargo.toml @@ -54,4 +54,10 @@ path = "../../../lib/core/libimagrt" default-features = false features = ["testing"] +[lib] +name = "libimaglinkcmd" +path = "src/lib.rs" +[[bin]] +name = "imag-link" +path = "src/bin.rs" diff --git a/bin/core/imag-link/src/bin.rs b/bin/core/imag-link/src/bin.rs new file mode 100644 index 00000000..1bcebf1d --- /dev/null +++ b/bin/core/imag-link/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaglinkcmd, ImagLink); diff --git a/bin/core/imag-link/src/main.rs b/bin/core/imag-link/src/lib.rs similarity index 89% rename from bin/core/imag-link/src/main.rs rename to bin/core/imag-link/src/lib.rs index 7e451a83..bfa927dd 100644 --- a/bin/core/imag-link/src/main.rs +++ b/bin/core/imag-link/src/lib.rs @@ -45,7 +45,7 @@ extern crate failure; extern crate libimagentrylink; extern crate libimagentryurl; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; @@ -69,7 +69,7 @@ use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::exit::ExitUnwrap; use libimagerror::io::ToExitCode; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreId; use libimagutil::warn_exit::warn_exit; @@ -77,57 +77,75 @@ use libimagutil::warn_result::*; use url::Url; use failure::Fallible as Result; +use clap::App; mod ui; -use crate::ui::build_ui; +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagLink {} +impl ImagApplication for ImagLink { + fn run(rt: Runtime) -> Result<()> { + if rt.cli().is_present("check-consistency") { + let exit_code = match rt.store().check_link_consistency() { + Ok(_) => { + info!("Store is consistent"); + 0 + } + Err(e) => { + trace_error(&e); + 1 + } + }; + ::std::process::exit(exit_code); + } -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-link", - &version, - "Link entries", - build_ui); - if rt.cli().is_present("check-consistency") { - let exit_code = match rt.store().check_link_consistency() { - Ok(_) => { - info!("Store is consistent"); - 0 - } - Err(e) => { - trace_error(&e); - 1 - } - }; - ::std::process::exit(exit_code); + let _ = rt.cli() + .subcommand_name() + .map(|name| { + match name { + "remove" => remove_linking(&rt), + "unlink" => unlink(&rt), + "list" => list_linkings(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-link", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } + }) + .or_else(|| { + if let (Some(from), Some(to)) = (rt.cli().value_of("from"), rt.cli().values_of("to")) { + Some(link_from_to(&rt, from, to)) + } else { + warn_exit("No commandline call", 1) + } + }) + .ok_or_else(|| err_msg("No commandline call".to_owned())) + .map_err_trace_exit_unwrap(); + + Ok(()) } - rt.cli() - .subcommand_name() - .map(|name| { - match name { - "remove" => remove_linking(&rt), - "unlink" => unlink(&rt), - "list" => list_linkings(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-link", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, - } - }) - .or_else(|| { - if let (Some(from), Some(to)) = (rt.cli().value_of("from"), rt.cli().values_of("to")) { - link_from_to(&rt, from, to); - Some(()) - } else { - warn_exit("No commandline call", 1) - } - }) - .ok_or_else(|| err_msg("No commandline call".to_owned())) - .map_err_trace_exit_unwrap(); + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Link entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } } fn get_entry_by_name<'a>(rt: &'a Runtime, name: &str) -> Result>> { From 4c9998ca1d54b447b47f714b4a9a467642c047ce Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:44:41 +0200 Subject: [PATCH 13/35] imag-markdown: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-markdown/Cargo.toml | 7 ++ bin/core/imag-markdown/src/bin.rs | 39 +++++++++ bin/core/imag-markdown/src/lib.rs | 123 +++++++++++++++++++++++++++++ bin/core/imag-markdown/src/main.rs | 102 ------------------------ 4 files changed, 169 insertions(+), 102 deletions(-) create mode 100644 bin/core/imag-markdown/src/bin.rs create mode 100644 bin/core/imag-markdown/src/lib.rs delete mode 100644 bin/core/imag-markdown/src/main.rs diff --git a/bin/core/imag-markdown/Cargo.toml b/bin/core/imag-markdown/Cargo.toml index a4575b91..e35d431a 100644 --- a/bin/core/imag-markdown/Cargo.toml +++ b/bin/core/imag-markdown/Cargo.toml @@ -34,3 +34,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagmarkdowncmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-markdown" +path = "src/bin.rs" diff --git a/bin/core/imag-markdown/src/bin.rs b/bin/core/imag-markdown/src/bin.rs new file mode 100644 index 00000000..66ddbd3c --- /dev/null +++ b/bin/core/imag-markdown/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagmarkdowncmd, ImagMarkdown); diff --git a/bin/core/imag-markdown/src/lib.rs b/bin/core/imag-markdown/src/lib.rs new file mode 100644 index 00000000..2250fe41 --- /dev/null +++ b/bin/core/imag-markdown/src/lib.rs @@ -0,0 +1,123 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] extern crate log; +extern crate failure; + +extern crate libimagerror; +extern crate libimagrt; +extern crate libimagstore; + +use std::io::Write; + +use failure::Error; +use failure::err_msg; +use failure::Fallible as Result; +use clap::App; + +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagstore::iter::get::StoreIdGetIteratorExtension; + +mod ui; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagMarkdown {} +impl ImagApplication for ImagMarkdown { + fn run(rt: Runtime) -> Result<()> { + let only_links = rt.cli().is_present("links"); + let out = rt.stdout(); + let mut outlock = out.lock(); + + let iter = rt + .ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter() + .map(Ok) + .into_get_iter(rt.store()) + .trace_unwrap_exit() + .map(|ofle| ofle.ok_or_else(|| { + err_msg("Entry does not exist but is in store. This is a BUG, please report!") + })) + .trace_unwrap_exit(); + + if only_links { + iter.map(|fle| libimagentrymarkdown::link::extract_links(fle.get_content())) + .for_each(|links| { + links.iter().for_each(|link| { + writeln!(outlock, "{title}: {link}", title = link.title, link = link.link) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + }) + }) + + } else { + iter.map(|fle| libimagentrymarkdown::html::to_html(fle.get_content())) + .trace_unwrap_exit() + .for_each(|html| { + writeln!(outlock, "{}", html).map_err(Error::from).map_err_trace_exit_unwrap(); + }) + } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Print one or more imag entries after processing them with a markdown parser" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} diff --git a/bin/core/imag-markdown/src/main.rs b/bin/core/imag-markdown/src/main.rs deleted file mode 100644 index f3c1029b..00000000 --- a/bin/core/imag-markdown/src/main.rs +++ /dev/null @@ -1,102 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -#[macro_use] extern crate log; -extern crate failure; - -extern crate libimagerror; -#[macro_use] extern crate libimagrt; -extern crate libimagstore; - -use std::io::Write; - -use failure::Error; -use failure::err_msg; - -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagrt::setup::generate_runtime_setup; -use libimagstore::iter::get::StoreIdGetIteratorExtension; - -mod ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-markdown", - &version, - "Print one or more imag entries after processing them with a markdown parser", - ui::build_ui); - - let only_links = rt.cli().is_present("links"); - let out = rt.stdout(); - let mut outlock = out.lock(); - - let iter = rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter() - .map(Ok) - .into_get_iter(rt.store()) - .trace_unwrap_exit() - .map(|ofle| ofle.ok_or_else(|| { - err_msg("Entry does not exist but is in store. This is a BUG, please report!") - })) - .trace_unwrap_exit(); - - if only_links { - iter.map(|fle| libimagentrymarkdown::link::extract_links(fle.get_content())) - .for_each(|links| { - links.iter().for_each(|link| { - writeln!(outlock, "{title}: {link}", title = link.title, link = link.link) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - }) - }) - - } else { - iter.map(|fle| libimagentrymarkdown::html::to_html(fle.get_content())) - .trace_unwrap_exit() - .for_each(|html| { - writeln!(outlock, "{}", html).map_err(Error::from).map_err_trace_exit_unwrap(); - }) - } -} - From 186b03deea1230ae77937d10214384ca0d8bbf74 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:45:49 +0200 Subject: [PATCH 14/35] imag-mv: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-mv/Cargo.toml | 8 ++ bin/core/imag-mv/src/bin.rs | 39 ++++++++ bin/core/imag-mv/src/lib.rs | 181 +++++++++++++++++++++++++++++++++++ bin/core/imag-mv/src/main.rs | 156 ------------------------------ 4 files changed, 228 insertions(+), 156 deletions(-) create mode 100644 bin/core/imag-mv/src/bin.rs create mode 100644 bin/core/imag-mv/src/lib.rs delete mode 100644 bin/core/imag-mv/src/main.rs diff --git a/bin/core/imag-mv/Cargo.toml b/bin/core/imag-mv/Cargo.toml index 8dd5e0d2..41df6adc 100644 --- a/bin/core/imag-mv/Cargo.toml +++ b/bin/core/imag-mv/Cargo.toml @@ -21,6 +21,7 @@ maintenance = { status = "actively-developed" } [dependencies] log = "0.4.6" +failure = "0.1.5" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } @@ -32,3 +33,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagmvcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-mv" +path = "src/bin.rs" diff --git a/bin/core/imag-mv/src/bin.rs b/bin/core/imag-mv/src/bin.rs new file mode 100644 index 00000000..36285798 --- /dev/null +++ b/bin/core/imag-mv/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagmvcmd, ImagMv); diff --git a/bin/core/imag-mv/src/lib.rs b/bin/core/imag-mv/src/lib.rs new file mode 100644 index 00000000..4107e7b3 --- /dev/null +++ b/bin/core/imag-mv/src/lib.rs @@ -0,0 +1,181 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate log; +extern crate clap; +extern crate failure; + +extern crate libimagrt; +extern crate libimagstore; +extern crate libimagerror; +extern crate libimagentrylink; + +use std::process::exit; + +mod ui; + +use std::path::PathBuf; +use std::result::Result as RResult; + +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagerror::exit::ExitUnwrap; +use libimagstore::storeid::StoreId; +use libimagstore::store::Store; +use libimagstore::store::FileLockEntry; +use libimagentrylink::linkable::Linkable; +use libimagstore::iter::get::StoreIdGetIteratorExtension; + +use failure::Fallible as Result; +use clap::App; + + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagMv {} +impl ImagApplication for ImagMv { + fn run(rt: Runtime) -> Result<()> { + let sourcename = rt + .cli() + .value_of("source") + .map(PathBuf::from) + .map(StoreId::new) + .unwrap() // unwrap safe by clap + .map_err_trace_exit_unwrap(); + + let destname = rt + .cli() + .value_of("dest") + .map(PathBuf::from) + .map(StoreId::new) + .unwrap() // unwrap safe by clap + .map_err_trace_exit_unwrap(); + + // remove links to entry, and re-add them later + let mut linked_entries = { + rt.store() + .get(sourcename.clone()) + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("Funny things happened: Entry moved to destination did not fail, but entry does not exist"); + exit(1) + }) + .links() + .map_err_trace_exit_unwrap() + .map(|link| Ok(link.get_store_id().clone()) as RResult<_, _>) + .into_get_iter(rt.store()) + .trace_unwrap_exit() + .map(|e| { + e.unwrap_or_else(|| { + error!("Linked entry does not exist"); + exit(1) + }) + }) + .collect::>() + }; + + { // remove links to linked entries from source + let mut entry = rt + .store() + .get(sourcename.clone()) + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("Source Entry does not exist"); + exit(1) + }); + + for link in linked_entries.iter_mut() { + let _ = entry.remove_link(link).map_err_trace_exit_unwrap(); + } + } + + let _ = rt + .store() + .move_by_id(sourcename.clone(), destname.clone()) + .map_err(|e| { // on error, re-add links + debug!("Re-adding links to source entry because moving failed"); + relink(rt.store(), sourcename.clone(), &mut linked_entries); + e + }) + .map_err_trace_exit_unwrap(); + + let _ = rt.report_touched(&destname).unwrap_or_exit(); + + // re-add links to moved entry + relink(rt.store(), destname, &mut linked_entries); + + info!("Ok."); + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Move things around in the store" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} + + + +fn relink<'a>(store: &'a Store, target: StoreId, linked_entries: &mut Vec>) { + let mut entry = store + .get(target) + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("Funny things happened: Entry moved to destination did not fail, but entry does not exist"); + exit(1) + }); + + + for mut link in linked_entries { + let _ = entry.add_link(&mut link).map_err_trace_exit_unwrap(); + } +} diff --git a/bin/core/imag-mv/src/main.rs b/bin/core/imag-mv/src/main.rs deleted file mode 100644 index 27393279..00000000 --- a/bin/core/imag-mv/src/main.rs +++ /dev/null @@ -1,156 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -#[macro_use] extern crate log; -extern crate clap; - -#[macro_use] extern crate libimagrt; -extern crate libimagstore; -extern crate libimagerror; -extern crate libimagentrylink; - -use std::process::exit; - -mod ui; -use crate::ui::build_ui; - -use std::path::PathBuf; - -use libimagrt::setup::generate_runtime_setup; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::exit::ExitUnwrap; -use libimagstore::storeid::StoreId; -use libimagstore::store::Store; -use libimagstore::store::FileLockEntry; -use libimagentrylink::linkable::Linkable; -use libimagstore::iter::get::StoreIdGetIteratorExtension; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-mv", - &version, - "Move things around in the store", - build_ui); - - debug!("mv"); - - let sourcename = rt - .cli() - .value_of("source") - .map(PathBuf::from) - .map(StoreId::new) - .unwrap() // unwrap safe by clap - .map_err_trace_exit_unwrap(); - - let destname = rt - .cli() - .value_of("dest") - .map(PathBuf::from) - .map(StoreId::new) - .unwrap() // unwrap safe by clap - .map_err_trace_exit_unwrap(); - - // remove links to entry, and re-add them later - let mut linked_entries = { - rt.store() - .get(sourcename.clone()) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("Funny things happened: Entry moved to destination did not fail, but entry does not exist"); - exit(1) - }) - .links() - .map_err_trace_exit_unwrap() - .map(|link| Ok(link.get_store_id().clone()) as Result<_, _>) - .into_get_iter(rt.store()) - .trace_unwrap_exit() - .map(|e| { - e.unwrap_or_else(|| { - error!("Linked entry does not exist"); - exit(1) - }) - }) - .collect::>() - }; - - { // remove links to linked entries from source - let mut entry = rt - .store() - .get(sourcename.clone()) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("Source Entry does not exist"); - exit(1) - }); - - for link in linked_entries.iter_mut() { - entry.remove_link(link).map_err_trace_exit_unwrap(); - } - } - - rt - .store() - .move_by_id(sourcename.clone(), destname.clone()) - .map_err(|e| { // on error, re-add links - debug!("Re-adding links to source entry because moving failed"); - relink(rt.store(), sourcename.clone(), &mut linked_entries); - e - }) - .map_err_trace_exit_unwrap(); - - rt.report_touched(&destname).unwrap_or_exit(); - - // re-add links to moved entry - relink(rt.store(), destname, &mut linked_entries); - - info!("Ok."); -} - -fn relink<'a>(store: &'a Store, target: StoreId, linked_entries: &mut Vec>) { - let mut entry = store - .get(target) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("Funny things happened: Entry moved to destination did not fail, but entry does not exist"); - exit(1) - }); - - - for mut link in linked_entries { - entry.add_link(&mut link).map_err_trace_exit_unwrap(); - } -} From fec52bdbc54493b4927767a918642439d5b6572d Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:46:07 +0200 Subject: [PATCH 15/35] imag-ref: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-ref/Cargo.toml | 7 +++ bin/core/imag-ref/src/bin.rs | 39 +++++++++++++ bin/core/imag-ref/src/{main.rs => lib.rs} | 67 +++++++++++++++-------- 3 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 bin/core/imag-ref/src/bin.rs rename bin/core/imag-ref/src/{main.rs => lib.rs} (83%) diff --git a/bin/core/imag-ref/Cargo.toml b/bin/core/imag-ref/Cargo.toml index 5333054a..a0223e0c 100644 --- a/bin/core/imag-ref/Cargo.toml +++ b/bin/core/imag-ref/Cargo.toml @@ -35,3 +35,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagrefcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-ref" +path = "src/bin.rs" diff --git a/bin/core/imag-ref/src/bin.rs b/bin/core/imag-ref/src/bin.rs new file mode 100644 index 00000000..721f3477 --- /dev/null +++ b/bin/core/imag-ref/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagrefcmd, ImagRef); diff --git a/bin/core/imag-ref/src/main.rs b/bin/core/imag-ref/src/lib.rs similarity index 83% rename from bin/core/imag-ref/src/main.rs rename to bin/core/imag-ref/src/lib.rs index 585c69f4..7cbcb251 100644 --- a/bin/core/imag-ref/src/main.rs +++ b/bin/core/imag-ref/src/lib.rs @@ -39,23 +39,24 @@ extern crate clap; #[macro_use] extern crate failure; extern crate libimagstore; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagentryref; extern crate libimagerror; extern crate libimaginteraction; extern crate libimagutil; mod ui; -use crate::ui::build_ui; use std::process::exit; use std::io::Write; use failure::Error; +use failure::Fallible as Result; +use clap::App; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagrt::runtime::Runtime; use libimagentryref::reference::Ref; use libimagentryref::reference::MutRef; @@ -63,27 +64,47 @@ use libimagentryref::reference::RefFassade; use libimagentryref::hasher::default::DefaultHasher; use libimagentryref::util::get_ref_config; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-ref", - &version, - "Reference files outside of the store", - build_ui); - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call: {}", name); - match name { - "deref" => deref(&rt), - "create" => create(&rt), - "remove" => remove(&rt), - "list-dead" => list_dead(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-ref", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagRef {} +impl ImagApplication for ImagRef { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + debug!("Call: {}", name); + match name { + "deref" => deref(&rt), + "create" => create(&rt), + "remove" => remove(&rt), + "list-dead" => list_dead(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-ref", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } }; + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Reference files outside of the store" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 4683b205b6d50462d4ea48191293837fd4958ae8 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:46:23 +0200 Subject: [PATCH 16/35] imag-store: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-store/Cargo.toml | 7 ++ bin/core/imag-store/src/bin.rs | 39 ++++++++++ bin/core/imag-store/src/{main.rs => lib.rs} | 81 +++++++++++++-------- 3 files changed, 97 insertions(+), 30 deletions(-) create mode 100644 bin/core/imag-store/src/bin.rs rename bin/core/imag-store/src/{main.rs => lib.rs} (52%) diff --git a/bin/core/imag-store/Cargo.toml b/bin/core/imag-store/Cargo.toml index 89b02275..a964363c 100644 --- a/bin/core/imag-store/Cargo.toml +++ b/bin/core/imag-store/Cargo.toml @@ -52,3 +52,10 @@ path = "../../../lib/core/libimagrt" default-features = false features = ["testing"] +[lib] +name = "libimagstorecmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-store" +path = "src/bin.rs" diff --git a/bin/core/imag-store/src/bin.rs b/bin/core/imag-store/src/bin.rs new file mode 100644 index 00000000..841df91b --- /dev/null +++ b/bin/core/imag-store/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagstorecmd, ImagStore); diff --git a/bin/core/imag-store/src/main.rs b/bin/core/imag-store/src/lib.rs similarity index 52% rename from bin/core/imag-store/src/main.rs rename to bin/core/imag-store/src/lib.rs index 6ba6ad98..1936ecef 100644 --- a/bin/core/imag-store/src/main.rs +++ b/bin/core/imag-store/src/lib.rs @@ -40,7 +40,7 @@ extern crate toml; #[cfg(test)] extern crate toml_query; extern crate failure; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; @@ -51,7 +51,8 @@ extern crate libimagutil; #[cfg(not(test))] extern crate libimagutil; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; +use libimagrt::runtime::Runtime; use libimagerror::trace::MapErrTrace; mod create; @@ -65,42 +66,62 @@ mod util; use std::ops::Deref; +use failure::Fallible as Result; +use clap::App; + use crate::create::create; use crate::delete::delete; use crate::get::get; use crate::retrieve::retrieve; -use crate::ui::build_ui; use crate::update::update; use crate::verify::verify; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-store", - &version, - "Direct interface to the store. Use with great care!", - build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagStore {} +impl ImagApplication for ImagStore { + fn run(rt: Runtime) -> Result<()> { + let command = rt.cli().subcommand_name().map(String::from); - let command = rt.cli().subcommand_name().map(String::from); + if let Some(command) = command { + debug!("Call: {}", command); + match command.deref() { + "create" => create(&rt), + "delete" => delete(&rt), + "get" => get(&rt), + "retrieve" => retrieve(&rt), + "update" => update(&rt), + "verify" => verify(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-store", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + }; + } else { + debug!("No command"); + } - if let Some(command) = command { - debug!("Call: {}", command); - match command.deref() { - "create" => create(&rt), - "delete" => delete(&rt), - "get" => get(&rt), - "retrieve" => retrieve(&rt), - "update" => update(&rt), - "verify" => verify(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-store", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, - }; - } else { - debug!("No command"); + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Direct interface to the store. Use with great care!" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } - From a68d1ce83907d5db398330ba72c8abbc89117391 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:48:38 +0200 Subject: [PATCH 17/35] imag-tag: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-tag/Cargo.toml | 7 ++ bin/core/imag-tag/src/bin.rs | 39 ++++++++ bin/core/imag-tag/src/{main.rs => lib.rs} | 107 +++++++++++++--------- 3 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 bin/core/imag-tag/src/bin.rs rename bin/core/imag-tag/src/{main.rs => lib.rs} (84%) diff --git a/bin/core/imag-tag/Cargo.toml b/bin/core/imag-tag/Cargo.toml index 43cd6a8c..bafc7b0b 100644 --- a/bin/core/imag-tag/Cargo.toml +++ b/bin/core/imag-tag/Cargo.toml @@ -51,3 +51,10 @@ path = "../../../lib/core/libimagrt" default-features = false features = ["testing"] +[lib] +name = "libimagtagcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-tag" +path = "src/bin.rs" diff --git a/bin/core/imag-tag/src/bin.rs b/bin/core/imag-tag/src/bin.rs new file mode 100644 index 00000000..aca06ce2 --- /dev/null +++ b/bin/core/imag-tag/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagtagcmd, ImagTag); diff --git a/bin/core/imag-tag/src/main.rs b/bin/core/imag-tag/src/lib.rs similarity index 84% rename from bin/core/imag-tag/src/main.rs rename to bin/core/imag-tag/src/lib.rs index 30eb37e2..2453ef45 100644 --- a/bin/core/imag-tag/src/main.rs +++ b/bin/core/imag-tag/src/lib.rs @@ -41,7 +41,7 @@ extern crate clap; extern crate failure; extern crate libimagstore; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagentrytag; extern crate libimagerror; @@ -61,7 +61,7 @@ extern crate env_logger; use std::io::Write; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagentrytag::tagable::Tagable; use libimagentrytag::tag::Tag; use libimagerror::trace::trace_error; @@ -71,53 +71,72 @@ use libimagerror::exit::ExitUnwrap; use libimagstore::storeid::StoreId; use libimagutil::warn_exit::warn_exit; -use clap::ArgMatches; +use clap::{App, ArgMatches}; +use failure::Fallible as Result; mod ui; -use crate::ui::build_ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-tag", - &version, - "Direct interface to the store. Use with great care!", - build_ui); - - let ids = rt - .ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter(); - - if let Some(name) = rt.cli().subcommand_name() { - match name { - "list" => for id in ids { - list(id, &rt) - }, - "remove" => for id in ids { - let add = None; - let rem = get_remove_tags(rt.cli()); - debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); - alter(&rt, id, add, rem); - }, - "add" => for id in ids { - let add = get_add_tags(rt.cli()); - let rem = None; - debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); - alter(&rt, id, add, rem); - }, - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-tag", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagTag {} +impl ImagApplication for ImagTag { + fn run(rt: Runtime) -> Result<()> { + let ids = rt + .ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter(); + + if let Some(name) = rt.cli().subcommand_name() { + match name { + "list" => for id in ids { + list(id, &rt) + }, + "remove" => for id in ids { + let add = None; + let rem = get_remove_tags(rt.cli()); + debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); + alter(&rt, id, add, rem); + }, + "add" => for id in ids { + let add = get_add_tags(rt.cli()); + let rem = None; + debug!("id = {:?}, add = {:?}, rem = {:?}", id, add, rem); + alter(&rt, id, add, rem); + }, + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-tag", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Manage tags of entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From ccbd5a1a52cd5d8b528dadac7f7f8cf7aa7d3f12 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:50:27 +0200 Subject: [PATCH 18/35] imag-view: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/core/imag-view/Cargo.toml | 7 + bin/core/imag-view/src/bin.rs | 39 ++++ bin/core/imag-view/src/lib.rs | 315 +++++++++++++++++++++++++++++++++ bin/core/imag-view/src/main.rs | 293 ------------------------------ 4 files changed, 361 insertions(+), 293 deletions(-) create mode 100644 bin/core/imag-view/src/bin.rs create mode 100644 bin/core/imag-view/src/lib.rs delete mode 100644 bin/core/imag-view/src/main.rs diff --git a/bin/core/imag-view/Cargo.toml b/bin/core/imag-view/Cargo.toml index e89905d3..0525afec 100644 --- a/bin/core/imag-view/Cargo.toml +++ b/bin/core/imag-view/Cargo.toml @@ -41,3 +41,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagviewcmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-view" +path = "src/bin.rs" diff --git a/bin/core/imag-view/src/bin.rs b/bin/core/imag-view/src/bin.rs new file mode 100644 index 00000000..ce5803f9 --- /dev/null +++ b/bin/core/imag-view/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagviewcmd, ImagView); diff --git a/bin/core/imag-view/src/lib.rs b/bin/core/imag-view/src/lib.rs new file mode 100644 index 00000000..7e9127cc --- /dev/null +++ b/bin/core/imag-view/src/lib.rs @@ -0,0 +1,315 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +#[macro_use] extern crate log; +extern crate handlebars; +extern crate tempfile; +extern crate toml; +extern crate toml_query; +extern crate failure; + +extern crate libimagentryview; +extern crate libimagerror; +extern crate libimagrt; +extern crate libimagstore; +extern crate libimagutil; + +use std::str::FromStr; +use std::collections::BTreeMap; +use std::io::Write; +use std::process::Command; +use std::process::exit; + +use handlebars::Handlebars; +use toml_query::read::TomlValueReadTypeExt; +use failure::Error; +use failure::err_msg; +use failure::Fallible as Result; +use clap::App; + +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagerror::io::ToExitCode; +use libimagerror::exit::ExitUnwrap; +use libimagentryview::builtin::stdout::StdoutViewer; +use libimagentryview::builtin::md::MarkdownViewer; +use libimagentryview::viewer::Viewer; +use libimagstore::iter::get::StoreIdGetIteratorExtension; +use libimagstore::store::FileLockEntry; + +mod ui; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagView {} +impl ImagApplication for ImagView { + fn run(rt: Runtime) -> Result<()> { + let view_header = rt.cli().is_present("view-header"); + let hide_content = rt.cli().is_present("not-view-content"); + let entries = rt + .ids::<::ui::PathProvider>() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter() + .map(Ok) + .into_get_iter(rt.store()) + .trace_unwrap_exit() + .map(|e| { + e.ok_or_else(|| err_msg("Entry not found")) + .map_err(Error::from) + .map_err_trace_exit_unwrap() + }); + + if rt.cli().is_present("in") { + let files = entries + .map(|entry| { + let tmpfile = create_tempfile_for(&entry, view_header, hide_content); + rt.report_touched(entry.get_location()).unwrap_or_exit(); + tmpfile + }) + .collect::>(); + + let mut command = { + let viewer = rt + .cli() + .value_of("in") + .ok_or_else(|| Error::from(err_msg("No viewer given"))) + .map_err_trace_exit_unwrap(); + + let config = rt + .config() + .ok_or_else(|| Error::from(err_msg("No configuration, cannot continue"))) + .map_err_trace_exit_unwrap(); + + let query = format!("view.viewers.{}", viewer); + + let viewer_template = config + .read_string(&query) + .map_err(Error::from) + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("Cannot find '{}' in config", query); + exit(1) + }); + + let mut handlebars = Handlebars::new(); + handlebars.register_escape_fn(::handlebars::no_escape); + + let _ = handlebars + .register_template_string("template", viewer_template) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + + let mut data = BTreeMap::new(); + + let file_paths = files + .iter() + .map(|&(_, ref path)| path.clone()) + .collect::>() + .join(" "); + + data.insert("entries", file_paths); + + let call = handlebars + .render("template", &data) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + let mut elems = call.split_whitespace(); + let command_string = elems + .next() + .ok_or_else(|| Error::from(err_msg("No command"))) + .map_err_trace_exit_unwrap(); + let mut cmd = Command::new(command_string); + + for arg in elems { + cmd.arg(arg); + } + + cmd + }; + + debug!("Calling: {:?}", command); + + if !command + .status() + .map_err(Error::from) + .map_err_trace_exit_unwrap() + .success() + { + exit(1) + } + + drop(files); + } else { + let out = rt.stdout(); + let mut outlock = out.lock(); + + let basesep = if rt.cli().occurrences_of("seperator") != 0 { // checker for default value + rt.cli().value_of("seperator").map(String::from) + } else { + None + }; + + let mut sep_width = 80; // base width, automatically overridden by wrap width + + // Helper to build the seperator with a base string `sep` and a `width` + let build_seperator = |sep: String, width: usize| -> String { + sep.repeat(width / sep.len()) + }; + + if rt.cli().is_present("compile-md") { + let viewer = MarkdownViewer::new(&rt); + let seperator = basesep.map(|s| build_seperator(s, sep_width)); + + entries + .enumerate() + .for_each(|(n, entry)| { + if n != 0 { + seperator + .as_ref() + .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); + } + + if let Err(e) = viewer.view_entry(&entry, &mut outlock) { + handle_error(e); + } + + rt.report_touched(entry.get_location()).unwrap_or_exit(); + }); + } else { + let mut viewer = StdoutViewer::new(view_header, !hide_content); + + if rt.cli().occurrences_of("autowrap") != 0 { + let width = rt.cli().value_of("autowrap").unwrap(); // ensured by clap + let width = usize::from_str(width).unwrap_or_else(|e| { + error!("Failed to parse argument to number: autowrap = {:?}", + rt.cli().value_of("autowrap").map(String::from)); + error!("-> {:?}", e); + ::std::process::exit(1) + }); + + // Copying this value over, so that the seperator has the right len as well + sep_width = width; + + viewer.wrap_at(width); + } + + let seperator = basesep.map(|s| build_seperator(s, sep_width)); + entries + .enumerate() + .for_each(|(n, entry)| { + if n != 0 { + seperator + .as_ref() + .map(|s| writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit()); + } + + if let Err(e) = viewer.view_entry(&entry, &mut outlock) { + handle_error(e); + } + + rt.report_touched(entry.get_location()).unwrap_or_exit(); + }); + } + } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "View entries (readonly)" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} + +fn create_tempfile_for<'a>(entry: &FileLockEntry<'a>, view_header: bool, hide_content: bool) + -> (tempfile::NamedTempFile, String) +{ + let mut tmpfile = tempfile::NamedTempFile::new() + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + + if view_header { + let hdr = toml::ser::to_string_pretty(entry.get_header()) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + let _ = tmpfile.write(format!("---\n{}---\n", hdr).as_bytes()) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + } + + if !hide_content { + let _ = tmpfile.write(entry.get_content().as_bytes()) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + } + + let file_path = tmpfile + .path() + .to_str() + .map(String::from) + .ok_or_else(|| Error::from(err_msg("Cannot build path"))) + .map_err_trace_exit_unwrap(); + + (tmpfile, file_path) +} + +fn handle_error(e: ::libimagentryview::error::Error) { + use libimagentryview::error::Error; + match e { + Error::Io(e) => Err(e).to_exit_code().unwrap_or_exit(), + Error::Other(e) => Err(e).map_err_trace_exit_unwrap() + } +} diff --git a/bin/core/imag-view/src/main.rs b/bin/core/imag-view/src/main.rs deleted file mode 100644 index cb35f0d0..00000000 --- a/bin/core/imag-view/src/main.rs +++ /dev/null @@ -1,293 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -extern crate clap; -#[macro_use] extern crate log; -extern crate handlebars; -extern crate tempfile; -extern crate toml; -extern crate toml_query; -extern crate failure; - -extern crate libimagentryview; -extern crate libimagerror; -#[macro_use] extern crate libimagrt; -extern crate libimagstore; -extern crate libimagutil; - -use std::str::FromStr; -use std::collections::BTreeMap; -use std::io::Write; -use std::process::Command; -use std::process::exit; - -use handlebars::Handlebars; -use toml_query::read::TomlValueReadTypeExt; -use failure::Error; -use failure::err_msg; - -use libimagrt::setup::generate_runtime_setup; -use libimagerror::trace::MapErrTrace; -use libimagerror::iter::TraceIterator; -use libimagerror::io::ToExitCode; -use libimagerror::exit::ExitUnwrap; -use libimagentryview::builtin::stdout::StdoutViewer; -use libimagentryview::builtin::md::MarkdownViewer; -use libimagentryview::viewer::Viewer; -use libimagstore::iter::get::StoreIdGetIteratorExtension; -use libimagstore::store::FileLockEntry; - -mod ui; -use crate::ui::build_ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup( "imag-view", - &version, - "View entries (readonly)", - build_ui); - - let view_header = rt.cli().is_present("view-header"); - let hide_content = rt.cli().is_present("not-view-content"); - let entries = rt - .ids::<::ui::PathProvider>() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter() - .map(Ok) - .into_get_iter(rt.store()) - .trace_unwrap_exit() - .map(|e| { - e.ok_or_else(|| err_msg("Entry not found")) - .map_err(Error::from) - .map_err_trace_exit_unwrap() - }); - - if rt.cli().is_present("in") { - let files = entries - .map(|entry| { - let tmpfile = create_tempfile_for(&entry, view_header, hide_content); - rt.report_touched(entry.get_location()).unwrap_or_exit(); - tmpfile - }) - .collect::>(); - - let mut command = { - let viewer = rt - .cli() - .value_of("in") - .ok_or_else(|| err_msg("No viewer given")) - .map_err_trace_exit_unwrap(); - - let config = rt - .config() - .ok_or_else(|| err_msg("No configuration, cannot continue")) - .map_err_trace_exit_unwrap(); - - let query = format!("view.viewers.{}", viewer); - - let viewer_template = config - .read_string(&query) - .map_err(Error::from) - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("Cannot find '{}' in config", query); - exit(1) - }); - - let mut handlebars = Handlebars::new(); - handlebars.register_escape_fn(::handlebars::no_escape); - - handlebars - .register_template_string("template", viewer_template) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - - let mut data = BTreeMap::new(); - - let file_paths = files - .iter() - .map(|&(_, ref path)| path.clone()) - .collect::>() - .join(" "); - - data.insert("entries", file_paths); - - let call = handlebars - .render("template", &data) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - let mut elems = call.split_whitespace(); - let command_string = elems - .next() - .ok_or_else(|| err_msg("No command")) - .map_err_trace_exit_unwrap(); - let mut cmd = Command::new(command_string); - - for arg in elems { - cmd.arg(arg); - } - - cmd - }; - - debug!("Calling: {:?}", command); - - if !command - .status() - .map_err(Error::from) - .map_err_trace_exit_unwrap() - .success() - { - exit(1) - } - - drop(files); - } else { - let out = rt.stdout(); - let mut outlock = out.lock(); - - let basesep = if rt.cli().occurrences_of("seperator") != 0 { // checker for default value - rt.cli().value_of("seperator").map(String::from) - } else { - None - }; - - let mut sep_width = 80; // base width, automatically overridden by wrap width - - // Helper to build the seperator with a base string `sep` and a `width` - let build_seperator = |sep: String, width: usize| -> String { - sep.repeat(width / sep.len()) - }; - - if rt.cli().is_present("compile-md") { - let viewer = MarkdownViewer::new(&rt); - let seperator = basesep.map(|s| build_seperator(s, sep_width)); - - entries - .enumerate() - .for_each(|(n, entry)| { - if n != 0 { - if let Some(s) = seperator - .as_ref() { writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit() } - } - - if let Err(e) = viewer.view_entry(&entry, &mut outlock) { - handle_error(e); - } - - rt.report_touched(entry.get_location()).unwrap_or_exit(); - }); - } else { - let mut viewer = StdoutViewer::new(view_header, !hide_content); - - if rt.cli().occurrences_of("autowrap") != 0 { - let width = rt.cli().value_of("autowrap").unwrap(); // ensured by clap - let width = usize::from_str(width).unwrap_or_else(|e| { - error!("Failed to parse argument to number: autowrap = {:?}", - rt.cli().value_of("autowrap").map(String::from)); - error!("-> {:?}", e); - ::std::process::exit(1) - }); - - // Copying this value over, so that the seperator has the right len as well - sep_width = width; - - viewer.wrap_at(width); - } - - let seperator = basesep.map(|s| build_seperator(s, sep_width)); - entries - .enumerate() - .for_each(|(n, entry)| { - if n != 0 { - if let Some(s) = seperator - .as_ref() { writeln!(outlock, "{}", s).to_exit_code().unwrap_or_exit() } - } - - if let Err(e) = viewer.view_entry(&entry, &mut outlock) { - handle_error(e); - } - - rt.report_touched(entry.get_location()).unwrap_or_exit(); - }); - } - } -} - -fn create_tempfile_for<'a>(entry: &FileLockEntry<'a>, view_header: bool, hide_content: bool) - -> (tempfile::NamedTempFile, String) -{ - let mut tmpfile = tempfile::NamedTempFile::new() - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - - if view_header { - let hdr = toml::ser::to_string_pretty(entry.get_header()) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - let _ = tmpfile.write(format!("---\n{}---\n", hdr).as_bytes()) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - } - - if !hide_content { - let _ = tmpfile.write(entry.get_content().as_bytes()) - .map_err(Error::from) - .map_err_trace_exit_unwrap(); - } - - let file_path = tmpfile - .path() - .to_str() - .map(String::from) - .ok_or_else(|| err_msg("Cannot build path")) - .map_err_trace_exit_unwrap(); - - (tmpfile, file_path) -} - -fn handle_error(e: ::libimagentryview::error::Error) { - use libimagentryview::error::Error; - match e { - Error::Io(e) => Err(e).to_exit_code().unwrap_or_exit(), - Error::Other(e) => Err(e).map_err_trace_exit_unwrap() - } -} - From cb69214e72d5e7108fabf168408df982de7b06ad Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:51:01 +0200 Subject: [PATCH 19/35] imag-bookmark: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-bookmark/Cargo.toml | 7 ++ bin/domain/imag-bookmark/src/bin.rs | 39 +++++++++++ .../imag-bookmark/src/{main.rs => lib.rs} | 70 ++++++++++++------- 3 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 bin/domain/imag-bookmark/src/bin.rs rename bin/domain/imag-bookmark/src/{main.rs => lib.rs} (82%) diff --git a/bin/domain/imag-bookmark/Cargo.toml b/bin/domain/imag-bookmark/Cargo.toml index d9cea246..b66a6f69 100644 --- a/bin/domain/imag-bookmark/Cargo.toml +++ b/bin/domain/imag-bookmark/Cargo.toml @@ -36,3 +36,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagbookmarkfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-bookmark" +path = "src/bin.rs" diff --git a/bin/domain/imag-bookmark/src/bin.rs b/bin/domain/imag-bookmark/src/bin.rs new file mode 100644 index 00000000..7497bd96 --- /dev/null +++ b/bin/domain/imag-bookmark/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagbookmarkfrontend, ImagBookmark); diff --git a/bin/domain/imag-bookmark/src/main.rs b/bin/domain/imag-bookmark/src/lib.rs similarity index 82% rename from bin/domain/imag-bookmark/src/main.rs rename to bin/domain/imag-bookmark/src/lib.rs index a932f381..bfa08b10 100644 --- a/bin/domain/imag-bookmark/src/main.rs +++ b/bin/domain/imag-bookmark/src/lib.rs @@ -41,7 +41,7 @@ extern crate toml_query; #[macro_use] extern crate failure; extern crate libimagbookmark; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; extern crate libimagutil; extern crate libimagentrylink; @@ -52,9 +52,11 @@ use std::ops::DerefMut; use toml_query::read::TomlValueReadTypeExt; use failure::Error; +use failure::Fallible as Result; +use clap::App; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagbookmark::collection::BookmarkCollection; use libimagbookmark::collection::BookmarkCollectionStore; use libimagbookmark::link::Link as BookmarkLink; @@ -64,33 +66,49 @@ use libimagerror::exit::ExitUnwrap; use libimagutil::debug_result::DebugResult; use libimagentrylink::linkable::Linkable; - mod ui; -use crate::ui::build_ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-bookmark", - &version, - "Bookmark collection tool", - build_ui); - - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "add" => add(&rt), - "collection" => collection(&rt), - "list" => list(&rt), - "remove" => remove(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagBookmark {} +impl ImagApplication for ImagBookmark { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + debug!("Call {}", name); + match name { + "add" => add(&rt), + "collection" => collection(&rt), + "list" => list(&rt), + "remove" => remove(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Bookmark collection tool" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 3144080488340e1f8c35eaab64803be4e85d734b Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:51:22 +0200 Subject: [PATCH 20/35] imag-contact: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-contact/Cargo.toml | 8 ++ bin/domain/imag-contact/src/bin.rs | 39 ++++++++++ .../imag-contact/src/{main.rs => lib.rs} | 74 ++++++++++++------- 3 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 bin/domain/imag-contact/src/bin.rs rename bin/domain/imag-contact/src/{main.rs => lib.rs} (88%) diff --git a/bin/domain/imag-contact/Cargo.toml b/bin/domain/imag-contact/Cargo.toml index 6f3db11e..6260fbb8 100644 --- a/bin/domain/imag-contact/Cargo.toml +++ b/bin/domain/imag-contact/Cargo.toml @@ -47,3 +47,11 @@ features = ["color", "suggestions", "wrap_help"] version = "0.9.2" default-features = false features = ["typed"] + +[lib] +name = "libimagcontactfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-contact" +path = "src/bin.rs" diff --git a/bin/domain/imag-contact/src/bin.rs b/bin/domain/imag-contact/src/bin.rs new file mode 100644 index 00000000..77857900 --- /dev/null +++ b/bin/domain/imag-contact/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagcontactfrontend, ImagContact); diff --git a/bin/domain/imag-contact/src/main.rs b/bin/domain/imag-contact/src/lib.rs similarity index 88% rename from bin/domain/imag-contact/src/main.rs rename to bin/domain/imag-contact/src/lib.rs index ac96198b..0285f128 100644 --- a/bin/domain/imag-contact/src/main.rs +++ b/bin/domain/imag-contact/src/lib.rs @@ -47,7 +47,7 @@ extern crate serde_json; extern crate libimagcontact; extern crate libimagstore; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; extern crate libimagutil; extern crate libimaginteraction; @@ -59,16 +59,17 @@ use std::path::PathBuf; use std::io::Write; use handlebars::Handlebars; -use clap::ArgMatches; +use clap::{App, ArgMatches}; use toml_query::read::TomlValueReadExt; use toml_query::read::TomlValueReadTypeExt; use toml_query::read::Partial; use walkdir::WalkDir; use failure::Error; use failure::err_msg; +use failure::Fallible as Result; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagerror::trace::MapErrTrace; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; @@ -82,36 +83,53 @@ mod util; mod create; mod edit; -use crate::ui::build_ui; use crate::util::build_data_object_for_handlebars; use crate::create::create; use crate::edit::edit; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-contact", - &version, - "Contact management tool", - build_ui); - - - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "list" => list(&rt), - "import" => import(&rt), - "show" => show(&rt), - "edit" => edit(&rt), - "find" => find(&rt), - "create" => create(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-contact", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagContact {} +impl ImagApplication for ImagContact { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + debug!("Call {}", name); + match name { + "list" => list(&rt), + "import" => import(&rt), + "show" => show(&rt), + "edit" => edit(&rt), + "find" => find(&rt), + "create" => create(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-contact", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Contact management tool" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 3e12bd99d4205a00e6ab33533efd07787143d381 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:52:21 +0200 Subject: [PATCH 21/35] imag-diary: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-diary/Cargo.toml | 7 ++ bin/domain/imag-diary/src/bin.rs | 39 +++++++++++ bin/domain/imag-diary/src/{main.rs => lib.rs} | 69 ++++++++++++------- 3 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 bin/domain/imag-diary/src/bin.rs rename bin/domain/imag-diary/src/{main.rs => lib.rs} (63%) diff --git a/bin/domain/imag-diary/Cargo.toml b/bin/domain/imag-diary/Cargo.toml index 9c506110..e46a36f3 100644 --- a/bin/domain/imag-diary/Cargo.toml +++ b/bin/domain/imag-diary/Cargo.toml @@ -42,3 +42,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagdiaryfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-diary" +path = "src/bin.rs" diff --git a/bin/domain/imag-diary/src/bin.rs b/bin/domain/imag-diary/src/bin.rs new file mode 100644 index 00000000..f9ac3e5e --- /dev/null +++ b/bin/domain/imag-diary/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagdiaryfrontend, ImagDiary); diff --git a/bin/domain/imag-diary/src/main.rs b/bin/domain/imag-diary/src/lib.rs similarity index 63% rename from bin/domain/imag-diary/src/main.rs rename to bin/domain/imag-diary/src/lib.rs index bc1c9a1f..23629dc9 100644 --- a/bin/domain/imag-diary/src/main.rs +++ b/bin/domain/imag-diary/src/lib.rs @@ -47,18 +47,20 @@ extern crate libimagentryedit; extern crate libimagentryview; extern crate libimagerror; extern crate libimaginteraction; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagtimeui; extern crate libimagutil; use std::io::Write; -use libimagrt::setup::generate_runtime_setup; use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; use libimagerror::trace::MapErrTrace; use itertools::Itertools; +use clap::App; +use failure::Fallible as Result; mod create; mod delete; @@ -72,29 +74,48 @@ use crate::delete::delete; use crate::list::list; use crate::view::view; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-diary", - &version, - "Personal Diary/Diaries", - ui::build_ui); - - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "diaries" => diaries(&rt), - "create" => create(&rt), - "delete" => delete(&rt), - "list" => list(&rt), - "view" => view(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-diary", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagDiary {} +impl ImagApplication for ImagDiary { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + debug!("Call {}", name); + match name { + "diaries" => diaries(&rt), + "create" => create(&rt), + "delete" => delete(&rt), + "list" => list(&rt), + "view" => view(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-diary", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Personal Diary/Diaries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From 621c5f96f85770223aab1d1184c3d9d6543a3aac Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:53:13 +0200 Subject: [PATCH 22/35] imag-habit: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-habit/Cargo.toml | 7 ++ bin/domain/imag-habit/src/bin.rs | 39 +++++++++ bin/domain/imag-habit/src/{main.rs => lib.rs} | 82 ++++++++++++------- 3 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 bin/domain/imag-habit/src/bin.rs rename bin/domain/imag-habit/src/{main.rs => lib.rs} (92%) diff --git a/bin/domain/imag-habit/Cargo.toml b/bin/domain/imag-habit/Cargo.toml index c4e6b80b..a796c2e6 100644 --- a/bin/domain/imag-habit/Cargo.toml +++ b/bin/domain/imag-habit/Cargo.toml @@ -42,3 +42,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimaghabitfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-habit" +path = "src/bin.rs" diff --git a/bin/domain/imag-habit/src/bin.rs b/bin/domain/imag-habit/src/bin.rs new file mode 100644 index 00000000..af996417 --- /dev/null +++ b/bin/domain/imag-habit/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaghabitfrontend, ImagHabit); diff --git a/bin/domain/imag-habit/src/main.rs b/bin/domain/imag-habit/src/lib.rs similarity index 92% rename from bin/domain/imag-habit/src/main.rs rename to bin/domain/imag-habit/src/lib.rs index 34c44959..86fa3b3d 100644 --- a/bin/domain/imag-habit/src/main.rs +++ b/bin/domain/imag-habit/src/lib.rs @@ -45,7 +45,7 @@ extern crate prettytable; extern crate libimaghabit; extern crate libimagstore; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; extern crate libimagutil; extern crate libimaginteraction; @@ -57,9 +57,11 @@ use prettytable::Table; use prettytable::Cell; use prettytable::Row; use failure::Error; +use failure::Fallible as Result; +use clap::App; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::iter::TraceIterator; use libimagerror::exit::ExitUnwrap; @@ -75,37 +77,55 @@ use libimagutil::debug_result::DebugResult; mod ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-habit", - &version, - "Habit tracking tool", - ui::build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagHabit {} +impl ImagApplication for ImagHabit { + fn run(rt: Runtime) -> Result<()> { + rt + .cli() + .subcommand_name() + .map(|name| { + debug!("Call {}", name); + match name { + "create" => create(&rt), + "delete" => delete(&rt), + "list" => list(&rt), + "today" => today(&rt, false), + "status" => today(&rt, true), + "show" => show(&rt), + "done" => done(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-habit", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } + }) + .unwrap_or_else(|| today(&rt, true)); + Ok(()) + } - rt - .cli() - .subcommand_name() - .map(|name| { - debug!("Call {}", name); - match name { - "create" => create(&rt), - "delete" => delete(&rt), - "list" => list(&rt), - "today" => today(&rt, false), - "status" => today(&rt, true), - "show" => show(&rt), - "done" => done(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-habit", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, - } - }) - .unwrap_or_else(|| today(&rt, true)); + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Habit tracking tool" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } } fn create(rt: &Runtime) { From 4c918c78c0579575b3bfdbccedf8446a1d8f7246 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:53:33 +0200 Subject: [PATCH 23/35] imag-log: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-log/Cargo.toml | 7 ++ bin/domain/imag-log/src/bin.rs | 39 +++++++++ bin/domain/imag-log/src/{main.rs => lib.rs} | 95 +++++++++++++-------- 3 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 bin/domain/imag-log/src/bin.rs rename bin/domain/imag-log/src/{main.rs => lib.rs} (80%) diff --git a/bin/domain/imag-log/Cargo.toml b/bin/domain/imag-log/Cargo.toml index 80b96eb4..5466caab 100644 --- a/bin/domain/imag-log/Cargo.toml +++ b/bin/domain/imag-log/Cargo.toml @@ -39,3 +39,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimaglogfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-log" +path = "src/bin.rs" diff --git a/bin/domain/imag-log/src/bin.rs b/bin/domain/imag-log/src/bin.rs new file mode 100644 index 00000000..b7e96de1 --- /dev/null +++ b/bin/domain/imag-log/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimaglogfrontend, ImagLog); diff --git a/bin/domain/imag-log/src/main.rs b/bin/domain/imag-log/src/lib.rs similarity index 80% rename from bin/domain/imag-log/src/main.rs rename to bin/domain/imag-log/src/lib.rs index 85164ab9..338a482d 100644 --- a/bin/domain/imag-log/src/main.rs +++ b/bin/domain/imag-log/src/lib.rs @@ -44,7 +44,7 @@ extern crate failure; extern crate textwrap; extern crate libimaglog; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagstore; extern crate libimagerror; extern crate libimagdiary; @@ -56,9 +56,10 @@ use std::str::FromStr; use failure::Error; use failure::err_msg; +use failure::Fallible as Result; +use libimagrt::application::ImagApplication; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; use libimagerror::trace::MapErrTrace; use libimagerror::io::ToExitCode; use libimagerror::exit::ExitUnwrap; @@ -70,50 +71,70 @@ use libimaglog::log::Log; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagstore::store::FileLockEntry; +use clap::App; + mod ui; -use crate::ui::build_ui; use toml::Value; use itertools::Itertools; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-log", - &version, - "Overlay to imag-diary to 'log' single lines of text", - build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagLog {} +impl ImagApplication for ImagLog { + fn run(rt: Runtime) -> Result<()> { + if let Some(scmd) = rt.cli().subcommand_name() { + match scmd { + "show" => show(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-log", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } + } else { + let text = get_log_text(&rt); + let diary_name = rt.cli() + .value_of("diaryname") + .map(String::from) + .unwrap_or_else(|| get_diary_name(&rt)); + debug!("Writing to '{}': {}", diary_name, text); + + rt + .store() + .new_entry_now(&diary_name) + .map(|mut fle| { + fle.make_log_entry().map_err_trace_exit_unwrap(); + *fle.get_content_mut() = text; + fle + }) + .map(|fle| rt.report_touched(fle.get_location()).unwrap_or_exit()) + .map_err_trace_exit_unwrap(); - if let Some(scmd) = rt.cli() .subcommand_name() { - match scmd { - "show" => show(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-log", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, } - } else { - let text = get_log_text(&rt); - let diary_name = rt.cli() - .value_of("diaryname") - .map(String::from) - .unwrap_or_else(|| get_diary_name(&rt)); - debug!("Writing to '{}': {}", diary_name, text); + Ok(()) + } - rt - .store() - .new_entry_now(&diary_name) - .map(|mut fle| { - fle.make_log_entry().map_err_trace_exit_unwrap(); - *fle.get_content_mut() = text; - fle - }) - .map(|fle| rt.report_touched(fle.get_location()).unwrap_or_exit()) - .map_err_trace_exit_unwrap(); + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Overlay to imag-diary to 'log' single lines of text" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } @@ -203,7 +224,7 @@ fn show(rt: &Runtime) { .unwrap_or_exit(); Ok(()) }) - .collect::, ExitCode>>() + .collect::, ExitCode>>() .unwrap_or_exit(); } From 870a09f1dc016dd510aad17ae260e655420f4c0a Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:53:51 +0200 Subject: [PATCH 24/35] imag-mail: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-mail/Cargo.toml | 7 +++ bin/domain/imag-mail/src/bin.rs | 39 ++++++++++++ bin/domain/imag-mail/src/{main.rs => lib.rs} | 65 +++++++++++++------- 3 files changed, 89 insertions(+), 22 deletions(-) create mode 100644 bin/domain/imag-mail/src/bin.rs rename bin/domain/imag-mail/src/{main.rs => lib.rs} (85%) diff --git a/bin/domain/imag-mail/Cargo.toml b/bin/domain/imag-mail/Cargo.toml index 52e42fa2..0c1afed6 100644 --- a/bin/domain/imag-mail/Cargo.toml +++ b/bin/domain/imag-mail/Cargo.toml @@ -41,3 +41,10 @@ version = "0.9.2" default-features = false features = ["typed"] +[lib] +name = "libimagmailfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-mail" +path = "src/bin.rs" diff --git a/bin/domain/imag-mail/src/bin.rs b/bin/domain/imag-mail/src/bin.rs new file mode 100644 index 00000000..bba7972b --- /dev/null +++ b/bin/domain/imag-mail/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagmailfrontend, ImagMail); diff --git a/bin/domain/imag-mail/src/main.rs b/bin/domain/imag-mail/src/lib.rs similarity index 85% rename from bin/domain/imag-mail/src/main.rs rename to bin/domain/imag-mail/src/lib.rs index 98baf7d1..d30062eb 100644 --- a/bin/domain/imag-mail/src/main.rs +++ b/bin/domain/imag-mail/src/lib.rs @@ -40,7 +40,7 @@ extern crate clap; extern crate toml_query; #[macro_use] extern crate indoc; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagmail; extern crate libimagerror; extern crate libimagstore; @@ -52,6 +52,7 @@ use std::path::PathBuf; use failure::Fallible as Result; use toml_query::read::TomlValueReadTypeExt; +use clap::App; use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::iter::TraceIterator; @@ -63,7 +64,7 @@ use libimagmail::util; use libimagentryref::reference::{Ref, RefFassade}; use libimagentryref::util::get_ref_config; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagutil::info_result::*; use libimagstore::store::FileLockEntry; use libimagstore::storeid::StoreIdIterator; @@ -71,32 +72,52 @@ use libimagstore::iter::get::StoreIdGetIteratorExtension; mod ui; -use crate::ui::build_ui; +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagMail {} +impl ImagApplication for ImagMail { + fn run(rt: Runtime) -> Result<()> { -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-mail", - &version, - "Mail collection tool", - build_ui); + if let Some(name) = rt.cli().subcommand_name() { - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "import-mail" => import_mail(&rt), - "list" => list(&rt), - "mail-store" => mail_store(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-mail", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); + debug!("Call {}", name); + match name { + "import-mail" => import_mail(&rt), + "list" => list(&rt), + "mail-store" => mail_store(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-mail", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + } + } } - } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Mail collection tool" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } + fn import_mail(rt: &Runtime) { let collection_name = get_ref_collection_name(rt).map_err_trace_exit_unwrap(); let refconfig = get_ref_config(rt, "imag-mail").map_err_trace_exit_unwrap(); From 6590a4b8cb67ee9e7db6526f104987a7bd4f7641 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:54:34 +0200 Subject: [PATCH 25/35] imag-notes: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-notes/Cargo.toml | 8 +++ bin/domain/imag-notes/src/bin.rs | 39 +++++++++++ bin/domain/imag-notes/src/{main.rs => lib.rs} | 70 ++++++++++++------- 3 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 bin/domain/imag-notes/src/bin.rs rename bin/domain/imag-notes/src/{main.rs => lib.rs} (74%) diff --git a/bin/domain/imag-notes/Cargo.toml b/bin/domain/imag-notes/Cargo.toml index 20193d86..90d15f90 100644 --- a/bin/domain/imag-notes/Cargo.toml +++ b/bin/domain/imag-notes/Cargo.toml @@ -22,6 +22,7 @@ maintenance = { status = "actively-developed" } [dependencies] log = "0.4.6" itertools = "0.8.0" +failure = "0.1.5" libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" } libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" } @@ -35,3 +36,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagnotesfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-notes" +path = "src/bin.rs" diff --git a/bin/domain/imag-notes/src/bin.rs b/bin/domain/imag-notes/src/bin.rs new file mode 100644 index 00000000..2de11de7 --- /dev/null +++ b/bin/domain/imag-notes/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagnotesfrontend, ImagNotes); diff --git a/bin/domain/imag-notes/src/main.rs b/bin/domain/imag-notes/src/lib.rs similarity index 74% rename from bin/domain/imag-notes/src/main.rs rename to bin/domain/imag-notes/src/lib.rs index 86ebd65a..a62d299b 100644 --- a/bin/domain/imag-notes/src/main.rs +++ b/bin/domain/imag-notes/src/lib.rs @@ -37,9 +37,10 @@ extern crate clap; #[macro_use] extern crate log; extern crate itertools; +extern crate failure; extern crate libimagnotes; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagentryedit; extern crate libimagerror; extern crate libimagutil; @@ -49,10 +50,12 @@ use std::io::Write; use std::process::exit; use itertools::Itertools; +use clap::App; +use failure::Fallible as Result; use libimagentryedit::edit::Edit; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagstore::iter::get::StoreIdGetIteratorExtension; use libimagnotes::note::Note; use libimagnotes::notestore::*; @@ -65,30 +68,49 @@ use libimagutil::warn_result::WarnResult; mod ui; -use crate::ui::build_ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-notes", - &version, - "Note taking helper", - build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagNotes {} +impl ImagApplication for ImagNotes { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call: {}", name); - match name { - "create" => create(&rt), - "delete" => delete(&rt), - "edit" => edit(&rt), - "list" => list(&rt), - other => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-notes", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, - }; + debug!("Call: {}", name); + match name { + "create" => create(&rt), + "delete" => delete(&rt), + "edit" => edit(&rt), + "list" => list(&rt), + other => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-notes", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + }; + } + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Note taking helper" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From e1dbb596a1c42f1e20db09cea89ada4eeda7cfaf Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:55:01 +0200 Subject: [PATCH 26/35] imag-timetrack: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-timetrack/Cargo.toml | 7 ++ bin/domain/imag-timetrack/src/bin.rs | 39 ++++++++ bin/domain/imag-timetrack/src/lib.rs | 137 ++++++++++++++++++++++++++ bin/domain/imag-timetrack/src/main.rs | 117 ---------------------- 4 files changed, 183 insertions(+), 117 deletions(-) create mode 100644 bin/domain/imag-timetrack/src/bin.rs create mode 100644 bin/domain/imag-timetrack/src/lib.rs delete mode 100644 bin/domain/imag-timetrack/src/main.rs diff --git a/bin/domain/imag-timetrack/Cargo.toml b/bin/domain/imag-timetrack/Cargo.toml index 1f023946..88408449 100644 --- a/bin/domain/imag-timetrack/Cargo.toml +++ b/bin/domain/imag-timetrack/Cargo.toml @@ -39,3 +39,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagtimetrackfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-timetrack" +path = "src/bin.rs" diff --git a/bin/domain/imag-timetrack/src/bin.rs b/bin/domain/imag-timetrack/src/bin.rs new file mode 100644 index 00000000..e9feb5f8 --- /dev/null +++ b/bin/domain/imag-timetrack/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagtimetrackfrontend, ImagTimetrack); diff --git a/bin/domain/imag-timetrack/src/lib.rs b/bin/domain/imag-timetrack/src/lib.rs new file mode 100644 index 00000000..6b94477f --- /dev/null +++ b/bin/domain/imag-timetrack/src/lib.rs @@ -0,0 +1,137 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] +extern crate log; + +extern crate clap; +extern crate chrono; +extern crate filters; +extern crate itertools; +extern crate prettytable; +extern crate kairos; +extern crate failure; + +extern crate libimagerror; +extern crate libimagstore; +extern crate libimagrt; +extern crate libimagtimetrack; +extern crate libimagutil; + +mod cont; +mod day; +mod list; +mod month; +mod shell; +mod start; +mod stop; +mod track; +mod ui; +mod week; +mod year; + +use crate::cont::cont; +use crate::day::day; +use crate::list::{list, list_impl}; +use crate::month::month; +use crate::shell::shell; +use crate::start::start; +use crate::stop::stop; +use crate::track::track; +use crate::week::week; +use crate::year::year; + +use clap::App; +use failure::Fallible as Result; + +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; + +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagTimetrack {} +impl ImagApplication for ImagTimetrack { + fn run(rt: Runtime) -> Result<()> { + let command = rt.cli().subcommand_name(); + let retval = if let Some(command) = command { + debug!("Call: {}", command); + match command { + "continue" => cont(&rt), + "day" => day(&rt), + "list" => list(&rt), + "month" => month(&rt), + "shell" => shell(&rt), + "start" => start(&rt), + "stop" => stop(&rt), + "track" => track(&rt), + "week" => week(&rt), + "year" => year(&rt), + other => { + debug!("Unknown command"); + rt.handle_unknown_subcommand("imag-timetrack", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .unwrap_or(0) + }, + } + } else { + let start = ::chrono::offset::Local::today().naive_local().and_hms(0, 0, 0); + let end = ::chrono::offset::Local::today().naive_local().and_hms(23, 59, 59); + list_impl(&rt, Some(start), Some(end), false, false) + }; + + ::std::process::exit(retval); + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Time tracking module" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} diff --git a/bin/domain/imag-timetrack/src/main.rs b/bin/domain/imag-timetrack/src/main.rs deleted file mode 100644 index 1c06e845..00000000 --- a/bin/domain/imag-timetrack/src/main.rs +++ /dev/null @@ -1,117 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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 -// - -#![forbid(unsafe_code)] - -#![deny( - non_camel_case_types, - non_snake_case, - path_statements, - trivial_numeric_casts, - unstable_features, - unused_allocation, - unused_import_braces, - unused_imports, - unused_must_use, - unused_mut, - unused_qualifications, - while_true, -)] - -#[macro_use] -extern crate log; - -extern crate clap; -extern crate chrono; -extern crate filters; -extern crate itertools; -extern crate prettytable; -extern crate kairos; -extern crate failure; - -extern crate libimagerror; -extern crate libimagstore; -#[macro_use] extern crate libimagrt; -extern crate libimagtimetrack; -extern crate libimagutil; - -mod cont; -mod day; -mod list; -mod month; -mod shell; -mod start; -mod stop; -mod track; -mod ui; -mod week; -mod year; - -use crate::cont::cont; -use crate::day::day; -use crate::list::{list, list_impl}; -use crate::month::month; -use crate::shell::shell; -use crate::start::start; -use crate::stop::stop; -use crate::track::track; -use crate::ui::build_ui; -use crate::week::week; -use crate::year::year; - -use libimagrt::setup::generate_runtime_setup; -use libimagerror::trace::MapErrTrace; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-timetrack", - &version, - "Time tracking module", - build_ui); - - let command = rt.cli().subcommand_name(); - let retval = if let Some(command) = command { - debug!("Call: {}", command); - match command { - "continue" => cont(&rt), - "day" => day(&rt), - "list" => list(&rt), - "month" => month(&rt), - "shell" => shell(&rt), - "start" => start(&rt), - "stop" => stop(&rt), - "track" => track(&rt), - "week" => week(&rt), - "year" => year(&rt), - other => { - debug!("Unknown command"); - rt.handle_unknown_subcommand("imag-timetrack", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .unwrap_or(0) - }, - } - } else { - let start = ::chrono::offset::Local::today().naive_local().and_hms(0, 0, 0); - let end = ::chrono::offset::Local::today().naive_local().and_hms(23, 59, 59); - list_impl(&rt, Some(start), Some(end), false, false) - }; - - ::std::process::exit(retval); -} From 2a1e78c70544170d091e633baac25811fe93e018 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:55:44 +0200 Subject: [PATCH 27/35] imag-todo: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-todo/Cargo.toml | 7 ++ bin/domain/imag-todo/src/bin.rs | 39 +++++++++++ bin/domain/imag-todo/src/{main.rs => lib.rs} | 68 +++++++++++++------- 3 files changed, 90 insertions(+), 24 deletions(-) create mode 100644 bin/domain/imag-todo/src/bin.rs rename bin/domain/imag-todo/src/{main.rs => lib.rs} (81%) diff --git a/bin/domain/imag-todo/Cargo.toml b/bin/domain/imag-todo/Cargo.toml index 136025cf..12a2719a 100644 --- a/bin/domain/imag-todo/Cargo.toml +++ b/bin/domain/imag-todo/Cargo.toml @@ -35,3 +35,10 @@ version = "2.33.0" default-features = false features = ["color", "suggestions", "wrap_help"] +[lib] +name = "libimagtodofrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-todo" +path = "src/bin.rs" diff --git a/bin/domain/imag-todo/src/bin.rs b/bin/domain/imag-todo/src/bin.rs new file mode 100644 index 00000000..a2181dca --- /dev/null +++ b/bin/domain/imag-todo/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagtodofrontend, ImagTodo); diff --git a/bin/domain/imag-todo/src/main.rs b/bin/domain/imag-todo/src/lib.rs similarity index 81% rename from bin/domain/imag-todo/src/main.rs rename to bin/domain/imag-todo/src/lib.rs index 36537ea9..16f42262 100644 --- a/bin/domain/imag-todo/src/main.rs +++ b/bin/domain/imag-todo/src/lib.rs @@ -41,7 +41,7 @@ extern crate toml_query; #[macro_use] extern crate is_match; extern crate failure; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; extern crate libimagtodo; @@ -49,9 +49,11 @@ use std::process::{Command, Stdio}; use std::io::stdin; use std::io::Write; use failure::Error; +use failure::Fallible as Result; +use clap::App; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagtodo::taskstore::TaskStore; use libimagerror::trace::{MapErrTrace, trace_error}; use libimagerror::iter::TraceIterator; @@ -60,29 +62,47 @@ use libimagerror::io::ToExitCode; mod ui; -use crate::ui::build_ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-todo", - &version, - "Interface with taskwarrior", - build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagTodo {} +impl ImagApplication for ImagTodo { + fn run(rt: Runtime) -> Result<()> { + match rt.cli().subcommand_name() { + Some("tw-hook") => tw_hook(&rt), + Some("list") => list(&rt), + Some(other) => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-todo", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + } + None => { + warn!("No command"); + }, + }; - match rt.cli().subcommand_name() { - Some("tw-hook") => tw_hook(&rt), - Some("list") => list(&rt), - Some(other) => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-todo", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - } - None => { - warn!("No command"); - }, - } // end match scmd -} // end main + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Interface with taskwarrior" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} fn tw_hook(rt: &Runtime) { let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap(); From e840d4502c54599fb66991d31dc4c1c74ed7c197 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 18:56:28 +0200 Subject: [PATCH 28/35] imag-wiki: implement ImagApplication Signed-off-by: Leon Schuermann --- bin/domain/imag-wiki/Cargo.toml | 8 ++ bin/domain/imag-wiki/src/bin.rs | 39 ++++++++++ bin/domain/imag-wiki/src/{main.rs => lib.rs} | 80 +++++++++++++------- 3 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 bin/domain/imag-wiki/src/bin.rs rename bin/domain/imag-wiki/src/{main.rs => lib.rs} (82%) diff --git a/bin/domain/imag-wiki/Cargo.toml b/bin/domain/imag-wiki/Cargo.toml index 123eeb90..eca68017 100644 --- a/bin/domain/imag-wiki/Cargo.toml +++ b/bin/domain/imag-wiki/Cargo.toml @@ -21,6 +21,7 @@ toml-query = "0.9.2" is-match = "0.1.0" regex = "1.1.7" filters = "0.3.0" +failure = "0.1.5" libimagentryedit = { version = "0.10.0", path = "../../../lib/entry/libimagentryedit" } libimagentrylink = { version = "0.10.0", path = "../../../lib/entry/libimagentrylink" } @@ -31,3 +32,10 @@ libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagst libimagwiki = { version = "0.10.0", path = "../../../lib/domain/libimagwiki" } libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } +[lib] +name = "libimagwikifrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-wiki" +path = "src/bin.rs" diff --git a/bin/domain/imag-wiki/src/bin.rs b/bin/domain/imag-wiki/src/bin.rs new file mode 100644 index 00000000..ae6b391d --- /dev/null +++ b/bin/domain/imag-wiki/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagwikifrontend, ImagWiki); diff --git a/bin/domain/imag-wiki/src/main.rs b/bin/domain/imag-wiki/src/lib.rs similarity index 82% rename from bin/domain/imag-wiki/src/main.rs rename to bin/domain/imag-wiki/src/lib.rs index 8a25776f..f541c14f 100644 --- a/bin/domain/imag-wiki/src/main.rs +++ b/bin/domain/imag-wiki/src/lib.rs @@ -23,8 +23,9 @@ extern crate clap; extern crate regex; extern crate filters; #[macro_use] extern crate log; +extern crate failure; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagerror; extern crate libimagstore; extern crate libimagwiki; @@ -33,9 +34,11 @@ extern crate libimagentrylink; extern crate libimagutil; use std::io::Write; +use failure::Fallible as Result; +use clap::App; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; use libimagerror::iter::TraceIterator; use libimagerror::trace::MapErrTrace; use libimagerror::exit::ExitUnwrap; @@ -44,36 +47,55 @@ use libimagwiki::store::WikiStore; use libimagentryedit::edit::{Edit, EditHeader}; mod ui; -use crate::ui::build_ui; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-wiki", - &version, - "Personal wiki", - build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binaries crates to execute business logic +/// or to build a CLI completion. +pub enum ImagWiki {} +impl ImagApplication for ImagWiki { + fn run(rt: Runtime) -> Result<()> { + let wiki_name = rt.cli().value_of("wikiname").unwrap_or("default"); + trace!("wiki_name = {}", wiki_name); + trace!("calling = {:?}", rt.cli().subcommand_name()); - let wiki_name = rt.cli().value_of("wikiname").unwrap_or("default"); - trace!("wiki_name = {}", wiki_name); - trace!("calling = {:?}", rt.cli().subcommand_name()); + match rt.cli().subcommand_name() { + Some("list") => list(&rt, wiki_name), + Some("idof") => idof(&rt, wiki_name), + Some("create") => create(&rt, wiki_name), + Some("create-wiki") => create_wiki(&rt), + Some("show") => show(&rt, wiki_name), + Some("delete") => delete(&rt, wiki_name), + Some(other) => { + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-wiki", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(std::process::exit); + } + None => warn!("No command"), + } // end match scmd + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Personal wiki" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} - match rt.cli().subcommand_name() { - Some("list") => list(&rt, wiki_name), - Some("idof") => idof(&rt, wiki_name), - Some("create") => create(&rt, wiki_name), - Some("create-wiki") => create_wiki(&rt), - Some("show") => show(&rt, wiki_name), - Some("delete") => delete(&rt, wiki_name), - Some(other) => { - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-wiki", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(std::process::exit); - } - None => warn!("No command"), - } // end match scmd -} // end main fn list(rt: &Runtime, wiki_name: &str) { let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap From 82e209bea80301c1d2a196902be60ea002fddae3 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Sep 2019 19:02:17 +0200 Subject: [PATCH 29/35] Introduce CLI completion support This is yet another attempt to bring CLI completion to this workspace project. It uses the subcommand-libraries implementing the ImagApplication trait to expose the clap CLI interface. This way, no file import magic happens, it's all just regular dependencies, which should also work with a regular `cargo install`. Signed-off-by: Leon Schuermann --- bin/core/imag/Cargo.toml | 77 +++++++++++++++++++ bin/core/imag/build.rs | 156 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 bin/core/imag/build.rs diff --git a/bin/core/imag/Cargo.toml b/bin/core/imag/Cargo.toml index c3a6df66..904eaacd 100644 --- a/bin/core/imag/Cargo.toml +++ b/bin/core/imag/Cargo.toml @@ -23,6 +23,31 @@ libimagutil = { version = "0.10.0", path = "../../../lib/etc/libimagutil" } failure = "0.1.5" log = "0.4.6" +# Build time dependencies for cli completion +imag-annotate = { optional = true, path = "../imag-annotate" } +imag-diagnostics = { optional = true, path = "../imag-diagnostics" } +imag-edit = { optional = true, path = "../imag-edit" } +imag-gps = { optional = true, path = "../imag-gps" } +imag-grep = { optional = true, path = "../imag-grep" } +imag-ids = { optional = true, path = "../imag-ids" } +imag-init = { optional = true, path = "../imag-init" } +imag-link = { optional = true, path = "../imag-link" } +imag-mv = { optional = true, path = "../imag-mv" } +imag-ref = { optional = true, path = "../imag-ref" } +imag-store = { optional = true, path = "../imag-store" } +imag-tag = { optional = true, path = "../imag-tag" } +imag-view = { optional = true, path = "../imag-view" } +imag-bookmark = { optional = true, path = "../../domain/imag-bookmark" } +imag-contact = { optional = true, path = "../../domain/imag-contact" } +imag-diary = { optional = true, path = "../../domain/imag-diary" } +imag-habit = { optional = true, path = "../../domain/imag-habit" } +imag-log = { optional = true, path = "../../domain/imag-log" } +imag-mail = { optional = true, path = "../../domain/imag-mail" } +imag-notes = { optional = true, path = "../../domain/imag-notes" } +imag-timetrack = { optional = true, path = "../../domain/imag-timetrack" } +imag-todo = { optional = true, path = "../../domain/imag-todo" } +imag-wiki = { optional = true, path = "../../domain/imag-wiki" } + [badges] travis-ci = { repository = "matthiasbeyer/imag" } is-it-maintained-issue-resolution = { repository = "matthiasbeyer/imag" } @@ -48,3 +73,55 @@ version = "0.10.0" path = "../../../lib/core/libimagrt" features = ["pub_logging_initialization"] +[features] +default = [ "cc-all" ] + +# Features for enabling cli completion files for individual subcommands +cc-all = [ + "cc-imag-annotate", + "cc-imag-diagnostics", + "cc-imag-edit", + "cc-imag-gps", + "cc-imag-grep", + "cc-imag-ids", + "cc-imag-init", + "cc-imag-link", + "cc-imag-mv", + "cc-imag-ref", + "cc-imag-store", + "cc-imag-tag", + "cc-imag-view", + "cc-imag-bookmark", + "cc-imag-contact", + "cc-imag-diary", + "cc-imag-habit", + "cc-imag-log", + "cc-imag-mail", + "cc-imag-notes", + "cc-imag-timetrack", + "cc-imag-todo", + "cc-imag-wiki", +] +cc-imag-annotate = [ "imag-annotate" ] +cc-imag-diagnostics = [ "imag-diagnostics" ] +cc-imag-edit = [ "imag-edit" ] +cc-imag-gps = [ "imag-gps" ] +cc-imag-grep = [ "imag-grep" ] +cc-imag-ids = [ "imag-ids" ] +cc-imag-init = [ "imag-init" ] +cc-imag-link = [ "imag-link" ] +cc-imag-mv = [ "imag-mv" ] +cc-imag-ref = [ "imag-ref" ] +cc-imag-store = [ "imag-store" ] +cc-imag-tag = [ "imag-tag" ] +cc-imag-view = [ "imag-view" ] +cc-imag-bookmark = [ "imag-bookmark" ] +cc-imag-contact = [ "imag-contact" ] +cc-imag-diary = [ "imag-diary" ] +cc-imag-habit = [ "imag-habit" ] +cc-imag-log = [ "imag-log" ] +cc-imag-mail = [ "imag-mail" ] +cc-imag-notes = [ "imag-notes" ] +cc-imag-timetrack = [ "imag-timetrack" ] +cc-imag-todo = [ "imag-todo" ] +cc-imag-wiki = [ "imag-wiki" ] \ No newline at end of file diff --git a/bin/core/imag/build.rs b/bin/core/imag/build.rs new file mode 100644 index 00000000..c51ee54c --- /dev/null +++ b/bin/core/imag/build.rs @@ -0,0 +1,156 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +extern crate clap; +extern crate libimagrt; +extern crate libimagentrytag; +extern crate libimagutil; + +use clap::Shell; +use libimagrt::runtime::Runtime; + +#[allow(unused_imports)] +use libimagrt::application::ImagApplication; + +#[cfg(feature = "cc-imag-annotate")] +extern crate libimagannotatecmd; +#[cfg(feature = "cc-imag-diagnostics")] +extern crate libimagdiagnosticscmd; +#[cfg(feature = "cc-imag-edit")] +extern crate libimageditcmd; +#[cfg(feature = "cc-imag-gps")] +extern crate libimaggpscmd; +#[cfg(feature = "cc-imag-grep")] +extern crate libimaggrepcmd; +#[cfg(feature = "cc-imag-ids")] +extern crate libimagidscmd; +#[cfg(feature = "cc-imag-init")] +extern crate libimaginitcmd; +#[cfg(feature = "cc-imag-link")] +extern crate libimaglinkcmd; +#[cfg(feature = "cc-imag-mv")] +extern crate libimagmvcmd; +#[cfg(feature = "cc-imag-ref")] +extern crate libimagrefcmd; +#[cfg(feature = "cc-imag-store")] +extern crate libimagstorecmd; +#[cfg(feature = "cc-imag-tag")] +extern crate libimagtagcmd; +#[cfg(feature = "cc-imag-view")] +extern crate libimagviewcmd; +#[cfg(feature = "cc-imag-bookmark")] +extern crate libimagbookmarkfrontend; +#[cfg(feature = "cc-imag-contact")] +extern crate libimagcontactfrontend; +#[cfg(feature = "cc-imag-diary")] +extern crate libimagdiaryfrontend; +#[cfg(feature = "cc-imag-habit")] +extern crate libimaghabitfrontend; +#[cfg(feature = "cc-imag-log")] +extern crate libimaglogfrontend; +#[cfg(feature = "cc-imag-mail")] +extern crate libimagmailfrontend; +#[cfg(feature = "cc-imag-notes")] +extern crate libimagnotesfrontend; +#[cfg(feature = "cc-imag-timetrack")] +extern crate libimagtimetrackfrontend; +#[cfg(feature = "cc-imag-todo")] +extern crate libimagtodofrontend; + +/// This macro reduces boilerplate code. +/// +/// For example: `build_subcommand!("counter", libbinimagcounter, ImagCounter)` +/// will result in the following code: +/// ```ignore +/// ImagCounter::build_cli(Runtime::get_default_cli_builder( +/// "counter", +/// "abc", +/// "counter")) +/// ``` +/// As for the `"abc"` part, it does not matter +/// which version the subcommand is getting here, as the +/// output of this script is a completion script, which +/// does not contain information about the version at all. +#[allow(unused_macros)] +macro_rules! build_subcommand { + ($name:expr, $lib:ident, $implementor:ident) => ( + $lib::$implementor::build_cli(Runtime::get_default_cli_builder($name, "abc", $name)) + ) +} + +fn main() { + // Make the `imag`-App... + let app = Runtime::get_default_cli_builder( + "imag", + "abc", + "imag"); + + // and add all the subapps as subcommands. + // TODO: This feels tedious, can we automate this? + #[cfg(feature = "cc-imag-annotate")] + let app = app.subcommand(build_subcommand!("annotate", libimagannotatecmd, ImagAnnotate)); + #[cfg(feature = "cc-imag-diagnostics")] + let app = app.subcommand(build_subcommand!("diagnostics", libimagdiagnosticscmd, ImagDiagnostics)); + #[cfg(feature = "cc-imag-edit")] + let app = app.subcommand(build_subcommand!("edit", libimageditcmd, ImagEdit)); + #[cfg(feature = "cc-imag-gps")] + let app = app.subcommand(build_subcommand!("gps", libimaggpscmd, ImagGps)); + #[cfg(feature = "cc-imag-grep")] + let app = app.subcommand(build_subcommand!("grep", libimaggrepcmd, ImagGrep)); + #[cfg(feature = "cc-imag-ids")] + let app = app.subcommand(build_subcommand!("ids", libimagidscmd, ImagIds)); + #[cfg(feature = "cc-imag-init")] + let app = app.subcommand(build_subcommand!("init", libimaginitcmd, ImagInit)); + #[cfg(feature = "cc-imag-link")] + let app = app.subcommand(build_subcommand!("link", libimaglinkcmd, ImagLink)); + #[cfg(feature = "cc-imag-mv")] + let app = app.subcommand(build_subcommand!("mv", libimagmvcmd, ImagMv)); + #[cfg(feature = "cc-imag-ref")] + let app = app.subcommand(build_subcommand!("ref", libimagrefcmd, ImagRef)); + #[cfg(feature = "cc-imag-store")] + let app = app.subcommand(build_subcommand!("store", libimagstorecmd, ImagStore)); + #[cfg(feature = "cc-imag-tag")] + let app = app.subcommand(build_subcommand!("tag", libimagtagcmd, ImagTag)); + #[cfg(feature = "cc-imag-view")] + let app = app.subcommand(build_subcommand!("view", libimagviewcmd, ImagView)); + #[cfg(feature = "cc-imag-bookmark")] + let app = app.subcommand(build_subcommand!("bookmark", libimagbookmarkfrontend, ImagBookmark)); + #[cfg(feature = "cc-imag-contact")] + let app = app.subcommand(build_subcommand!("contact", libimagcontactfrontend, ImagContact)); + #[cfg(feature = "cc-imag-diary")] + let app = app.subcommand(build_subcommand!("diary", libimagdiaryfrontend, ImagDiary)); + #[cfg(feature = "cc-imag-habit")] + let app = app.subcommand(build_subcommand!("habit", libimaghabitfrontend, ImagHabit)); + #[cfg(feature = "cc-imag-log")] + let app = app.subcommand(build_subcommand!("log", libimaglogfrontend, ImagLog)); + #[cfg(feature = "cc-imag-mail")] + let app = app.subcommand(build_subcommand!("mail", libimagmailfrontend, ImagMail)); + #[cfg(feature = "cc-imag-notes")] + let app = app.subcommand(build_subcommand!("notes", libimagnotesfrontend, ImagNotes)); + #[cfg(feature = "cc-imag-timetrack")] + let app = app.subcommand(build_subcommand!("timetrack", libimagtimetrackfrontend, ImagTimetrack)); + #[cfg(feature = "cc-imag-todo")] + let app = app.subcommand(build_subcommand!("todo", libimagtodofrontend, ImagTodo)); + + let mut app = app; + // Actually generates the completion files + app.gen_completions("imag", Shell::Bash, "../../../target/"); + app.gen_completions("imag", Shell::Fish, "../../../target/"); + app.gen_completions("imag", Shell::Zsh, "../../../target/"); +} From e66f29187fc7aed1c6e278fa98a1980d64843328 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Fri, 25 Oct 2019 18:00:18 +0200 Subject: [PATCH 30/35] imag-create: implement ImagApplication & add CLI completion Signed-off-by: Leon Schuermann --- bin/core/imag-create/Cargo.toml | 7 +++ bin/core/imag-create/src/bin.rs | 39 ++++++++++++ bin/core/imag-create/src/lib.rs | 105 +++++++++++++++++++++++++++++++ bin/core/imag-create/src/main.rs | 84 ------------------------- bin/core/imag/Cargo.toml | 3 + bin/core/imag/build.rs | 4 ++ 6 files changed, 158 insertions(+), 84 deletions(-) create mode 100644 bin/core/imag-create/src/bin.rs create mode 100644 bin/core/imag-create/src/lib.rs delete mode 100644 bin/core/imag-create/src/main.rs diff --git a/bin/core/imag-create/Cargo.toml b/bin/core/imag-create/Cargo.toml index 4aac3d4f..fca9dedc 100644 --- a/bin/core/imag-create/Cargo.toml +++ b/bin/core/imag-create/Cargo.toml @@ -27,3 +27,10 @@ version = "2.33.0" default-features = false features = ["suggestions", "color", "wrap_help"] +[lib] +name = "libimagcreatecmd" +path = "src/lib.rs" + +[[bin]] +name = "imag-create" +path = "src/bin.rs" diff --git a/bin/core/imag-create/src/bin.rs b/bin/core/imag-create/src/bin.rs new file mode 100644 index 00000000..4f38c625 --- /dev/null +++ b/bin/core/imag-create/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagcreatecmd, ImagCreate); diff --git a/bin/core/imag-create/src/lib.rs b/bin/core/imag-create/src/lib.rs new file mode 100644 index 00000000..aca33344 --- /dev/null +++ b/bin/core/imag-create/src/lib.rs @@ -0,0 +1,105 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +extern crate clap; +extern crate failure; +#[macro_use] extern crate log; + +extern crate libimagerror; +extern crate libimagrt; +extern crate libimagstore; + +use failure::Fallible as Result; +use clap::App; + +use libimagrt::runtime::Runtime; +use libimagrt::application::ImagApplication; +use libimagerror::trace::MapErrTrace; +use libimagstore::iter::create::StoreIdCreateIteratorExtension; +use libimagstore::iter::retrieve::StoreIdRetrieveIteratorExtension; +use libimagerror::exit::ExitUnwrap; + +mod ui; + + + +pub enum ImagCreate {} +impl ImagApplication for ImagCreate { + fn run(rt: Runtime) -> Result<()> { + let force = rt.cli().is_present("force"); + debug!("Detected force = {}", force); + + let ids = rt.ids::() + .map_err_trace_exit_unwrap() + .unwrap_or_else(|| { + error!("No ids supplied"); + ::std::process::exit(1); + }) + .into_iter() + .map(|id| { debug!("id = {}", id); id }) + .map(Ok); + + if force { + ids.into_retrieve_iter(rt.store()).collect::>>() + } else { + ids.into_create_iter(rt.store()).collect::>>() + }.map_err_trace_exit_unwrap() + .into_iter() + .for_each(|el| { + rt.report_touched(el.get_location()).unwrap_or_exit(); + trace!("Entry = {}", el.get_location()); + }); + + Ok(()) + } + + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Plumbing tool to create entries" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") + } +} + diff --git a/bin/core/imag-create/src/main.rs b/bin/core/imag-create/src/main.rs deleted file mode 100644 index 54208981..00000000 --- a/bin/core/imag-create/src/main.rs +++ /dev/null @@ -1,84 +0,0 @@ -// -// imag - the personal information management suite for the commandline -// Copyright (C) 2015-2019 Matthias Beyer 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_must_use, -// unused_mut, -// unused_qualifications, -// while_true, -//)] - -extern crate clap; -extern crate failure; -#[macro_use] extern crate log; - -extern crate libimagerror; -#[macro_use] extern crate libimagrt; -extern crate libimagstore; - -use failure::Fallible as Result; - -use libimagerror::trace::MapErrTrace; -use libimagrt::setup::generate_runtime_setup; -use libimagstore::iter::create::StoreIdCreateIteratorExtension; -use libimagstore::iter::retrieve::StoreIdRetrieveIteratorExtension; -use libimagerror::exit::ExitUnwrap; - -mod ui; - -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-create", - &version, - "Plumbing tool creating entries", - ui::build_ui); - - let force = rt.cli().is_present("force"); - debug!("Detected force = {}", force); - - let ids = rt.ids::() - .map_err_trace_exit_unwrap() - .unwrap_or_else(|| { - error!("No ids supplied"); - ::std::process::exit(1); - }) - .into_iter() - .map(|id| { debug!("id = {}", id); id }) - .map(Ok); - - if force { - ids.into_retrieve_iter(rt.store()).collect::>>() - } else { - ids.into_create_iter(rt.store()).collect::>>() - }.map_err_trace_exit_unwrap() - .into_iter() - .for_each(|el| { - rt.report_touched(el.get_location()).unwrap_or_exit(); - trace!("Entry = {}", el.get_location()); - }); -} - diff --git a/bin/core/imag/Cargo.toml b/bin/core/imag/Cargo.toml index 904eaacd..ba74f34e 100644 --- a/bin/core/imag/Cargo.toml +++ b/bin/core/imag/Cargo.toml @@ -25,6 +25,7 @@ log = "0.4.6" # Build time dependencies for cli completion imag-annotate = { optional = true, path = "../imag-annotate" } +imag-create = { optional = true, path = "../imag-create" } imag-diagnostics = { optional = true, path = "../imag-diagnostics" } imag-edit = { optional = true, path = "../imag-edit" } imag-gps = { optional = true, path = "../imag-gps" } @@ -79,6 +80,7 @@ default = [ "cc-all" ] # Features for enabling cli completion files for individual subcommands cc-all = [ "cc-imag-annotate", + "cc-imag-create", "cc-imag-diagnostics", "cc-imag-edit", "cc-imag-gps", @@ -103,6 +105,7 @@ cc-all = [ "cc-imag-wiki", ] cc-imag-annotate = [ "imag-annotate" ] +cc-imag-create = [ "imag-create" ] cc-imag-diagnostics = [ "imag-diagnostics" ] cc-imag-edit = [ "imag-edit" ] cc-imag-gps = [ "imag-gps" ] diff --git a/bin/core/imag/build.rs b/bin/core/imag/build.rs index c51ee54c..c670bf46 100644 --- a/bin/core/imag/build.rs +++ b/bin/core/imag/build.rs @@ -30,6 +30,8 @@ use libimagrt::application::ImagApplication; #[cfg(feature = "cc-imag-annotate")] extern crate libimagannotatecmd; +#[cfg(feature = "cc-imag-create")] +extern crate libimagcreatecmd; #[cfg(feature = "cc-imag-diagnostics")] extern crate libimagdiagnosticscmd; #[cfg(feature = "cc-imag-edit")] @@ -105,6 +107,8 @@ fn main() { // TODO: This feels tedious, can we automate this? #[cfg(feature = "cc-imag-annotate")] let app = app.subcommand(build_subcommand!("annotate", libimagannotatecmd, ImagAnnotate)); + #[cfg(feature = "cc-imag-create")] + let app = app.subcommand(build_subcommand!("create", libimagcreatecmd, ImagCreate)); #[cfg(feature = "cc-imag-diagnostics")] let app = app.subcommand(build_subcommand!("diagnostics", libimagdiagnosticscmd, ImagDiagnostics)); #[cfg(feature = "cc-imag-edit")] From 26b05b4bb91b0d8e872f9d5807bdce4ffbb28b02 Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 26 Oct 2019 11:55:19 +0200 Subject: [PATCH 31/35] imag-calendar: implement ImagApplication & add CLI completion Signed-off-by: Leon Schuermann --- bin/core/imag/Cargo.toml | 3 + bin/core/imag/build.rs | 4 ++ bin/domain/imag-calendar/Cargo.toml | 7 ++ bin/domain/imag-calendar/src/bin.rs | 39 +++++++++++ .../imag-calendar/src/{main.rs => lib.rs} | 65 ++++++++++++------- 5 files changed, 95 insertions(+), 23 deletions(-) create mode 100644 bin/domain/imag-calendar/src/bin.rs rename bin/domain/imag-calendar/src/{main.rs => lib.rs} (90%) diff --git a/bin/core/imag/Cargo.toml b/bin/core/imag/Cargo.toml index ba74f34e..4c7df6dc 100644 --- a/bin/core/imag/Cargo.toml +++ b/bin/core/imag/Cargo.toml @@ -39,6 +39,7 @@ imag-store = { optional = true, path = "../imag-store" } imag-tag = { optional = true, path = "../imag-tag" } imag-view = { optional = true, path = "../imag-view" } imag-bookmark = { optional = true, path = "../../domain/imag-bookmark" } +imag-calendar = { optional = true, path = "../../domain/imag-calendar" } imag-contact = { optional = true, path = "../../domain/imag-contact" } imag-diary = { optional = true, path = "../../domain/imag-diary" } imag-habit = { optional = true, path = "../../domain/imag-habit" } @@ -94,6 +95,7 @@ cc-all = [ "cc-imag-tag", "cc-imag-view", "cc-imag-bookmark", + "cc-imag-calendar", "cc-imag-contact", "cc-imag-diary", "cc-imag-habit", @@ -119,6 +121,7 @@ cc-imag-store = [ "imag-store" ] cc-imag-tag = [ "imag-tag" ] cc-imag-view = [ "imag-view" ] cc-imag-bookmark = [ "imag-bookmark" ] +cc-imag-calendar = [ "imag-calendar" ] cc-imag-contact = [ "imag-contact" ] cc-imag-diary = [ "imag-diary" ] cc-imag-habit = [ "imag-habit" ] diff --git a/bin/core/imag/build.rs b/bin/core/imag/build.rs index c670bf46..c7675ff2 100644 --- a/bin/core/imag/build.rs +++ b/bin/core/imag/build.rs @@ -58,6 +58,8 @@ extern crate libimagtagcmd; extern crate libimagviewcmd; #[cfg(feature = "cc-imag-bookmark")] extern crate libimagbookmarkfrontend; +#[cfg(feature = "cc-imag-calendar")] +extern crate libimagcalendarfrontend; #[cfg(feature = "cc-imag-contact")] extern crate libimagcontactfrontend; #[cfg(feature = "cc-imag-diary")] @@ -135,6 +137,8 @@ fn main() { let app = app.subcommand(build_subcommand!("view", libimagviewcmd, ImagView)); #[cfg(feature = "cc-imag-bookmark")] let app = app.subcommand(build_subcommand!("bookmark", libimagbookmarkfrontend, ImagBookmark)); + #[cfg(feature = "cc-imag-calendar")] + let app = app.subcommand(build_subcommand!("calendar", libimagcalendarfrontend, ImagCalendar)); #[cfg(feature = "cc-imag-contact")] let app = app.subcommand(build_subcommand!("contact", libimagcontactfrontend, ImagContact)); #[cfg(feature = "cc-imag-diary")] diff --git a/bin/domain/imag-calendar/Cargo.toml b/bin/domain/imag-calendar/Cargo.toml index 192a7402..ccc4e09d 100644 --- a/bin/domain/imag-calendar/Cargo.toml +++ b/bin/domain/imag-calendar/Cargo.toml @@ -48,3 +48,10 @@ version = "0.9.2" default-features = false features = ["typed"] +[lib] +name = "libimagcalendarfrontend" +path = "src/lib.rs" + +[[bin]] +name = "imag-calendar" +path = "src/bin.rs" \ No newline at end of file diff --git a/bin/domain/imag-calendar/src/bin.rs b/bin/domain/imag-calendar/src/bin.rs new file mode 100644 index 00000000..c164a412 --- /dev/null +++ b/bin/domain/imag-calendar/src/bin.rs @@ -0,0 +1,39 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer 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 +// + +#![forbid(unsafe_code)] + +#![deny( + non_camel_case_types, + non_snake_case, + path_statements, + trivial_numeric_casts, + unstable_features, + unused_allocation, + unused_import_braces, + unused_imports, + unused_must_use, + unused_mut, + unused_qualifications, + while_true, +)] + +#[macro_use] extern crate libimagrt; + +simple_imag_application_binary!(libimagcalendarfrontend, ImagCalendar); diff --git a/bin/domain/imag-calendar/src/main.rs b/bin/domain/imag-calendar/src/lib.rs similarity index 90% rename from bin/domain/imag-calendar/src/main.rs rename to bin/domain/imag-calendar/src/lib.rs index c87d77d0..bb18e06b 100644 --- a/bin/domain/imag-calendar/src/main.rs +++ b/bin/domain/imag-calendar/src/lib.rs @@ -43,7 +43,7 @@ extern crate handlebars; extern crate chrono; extern crate kairos; -#[macro_use] extern crate libimagrt; +extern crate libimagrt; extern crate libimagcalendar; extern crate libimagerror; extern crate libimagstore; @@ -61,6 +61,7 @@ use toml_query::read::TomlValueReadExt; use walkdir::DirEntry; use walkdir::WalkDir; use vobject::icalendar::Event; +use clap::App; use libimagcalendar::store::EventStore; use libimagerror::io::ToExitCode; @@ -68,35 +69,53 @@ use libimagerror::exit::ExitUnwrap; use libimagerror::iter::TraceIterator; use libimagerror::trace::MapErrTrace; use libimagrt::runtime::Runtime; -use libimagrt::setup::generate_runtime_setup; +use libimagrt::application::ImagApplication; mod filters; mod ui; mod util; -fn main() { - let version = make_imag_version!(); - let rt = generate_runtime_setup("imag-calendar", - &version, - "Calendar management tool", - crate::ui::build_ui); +/// Marker enum for implementing ImagApplication on +/// +/// This is used by binary crates to execute business logic or to +/// build a CLI completion. +pub enum ImagCalendar {} +impl ImagApplication for ImagCalendar { + fn run(rt: Runtime) -> Result<()> { + if let Some(name) = rt.cli().subcommand_name() { + debug!("Call {}", name); + match name { + "import" => import(&rt), + "list" => list(&rt), + "show" => show(&rt), + other => { + warn!("Right now, only the 'import' command is available"); + debug!("Unknown command"); + let _ = rt.handle_unknown_subcommand("imag-calendar", other, rt.cli()) + .map_err_trace_exit_unwrap() + .code() + .map(::std::process::exit); + }, + } + } + Ok(()) + } - if let Some(name) = rt.cli().subcommand_name() { - debug!("Call {}", name); - match name { - "import" => import(&rt), - "list" => list(&rt), - "show" => show(&rt), - other => { - warn!("Right now, only the 'import' command is available"); - debug!("Unknown command"); - let _ = rt.handle_unknown_subcommand("imag-calendar", other, rt.cli()) - .map_err_trace_exit_unwrap() - .code() - .map(::std::process::exit); - }, - } + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + ui::build_ui(app) + } + + fn name() -> &'static str { + env!("CARGO_PKG_NAME") + } + + fn description() -> &'static str { + "Calendar management tool" + } + + fn version() -> &'static str { + env!("CARGO_PKG_VERSION") } } From e331b9efb3348a227b274570924c1871df8ab111 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 26 Oct 2019 15:00:09 +0200 Subject: [PATCH 32/35] Pass the path to the ui builder function when creating a mock application Signed-off-by: Matthias Beyer --- lib/etc/libimagutil/src/testing.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/etc/libimagutil/src/testing.rs b/lib/etc/libimagutil/src/testing.rs index beab21a6..feee2a11 100644 --- a/lib/etc/libimagutil/src/testing.rs +++ b/lib/etc/libimagutil/src/testing.rs @@ -45,6 +45,7 @@ macro_rules! make_mock_app { modulename $module:ident; version $version:expr; with help $help:expr; + with ui builder function $buildui:path; }=> { mod $module { use clap::{App, ArgMatches}; @@ -64,7 +65,7 @@ macro_rules! make_mock_app { fn new(args: Vec<&'static str>) -> Self { MockLinkApp { args: args, - inner: ::build_ui(Runtime::get_default_cli_builder($appname, $version, $help)), + inner: ($buildui)(Runtime::get_default_cli_builder($appname, $version, $help)), } } } From 47ba9fd2eb59d62178308ef87322225c7ce1fba9 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 26 Oct 2019 15:00:37 +0200 Subject: [PATCH 33/35] Fix: Pass path to ui builder function when creating mock app Signed-off-by: Matthias Beyer --- bin/core/imag-link/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/core/imag-link/src/lib.rs b/bin/core/imag-link/src/lib.rs index bfa927dd..47851127 100644 --- a/bin/core/imag-link/src/lib.rs +++ b/bin/core/imag-link/src/lib.rs @@ -396,6 +396,7 @@ mod tests { modulename mock; version env!("CARGO_PKG_VERSION"); with help "imag-link mocking app"; + with ui builder function crate::ui::build_ui; } use self::mock::generate_test_runtime; use self::mock::reset_test_runtime; From c301b4b0ab1840a4545faf6f3de314296fb85645 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 26 Oct 2019 15:00:37 +0200 Subject: [PATCH 34/35] Fix: Pass path to ui builder function when creating mock app Signed-off-by: Matthias Beyer --- bin/core/imag-store/src/create.rs | 1 + bin/core/imag-store/src/delete.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/core/imag-store/src/create.rs b/bin/core/imag-store/src/create.rs index 0384310f..c4a8ad14 100644 --- a/bin/core/imag-store/src/create.rs +++ b/bin/core/imag-store/src/create.rs @@ -168,6 +168,7 @@ mod tests { modulename mock; version env!("CARGO_PKG_VERSION"); with help "imag-store mocking app"; + with ui builder function crate::ui::build_ui; } use self::mock::generate_test_runtime; diff --git a/bin/core/imag-store/src/delete.rs b/bin/core/imag-store/src/delete.rs index b6189414..e361d535 100644 --- a/bin/core/imag-store/src/delete.rs +++ b/bin/core/imag-store/src/delete.rs @@ -49,6 +49,7 @@ mod tests { modulename mock; version env!("CARGO_PKG_VERSION"); with help "imag-store mocking app"; + with ui builder function crate::ui::build_ui; } use self::mock::generate_test_runtime; use self::mock::reset_test_runtime; From ae7a633ab3c7fde2f745f2a532df6d511565ac1a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 26 Oct 2019 15:00:37 +0200 Subject: [PATCH 35/35] Fix: Pass path to ui builder function when creating mock app Signed-off-by: Matthias Beyer --- bin/core/imag-tag/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/core/imag-tag/src/lib.rs b/bin/core/imag-tag/src/lib.rs index 2453ef45..2e917884 100644 --- a/bin/core/imag-tag/src/lib.rs +++ b/bin/core/imag-tag/src/lib.rs @@ -92,7 +92,7 @@ impl ImagApplication for ImagTag { ::std::process::exit(1); }) .into_iter(); - + if let Some(name) = rt.cli().subcommand_name() { match name { "list" => for id in ids { @@ -282,6 +282,7 @@ mod tests { modulename mock; version env!("CARGO_PKG_VERSION"); with help "imag-tag mocking app"; + with ui builder function crate::ui::build_ui; } use self::mock::generate_test_runtime;