From c722e290f3dfed94a715c50471c67df7d82eae94 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 | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs index 35db04168699..3b26d5262915 100644 --- a/clap_complete/src/shells/shell.rs +++ b/clap_complete/src/shells/shell.rs @@ -1,4 +1,5 @@ use std::fmt::Display; +use std::path::PathBuf; use std::str::FromStr; use clap::builder::PossibleValue; @@ -89,3 +90,39 @@ 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()) + } + } +}