From 69d81cc065731b2e69fcda7e7c58cc4d67047117 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:06:49 -0500 Subject: [PATCH] add command_type to help (#14165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR adds an indicator when listing subcommands. That indicator tells whether the command is a plugin, alias, or custom_command. ![image](https://github.com/user-attachments/assets/02889f8a-17b4-4678-bb44-3a487b3d1066) I changed some of the API to make this work a little easier, namely `get_signatures()` is now `get_signatures_and_declids()`. It was used in only one other place (run-external), so I thought it was fine to change it. There is a long-standing issue with aliases where they reference the command name instead of the alias name. This PR doesn't fix that bug. Example. ```nushell ❯ alias "str fill" = str wrap ``` ```nushell ❯ str ... other stuff Subcommands: str wrap (alias) - Alias for `str wrap` str wrap (plugin) - Wrap text passed into pipeline. ``` # User-Facing Changes Slightly different output of subcommands. --- crates/nu-command/src/system/run_external.rs | 6 ++--- crates/nu-engine/src/documentation.rs | 26 ++++++++++++++----- crates/nu-protocol/src/engine/engine_state.rs | 6 ++--- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/crates/nu-command/src/system/run_external.rs b/crates/nu-command/src/system/run_external.rs index 8d6b4e2bf3..b38650894c 100644 --- a/crates/nu-command/src/system/run_external.rs +++ b/crates/nu-command/src/system/run_external.rs @@ -449,8 +449,8 @@ pub fn command_not_found( } // Try to match the name with the search terms of existing commands. - let signatures = engine_state.get_signatures(false); - if let Some(sig) = signatures.iter().find(|sig| { + let signatures = engine_state.get_signatures_and_declids(false); + if let Some((sig, _)) = signatures.iter().find(|(sig, _)| { sig.search_terms .iter() .any(|term| term.to_folded_case() == name.to_folded_case()) @@ -463,7 +463,7 @@ pub fn command_not_found( } // Try a fuzzy search on the names of all existing commands. - if let Some(cmd) = did_you_mean(signatures.iter().map(|sig| &sig.name), name) { + if let Some(cmd) = did_you_mean(signatures.iter().map(|(sig, _)| &sig.name), name) { // The user is invoking an external command with the same name as a // built-in command. Remind them of this. if cmd == name { diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs index ef00d6cf24..81add7af4d 100644 --- a/crates/nu-engine/src/documentation.rs +++ b/crates/nu-engine/src/documentation.rs @@ -2,6 +2,7 @@ use crate::eval_call; use nu_protocol::{ ast::{Argument, Call, Expr, Expression, RecordItem}, debugger::WithoutDebug, + engine::CommandType, engine::{Command, EngineState, Stack, UNKNOWN_SPAN_ID}, record, Category, Config, Example, IntoPipelineData, PipelineData, PositionalArg, Signature, Span, SpanId, Spanned, SyntaxShape, Type, Value, @@ -112,16 +113,29 @@ fn get_documentation( // - https://github.com/nushell/nushell/issues/11447 // - https://github.com/nushell/nushell/issues/11625 let mut subcommands = vec![]; - let signatures = engine_state.get_signatures(true); - for sig in signatures { + let signatures = engine_state.get_signatures_and_declids(true); + for (sig, decl_id) in signatures { + let command_type = engine_state.get_decl(decl_id).command_type(); + // Don't display removed/deprecated commands in the Subcommands list if sig.name.starts_with(&format!("{cmd_name} ")) && !matches!(sig.category, Category::Removed) { - subcommands.push(format!( - " {help_subcolor_one}{}{RESET} - {}", - sig.name, sig.description - )); + // If it's a plugin, alias, or custom command, display that information in the help + if command_type == CommandType::Plugin + || command_type == CommandType::Alias + || command_type == CommandType::Custom + { + subcommands.push(format!( + " {help_subcolor_one}{} {help_section_name}({}){RESET} - {}", + sig.name, command_type, sig.description + )); + } else { + subcommands.push(format!( + " {help_subcolor_one}{}{RESET} - {}", + sig.name, sig.description + )); + } } } diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 71c1a58905..9704509de1 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -820,14 +820,14 @@ impl EngineState { } } - /// Get signatures of all commands within scope. - pub fn get_signatures(&self, include_hidden: bool) -> Vec { + /// Get signatures of all commands within scope with their decl ids. + pub fn get_signatures_and_declids(&self, include_hidden: bool) -> Vec<(Signature, DeclId)> { self.get_decls_sorted(include_hidden) .into_iter() .map(|(_, id)| { let decl = self.get_decl(id); - self.get_signature(decl).update_from_command(decl) + (self.get_signature(decl).update_from_command(decl), id) }) .collect() }