diff --git a/lib/core/libimagrt/src/application.rs b/lib/core/libimagrt/src/application.rs new file mode 100644 index 00000000..74ad4b68 --- /dev/null +++ b/lib/core/libimagrt/src/application.rs @@ -0,0 +1,70 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015-2019 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use runtime::Runtime; +use clap::App; +use failure::Fallible as Result; + +pub trait ImagApplication { + fn run(rt: Runtime) -> Result<()>; + fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a>; + fn name() -> &'static str; + fn version() -> &'static str; + fn description() -> &'static str; +} + + +#[macro_export] +macro_rules! simple_imag_application_binary { + ($application_library:ident, $application_implementor:ident) => { + extern crate libimagerror; + extern crate failure; + extern crate $application_library; + + use failure::{Error, Fallible as Result}; + + fn main() { + use libimagerror::trace::MapErrTrace; + use libimagrt::application::ImagApplication; + use libimagrt::setup::generate_runtime_setup; + use $application_library::$application_implementor; + + let version = make_imag_version!(); + let rt = generate_runtime_setup($application_implementor::name(), + &version, + $application_implementor::description(), + $application_implementor::build_cli); + + // The error context must have a 'static lifetime + // Therefore, the easiest, safe, but hacky way to achieve this + // is to allocate a string, which is then forgotten to + // leak memory and return it's contents as a &'static str + // Because this is the very end of the application and only + // happens once, it should have no impact whatsoever + let error_context: &'static str = Box::leak( + format!("Failed to run {}", $application_implementor::name()) + .into_boxed_str() + ); + $application_implementor::run(rt) + .map_err(|e| e.context(error_context)) + .map_err(Error::from) + .map_err_trace_exit_unwrap(); + } + }; +} diff --git a/lib/core/libimagrt/src/lib.rs b/lib/core/libimagrt/src/lib.rs index ebe8f4fc..f9d349c0 100644 --- a/lib/core/libimagrt/src/lib.rs +++ b/lib/core/libimagrt/src/lib.rs @@ -55,6 +55,7 @@ extern crate libimagutil; extern crate libimagerror; extern crate libimaginteraction; +pub mod application; pub mod configuration; pub mod logger; pub mod io;