diff --git a/crates/nu-cli/src/commands/which_.rs b/crates/nu-cli/src/commands/which_.rs index 028da77206..ff07833d67 100644 --- a/crates/nu-cli/src/commands/which_.rs +++ b/crates/nu-cli/src/commands/which_.rs @@ -20,7 +20,7 @@ impl WholeStreamCommand for Which { } fn usage(&self) -> &str { - "Finds a program file." + "Finds a program file, alias or custom command." } async fn run(&self, args: CommandArgs) -> Result { @@ -44,13 +44,12 @@ fn entry(arg: impl Into, path: Value, builtin: bool, tag: Tag) -> Value UntaggedValue::row(map).into_value(tag) } -macro_rules! entry_builtin { - ($arg:expr, $tag:expr) => { +macro_rules! create_entry { + ($arg:expr, $path:expr, $tag:expr, $is_builtin:expr) => { entry( $arg.clone(), - UntaggedValue::Primitive(Primitive::String("nushell built-in command".to_string())) - .into_value($tag.clone()), - true, + UntaggedValue::Primitive(Primitive::String($path.to_string())).into_value($tag.clone()), + $is_builtin, $tag, ) }; @@ -86,12 +85,8 @@ async fn which(args: CommandArgs) -> Result { application.item.clone() }; if !external { - let builtin = scope.has_command(&item); - if builtin { - output.push(ReturnSuccess::value(entry_builtin!( - item, - application.tag.clone() - ))); + if let Some(entry) = entry_for(&scope, &item, application.tag.clone()) { + output.push(ReturnSuccess::value(entry)); } } @@ -115,6 +110,18 @@ async fn which(args: CommandArgs) -> Result { } } +fn entry_for(scope: &Scope, name: &str, tag: Tag) -> Option { + if scope.has_custom_command(name) { + Some(create_entry!(name, "Nushell custom command", tag, false)) + } else if scope.has_command(name) { + Some(create_entry!(name, "Nushell built-in command", tag, true)) + } else if scope.has_alias(name) { + Some(create_entry!(name, "Nushell alias", tag, false)) + } else { + None + } +} + #[cfg(test)] mod tests { use super::ShellError; diff --git a/crates/nu-cli/src/evaluate/scope.rs b/crates/nu-cli/src/evaluate/scope.rs index fde626bc64..0941645bff 100644 --- a/crates/nu-cli/src/evaluate/scope.rs +++ b/crates/nu-cli/src/evaluate/scope.rs @@ -52,14 +52,20 @@ impl Scope { names } - pub fn has_command(&self, name: &str) -> bool { - for frame in self.frames.lock().iter() { - if frame.has_command(name) { - return true; - } - } + fn has_cmd_helper(&self, name: &str, f: fn(&ScopeFrame, &str) -> bool) -> bool { + self.frames.lock().iter().any(|frame| f(frame, name)) + } - false + pub fn has_command(&self, name: &str) -> bool { + self.has_cmd_helper(name, ScopeFrame::has_command) + } + + pub fn has_custom_command(&self, name: &str) -> bool { + self.has_cmd_helper(name, ScopeFrame::has_custom_command) + } + + pub fn has_alias(&self, name: &str) -> bool { + self.has_cmd_helper(name, ScopeFrame::has_alias) } pub fn expect_command(&self, name: &str) -> Result { @@ -203,6 +209,14 @@ impl ScopeFrame { self.commands.contains_key(name) } + pub fn has_custom_command(&self, name: &str) -> bool { + self.custom_commands.contains_key(name) + } + + pub fn has_alias(&self, name: &str) -> bool { + self.aliases.contains_key(name) + } + pub fn get_command_names(&self) -> Vec { self.commands.keys().map(|x| x.to_string()).collect() } diff --git a/docs/commands/which.md b/docs/commands/which.md index 3e82691958..2fe86934bc 100644 --- a/docs/commands/which.md +++ b/docs/commands/which.md @@ -79,3 +79,27 @@ Passing the `all` flag identifies all instances of a command or binary builtin │ No ─────────┴──────────────────────────────── ``` + +`which` also identifies aliases + +```shell +> alias e = echo +> which e +───┬─────┬───────────────┬───────── + # │ arg │ path │ builtin +───┼─────┼───────────────┼───────── + 0 │ e │ Nushell alias │ No +───┴─────┴───────────────┴───────── +``` + +and custom commands + +```shell +> def my_cool_echo [arg] { echo $arg } +> which my_cool_echo +───┬──────────────┬────────────────────────┬───────── + # │ arg │ path │ builtin +───┼──────────────┼────────────────────────┼───────── + 0 │ my_cool_echo │ Nushell custom command │ No +───┴──────────────┴────────────────────────┴───────── +```