diff options
Diffstat (limited to 'src/finder.rs')
-rw-r--r-- | src/finder.rs | 93 |
1 files changed, 65 insertions, 28 deletions
diff --git a/src/finder.rs b/src/finder.rs index db92c83..c5b5bd5 100644 --- a/src/finder.rs +++ b/src/finder.rs @@ -1,8 +1,9 @@ +use figment::Provider; use std::{ + ffi::OsStr, io::Write, ops::{Deref, DerefMut}, os::unix::prelude::OsStrExt, - path::PathBuf, process::{Child, Command, Output, Stdio}, }; @@ -12,41 +13,57 @@ pub use error::{Error, Result}; mod config; mod error; -pub struct Finder(Child); +pub struct Finder { + program: String, + args: Vec<String>, +} impl Finder { - pub fn new(config: &Config) -> Result<Self> { - Command::new(&config.program) - .args(&config.args) + pub fn new() -> Result<Self> { + Self::from_provider(Config::figment()) + } + + /// Extract `Config` from `provider` to construct new `Finder` + pub fn from_provider<T: Provider>(provider: T) -> Result<Self> { + Config::extract(&provider) + .map(|config| Finder { + program: config.program, + args: config.args, + }) + .map_err(Into::into) + } + + pub fn spawn(self) -> Result<FinderChild> { + Command::new(self.program) + .args(self.args) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() - .map(Into::into) + .map(FinderChild) .map_err(Into::into) } +} - pub fn into_inner(self) -> Child { - self.0 - } +pub struct FinderChild(Child); - pub fn write_path_buf_vectored<V>(&mut self, directories: V) -> Result<()> +impl FinderChild { + pub fn find<V, I>(mut self, items: V) -> Result<Output> where - V: IntoIterator<Item = PathBuf>, + V: IntoIterator<Item = I>, + I: AsRef<OsStr>, { let stdin = self.stdin.as_mut().ok_or(Error::Stdin)?; - directories.into_iter().try_for_each(|path_buf| { - stdin - .write_all(path_buf.into_os_string().as_bytes()) - .map_err(From::from) - }) - } - pub fn wait_with_output(self) -> Result<Output> { - self.into_inner().wait_with_output().map_err(From::from) + items.into_iter().try_for_each(|item| -> Result<()> { + stdin.write_all(item.as_ref().as_bytes())?; + stdin.write_all("\n".as_bytes()).map_err(From::from) + })?; + + self.0.wait_with_output().map_err(Into::into) } } -impl Deref for Finder { +impl Deref for FinderChild { type Target = Child; fn deref(&self) -> &Self::Target { @@ -54,20 +71,40 @@ impl Deref for Finder { } } -impl DerefMut for Finder { +impl DerefMut for FinderChild { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl From<Child> for Finder { - fn from(value: Child) -> Self { - Self(value) +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_output() { + let items = Vec::from(["item1"]); + + let finder = Finder { + program: "fzf".into(), + args: ["-1".into()].into(), + }; + + let selected = finder.spawn().unwrap().find(items).unwrap().stdout; + assert_eq!(selected.as_slice(), "item1\n".as_bytes()) } -} -impl From<Finder> for Child { - fn from(value: Finder) -> Child { - value.0 + #[test] + #[ignore] + fn test_selection() { + let items = Vec::from(["item1", "item2", "item3", "item4"]); + + let finder = Finder { + program: "fzf".into(), + args: [].into(), + }; + + let selected = finder.spawn().unwrap().find(items).unwrap().stdout; + assert_eq!(selected.as_slice(), "item1\n".as_bytes()) } } |