From d93bb4219f3e1dac7de8afab7c823bdc71226f64 Mon Sep 17 00:00:00 2001 From: Gal Schlezinger Date: Wed, 28 Oct 2020 10:05:18 +0200 Subject: [PATCH] Throw an error instead of panicking when can't infer shell (#306) --- src/commands/completions.rs | 29 +++++++++++++++++++++++++---- src/commands/env.rs | 24 +++++++++++++++++++++--- src/shell/mod.rs | 11 ++++------- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/commands/completions.rs b/src/commands/completions.rs index 494fd6f..0c1289f 100644 --- a/src/commands/completions.rs +++ b/src/commands/completions.rs @@ -1,7 +1,8 @@ use super::command::Command; use crate::cli::Cli; use crate::config::FnmConfig; -use crate::shell::infer_shell; +use crate::shell::{infer_shell, AVAILABLE_SHELLS}; +use snafu::{OptionExt, Snafu}; use structopt::clap::Shell; use structopt::StructOpt; @@ -17,11 +18,31 @@ impl Command for Completions { fn apply(self, _config: &FnmConfig) -> Result<(), Self::Error> { let mut stdio = std::io::stdout(); - let shell = self.shell.unwrap_or_else(|| infer_shell().into()); + let shell = self + .shell + .or_else(|| infer_shell().map(Into::into)) + .context(CantInferShell)?; Cli::clap().gen_completions_to(env!("CARGO_PKG_NAME"), shell, &mut stdio); Ok(()) } } -#[derive(snafu::Snafu, Debug)] -pub enum Error {} +#[derive(Snafu, Debug)] +pub enum Error { + #[snafu(display( + "{}\n{}\n{}\n{}", + "Can't infer shell!", + "fnm can't infer your shell based on the process tree.", + "Maybe it is unsupported? we support the following shells:", + shells_as_string() + ))] + CantInferShell, +} + +fn shells_as_string() -> String { + AVAILABLE_SHELLS + .iter() + .map(|x| format!("* {}", x)) + .collect::>() + .join("\n") +} diff --git a/src/commands/env.rs b/src/commands/env.rs index a2369e5..a84b89e 100644 --- a/src/commands/env.rs +++ b/src/commands/env.rs @@ -4,6 +4,7 @@ use crate::fs::symlink_dir; use crate::outln; use crate::shell::{infer_shell, Shell, AVAILABLE_SHELLS}; use colored::Colorize; +use snafu::{OptionExt, Snafu}; use std::fmt::Debug; use structopt::StructOpt; @@ -50,7 +51,7 @@ impl Command for Env { outln!(config#Error, "{} {} is deprecated. This is now the default.", "warning:".yellow().bold(), "--multi".italic()); } - let shell: Box = self.shell.unwrap_or_else(&infer_shell); + let shell: Box = self.shell.or_else(&infer_shell).context(CantInferShell)?; let multishell_path = make_symlink(&config); let binary_path = if cfg!(windows) { multishell_path.clone() @@ -81,8 +82,25 @@ impl Command for Env { } } -#[derive(Debug, snafu::Snafu)] -pub enum Error {} +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display( + "{}\n{}\n{}\n{}", + "Can't infer shell!", + "fnm can't infer your shell based on the process tree.", + "Maybe it is unsupported? we support the following shells:", + shells_as_string() + ))] + CantInferShell, +} + +fn shells_as_string() -> String { + AVAILABLE_SHELLS + .iter() + .map(|x| format!("* {}", x)) + .collect::>() + .join("\n") +} #[cfg(test)] mod tests { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 3cc35a1..feb83c5 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -15,15 +15,12 @@ pub use shell::{Shell, AVAILABLE_SHELLS}; pub use windows_cmd::WindowsCmd; pub use zsh::Zsh; -/// Always returns WindowsCmd (because this is what we support on Windows) #[cfg(windows)] -pub fn infer_shell() -> Box { - let inferred = self::infer::windows::infer_shell(); - inferred.expect("Can't infer shell") +pub fn infer_shell() -> Option> { + self::infer::windows::infer_shell() } -/// Tries to infer shell or dies trying #[cfg(unix)] -pub fn infer_shell() -> Box { - infer::unix::infer_shell().expect("Can't infer shell") +pub fn infer_shell() -> Option> { + infer::unix::infer_shell() }