Skip to main content

nu_command/filesystem/idx/
find.rs

1use super::state::stream_find;
2use nu_engine::command_prelude::*;
3
4#[derive(Clone)]
5pub struct IdxFind;
6
7impl Command for IdxFind {
8    fn name(&self) -> &str {
9        "idx find"
10    }
11
12    fn signature(&self) -> Signature {
13        Signature::build(self.name())
14            .required("query", SyntaxShape::String, "Freeform fuzzy query.")
15            .switch("verbose", "Include verbose scoring details.", Some('v'))
16            .switch("dirs", "Search directories only.", Some('d'))
17            .switch("files", "Search files only.", Some('f'))
18            .named(
19                "limit",
20                SyntaxShape::Int,
21                "Maximum number of rows to return.",
22                Some('l'),
23            )
24            .input_output_types(vec![(Type::Nothing, Type::List(Box::new(Type::record())))])
25            .category(Category::FileSystem)
26    }
27
28    fn description(&self) -> &str {
29        "Search idx with fuzzy matching across files and directories by default."
30    }
31
32    fn extra_description(&self) -> &str {
33        "`idx find` searches both files and directories unless you narrow it with `--files` or `--dirs`."
34    }
35
36    fn examples(&self) -> Vec<Example<'_>> {
37        vec![
38            Example {
39                description: "Fuzzy search for files and directories matching 'main'",
40                example: "idx find main",
41                result: None,
42            },
43            Example {
44                description: "Search only files with verbose scoring output",
45                example: "idx find config --files --verbose",
46                result: None,
47            },
48            Example {
49                description: "Search only directories, limited to top 10 results",
50                example: "idx find src --dirs --limit 10",
51                result: None,
52            },
53        ]
54    }
55
56    fn run(
57        &self,
58        engine_state: &EngineState,
59        stack: &mut Stack,
60        call: &Call,
61        _input: PipelineData,
62    ) -> Result<PipelineData, ShellError> {
63        let query: String = call.req(engine_state, stack, 0)?;
64        let verbose = call.has_flag(engine_state, stack, "verbose")?;
65        let dirs = call.has_flag(engine_state, stack, "dirs")?;
66        let files = call.has_flag(engine_state, stack, "files")?;
67
68        if files && dirs {
69            return Err(ShellError::IncompatibleParameters {
70                left_message: "--files cannot be used with --dirs".to_string(),
71                left_span: call.get_flag_span(stack, "files").unwrap_or(call.head),
72                right_message: "--dirs cannot be used with --files".to_string(),
73                right_span: call.get_flag_span(stack, "dirs").unwrap_or(call.head),
74            });
75        }
76
77        let limit = call
78            .get_flag::<i64>(engine_state, stack, "limit")?
79            .and_then(|v| usize::try_from(v).ok())
80            .unwrap_or(100);
81
82        let signals = engine_state.signals();
83        stream_find(&query, files, dirs, verbose, limit, call.head, signals)
84    }
85}