From 192b3b588553bf461777068e1ae4157ed88b238a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 5 Mar 2016 12:30:40 +0100 Subject: [PATCH 1/3] Switch to TOML as configuration language behind the scenes --- libimagrt/Cargo.toml | 2 +- libimagrt/src/configuration.rs | 57 +++++++++++++++++++++++++++------- libimagrt/src/lib.rs | 2 +- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/libimagrt/Cargo.toml b/libimagrt/Cargo.toml index 276295fb..655546b9 100644 --- a/libimagrt/Cargo.toml +++ b/libimagrt/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Matthias Beyer "] [dependencies] clap = "2.1.1" -config = "0.1.3" +toml = "0.1.27" log = "0.3.4" xdg-basedir = "0.2.2" itertools = "0.4.6" diff --git a/libimagrt/src/configuration.rs b/libimagrt/src/configuration.rs index 79ff6ee5..e46da970 100644 --- a/libimagrt/src/configuration.rs +++ b/libimagrt/src/configuration.rs @@ -2,8 +2,7 @@ use std::default::Default; use std::path::PathBuf; use std::result::Result as RResult; -pub use config::types::Config; -pub use config::reader::from_file; +use toml::{Parser, Value}; /** * Errors which are related to configuration-file loading @@ -133,9 +132,9 @@ impl Configuration { */ pub fn new(rtp: &PathBuf) -> Result { fetch_config(&rtp).map(|cfg| { - let verbosity = cfg.lookup_boolean("verbosity").unwrap_or(false); - let editor = cfg.lookup_str("editor").map(String::from); - let editor_opts = String::from(cfg.lookup_str("editor-opts").unwrap_or("")); + let verbosity = get_verbosity(&cfg); + let editor = get_editor(&cfg); + let editor_opts = get_editor_opts(&cfg); debug!("Building configuration"); debug!(" - verbosity : {:?}", verbosity); @@ -152,13 +151,41 @@ impl Configuration { } +fn get_verbosity(v: &Value) -> bool { + match v { + &Value::Table(ref t) => t.get("verbose") + .map(|v| match v { &Value::Boolean(b) => b, _ => false, }) + .unwrap_or(false), + _ => false, + } +} + +fn get_editor(v: &Value) -> Option { + match v { + &Value::Table(ref t) => t.get("editor") + .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, }), + _ => None, + } +} + +fn get_editor_opts(v: &Value) -> String { + match v { + &Value::Table(ref t) => t.get("editor-opts") + .and_then(|v| match v { &Value::String(ref s) => Some(s.clone()), _ => None, }) + .unwrap_or(String::new()), + _ => String::new(), + } +} + /** * Helper to fetch the config file * * Tests several variants for the config file path and uses the first one which works. */ -fn fetch_config(rtp: &PathBuf) -> Result { +fn fetch_config(rtp: &PathBuf) -> Result { use std::env; + use std::fs::File; + use std::io::Read; use xdg_basedir; use itertools::Itertools; @@ -184,14 +211,20 @@ fn fetch_config(rtp: &PathBuf) -> Result { .flatten() .filter(|path| path.exists()) .map(|path| { - from_file(&path) - .map_err(|e| { - ConfigError::new(ConfigErrorKind::ConfigParsingFailed, Some(Box::new(e))) - }) + let content = { + let mut s = String::new(); + let mut f = File::open(path); + if f.is_err() { + } + let mut f = f.unwrap(); + f.read_to_string(&mut s); + s + }; + Parser::new(&content[..]).parse() }) - .filter(|loaded| loaded.is_ok()) + .filter(|loaded| loaded.is_some()) .nth(0) - .map(|inner| inner.unwrap()) + .map(|inner| Value::Table(inner.unwrap())) .ok_or(ConfigError::new(ConfigErrorKind::NoConfigFileFound, None)) } diff --git a/libimagrt/src/lib.rs b/libimagrt/src/lib.rs index 9e81f088..4db24dc5 100644 --- a/libimagrt/src/lib.rs +++ b/libimagrt/src/lib.rs @@ -3,7 +3,7 @@ #[cfg(unix)] extern crate xdg_basedir; extern crate clap; -extern crate config; +extern crate toml; extern crate libimagstore; extern crate libimagutil; From 21d5d32d50de52b34f56ab58f384b866ade7537a Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 5 Mar 2016 12:36:11 +0100 Subject: [PATCH 2/3] Configuration: Provide config() getter, remove the default() implementation therefor --- libimagrt/src/configuration.rs | 26 ++++++++++---------------- libimagrt/src/runtime.rs | 11 ++++++++++- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/libimagrt/src/configuration.rs b/libimagrt/src/configuration.rs index e46da970..7eb8e30f 100644 --- a/libimagrt/src/configuration.rs +++ b/libimagrt/src/configuration.rs @@ -1,4 +1,3 @@ -use std::default::Default; use std::path::PathBuf; use std::result::Result as RResult; @@ -103,6 +102,11 @@ pub type Result = RResult; #[derive(Debug)] pub struct Configuration { + /** + * The plain configuration object for direct access if necessary + */ + config: Value, + /** * The verbosity the program should run with */ @@ -142,6 +146,7 @@ impl Configuration { debug!(" - editor-opts: {}", editor_opts); Configuration { + config: cfg, verbosity: verbosity, editor: editor, editor_opts: editor_opts, @@ -149,6 +154,10 @@ impl Configuration { }) } + pub fn config(&self) -> &Value { + &self.config + } + } fn get_verbosity(v: &Value) -> bool { @@ -228,18 +237,3 @@ fn fetch_config(rtp: &PathBuf) -> Result { .ok_or(ConfigError::new(ConfigErrorKind::NoConfigFileFound, None)) } -impl Default for Configuration { - - /** - * Get a default configuration object - */ - fn default() -> Configuration { - Configuration { - verbosity: false, - editor: Some(String::from("nano")), - editor_opts: String::from(""), - } - } - -} - diff --git a/libimagrt/src/runtime.rs b/libimagrt/src/runtime.rs index 23383b1d..c5b7412f 100644 --- a/libimagrt/src/runtime.rs +++ b/libimagrt/src/runtime.rs @@ -32,6 +32,7 @@ impl<'a> Runtime<'a> { */ pub fn new(cli_spec: App<'a, 'a>) -> Result, RuntimeError> { use std::env; + use std::error::Error; let matches = cli_spec.get_matches(); let rtp : PathBuf = matches.value_of("runtimepath") @@ -51,10 +52,18 @@ impl<'a> Runtime<'a> { spath.push("store"); spath }); + + let cfg = Configuration::new(&rtp); + if cfg.is_err() { + let cause : Option> = Some(Box::new(cfg.err().unwrap())); + return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause)); + } + let cfg = cfg.unwrap(); + Store::new(storepath).map(|store| { Runtime { cli_matches: matches, - configuration: Configuration::new(&rtp).unwrap_or(Configuration::default()), + configuration: cfg, rtp: rtp, store: store, } From 2fa10067fbbb33dfa7ff8c1269a8b22d85bdad7c Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Sat, 5 Mar 2016 13:01:09 +0100 Subject: [PATCH 3/3] Configuration is optional --- libimagrt/src/configuration.rs | 2 -- libimagrt/src/runtime.rs | 20 ++++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libimagrt/src/configuration.rs b/libimagrt/src/configuration.rs index 7eb8e30f..f5f06662 100644 --- a/libimagrt/src/configuration.rs +++ b/libimagrt/src/configuration.rs @@ -16,7 +16,6 @@ pub mod error { */ #[derive(Clone, Debug, PartialEq)] pub enum ConfigErrorKind { - ConfigNotFound, ConfigParsingFailed, NoConfigFileFound, } @@ -54,7 +53,6 @@ pub mod error { */ pub fn as_str(e: &ConfigError) -> &'static str { match e.kind() { - ConfigErrorKind::ConfigNotFound => "Config not found", ConfigErrorKind::ConfigParsingFailed => "Config parsing failed", ConfigErrorKind::NoConfigFileFound => "No config file found", } diff --git a/libimagrt/src/runtime.rs b/libimagrt/src/runtime.rs index c5b7412f..a1cbc63d 100644 --- a/libimagrt/src/runtime.rs +++ b/libimagrt/src/runtime.rs @@ -15,7 +15,7 @@ use libimagstore::store::Store; pub struct Runtime<'a> { rtp: PathBuf, - configuration: Configuration, + configuration: Option, cli_matches: ArgMatches<'a>, store: Store, } @@ -34,6 +34,8 @@ impl<'a> Runtime<'a> { use std::env; use std::error::Error; + use configuration::error::ConfigErrorKind; + let matches = cli_spec.get_matches(); let rtp : PathBuf = matches.value_of("runtimepath") .map(PathBuf::from) @@ -54,11 +56,17 @@ impl<'a> Runtime<'a> { }); let cfg = Configuration::new(&rtp); - if cfg.is_err() { - let cause : Option> = Some(Box::new(cfg.err().unwrap())); - return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause)); - } - let cfg = cfg.unwrap(); + let cfg = if cfg.is_err() { + let e = cfg.err().unwrap(); + if e.kind() != ConfigErrorKind::NoConfigFileFound { + let cause : Option> = Some(Box::new(e)); + return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, cause)); + } else { + None + } + } else { + Some(cfg.unwrap()) + }; Store::new(storepath).map(|store| { Runtime {