2016-10-01 15:35:06 +00:00
//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
2016-01-20 19:46:42 +00:00
use std ::path ::PathBuf ;
2016-03-21 09:19:03 +00:00
use std ::process ::Command ;
use std ::env ;
2017-08-26 13:27:13 +00:00
use std ::process ::exit ;
2016-01-20 19:46:42 +00:00
pub use clap ::App ;
use clap ::{ Arg , ArgMatches } ;
use log ;
2017-06-08 21:35:15 +00:00
use configuration ::{ Configuration , InternalConfiguration } ;
2016-01-21 17:43:03 +00:00
use error ::RuntimeError ;
use error ::RuntimeErrorKind ;
2017-09-02 21:02:53 +00:00
use error ::ResultExt ;
2016-01-20 19:46:42 +00:00
use logger ::ImagLogger ;
2017-08-26 13:27:13 +00:00
use libimagerror ::trace ::* ;
2017-06-25 15:08:18 +00:00
use libimagstore ::store ::Store ;
use libimagstore ::file_abstraction ::InMemoryFileAbstraction ;
2017-05-30 21:09:03 +00:00
use spec ::CliSpec ;
2016-01-20 19:46:42 +00:00
2017-02-21 14:31:24 +00:00
/// The Runtime object
///
/// This object contains the complete runtime environment of the imag application running.
2016-04-18 12:02:57 +00:00
#[ derive(Debug) ]
2016-01-20 19:46:42 +00:00
pub struct Runtime < ' a > {
rtp : PathBuf ,
2016-03-05 12:01:09 +00:00
configuration : Option < Configuration > ,
2016-02-20 20:15:09 +00:00
cli_matches : ArgMatches < ' a > ,
2016-01-20 19:46:42 +00:00
store : Store ,
}
impl < ' a > Runtime < ' a > {
2017-02-21 14:31:24 +00:00
/// Gets the CLI spec for the program and retreives the config file path (or uses the default on
/// in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
/// and builds the Runtime object with it.
///
2017-06-03 23:34:21 +00:00
/// The cli_app object should be initially build with the ::get_default_cli_builder() function.
2017-06-08 21:35:15 +00:00
pub fn new < C > ( cli_app : C ) -> Result < Runtime < ' a > , RuntimeError >
where C : Clone + CliSpec < ' a > + InternalConfiguration
2017-06-03 23:34:21 +00:00
{
2016-05-16 16:59:02 +00:00
use libimagerror ::trace ::trace_error ;
2016-03-24 11:09:45 +00:00
2017-09-03 12:38:46 +00:00
use configuration ::ConfigErrorKind ;
2016-03-05 12:01:09 +00:00
2017-06-03 23:34:21 +00:00
let matches = cli_app . clone ( ) . matches ( ) ;
2016-04-05 15:46:51 +00:00
2017-06-08 21:35:15 +00:00
let rtp = get_rtp_match ( & matches ) ;
let configpath = matches . value_of ( Runtime ::arg_config_name ( ) )
. map_or_else ( | | rtp . clone ( ) , PathBuf ::from ) ;
2017-06-25 14:58:25 +00:00
debug! ( " Config path = {:?} " , configpath ) ;
2017-06-08 21:35:15 +00:00
let config = match Configuration ::new ( & configpath ) {
2017-09-03 12:38:46 +00:00
Err ( e ) = > if ! is_match! ( e . kind ( ) , & ConfigErrorKind ::NoConfigFileFound ) {
return Err ( e ) . chain_err ( | | RuntimeErrorKind ::Instantiate ) ;
2017-06-08 21:35:15 +00:00
} else {
2017-08-27 12:13:43 +00:00
println! ( " No config file found. " ) ;
println! ( " Continuing without configuration file " ) ;
2017-06-08 21:35:15 +00:00
None
} ,
Ok ( mut config ) = > {
if let Err ( e ) = config . override_config ( get_override_specs ( & matches ) ) {
error! ( " Could not apply config overrides " ) ;
trace_error ( & e ) ;
// TODO: continue question (interactive)
}
Some ( config )
}
} ;
2017-06-12 17:10:53 +00:00
Runtime ::_new ( cli_app , matches , config )
2017-06-08 21:35:15 +00:00
}
/// Builds the Runtime object using the given `config`.
2017-06-12 17:10:53 +00:00
pub fn with_configuration < C > ( cli_app : C , config : Option < Configuration > )
-> Result < Runtime < ' a > , RuntimeError >
2017-06-08 21:35:15 +00:00
where C : Clone + CliSpec < ' a > + InternalConfiguration
2017-06-12 17:10:53 +00:00
{
let matches = cli_app . clone ( ) . matches ( ) ;
Runtime ::_new ( cli_app , matches , config )
}
fn _new < C > ( mut cli_app : C , matches : ArgMatches < ' a > , config : Option < Configuration > )
-> Result < Runtime < ' a > , RuntimeError >
where C : Clone + CliSpec < ' a > + InternalConfiguration
2017-06-08 21:35:15 +00:00
{
use std ::io ::stdout ;
use clap ::Shell ;
2017-06-06 20:36:20 +00:00
if cli_app . enable_logging ( ) {
2017-08-26 13:27:13 +00:00
Runtime ::init_logger ( & matches , config . as_ref ( ) )
2017-06-03 23:34:21 +00:00
}
2016-03-25 18:42:10 +00:00
2016-10-28 07:42:44 +00:00
match matches . value_of ( Runtime ::arg_generate_compl ( ) ) {
Some ( shell ) = > {
debug! ( " Generating shell completion script, writing to stdout " ) ;
2016-11-02 12:22:58 +00:00
let shell = shell . parse ::< Shell > ( ) . unwrap ( ) ; // clap has our back here.
2017-06-03 23:34:21 +00:00
let appname = String ::from ( cli_app . name ( ) ) ;
cli_app . completions ( appname , shell , & mut stdout ( ) ) ;
2016-10-28 07:42:44 +00:00
} ,
_ = > debug! ( " Not generating shell completion script " ) ,
}
2017-06-08 21:35:15 +00:00
let rtp = get_rtp_match ( & matches ) ;
let storepath = matches . value_of ( Runtime ::arg_storepath_name ( ) )
2016-05-03 21:10:32 +00:00
. map_or_else ( | | {
2016-01-20 19:46:42 +00:00
let mut spath = rtp . clone ( ) ;
2016-01-28 19:05:43 +00:00
spath . push ( " store " ) ;
2016-01-20 19:46:42 +00:00
spath
2016-05-03 21:10:32 +00:00
} , PathBuf ::from ) ;
2016-03-05 11:36:11 +00:00
2017-06-25 14:58:25 +00:00
debug! ( " RTP path = {:?} " , rtp ) ;
debug! ( " Store path = {:?} " , storepath ) ;
2017-06-08 21:35:15 +00:00
let store_config = match config {
2016-05-14 17:47:34 +00:00
Some ( ref c ) = > c . store_config ( ) . cloned ( ) ,
None = > None ,
2016-03-05 17:42:59 +00:00
} ;
2017-08-26 13:27:13 +00:00
if matches . is_present ( Runtime ::arg_debugging_name ( ) ) {
debug! ( " Config: {:?} \n " , config ) ;
debug! ( " Store-config: {:?} \n " , store_config ) ;
2016-03-24 11:09:45 +00:00
}
2017-06-25 14:57:48 +00:00
let store_result = if cli_app . use_inmemory_fs ( ) {
Store ::new_with_backend ( storepath ,
store_config ,
Box ::new ( InMemoryFileAbstraction ::new ( ) ) )
} else {
Store ::new ( storepath , store_config )
} ;
store_result . map ( | store | {
2016-01-21 17:43:03 +00:00
Runtime {
cli_matches : matches ,
2017-06-08 21:35:15 +00:00
configuration : config ,
2016-01-21 17:43:03 +00:00
rtp : rtp ,
store : store ,
}
} )
2017-09-03 12:38:46 +00:00
. chain_err ( | | RuntimeErrorKind ::Instantiate )
2016-01-20 19:46:42 +00:00
}
2017-02-21 14:31:24 +00:00
///
/// Get a commandline-interface builder object from `clap`
///
/// This commandline interface builder object already contains some predefined interface flags:
/// * -v | --verbose for verbosity
/// * --debug for debugging
/// * -c <file> | --config <file> for alternative configuration file
/// * -r <path> | --rtp <path> for alternative runtimepath
/// * --store <path> for alternative store path
/// Each has the appropriate help text included.
///
/// The `appname` shall be "imag-<command>".
///
2016-01-20 19:46:42 +00:00
pub fn get_default_cli_builder ( appname : & ' a str ,
version : & ' a str ,
about : & ' a str )
2016-02-20 20:15:09 +00:00
-> App < ' a , ' a >
2016-01-20 19:46:42 +00:00
{
App ::new ( appname )
. version ( version )
. author ( " Matthias Beyer <mail@beyermatthias.de> " )
. about ( about )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_verbosity_name ( ) )
2016-01-20 19:46:42 +00:00
. short ( " v " )
. long ( " verbose " )
2017-08-26 13:27:13 +00:00
. help ( " Enables verbosity, can be used to set log level to one of 'trace', 'debug', 'info', 'warn' or 'error' " )
2016-01-20 19:46:42 +00:00
. required ( false )
2017-08-26 13:27:13 +00:00
. takes_value ( true )
. possible_values ( & [ " trace " , " debug " , " info " , " warn " , " error " ] )
. value_name ( " LOGLEVEL " ) )
2016-01-20 19:46:42 +00:00
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_debugging_name ( ) )
2016-01-20 19:46:42 +00:00
. long ( " debug " )
. help ( " Enables debugging output " )
. required ( false )
. takes_value ( false ) )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_no_color_output_name ( ) )
2016-08-02 09:39:01 +00:00
. long ( " no-color " )
. help ( " Disable color output " )
. required ( false )
. takes_value ( false ) )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_config_name ( ) )
2016-01-20 19:46:42 +00:00
. long ( " config " )
. help ( " Path to alternative config file " )
. required ( false )
. takes_value ( true ) )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_config_override_name ( ) )
2016-07-24 16:05:29 +00:00
. long ( " override-config " )
. help ( " Override a configuration settings. Use 'key=value' pairs, where the key is a path in the TOML configuration. The value must be present in the configuration and be convertible to the type of the configuration setting. If the argument does not contain a '=', it gets ignored. Setting Arrays and Tables is not yet supported. " )
. required ( false )
. takes_value ( true ) )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_runtimepath_name ( ) )
2016-01-20 19:46:42 +00:00
. long ( " rtp " )
. help ( " Alternative runtimepath " )
. required ( false )
. takes_value ( true ) )
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_storepath_name ( ) )
2016-01-20 19:46:42 +00:00
. long ( " store " )
. help ( " Alternative storepath. Must be specified as full path, can be outside of the RTP " )
. required ( false )
. takes_value ( true ) )
2016-03-21 09:19:03 +00:00
2016-08-06 15:43:14 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_editor_name ( ) )
2016-03-21 09:19:03 +00:00
. long ( " editor " )
. help ( " Set editor " )
. required ( false )
. takes_value ( true ) )
2016-10-28 07:42:44 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_generate_compl ( ) )
. long ( " generate-commandline-completion " )
. help ( " Generate the commandline completion for bash or zsh or fish " )
. required ( false )
. takes_value ( true )
. value_name ( " SHELL " )
. possible_values ( & [ " bash " , " fish " , " zsh " ] ) )
2017-08-26 13:27:13 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_logdest_name ( ) )
. long ( Runtime ::arg_logdest_name ( ) )
. help ( " Override the logging destinations from the configuration: values can be seperated by ',', a value of '-' marks the stderr output, everything else is expected to be a path " )
. required ( false )
. takes_value ( true )
. value_name ( " LOGDESTS " ) )
. arg ( Arg ::with_name ( Runtime ::arg_override_module_logging_setting_name ( ) )
. long ( Runtime ::arg_override_module_logging_setting_name ( ) )
. help ( " Override a module logging setting for one module. Format: <modulename>=<setting>=<value>, whereas <setting> is either 'enabled', 'level' or 'destinations' - This commandline argument is CURRENTLY NOT IMPLEMENTED " )
. multiple ( true )
. required ( false )
. takes_value ( true )
. value_name ( " SPEC " ) )
2017-08-26 21:00:48 +00:00
. arg ( Arg ::with_name ( Runtime ::arg_override_trace_logging_format ( ) )
. long ( Runtime ::arg_override_trace_logging_format ( ) )
. help ( " Override the logging format for the trace logging " )
. multiple ( false )
. required ( false )
. takes_value ( true )
. value_name ( " FMT " ) )
. arg ( Arg ::with_name ( Runtime ::arg_override_debug_logging_format ( ) )
. long ( Runtime ::arg_override_debug_logging_format ( ) )
. help ( " Override the logging format for the debug logging " )
. multiple ( false )
. required ( false )
. takes_value ( true )
. value_name ( " FMT " ) )
. arg ( Arg ::with_name ( Runtime ::arg_override_info_logging_format ( ) )
. long ( Runtime ::arg_override_info_logging_format ( ) )
. help ( " Override the logging format for the info logging " )
. multiple ( false )
. required ( false )
. takes_value ( true )
. value_name ( " FMT " ) )
. arg ( Arg ::with_name ( Runtime ::arg_override_warn_logging_format ( ) )
. long ( Runtime ::arg_override_warn_logging_format ( ) )
. help ( " Override the logging format for the warn logging " )
. multiple ( false )
. required ( false )
. takes_value ( true )
. value_name ( " FMT " ) )
. arg ( Arg ::with_name ( Runtime ::arg_override_error_logging_format ( ) )
. long ( Runtime ::arg_override_error_logging_format ( ) )
. help ( " Override the logging format for the error logging " )
. multiple ( false )
. required ( false )
. takes_value ( true )
. value_name ( " FMT " ) )
2016-01-20 19:46:42 +00:00
}
2017-02-21 14:31:24 +00:00
/// Get the argument names of the Runtime which are available
2016-08-06 15:43:14 +00:00
pub fn arg_names ( ) -> Vec < & 'static str > {
vec! [
Runtime ::arg_verbosity_name ( ) ,
Runtime ::arg_debugging_name ( ) ,
Runtime ::arg_no_color_output_name ( ) ,
Runtime ::arg_config_name ( ) ,
Runtime ::arg_config_override_name ( ) ,
Runtime ::arg_runtimepath_name ( ) ,
Runtime ::arg_storepath_name ( ) ,
Runtime ::arg_editor_name ( ) ,
]
}
2017-02-21 14:31:24 +00:00
/// Get the verbosity argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_verbosity_name ( ) -> & 'static str {
" verbosity "
}
2017-02-21 14:31:24 +00:00
/// Get the debugging argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_debugging_name ( ) -> & 'static str {
" debugging "
}
2017-02-21 14:31:24 +00:00
/// Get the argument name for no color output of the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_no_color_output_name ( ) -> & 'static str {
" no-color-output "
}
2017-02-21 14:31:24 +00:00
/// Get the config argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_config_name ( ) -> & 'static str {
" config "
}
2017-02-21 14:31:24 +00:00
/// Get the config-override argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_config_override_name ( ) -> & 'static str {
" config-override "
}
2017-02-21 14:31:24 +00:00
/// Get the runtime argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_runtimepath_name ( ) -> & 'static str {
" runtimepath "
}
2017-02-21 14:31:24 +00:00
/// Get the storepath argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_storepath_name ( ) -> & 'static str {
" storepath "
}
2017-02-21 14:31:24 +00:00
/// Get the editor argument name for the Runtime
2016-08-06 15:43:14 +00:00
pub fn arg_editor_name ( ) -> & 'static str {
" editor "
}
2017-02-21 14:31:24 +00:00
/// Get the argument name for generating the completion
2016-10-28 07:42:44 +00:00
pub fn arg_generate_compl ( ) -> & 'static str {
" generate-completion "
}
2017-09-02 08:29:10 +00:00
/// Extract the Store object from the Runtime object, destroying the Runtime object
///
/// # Warning
///
/// This function is for testing _only_! It can be used to re-build a Runtime object with an
/// alternative Store.
#[ cfg(feature = " testing " ) ]
pub fn extract_store ( self ) -> Store {
self . store
}
/// Re-set the Store object within
///
/// # Warning
///
/// This function is for testing _only_! It can be used to re-build a Runtime object with an
/// alternative Store.
#[ cfg(feature = " testing " ) ]
pub fn with_store ( mut self , s : Store ) -> Self {
self . store = s ;
self
}
2017-08-26 13:27:13 +00:00
/// Get the argument name for the logging destination
pub fn arg_logdest_name ( ) -> & 'static str {
" logging-destinations "
}
pub fn arg_override_module_logging_setting_name ( ) -> & 'static str {
" override-module-log-setting "
}
2017-08-26 21:00:48 +00:00
pub fn arg_override_trace_logging_format ( ) -> & 'static str {
" override-logging-format-trace "
}
pub fn arg_override_debug_logging_format ( ) -> & 'static str {
" override-logging-format-debug "
}
pub fn arg_override_info_logging_format ( ) -> & 'static str {
" override-logging-format-info "
}
pub fn arg_override_warn_logging_format ( ) -> & 'static str {
" override-logging-format-warn "
}
pub fn arg_override_error_logging_format ( ) -> & 'static str {
" override-logging-format-error "
}
2017-02-21 14:31:24 +00:00
/// Initialize the internal logger
2017-08-26 13:27:13 +00:00
fn init_logger ( matches : & ArgMatches , config : Option < & Configuration > ) {
2016-05-24 14:43:04 +00:00
use std ::env ::var as env_var ;
use env_logger ;
2016-01-20 19:46:42 +00:00
2016-05-24 14:43:04 +00:00
if env_var ( " IMAG_LOG_ENV " ) . is_ok ( ) {
env_logger ::init ( ) . unwrap ( ) ;
} else {
log ::set_logger ( | max_log_lvl | {
2017-08-26 13:27:13 +00:00
let logger = ImagLogger ::new ( matches , config )
. map_err_trace ( )
. unwrap_or_else ( | _ | exit ( 1 ) ) ;
max_log_lvl . set ( logger . global_loglevel ( ) . to_log_level_filter ( ) ) ;
debug! ( " Init logger with {} " , logger . global_loglevel ( ) ) ;
Box ::new ( logger )
2016-05-24 14:43:04 +00:00
} )
2017-06-03 12:43:02 +00:00
. map_err ( | e | panic! ( " Could not setup logger: {:?} " , e ) )
2016-05-24 14:43:04 +00:00
. ok ( ) ;
}
2016-01-20 19:46:42 +00:00
}
2017-02-21 14:31:24 +00:00
/// Get the verbosity flag value
2016-01-20 19:46:42 +00:00
pub fn is_verbose ( & self ) -> bool {
self . cli_matches . is_present ( " verbosity " )
}
2017-02-21 14:31:24 +00:00
/// Get the debugging flag value
2016-01-20 19:46:42 +00:00
pub fn is_debugging ( & self ) -> bool {
self . cli_matches . is_present ( " debugging " )
}
2017-02-21 14:31:24 +00:00
/// Get the runtimepath
2016-01-20 19:46:42 +00:00
pub fn rtp ( & self ) -> & PathBuf {
& self . rtp
}
2017-02-21 14:31:24 +00:00
/// Get the commandline interface matches
2016-01-20 19:46:42 +00:00
pub fn cli ( & self ) -> & ArgMatches {
& self . cli_matches
}
2017-02-21 14:31:24 +00:00
/// Get the configuration object
2016-03-26 18:50:13 +00:00
pub fn config ( & self ) -> Option < & Configuration > {
self . configuration . as_ref ( )
}
2017-02-21 14:31:24 +00:00
/// Get the store object
2016-01-20 19:46:42 +00:00
pub fn store ( & self ) -> & Store {
& self . store
}
2017-06-18 11:04:08 +00:00
/// Change the store backend to stdout
///
/// For the documentation on purpose and cavecats, have a look at the documentation of the
/// `Store::reset_backend()` function.
///
pub fn store_backend_to_stdio ( & mut self ) -> Result < ( ) , RuntimeError > {
use libimagstore ::file_abstraction ::stdio ::* ;
use libimagstore ::file_abstraction ::stdio ::mapper ::json ::JsonMapper ;
use std ::rc ::Rc ;
use std ::cell ::RefCell ;
2017-06-20 18:57:03 +00:00
let mut input = ::std ::io ::stdin ( ) ;
2017-06-18 11:04:08 +00:00
let output = ::std ::io ::stdout ( ) ;
let output = Rc ::new ( RefCell ::new ( output ) ) ;
let mapper = JsonMapper ::new ( ) ;
StdIoFileAbstraction ::new ( & mut input , output , mapper )
2017-09-03 12:38:46 +00:00
. chain_err ( | | RuntimeErrorKind ::Instantiate )
2017-06-18 11:04:08 +00:00
. and_then ( | backend | {
self . store
. reset_backend ( Box ::new ( backend ) )
2017-09-03 12:38:46 +00:00
. chain_err ( | | RuntimeErrorKind ::Instantiate )
2017-06-20 18:57:03 +00:00
} )
}
pub fn store_backend_to_stdout ( & mut self ) -> Result < ( ) , RuntimeError > {
use libimagstore ::file_abstraction ::stdio ::mapper ::json ::JsonMapper ;
use libimagstore ::file_abstraction ::stdio ::out ::StdoutFileAbstraction ;
use std ::rc ::Rc ;
use std ::cell ::RefCell ;
let output = ::std ::io ::stdout ( ) ;
let output = Rc ::new ( RefCell ::new ( output ) ) ;
let mapper = JsonMapper ::new ( ) ;
StdoutFileAbstraction ::new ( output , mapper )
2017-09-03 12:38:46 +00:00
. chain_err ( | | RuntimeErrorKind ::Instantiate )
2017-06-20 18:57:03 +00:00
. and_then ( | backend | {
self . store
. reset_backend ( Box ::new ( backend ) )
2017-09-03 12:38:46 +00:00
. chain_err ( | | RuntimeErrorKind ::Instantiate )
2017-06-18 11:04:08 +00:00
} )
}
2017-02-21 14:31:24 +00:00
/// Get a editor command object which can be called to open the $EDITOR
2016-03-21 09:19:03 +00:00
pub fn editor ( & self ) -> Option < Command > {
self . cli ( )
. value_of ( " editor " )
. map ( String ::from )
2017-06-03 12:43:46 +00:00
. or ( match self . configuration {
Some ( ref c ) = > c . editor ( ) . cloned ( ) ,
_ = > None ,
2016-03-21 09:19:03 +00:00
} )
. or ( env ::var ( " EDITOR " ) . ok ( ) )
. map ( Command ::new )
}
2016-01-20 19:46:42 +00:00
}
2017-06-08 21:35:15 +00:00
fn get_rtp_match < ' a > ( matches : & ArgMatches < ' a > ) -> PathBuf {
use std ::env ;
matches . value_of ( Runtime ::arg_runtimepath_name ( ) )
. map_or_else ( | | {
env ::var ( " HOME " )
. map ( PathBuf ::from )
. map ( | mut p | { p . push ( " .imag " ) ; p } )
. unwrap_or_else ( | _ | {
panic! ( " You seem to be $HOME-less. Please get a $HOME before using this \
software . We are sorry for you and hope you have some \
accommodation anyways . " );
} )
} , PathBuf ::from )
}
2016-07-24 16:06:01 +00:00
fn get_override_specs ( matches : & ArgMatches ) -> Vec < String > {
matches
. values_of ( " config-override " )
. map ( | values | {
values
. filter ( | s | {
let b = s . contains ( " = " ) ;
if ! b { warn! ( " override '{}' does not contain '=' - will be ignored! " , s ) ; }
b
} )
. map ( String ::from )
. collect ( )
} )
. unwrap_or ( vec! [ ] )
}