Lines
98.53 %
Functions
66.67 %
Branches
100 %
use std::env;
mod bash;
mod fish;
mod pwsh;
mod zsh;
/// Shell integration script
#[derive(Debug, PartialEq)]
pub struct Shell {
/// Alias to use for the shell function
alias: String,
/// Integration script template
script: String,
}
impl Shell {
/// Compile the shell integration template
pub fn compile_script(&self) -> String {
self.script.replace("{alias}", &self.alias)
/// Create a new shell integration script
pub fn new(alias: String, script: String) -> Self {
Shell { alias, script }
/// Return the shell integration script for shell given in `hint`. If `hint` is
/// `None`, try to detect the current shell. Use `bash` as fallback.
///
/// `alias` is the name of the shell function to use in the integration script.
/// # Errors
/// If `hint` is `None` and the `SHELL` environment variable is not set, an
/// error is returned.
pub fn initialize(alias: String, hint: &Option<String>) -> Result<Shell, &'static str> {
let shell = match hint {
Some(hint) => hint.clone(),
None => match detect() {
Some(shell) => shell,
None => return Err("No hint given and SHELL environment variable not found."),
},
};
match shell.as_str() {
s if s.contains("bash") => Ok(Shell::new(alias, bash::SCRIPT.to_string())),
s if s.contains("fish") => Ok(Shell::new(alias, fish::SCRIPT.to_string())),
s if s.contains("powershell") => Ok(Shell::new(alias, pwsh::SCRIPT.to_string())),
s if s.contains("pwsh") => Ok(Shell::new(alias, pwsh::SCRIPT.to_string())),
s if s.contains("zsh") => Ok(Shell::new(alias, zsh::SCRIPT.to_string())),
_ => Ok(Shell::new(alias, bash::SCRIPT.to_string())),
/// Detect the current shell
fn detect() -> Option<String> {
if let Ok(shell) = env::var("SHELL") {
Some(shell)
} else {
None
#[cfg(test)]
macro_rules! initialize_shell {
($($name: ident: $value:expr,)*) => {
$(
#[test]
fn $name() {
// GIVEN a shell hint
let hint = Some($value.to_string());
// WHEN trying to initialize the hinted shell
let alias = String::from("up");
let actual = initialize(alias, &hint);
// THEN we should get the initialization function for the expected
// shell
let expected = format!("init {}", &hint.unwrap());
assert!(actual.unwrap().compile_script().contains(&expected))
)*
mod tests {
use super::*;
fn initialize_from_env() {
// GIVEN non-existing shell
env::set_var("SHELL", "radish");
// WHEN trying initialize without a hint
let actual = initialize(alias, &None);
// THEN we should get the initialization function for the default shell
let expected = "init bash";
fn initialize_non_existant() {
// GIVEN empty SHELL variable
env::remove_var("SHELL");
// THEN we should get an error
let expected = Err("No hint given and SHELL environment variable not found.");
assert_eq!(actual, expected);
initialize_shell! {
initialize_bash: ("bash"),
initialize_fish: ("fish"),
initialize_pwsh: ("pwsh"),
initialize_zsh: ("zsh"),