diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/cli.rs | 15 | ||||
-rw-r--r-- | src/config.rs | 109 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 15 | ||||
-rw-r--r-- | src/search.rs | 40 | ||||
-rw-r--r-- | src/search/entry.rs | 14 |
8 files changed, 67 insertions, 131 deletions
@@ -2447,6 +2447,7 @@ dependencies = [ "tempfile", "thiserror", "tmux_interface", + "toml", "tracing", "tracing-subscriber", ] @@ -31,6 +31,7 @@ tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } [dev-dependencies] tempfile = "3.3.0" +toml = "0.5.9" [features] default = ["git", "preview"] @@ -1,10 +1,9 @@ use clap::{Args, Parser}; -use figment::{value, Metadata, Profile, Provider}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use tracing::{metadata::LevelFilter, Level}; -use crate::{config::Entry, Config}; +use crate::{config::SearchEntryConfig, Config}; /// Tool for listing project directories. #[derive(Debug, Clone, Default, Parser, Serialize, Deserialize)] @@ -48,23 +47,13 @@ pub struct Projects { git: bool, } -impl Provider for Projects { - fn metadata(&self) -> Metadata { - Metadata::named("Projectr cli provider") - } - - fn data(&self) -> figment::error::Result<value::Map<Profile, value::Dict>> { - Config::from(self.to_owned()).data() - } -} - impl From<Projects> for Config { fn from(value: Projects) -> Self { let paths = value .paths .iter() .cloned() - .map(|path_buf| Entry { + .map(|path_buf| SearchEntryConfig { path_buf, hidden: value.hidden, max_depth: value.max_depth, diff --git a/src/config.rs b/src/config.rs index e73b7e1..cc1f28f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,3 @@ -use figment::{providers::Serialized, value, Figment, Metadata, Profile, Provider}; use serde::{Deserialize, Serialize}; use std::{convert::Infallible, path::PathBuf, str::FromStr}; @@ -6,34 +5,12 @@ use std::{convert::Infallible, path::PathBuf, str::FromStr}; #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] pub struct Config { #[serde_as(as = "Vec<serde_with::PickFirst<(_, serde_with::DisplayFromStr)>>")] - pub(crate) paths: Vec<Entry>, -} - -impl 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 { - fn metadata(&self) -> Metadata { - Metadata::named("Projectr config") - } - - fn data(&self) -> figment::error::Result<value::Map<Profile, value::Dict>> { - Serialized::defaults(self).data() - } + pub paths: Vec<SearchEntryConfig>, } #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] #[serde(default)] -pub struct Entry { +pub struct SearchEntryConfig { pub path_buf: PathBuf, pub hidden: bool, pub max_depth: Option<usize>, @@ -42,7 +19,7 @@ pub struct Entry { pub git: bool, } -impl Entry { +impl SearchEntryConfig { pub fn new(path_buf: PathBuf) -> Self { Self { path_buf, @@ -51,13 +28,13 @@ impl Entry { } } -impl From<PathBuf> for Entry { +impl From<PathBuf> for SearchEntryConfig { fn from(path_buf: PathBuf) -> Self { Self::new(path_buf) } } -impl FromStr for Entry { +impl FromStr for SearchEntryConfig { type Err = Infallible; fn from_str(s: &str) -> Result<Self, Self::Err> { @@ -71,54 +48,44 @@ impl FromStr for Entry { #[cfg(test)] mod tests { use super::*; - use figment::providers::{Format, Serialized, Toml}; use pretty_assertions::assert_eq; #[test] fn test_extract_config() { - figment::Jail::expect_with(|jail| { - jail.create_file( - "file.toml", - r#" - paths = [ - "/path/to/projects", - { path_buf = "/path/to/other_projects", hidden = true, max_depth = 1 }, - { path_buf = "/path/to/another_project", max_depth = 0 } - ] - "#, - )?; - - let config: Config = Figment::from(Serialized::defaults(Config::default())) - .merge(Toml::file("file.toml")) - .extract()?; + let s = r#" + paths = [ + "/path/to/projects", + { path_buf = "/path/to/other_projects", hidden = true, max_depth = 1 }, + { path_buf = "/path/to/another_project", max_depth = 0 } + ] + "#; - assert_eq!( - config, - Config { - paths: Vec::from([ - Entry { - path_buf: "/path/to/projects".into(), - hidden: false, - max_depth: None, - ..Default::default() - }, - Entry { - path_buf: "/path/to/other_projects".into(), - hidden: true, - max_depth: Some(1), - ..Default::default() - }, - Entry { - path_buf: "/path/to/another_project".into(), - hidden: false, - max_depth: Some(0), - ..Default::default() - }, - ]), - } - ); + let config: Config = toml::from_str(s).unwrap(); - Ok(()) - }); + assert_eq!( + config, + Config { + paths: Vec::from([ + SearchEntryConfig { + path_buf: "/path/to/projects".into(), + hidden: false, + max_depth: None, + ..Default::default() + }, + SearchEntryConfig { + path_buf: "/path/to/other_projects".into(), + hidden: true, + max_depth: Some(1), + ..Default::default() + }, + SearchEntryConfig { + path_buf: "/path/to/another_project".into(), + hidden: false, + max_depth: Some(0), + ..Default::default() + }, + ]), + } + ); } } diff --git a/src/error.rs b/src/error.rs index f22cff2..d923642 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,9 +3,6 @@ pub type Result<T> = std::result::Result<T, Error>; #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Config(#[from] figment::error::Error), - - #[error(transparent)] Ignore(#[from] ignore::Error), #[error(transparent)] diff --git a/src/main.rs b/src/main.rs index 877cfaa..35ae66d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,17 @@ use anyhow::{Context, Result}; use clap::Parser; -use figment::providers::{Env, Format, Toml}; -use projectr::{search::Search, Cli, Config}; +use figment::{ + providers::{Env, Format, Serialized, Toml}, + Figment, +}; +use projectr::{project::ProjectItem, search::Search, Cli, Config}; #[tracing::instrument] fn main() -> Result<()> { let cli = Cli::parse(); - let config = Config::figment() - .merge(&cli.projects) + let config: Config = Figment::new() + .merge(Figment::from(Serialized::defaults(&cli.projects))) .merge(Toml::file("projectr.toml")) .merge(Env::prefixed("PROJECTR_")) .extract() @@ -25,9 +28,7 @@ fn main() -> Result<()> { #[tracing::instrument] pub fn run(config: &Config) -> Result<()> { - let mut projects: Vec<_> = Search::from_provider(config) - .context("Failed to extract paths config")? - .collect(); + let mut projects: Vec<ProjectItem> = Search::from(config.paths.to_owned()).collect(); projects.sort_unstable_by_key(|p| *p.timestamp()); diff --git a/src/search.rs b/src/search.rs index 6249da4..fc794ea 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,14 +1,13 @@ -use figment::Provider; -use std::vec::IntoIter; - -use self::entry::EntryIter; -use crate::{config::Entry, project::ProjectItem, Config, Result}; +use self::entry::SearchEntry; +use crate::{config::SearchEntryConfig, project::ProjectItem}; pub mod entry; +type EntryIter = std::vec::IntoIter<SearchEntryConfig>; + pub struct Search { - iter: IntoIter<Entry>, - curr: Option<EntryIter>, + iter: EntryIter, + curr: Option<SearchEntry>, } impl std::fmt::Debug for Search { @@ -19,28 +18,9 @@ impl std::fmt::Debug for Search { } } -impl Search { - pub fn new() -> Result<Self> { - Self::from_provider(Config::figment()) - } - - /// Extract `Config` from `provider` to construct new `Paths` - pub fn from_provider<T: Provider>(provider: T) -> Result<Self> { - Config::extract(&provider) - .map_err(Into::into) - .map(|config| config.paths.into()) - } -} - -impl From<Config> for Search { - fn from(config: Config) -> Self { - config.paths.into() - } -} - impl<T> From<T> for Search where - T: IntoIterator<IntoIter = IntoIter<Entry>>, + T: IntoIterator<IntoIter = EntryIter>, { fn from(value: T) -> Self { Self { @@ -86,17 +66,17 @@ mod tests { let project4 = temp_dir.join("subdir/project4"); let paths = Search::from(Vec::from([ - Entry { + SearchEntryConfig { path_buf: project_dir.to_owned(), max_depth: Some(1), ..Default::default() }, - Entry { + SearchEntryConfig { path_buf: project3.to_owned(), max_depth: Some(0), ..Default::default() }, - Entry { + SearchEntryConfig { path_buf: project4.to_owned(), max_depth: Some(0), ..Default::default() diff --git a/src/search/entry.rs b/src/search/entry.rs index 9e58962..eb845e1 100644 --- a/src/search/entry.rs +++ b/src/search/entry.rs @@ -2,18 +2,18 @@ use ignore::{Walk, WalkBuilder}; use tracing::error; use crate::{ - config::Entry, + config::SearchEntryConfig, project::{path::PathMatcher, ProjectParser, ProjectParserGroup}, search::ProjectItem, }; -pub struct EntryIter { +pub struct SearchEntry { parsers: ProjectParserGroup, iter: Walk, } -impl EntryIter { - fn new(config: &Entry) -> Self { +impl SearchEntry { + fn new(config: &SearchEntryConfig) -> Self { let iter = WalkBuilder::new(&config.path_buf) .standard_filters(true) .max_depth(config.max_depth) @@ -35,13 +35,13 @@ impl EntryIter { } } -impl From<Entry> for EntryIter { - fn from(config: Entry) -> Self { +impl From<SearchEntryConfig> for SearchEntry { + fn from(config: SearchEntryConfig) -> Self { Self::new(&config) } } -impl Iterator for EntryIter { +impl Iterator for SearchEntry { type Item = ProjectItem; fn next(&mut self) -> Option<Self::Item> { |