summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2019-10-26 15:09:41 +0200
committerMatthias Beyer <mail@beyermatthias.de>2019-10-26 15:15:35 +0200
commit7a0654465413fb7e447d4a7e80a6bc24adebf605 (patch)
tree76e7465cafeb6dbc5c41c329c954d0e5e74cd679
parent564a7407414a3bb2ea55f84e197728f79156c646 (diff)
parentae7a633ab3c7fde2f745f2a532df6d511565ac1a (diff)
downloadimag-7a0654465413fb7e447d4a7e80a6bc24adebf605.tar.gz
imag-7a0654465413fb7e447d4a7e80a6bc24adebf605.tar.xz
-rw-r--r--bin/core/imag-annotate/Cargo.toml7
-rw-r--r--bin/core/imag-annotate/src/bin.rs39
-rw-r--r--bin/core/imag-annotate/src/lib.rs (renamed from bin/core/imag-annotate/src/main.rs)59
-rw-r--r--bin/core/imag-category/Cargo.toml7
-rw-r--r--bin/core/imag-category/src/bin.rs39
-rw-r--r--bin/core/imag-category/src/lib.rs (renamed from bin/core/imag-category/src/main.rs)71
-rw-r--r--bin/core/imag-create/Cargo.toml7
-rw-r--r--bin/core/imag-create/src/bin.rs39
-rw-r--r--bin/core/imag-create/src/lib.rs105
-rw-r--r--bin/core/imag-create/src/main.rs84
-rw-r--r--bin/core/imag-diagnostics/Cargo.toml7
-rw-r--r--bin/core/imag-diagnostics/src/bin.rs39
-rw-r--r--bin/core/imag-diagnostics/src/lib.rs288
-rw-r--r--bin/core/imag-diagnostics/src/main.rs269
-rw-r--r--bin/core/imag-edit/Cargo.toml7
-rw-r--r--bin/core/imag-edit/src/bin.rs39
-rw-r--r--bin/core/imag-edit/src/lib.rs121
-rw-r--r--bin/core/imag-edit/src/main.rs99
-rw-r--r--bin/core/imag-git/Cargo.toml8
-rw-r--r--bin/core/imag-git/src/bin.rs39
-rw-r--r--bin/core/imag-git/src/lib.rs197
-rw-r--r--bin/core/imag-git/src/main.rs171
-rw-r--r--bin/core/imag-gps/Cargo.toml7
-rw-r--r--bin/core/imag-gps/src/bin.rs39
-rw-r--r--bin/core/imag-gps/src/lib.rs (renamed from bin/core/imag-gps/src/main.rs)61
-rw-r--r--bin/core/imag-grep/Cargo.toml8
-rw-r--r--bin/core/imag-grep/src/bin.rs39
-rw-r--r--bin/core/imag-grep/src/lib.rs (renamed from bin/core/imag-grep/src/main.rs)120
-rw-r--r--bin/core/imag-header/Cargo.toml7
-rw-r--r--bin/core/imag-header/src/bin.rs39
-rw-r--r--bin/core/imag-header/src/lib.rs (renamed from bin/core/imag-header/src/main.rs)116
-rw-r--r--bin/core/imag-ids/Cargo.toml7
-rw-r--r--bin/core/imag-ids/src/bin.rs39
-rw-r--r--bin/core/imag-ids/src/lib.rs134
-rw-r--r--bin/core/imag-ids/src/main.rs113
-rw-r--r--bin/core/imag-init/Cargo.toml9
-rw-r--r--bin/core/imag-init/src/bin.rs46
-rw-r--r--bin/core/imag-init/src/lib.rs (renamed from bin/core/imag-init/src/main.rs)35
-rw-r--r--bin/core/imag-link/Cargo.toml6
-rw-r--r--bin/core/imag-link/src/bin.rs39
-rw-r--r--bin/core/imag-link/src/lib.rs (renamed from bin/core/imag-link/src/main.rs)115
-rw-r--r--bin/core/imag-markdown/Cargo.toml7
-rw-r--r--bin/core/imag-markdown/src/bin.rs39
-rw-r--r--bin/core/imag-markdown/src/lib.rs123
-rw-r--r--bin/core/imag-markdown/src/main.rs102
-rw-r--r--bin/core/imag-mv/Cargo.toml8
-rw-r--r--bin/core/imag-mv/src/bin.rs39
-rw-r--r--bin/core/imag-mv/src/lib.rs181
-rw-r--r--bin/core/imag-mv/src/main.rs156
-rw-r--r--bin/core/imag-ref/Cargo.toml7
-rw-r--r--bin/core/imag-ref/src/bin.rs39
-rw-r--r--bin/core/imag-ref/src/lib.rs (renamed from bin/core/imag-ref/src/main.rs)67
-rw-r--r--bin/core/imag-store/Cargo.toml7
-rw-r--r--bin/core/imag-store/src/bin.rs39
-rw-r--r--bin/core/imag-store/src/create.rs1
-rw-r--r--bin/core/imag-store/src/delete.rs1
-rw-r--r--bin/core/imag-store/src/lib.rs (renamed from bin/core/imag-store/src/main.rs)85
-rw-r--r--bin/core/imag-tag/Cargo.toml7
-rw-r--r--bin/core/imag-tag/src/bin.rs39
-rw-r--r--bin/core/imag-tag/src/lib.rs (renamed from bin/core/imag-tag/src/main.rs)110
-rw-r--r--bin/core/imag-view/Cargo.toml7
-rw-r--r--bin/core/imag-view/src/bin.rs39
-rw-r--r--bin/core/imag-view/src/lib.rs315
-rw-r--r--bin/core/imag-view/src/main.rs293
-rw-r--r--bin/core/imag/Cargo.toml83
-rw-r--r--bin/core/imag/build.rs164
-rw-r--r--bin/domain/imag-bookmark/Cargo.toml7
-rw-r--r--bin/domain/imag-bookmark/src/bin.rs39
-rw-r--r--bin/domain/imag-bookmark/src/lib.rs (renamed from bin/domain/imag-bookmark/src/main.rs)70
-rw-r--r--bin/domain/imag-calendar/Cargo.toml7
-rw-r--r--bin/domain/imag-calendar/src/bin.rs39
-rw-r--r--bin/domain/imag-calendar/src/lib.rs (renamed from bin/domain/imag-calendar/src/main.rs)69
-rw-r--r--bin/domain/imag-contact/Cargo.toml8
-rw-r--r--bin/domain/imag-contact/src/bin.rs39
-rw-r--r--bin/domain/imag-contact/src/lib.rs (renamed from bin/domain/imag-contact/src/main.rs)74
-rw-r--r--bin/domain/imag-diary/Cargo.toml7
-rw-r--r--bin/domain/imag-diary/src/bin.rs39
-rw-r--r--bin/domain/imag-diary/src/lib.rs (renamed from bin/domain/imag-diary/src/main.rs)69
-rw-r--r--bin/domain/imag-habit/Cargo.toml7
-rw-r--r--bin/domain/imag-habit/src/bin.rs39
-rw-r--r--bin/domain/imag-habit/src/lib.rs (renamed from bin/domain/imag-habit/src/main.rs)82
-rw-r--r--bin/domain/imag-log/Cargo.toml7
-rw-r--r--bin/domain/imag-log/src/bin.rs39
-rw-r--r--bin/domain/imag-log/src/lib.rs (renamed from bin/domain/imag-log/src/main.rs)103
-rw-r--r--bin/domain/imag-mail/Cargo.toml7
-rw-r--r--bin/domain/imag-mail/src/bin.rs39
-rw-r--r--bin/domain/imag-mail/src/lib.rs (renamed from bin/domain/imag-mail/src/main.rs)69
-rw-r--r--bin/domain/imag-notes/Cargo.toml8
-rw-r--r--bin/domain/imag-notes/src/bin.rs39
-rw-r--r--bin/domain/imag-notes/src/lib.rs (renamed from bin/domain/imag-notes/src/main.rs)74
-rw-r--r--bin/domain/imag-timetrack/Cargo.toml7
-rw-r--r--bin/domain/imag-timetrack/src/bin.rs39
-rw-r--r--bin/domain/imag-timetrack/src/lib.rs137
-rw-r--r--bin/domain/imag-timetrack/src/main.rs117
-rw-r--r--bin/domain/imag-todo/Cargo.toml7
-rw-r--r--bin/domain/imag-todo/src/bin.rs39
-rw-r--r--bin/domain/imag-todo/src/lib.rs (renamed from bin/domain/imag-todo/src/main.rs)70
-rw-r--r--bin/domain/imag-wiki/Cargo.toml8
-rw-r--r--bin/domain/imag-wiki/src/bin.rs39
-rw-r--r--bin/domain/imag-wiki/src/lib.rs (renamed from bin/domain/imag-wiki/src/main.rs)86
-rw-r--r--lib/core/libimagrt/src/application.rs70
-rw-r--r--lib/core/libimagrt/src/lib.rs1
-rw-r--r--lib/etc/libimagutil/src/testing.rs3
103 files changed, 4281 insertions, 2000 deletions
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<crate::ui::PathProvider>()
+ .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::<Result<Vec<_>>>()
+ } else {
+ ids.into_create_iter(rt.store()).collect::<Result<Vec<_>>>()
+ }.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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-//#![deny(
-// non_camel_case_types,
-// non_snake_case,
-// path_statements,
-// trivial_numeric_casts,
-// unstable_features,
-// unused_allocation,
-// unused_import_braces,
-// unused_imports,
-// unused_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::<crate::ui::PathProvider>()
- .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::<Result<Vec<_>>>()
- } else {
- ids.into_create_iter(rt.store()).collect::<Result<Vec<_>>>()
- }.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-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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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<Diagnostic> {
+ 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::<Result<Vec<_>>>()
+ .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<String, usize> = 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<String> {
+ 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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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<Diagnostic> {
- 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::<Result<Vec<_>>>()
- .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<String, usize> = 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<String> {
- 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-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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<crate::ui::PathProvider>()
+ .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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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::<crate::ui::PathProvider>()
- .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();
- }
- });
-}
-
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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);
- }
- }
- }
- }
-}
-
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
- 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 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();
-
- 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();
+/// 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 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 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();
+ }
+
+ 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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
- 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);
-
- let sids = rt
- .ids::<crate::ui::PathProvider>()
- .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);
-
- 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)
- });
- },
+/// 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");
+
+ trace!("list_output_with_ids = {:?}", list_output_with_ids );
+ trace!("list_output_with_ids_fmt = {:?}", list_output_with_ids_fmt);
+
+ let sids = rt
+ .ids::<crate::ui::PathProvider>()
+ .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);
+
+ 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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<crate::ui::PathProvider>()
+ .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<dyn Iterator<Item = RResult<StoreId, _>>>
+ } else {
+ Box::new(rt.store().entries().map_err_trace_exit_unwrap())
+ as Box<dyn Iterator<Item = RResult<StoreId, _>>>
+ }
+ .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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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::<crate::ui::PathProvider>()
- .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<dyn Iterator<Item = Result<StoreId, _>>>
- } else {
- Box::new(rt.store().entries().map_err_trace_exit_unwrap())
- as Box<dyn Iterator<Item = Result<StoreId, _>>>
- }
- .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();
- }
- })
-}
-
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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",
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
index 7e451a83..47851127 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;
-
-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);
+/// 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);
+ }
+
+ 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<Option<FileLockEntry<'a>>> {
@@ -378,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;
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<crate::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(|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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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::<crate::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(|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();
- })
- }
-}
-
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<Vec<_>>()
+ };
+
+ { // 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<FileLockEntry<'a>>) {
+ 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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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::<Vec<_>>()
- };
-
- { // 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<FileLockEntry<'a>>) {
- 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();
- }
-}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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/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;
diff --git a/bin/core/imag-store/src/main.rs b/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);
-
- 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");
+/// 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);
+
+ 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")
+ }
+}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
index 30eb37e2..2e917884 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::<crate::ui::PathProvider>()
- .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::<crate::ui::PathProvider>()
+ .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")
}
}
@@ -263,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;
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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::<Vec<_>>();
+
+ 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::<Vec<String>>()
+ .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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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::<Vec<_>>();
-
- 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::<Vec<String>>()
- .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()
- }
-}
-
diff --git a/bin/core/imag/Cargo.toml b/bin/core/imag/Cargo.toml
index c3a6df66..4c7df6dc 100644
--- a/bin/core/imag/Cargo.toml
+++ b/bin/core/imag/Cargo.toml
@@ -23,6 +23,33 @@ 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-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" }
+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-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" }
+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 +75,59 @@ 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-create",
+ "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-calendar",
+ "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-create = [ "imag-create" ]
+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-calendar = [ "imag-calendar" ]
+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..c7675ff2
--- /dev/null
+++ b/bin/core/imag/build.rs
@@ -0,0 +1,164 @@
+//
+// imag - the personal information management suite for the commandline
+// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+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-create")]
+extern crate libimagcreatecmd;
+#[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-calendar")]
+extern crate libimagcalendarfrontend;
+#[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-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")]
+ 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-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")]
+ 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/");
+}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
-
- 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);
- },
- }
+/// 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(())
+ }
+
+ 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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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) {
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
-
- 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);
- },
+/// 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();
+
}
- } 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();
+
+ 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 {
+ "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::<Result<Vec<()>, ExitCode>>()
+ .collect::<RResult<Vec<()>, ExitCode>>()
.unwrap_or_exit();
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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;
-
-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() {
- 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);
+/// 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<()> {
+
+ 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);
+ }
+ }
}
- }
+
+ 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();
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
- 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);
- },
- };
+
+/// 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() {
+
+ 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")
}
}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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 <mail@beyermatthias.de> and contributors
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; version
-// 2.1 of the License.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-//
-
-#![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);
-}
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
- 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
+/// 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");
+ },
+ };
+
+ 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();
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+#![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
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);
-
- 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
-} // end 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 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());
+
+ 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")
+ }
+}
+
fn list(rt: &Runtime, wiki_name: &str) {
let scmd = rt.cli().subcommand_matches("list").unwrap(); // safed by clap
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 <mail@beyermatthias.de> and contributors
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; version
+// 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+//
+
+use 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;
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)),
}
}
}