use crate::shell_interface::{ build_command_from_shell_command, CommandOutput, CommandResult, ExitStatus, ShellCommand, ShellInterface, StartError, }; use std::env::VarError; use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, io}; pub trait Environment { fn args_os(&self) -> Vec; fn var_os(&self, key: K) -> Option where K: AsRef; fn var(&self, key: K) -> Result where K: AsRef, { self .var_os(key) .ok_or(VarError::NotPresent) .and_then(|s| s.into_string().map_err(VarError::NotUnicode)) } fn set_var(&mut self, key: K, value: V) where K: AsRef, V: AsRef; fn get_home_directory(&self) -> Option; fn read_line(&mut self) -> Result; } #[derive(Debug, Default)] pub struct Prod; impl Environment for Prod { fn args_os(&self) -> Vec { env::args_os().collect() } fn var_os(&self, key: K) -> Option where K: AsRef { env::var_os(key) } fn var(&self, key: K) -> Result where K: AsRef, { env::var(key) } fn set_var(&mut self, key: K, value: V) where K: AsRef, V: AsRef, { env::set_var(key, value); } fn get_home_directory(&self) -> Option { homedir::my_home().ok().flatten() } fn read_line(&mut self) -> Result { let mut buffer = String::new(); io::stdin().read_line(&mut buffer)?; Ok(buffer.trim().to_string()) } } impl ShellInterface for Prod { fn run_command(&mut self, command: ShellCommand) -> CommandResult { CommandResult { result: build_command_from_shell_command(&command) .status() .map(ExitStatus::from) .map_err(StartError::from), command, } } fn collect_command_output( &mut self, command: ShellCommand, ) -> CommandResult { CommandResult { result: build_command_from_shell_command(&command) .output() .map(CommandOutput::from) .map_err(StartError::from), command, } } }