nu_command/help/
help_externs.rs1use crate::help::highlight_search_in_table;
2use nu_color_config::StyleComputer;
3use nu_engine::{command_prelude::*, get_full_help, scope::ScopeData};
4
5#[derive(Clone)]
6pub struct HelpExterns;
7
8impl Command for HelpExterns {
9 fn name(&self) -> &str {
10 "help externs"
11 }
12
13 fn description(&self) -> &str {
14 "Show help on nushell externs."
15 }
16
17 fn signature(&self) -> Signature {
18 Signature::build("help externs")
19 .category(Category::Core)
20 .rest(
21 "rest",
22 SyntaxShape::String,
23 "The name of extern to get help on.",
24 )
25 .named(
26 "find",
27 SyntaxShape::String,
28 "string to find in extern 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 externs",
39 example: "help externs",
40 result: None,
41 },
42 Example {
43 description: "show help for single extern",
44 example: "help externs smth",
45 result: None,
46 },
47 Example {
48 description: "search for string in extern names and descriptions",
49 example: "help externs --find smth",
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_externs(engine_state, stack, call)
63 }
64}
65
66pub fn help_externs(
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_externs(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_externs(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 if let Some(decl) = engine_state.find_decl(name.as_bytes(), &[]) {
111 let cmd = engine_state.get_decl(decl);
112 let help_text = get_full_help(cmd, engine_state, stack);
113 Ok(Value::string(help_text, call.head).into_pipeline_data())
114 } else {
115 Err(ShellError::CommandNotFound {
116 span: Span::merge_many(rest.iter().map(|s| s.span)),
117 })
118 }
119 }
120}
121
122fn build_help_externs(engine_state: &EngineState, stack: &Stack, span: Span) -> Vec<Value> {
123 let mut scope = ScopeData::new(engine_state, stack);
124 scope.populate_decls();
125 scope.collect_externs(span)
126}
127
128#[cfg(test)]
129mod test {
130 #[test]
131 fn test_examples() {
132 use super::HelpExterns;
133 use crate::test_examples;
134 test_examples(HelpExterns {})
135 }
136}