use derive_getters::Getters;
use log::{debug, error};
use crate::error::VsmRuntimeFault;
#[derive(Debug, Getters)]
pub struct CommandExecutor {
user_shell: String,
}
impl Default for CommandExecutor {
fn default() -> Self {
Self::new()
}
}
impl CommandExecutor {
#[must_use]
pub fn new() -> Self {
std::env::var("SHELL").map_or_else(
|_| Self {
user_shell: "/bin/sh".to_owned(),
},
|user_shell| Self { user_shell },
)
}
pub fn is_installed(&self, program: &str) -> bool {
let cmd = format!("command -v {}", program);
debug!("Executing {}", &cmd);
let exit_status = std::process::Command::new(&self.user_shell)
.arg("-c")
.arg(cmd)
.stdout(std::process::Stdio::null())
.status();
match exit_status {
Ok(status) => status.success(),
Err(e) => {
error!("{}", e.to_string());
false
}
}
}
pub fn open_editor_with_session(
&self,
vim_variant: &String,
shell_command: &String,
session_file: &String,
) -> Result<(), VsmRuntimeFault> {
debug!(
"Executing: {} {} {}",
vim_variant, shell_command, session_file
);
let spawned_process = std::process::Command::new(vim_variant)
.args(shell_command.split_whitespace())
.arg(session_file)
.spawn();
match spawned_process {
Ok(mut process) => match process.wait() {
Ok(_) => Ok(()),
Err(e) => Err(VsmRuntimeFault::CommandExecutor { msg: e.to_string() }),
},
Err(e) => Err(VsmRuntimeFault::CommandExecutor { msg: e.to_string() }),
}
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::CommandExecutor;
#[test]
fn test_is_program_installed_with_installed_program() {
let shell = CommandExecutor::default();
let programs = [
"ls", "cat", "less", "more", "man", "mkdir", "cp", "sh", "bash",
];
for program in programs {
assert_eq!(shell.is_installed(program), true);
}
}
#[test]
fn test_is_program_installed_with_non_existent_program() {
let shell = CommandExecutor::new();
assert_eq!(shell.is_installed("non_existant_program"), false);
}
}