Skip to main content

nu_command/strings/str_/case/
upcase.rs

1use nu_engine::command_prelude::*;
2use nu_protocol::{DeprecationEntry, DeprecationType, ReportMode};
3
4#[derive(Clone)]
5pub struct StrUpcase;
6
7impl Command for StrUpcase {
8    fn name(&self) -> &str {
9        "str upcase"
10    }
11
12    fn signature(&self) -> Signature {
13        Signature::build("str upcase")
14            .input_output_types(vec![
15                (Type::String, Type::String),
16                (
17                    Type::List(Box::new(Type::String)),
18                    Type::List(Box::new(Type::String)),
19                ),
20                (Type::table(), Type::table()),
21                (Type::record(), Type::record()),
22            ])
23            .allow_variants_without_examples(true)
24            .rest(
25                "rest",
26                SyntaxShape::CellPath,
27                "For a data structure input, convert strings at the given cell paths.",
28            )
29            .category(Category::Strings)
30    }
31
32    fn description(&self) -> &str {
33        "Convert text to uppercase."
34    }
35
36    fn search_terms(&self) -> Vec<&str> {
37        vec!["uppercase", "upper case", "upper-case"]
38    }
39
40    fn is_const(&self) -> bool {
41        true
42    }
43
44    fn run(
45        &self,
46        engine_state: &EngineState,
47        stack: &mut Stack,
48        call: &Call,
49        input: PipelineData,
50    ) -> Result<PipelineData, ShellError> {
51        let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
52        operate(engine_state, call, input, column_paths)
53    }
54
55    fn run_const(
56        &self,
57        working_set: &StateWorkingSet,
58        call: &Call,
59        input: PipelineData,
60    ) -> Result<PipelineData, ShellError> {
61        let column_paths: Vec<CellPath> = call.rest_const(working_set, 0)?;
62        operate(working_set.permanent(), call, input, column_paths)
63    }
64
65    fn examples(&self) -> Vec<Example<'_>> {
66        vec![Example {
67            description: "Upcase contents.",
68            example: "'nu' | str upcase",
69            result: Some(Value::test_string("NU")),
70        }]
71    }
72
73    fn deprecation_info(&self) -> Vec<DeprecationEntry> {
74        vec![DeprecationEntry {
75            ty: DeprecationType::Command,
76            report_mode: ReportMode::FirstUse,
77            since: Some("0.114.0".into()),
78            expected_removal: None,
79            help: Some("Use `str uppercase` instead.".into()),
80        }]
81    }
82}
83
84#[derive(Clone)]
85pub struct StrUppercase;
86
87impl Command for StrUppercase {
88    fn name(&self) -> &str {
89        "str uppercase"
90    }
91
92    fn signature(&self) -> Signature {
93        Signature::build("str uppercase")
94            .input_output_types(vec![
95                (Type::String, Type::String),
96                (
97                    Type::List(Box::new(Type::String)),
98                    Type::List(Box::new(Type::String)),
99                ),
100                (Type::table(), Type::table()),
101                (Type::record(), Type::record()),
102            ])
103            .allow_variants_without_examples(true)
104            .rest(
105                "rest",
106                SyntaxShape::CellPath,
107                "For a data structure input, convert strings at the given cell paths.",
108            )
109            .category(Category::Strings)
110    }
111
112    fn description(&self) -> &str {
113        "Convert text to uppercase."
114    }
115
116    fn search_terms(&self) -> Vec<&str> {
117        vec!["upcase"]
118    }
119
120    fn is_const(&self) -> bool {
121        true
122    }
123
124    fn run(
125        &self,
126        engine_state: &EngineState,
127        stack: &mut Stack,
128        call: &Call,
129        input: PipelineData,
130    ) -> Result<PipelineData, ShellError> {
131        let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
132        operate(engine_state, call, input, column_paths)
133    }
134
135    fn run_const(
136        &self,
137        working_set: &StateWorkingSet,
138        call: &Call,
139        input: PipelineData,
140    ) -> Result<PipelineData, ShellError> {
141        let column_paths: Vec<CellPath> = call.rest_const(working_set, 0)?;
142        operate(working_set.permanent(), call, input, column_paths)
143    }
144
145    fn examples(&self) -> Vec<Example<'_>> {
146        vec![Example {
147            description: "Uppercase contents.",
148            example: "'nu' | str uppercase",
149            result: Some(Value::test_string("NU")),
150        }]
151    }
152}
153
154fn operate(
155    engine_state: &EngineState,
156    call: &Call,
157    input: PipelineData,
158    column_paths: Vec<CellPath>,
159) -> Result<PipelineData, ShellError> {
160    let head = call.head;
161    input.map(
162        move |v| {
163            if column_paths.is_empty() {
164                action(&v, head)
165            } else {
166                let mut ret = v;
167                for path in &column_paths {
168                    let r =
169                        ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
170                    if let Err(error) = r {
171                        return Value::error(error, head);
172                    }
173                }
174                ret
175            }
176        },
177        engine_state.signals(),
178    )
179}
180
181fn action(input: &Value, head: Span) -> Value {
182    match input {
183        Value::String { val: s, .. } => Value::string(s.to_uppercase(), head),
184        Value::Error { .. } => input.clone(),
185        _ => Value::error(
186            ShellError::OnlySupportsThisInputType {
187                exp_input_type: "string".into(),
188                wrong_type: input.get_type().to_string(),
189                dst_span: head,
190                src_span: input.span(),
191            },
192            head,
193        ),
194    }
195}
196
197#[cfg(test)]
198mod tests {
199    use super::*;
200
201    #[test]
202    fn test_upcase_examples() -> nu_test_support::Result {
203        nu_test_support::test().examples(StrUpcase)
204    }
205
206    #[test]
207    fn test_uppercase_examples() -> nu_test_support::Result {
208        nu_test_support::test().examples(StrUppercase)
209    }
210
211    #[test]
212    fn upcases() {
213        let word = Value::test_string("andres");
214
215        let actual = action(&word, Span::test_data());
216        let expected = Value::test_string("ANDRES");
217        assert_eq!(actual, expected);
218    }
219}