diff options
author | Toby Vincent <tobyv@tobyvin.dev> | 2024-02-24 18:09:58 -0600 |
---|---|---|
committer | Toby Vincent <tobyv@tobyvin.dev> | 2024-02-24 18:09:58 -0600 |
commit | 04814c4996140871674d7ce5552f55d9ba07615a (patch) | |
tree | 804e57beed1a4d3c2b8908523c0453f4655b5bbd /src/config.rs | |
parent | 12cc1358ad636c194a2464561939ff72fb8aaa9c (diff) |
feat!: remove tmux functionalilty and more async
Diffstat (limited to 'src/config.rs')
-rw-r--r-- | src/config.rs | 104 |
1 files changed, 53 insertions, 51 deletions
diff --git a/src/config.rs b/src/config.rs index c5f6db5..44d500e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, str::FromStr, sync::atomic::AtomicBool}; +use std::{collections::HashSet, path::PathBuf, str::FromStr, sync::atomic::AtomicBool}; use clap::Parser; #[derive(Debug, Clone, Parser)] @@ -11,72 +11,74 @@ pub struct Config { #[arg(short, long)] pub resolve: bool, - /// include host in output - #[arg(short, long)] - pub include: Vec<sshr::Host>, + /// include <NAME>. If <NAME> is a valid path or '-', hosts with be read from the file or + /// stdin, respectivly. + #[arg(short, long, id = "NAME")] + pub include: Vec<IncludeExclude>, - /// include lines from file, use '-' for stdin - #[arg(short = 'I', long)] - pub include_file: Vec<FileOrStdin>, + /// include <NAME>. If <NAME> is a valid path or '-', hosts with be read from the file or + /// stdin, respectivly. + #[arg(short, long, id = "HOST")] + pub exclude: Vec<IncludeExclude>, +} - /// exclude host from output - #[arg(short, long)] - pub exclude: Vec<sshr::Host>, +impl Config { + pub fn included(&self) -> std::io::Result<HashSet<String>> { + Self::collect_values(&self.include) + } - /// include lines from file, use '-' for stdin - #[arg(short = 'E', long)] - pub exclude_file: Vec<FileOrStdin>, + pub fn excluded(&self) -> std::io::Result<HashSet<String>> { + Self::collect_values(&self.exclude) + } + + fn collect_values(values: &[IncludeExclude]) -> std::io::Result<HashSet<String>> { + use std::io::BufRead; + values.iter().try_fold(HashSet::new(), |mut acc, item| { + match item { + IncludeExclude::Stdin => { + acc.extend(std::io::stdin().lock().lines().map_while(Result::ok)) + } + IncludeExclude::File(filepath) => acc.extend( + std::io::BufReader::new(std::fs::File::open(filepath)?) + .lines() + .map_while(Result::ok), + ), + IncludeExclude::Item(s) => { + acc.insert(s.to_owned()); + } + } + Ok(acc) + }) + } } static READ_STDIN: AtomicBool = AtomicBool::new(false); #[derive(Debug, Clone)] -pub enum FileOrStdin { +pub enum IncludeExclude { Stdin, + Item(String), File(PathBuf), } -impl FileOrStdin { - pub fn hosts(self) -> Result<Vec<sshr::Host>, anyhow::Error> { - use std::io::Read; - let mut buf = String::new(); - let _ = self.into_reader()?.read_to_string(&mut buf)?; - buf.lines() - .map(|s| s.trim_end().parse()) - .collect::<Result<Vec<_>, _>>() - .map_err(|e| anyhow::format_err!("{e}")) - } - - pub fn into_reader(&self) -> Result<impl std::io::Read, anyhow::Error> { - let input: Box<dyn std::io::Read + 'static> = match &self { - Self::Stdin => Box::new(std::io::stdin()), - Self::File(filepath) => { - let f = std::fs::File::open(filepath)?; - Box::new(f) - } - }; - Ok(input) - } -} - -impl FromStr for FileOrStdin { +impl FromStr for IncludeExclude { type Err = std::io::Error; fn from_str(s: &str) -> Result<Self, Self::Err> { - match s { - "-" => { - if READ_STDIN.load(std::sync::atomic::Ordering::Acquire) { - return Err(std::io::Error::new( - std::io::ErrorKind::Other, - "stdin argument used more than once", - )); - } - READ_STDIN.store(true, std::sync::atomic::Ordering::SeqCst); - Ok(Self::Stdin) + if s == "-" { + if READ_STDIN.load(std::sync::atomic::Ordering::Acquire) { + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "stdin argument used more than once", + )); + } + READ_STDIN.store(true, std::sync::atomic::Ordering::SeqCst); + Ok(Self::Stdin) + } else { + match PathBuf::from_str(s) { + Ok(path) if path.exists() => Ok(Self::File(path)), + _ => Ok(Self::Item(s.to_owned())), } - path => PathBuf::from_str(path) - .map(Self::File) - .map_err(|_| unreachable!()), } } } |