nu_command/help/
help_externs.rs

1use 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    // 🚩The following two-lines are copied from filters/find.rs:
76    let style_computer = StyleComputer::from_config(engine_state, stack);
77    // Currently, search results all use the same style.
78    // Also note that this sample string is passed into user-written code (the closure that may or may not be
79    // defined for "string").
80    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}