From 43503103c27ed66cda1a68e92feeb695d3617908 Mon Sep 17 00:00:00 2001 From: Thayne McCombs Date: Thu, 3 Nov 2022 02:10:36 -0600 Subject: [PATCH] Add support for determining current shell from environment Closes: #4446 --- clap_complete/src/shells/shell.rs | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs index 35db04168699..39f21eff8e1e 100644 --- a/clap_complete/src/shells/shell.rs +++ b/clap_complete/src/shells/shell.rs @@ -1,5 +1,6 @@ use std::fmt::Display; use std::str::FromStr; +use std::path::PathBuf; use clap::builder::PossibleValue; use clap::ValueEnum; @@ -89,3 +90,35 @@ impl Generator for Shell { } } } + +impl Shell { + /// Determine the user's current shell from the environment + /// + /// This will read the SHELL environment variable and try to determine which shell is in use + /// from that. + /// + /// If SHELL is not set, then on windows, it will default to powershell, and on + /// other OSes it will return an error. + /// + /// If SHELL is set, but contains a value that doesn't correspond to one of the supported shell + /// types, then an error is returned. + /// + /// # Example: + /// + /// ```ignore + /// use clap_complete::{generate, shells::Shell} + /// let mut cmd = build_cli(); + /// generate(Shell::from_env().unwrap_or(Shell::Bash), "myapp", &mut std::io::stdout()); + /// ``` + pub fn from_env() -> Result { + let env_shell = std::env::var_os("SHELL").map(PathBuf::from); + if let Some(shell) = env_shell.as_ref().and_then(|s| s.file_name()).and_then(|s| s.to_str()) { + Ok(shell.parse::()?) + } else if cfg!(windows) { + // Assume powershell for windows + Ok(Shell::PowerShell) + } else { + Err("SHELL environment variable not set".to_string()) + } + } +}