nu_command/strings/str_/case/
upcase.rs1use 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}