nu_command/conversions/into/
glob.rs

1use nu_cmd_base::input_handler::{CmdArgument, operate};
2use nu_engine::command_prelude::*;
3
4struct Arguments {
5    cell_paths: Option<Vec<CellPath>>,
6}
7
8impl CmdArgument for Arguments {
9    fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
10        self.cell_paths.take()
11    }
12}
13
14#[derive(Clone)]
15pub struct IntoGlob;
16
17impl Command for IntoGlob {
18    fn name(&self) -> &str {
19        "into glob"
20    }
21
22    fn signature(&self) -> Signature {
23        Signature::build("into glob")
24            .input_output_types(vec![
25                (Type::Glob, Type::Glob),
26                (Type::String, Type::Glob),
27                (
28                    Type::List(Box::new(Type::String)),
29                    Type::List(Box::new(Type::Glob)),
30                ),
31                (Type::table(), Type::table()),
32                (Type::record(), Type::record()),
33            ])
34            .allow_variants_without_examples(true) // https://github.com/nushell/nushell/issues/7032
35            .rest(
36                "rest",
37                SyntaxShape::CellPath,
38                "For a data structure input, convert data at the given cell paths.",
39            )
40            .category(Category::Conversions)
41    }
42
43    fn description(&self) -> &str {
44        "Convert value to glob."
45    }
46
47    fn search_terms(&self) -> Vec<&str> {
48        vec!["convert", "text"]
49    }
50
51    fn run(
52        &self,
53        engine_state: &EngineState,
54        stack: &mut Stack,
55        call: &Call,
56        input: PipelineData,
57    ) -> Result<PipelineData, ShellError> {
58        glob_helper(engine_state, stack, call, input)
59    }
60
61    fn examples(&self) -> Vec<Example<'_>> {
62        vec![
63            Example {
64                description: "convert string to glob",
65                example: "'1234' | into glob",
66                result: Some(Value::test_glob("1234")),
67            },
68            Example {
69                description: "convert glob to glob",
70                example: "'1234' | into glob | into glob",
71                result: Some(Value::test_glob("1234")),
72            },
73            Example {
74                description: "convert filepath to glob",
75                example: "ls Cargo.toml | get name | into glob",
76                result: None,
77            },
78        ]
79    }
80}
81
82fn glob_helper(
83    engine_state: &EngineState,
84    stack: &mut Stack,
85    call: &Call,
86    input: PipelineData,
87) -> Result<PipelineData, ShellError> {
88    let head = call.head;
89    let cell_paths = call.rest(engine_state, stack, 0)?;
90    let cell_paths = (!cell_paths.is_empty()).then_some(cell_paths);
91    if let PipelineData::ByteStream(stream, ..) = input {
92        // TODO: in the future, we may want this to stream out, converting each to bytes
93        Ok(Value::glob(stream.into_string()?, false, head).into_pipeline_data())
94    } else {
95        let args = Arguments { cell_paths };
96        operate(action, args, input, head, engine_state.signals())
97    }
98}
99
100fn action(input: &Value, _args: &Arguments, span: Span) -> Value {
101    match input {
102        Value::String { val, .. } => Value::glob(val.to_string(), false, span),
103        Value::Glob { .. } => input.clone(),
104        x => Value::error(
105            ShellError::CantConvert {
106                to_type: String::from("glob"),
107                from_type: x.get_type().to_string(),
108                span,
109                help: None,
110            },
111            span,
112        ),
113    }
114}
115
116#[cfg(test)]
117mod test {
118    use super::*;
119
120    #[test]
121    fn test_examples() {
122        use crate::test_examples;
123
124        test_examples(IntoGlob {})
125    }
126}