diff options
Diffstat (limited to 'src/paths')
-rw-r--r-- | src/paths/config.rs | 107 | ||||
-rw-r--r-- | src/paths/error.rs | 5 |
2 files changed, 74 insertions, 38 deletions
diff --git a/src/paths/config.rs b/src/paths/config.rs index 72c5da7..eea176f 100644 --- a/src/paths/config.rs +++ b/src/paths/config.rs @@ -1,6 +1,6 @@ use figment::{providers::Serialized, value, Figment, Metadata, Profile, Provider}; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; +use serde::{Deserialize, Deserializer, Serialize}; +use std::{convert::Infallible, path::PathBuf, str::FromStr}; #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] pub struct Config { @@ -8,9 +8,15 @@ pub struct Config { } impl Config { - pub fn from<T: Provider>(provider: T) -> figment::error::Result<Config> { + // Extract the configuration from any `Provider` + pub fn extract<T: Provider>(provider: T) -> figment::error::Result<Config> { Figment::from(provider).extract() } + + // Provide a default provider, a `Figment`. + pub fn figment() -> Figment { + Figment::from(Config::default()) + } } impl Provider for Config { @@ -19,25 +25,64 @@ impl Provider for Config { } fn data(&self) -> figment::error::Result<value::Map<Profile, value::Dict>> { - Serialized::defaults(Config::default()).data() + Serialized::defaults(Self::default()).data() } } -#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize)] pub struct PathEntry { pub path: PathBuf, pub hidden: bool, pub recurse: Option<usize>, } -impl std::str::FromStr for PathEntry { - type Err = std::convert::Infallible; +impl From<PathBuf> for PathEntry { + fn from(path: PathBuf) -> Self { + Self { + path, + ..Default::default() + } + } +} + +impl FromStr for PathEntry { + type Err = Infallible; fn from_str(s: &str) -> Result<Self, Self::Err> { - Ok(PathEntry { - path: s.to_string().into(), - ..Default::default() - }) + s.parse().map(PathBuf::into) + } +} + +impl<'de> Deserialize<'de> for PathEntry { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum Variants { + String(String), + Struct { + path: PathBuf, + #[serde(default)] + hidden: bool, + #[serde(default)] + recurse: Option<usize>, + }, + } + + match Variants::deserialize(deserializer)? { + Variants::String(s) => s.parse().map_err(serde::de::Error::custom), + Variants::Struct { + path, + hidden, + recurse, + } => Ok(Self { + path, + hidden, + recurse, + }), + } } } @@ -47,34 +92,15 @@ mod tests { use figment::providers::{Format, Serialized, Toml}; #[test] - fn defaults() { - figment::Jail::expect_with(|jail| { - jail.create_file( - "tmuxr.toml", - r#" - paths = [] - "#, - )?; - - let config: Config = Figment::from(Serialized::defaults(Config::default())) - .merge(Toml::file("tmuxr.toml")) - .extract()?; - - assert_eq!(config, Config::default()); - - Ok(()) - }); - } - - #[test] - fn custom() { + fn test_extract() { figment::Jail::expect_with(|jail| { jail.create_file( "tmuxr.toml", r#" paths = [ - "/tmp/projects", - { path = "/tmp/tmuxr/test/other_projects", recursive = false, hidden = true }, + "/path/to/projects", + { path = "/path/to/other_projects", recurse = 1, hidden = true }, + { path = "/path/to/another_project", recurse = 0 }, ] "#, )?; @@ -88,15 +114,20 @@ mod tests { Config { paths: Vec::from([ PathEntry { - path: "/tmp/tmuxr/test/project_1".into(), + path: "/path/to/projects".into(), hidden: false, recurse: None, }, PathEntry { - path: "/tmp/tmuxr/test/projects".into(), - hidden: false, + path: "/path/to/other_projects".into(), + hidden: true, recurse: Some(1), - } + }, + PathEntry { + path: "/path/to/another_project".into(), + hidden: false, + recurse: Some(0), + }, ]), } ); diff --git a/src/paths/error.rs b/src/paths/error.rs index 08fdc89..3a5a580 100644 --- a/src/paths/error.rs +++ b/src/paths/error.rs @@ -1,5 +1,10 @@ +pub type Result<T> = std::result::Result<T, Error>; + #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Config error: {0}")] + Config(#[from] figment::error::Error), + #[error("Ignore error: {0}")] Ignore(#[from] ignore::Error), } |