use crate::errors::{Error, Result}; use std::ffi::OsStr; use std::fmt::Display; use std::io::Write; use std::process::{Command, Stdio}; use std::str::FromStr; /// Sends each item as a line to stdin to the `fzf` command and returns the selected item's string /// representation as output pub fn select( input: impl IntoIterator, extra: impl IntoIterator, ) -> Result> where O: FromStr, I: Display, Error: From<::Err>, S: AsRef, { let mut command = Command::new("fzf"); let mut child = command .args(extra) .arg("--read0") .stderr(Stdio::inherit()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; // unwrap: this can never fail let child_in = child.stdin.as_mut().unwrap(); for item in input.into_iter() { write!(child_in, "{item}\0")?; } let output = child.wait_with_output()?; if output.stdout.is_empty() { Ok(None) } else { Ok(Some(String::from_utf8(output.stdout)?.parse()?)) } }