nu_command/help/
help_aliases.rs1use crate::help::highlight_search_in_table;
2use nu_color_config::StyleComputer;
3use nu_engine::{command_prelude::*, scope::ScopeData};
4
5#[derive(Clone)]
6pub struct HelpAliases;
7
8impl Command for HelpAliases {
9 fn name(&self) -> &str {
10 "help aliases"
11 }
12
13 fn description(&self) -> &str {
14 "Show help on nushell aliases."
15 }
16
17 fn signature(&self) -> Signature {
18 Signature::build("help aliases")
19 .category(Category::Core)
20 .rest(
21 "rest",
22 SyntaxShape::String,
23 "The name of alias to get help on.",
24 )
25 .named(
26 "find",
27 SyntaxShape::String,
28 "string to find in alias names and descriptions",
29 Some('f'),
30 )
31 .input_output_types(vec![(Type::Nothing, Type::table())])
32 .allow_variants_without_examples(true)
33 }
34
35 fn examples(&self) -> Vec<Example> {
36 vec![
37 Example {
38 description: "show all aliases",
39 example: "help aliases",
40 result: None,
41 },
42 Example {
43 description: "show help for single alias",
44 example: "help aliases my-alias",
45 result: None,
46 },
47 Example {
48 description: "search for string in alias names and descriptions",
49 example: "help aliases --find my-alias",
50 result: None,
51 },
52 ]
53 }
54
55 fn run(
56 &self,
57 engine_state: &EngineState,
58 stack: &mut Stack,
59 call: &Call,
60 _input: PipelineData,
61 ) -> Result<PipelineData, ShellError> {
62 help_aliases(engine_state, stack, call)
63 }
64}
65
66pub fn help_aliases(
67 engine_state: &EngineState,
68 stack: &mut Stack,
69 call: &Call,
70) -> Result<PipelineData, ShellError> {
71 let head = call.head;
72 let find: Option<Spanned<String>> = call.get_flag(engine_state, stack, "find")?;
73 let rest: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?;
74
75 let style_computer = StyleComputer::from_config(engine_state, stack);
77 let string_style = style_computer.compute("string", &Value::string("search result", head));
81 let highlight_style =
82 style_computer.compute("search_result", &Value::string("search result", head));
83
84 if let Some(f) = find {
85 let all_cmds_vec = build_help_aliases(engine_state, stack, head);
86 let found_cmds_vec = highlight_search_in_table(
87 all_cmds_vec,
88 &f.item,
89 &["name", "description"],
90 &string_style,
91 &highlight_style,
92 )?;
93
94 return Ok(Value::list(found_cmds_vec, head).into_pipeline_data());
95 }
96
97 if rest.is_empty() {
98 let found_cmds_vec = build_help_aliases(engine_state, stack, head);
99 Ok(Value::list(found_cmds_vec, head).into_pipeline_data())
100 } else {
101 let mut name = String::new();
102
103 for r in &rest {
104 if !name.is_empty() {
105 name.push(' ');
106 }
107 name.push_str(&r.item);
108 }
109
110 let Some(alias) = engine_state.find_decl(name.as_bytes(), &[]) else {
111 return Err(ShellError::AliasNotFound {
112 span: Span::merge_many(rest.iter().map(|s| s.span)),
113 });
114 };
115
116 let Some(alias) = engine_state.get_decl(alias).as_alias() else {
117 return Err(ShellError::AliasNotFound {
118 span: Span::merge_many(rest.iter().map(|s| s.span)),
119 });
120 };
121
122 let alias_expansion =
123 String::from_utf8_lossy(engine_state.get_span_contents(alias.wrapped_call.span));
124 let description = alias.description();
125 let extra_desc = alias.extra_description();
126
127 const G: &str = "\x1b[32m"; const C: &str = "\x1b[36m"; const RESET: &str = "\x1b[0m"; let mut long_desc = String::new();
133
134 long_desc.push_str(description);
135 long_desc.push_str("\n\n");
136
137 if !extra_desc.is_empty() {
138 long_desc.push_str(extra_desc);
139 long_desc.push_str("\n\n");
140 }
141
142 long_desc.push_str(&format!("{G}Alias{RESET}: {C}{name}{RESET}"));
143 long_desc.push_str("\n\n");
144 long_desc.push_str(&format!("{G}Expansion{RESET}:\n {alias_expansion}"));
145
146 let config = stack.get_config(engine_state);
147 if !config.use_ansi_coloring.get(engine_state) {
148 long_desc = nu_utils::strip_ansi_string_likely(long_desc);
149 }
150
151 Ok(Value::string(long_desc, call.head).into_pipeline_data())
152 }
153}
154
155fn build_help_aliases(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
156 let mut scope_data = ScopeData::new(engine_state, stack);
157 scope_data.populate_decls();
158
159 scope_data.collect_aliases(span)
160}
161
162#[cfg(test)]
163mod test {
164 #[test]
165 fn test_examples() {
166 use super::HelpAliases;
167 use crate::test_examples;
168 test_examples(HelpAliases {})
169 }
170}