nu_command/help/
help_externs.rs

1use crate::filters::find_internal;
2use nu_engine::{command_prelude::*, get_full_help, scope::ScopeData};
3
4#[derive(Clone)]
5pub struct HelpExterns;
6
7impl Command for HelpExterns {
8    fn name(&self) -> &str {
9        "help externs"
10    }
11
12    fn description(&self) -> &str {
13        "Show help on nushell externs."
14    }
15
16    fn signature(&self) -> Signature {
17        Signature::build("help externs")
18            .category(Category::Core)
19            .rest(
20                "rest",
21                SyntaxShape::String,
22                "The name of extern to get help on.",
23            )
24            .named(
25                "find",
26                SyntaxShape::String,
27                "string to find in extern names and descriptions",
28                Some('f'),
29            )
30            .input_output_types(vec![(Type::Nothing, Type::table())])
31            .allow_variants_without_examples(true)
32    }
33
34    fn examples(&self) -> Vec<Example> {
35        vec![
36            Example {
37                description: "show all externs",
38                example: "help externs",
39                result: None,
40            },
41            Example {
42                description: "show help for single extern",
43                example: "help externs smth",
44                result: None,
45            },
46            Example {
47                description: "search for string in extern names and descriptions",
48                example: "help externs --find smth",
49                result: None,
50            },
51        ]
52    }
53
54    fn run(
55        &self,
56        engine_state: &EngineState,
57        stack: &mut Stack,
58        call: &Call,
59        _input: PipelineData,
60    ) -> Result<PipelineData, ShellError> {
61        help_externs(engine_state, stack, call)
62    }
63}
64
65pub fn help_externs(
66    engine_state: &EngineState,
67    stack: &mut Stack,
68    call: &Call,
69) -> Result<PipelineData, ShellError> {
70    let head = call.head;
71    let find: Option<Spanned<String>> = call.get_flag(engine_state, stack, "find")?;
72    let rest: Vec<Spanned<String>> = call.rest(engine_state, stack, 0)?;
73
74    if let Some(f) = find {
75        let all_cmds_vec = build_help_externs(engine_state, stack, head);
76        return find_internal(
77            all_cmds_vec,
78            engine_state,
79            stack,
80            &f.item,
81            &["name", "description"],
82            true,
83        );
84    }
85
86    if rest.is_empty() {
87        Ok(build_help_externs(engine_state, stack, head))
88    } else {
89        let mut name = String::new();
90
91        for r in &rest {
92            if !name.is_empty() {
93                name.push(' ');
94            }
95            name.push_str(&r.item);
96        }
97
98        if let Some(decl) = engine_state.find_decl(name.as_bytes(), &[]) {
99            let cmd = engine_state.get_decl(decl);
100            let help_text = get_full_help(cmd, engine_state, stack);
101            Ok(Value::string(help_text, call.head).into_pipeline_data())
102        } else {
103            Err(ShellError::CommandNotFound {
104                span: Span::merge_many(rest.iter().map(|s| s.span)),
105            })
106        }
107    }
108}
109
110fn build_help_externs(engine_state: &EngineState, stack: &Stack, span: Span) -> PipelineData {
111    let mut scope = ScopeData::new(engine_state, stack);
112    scope.populate_decls();
113    Value::list(scope.collect_externs(span), span).into_pipeline_data()
114}
115
116#[cfg(test)]
117mod test {
118    #[test]
119    fn test_examples() {
120        use super::HelpExterns;
121        use crate::test_examples;
122        test_examples(HelpExterns {})
123    }
124}