nu_command/strings/str_/case/
upcase.rs1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct StrUpcase;
5
6impl Command for StrUpcase {
7 fn name(&self) -> &str {
8 "str upcase"
9 }
10
11 fn signature(&self) -> Signature {
12 Signature::build("str upcase")
13 .input_output_types(vec![
14 (Type::String, Type::String),
15 (
16 Type::List(Box::new(Type::String)),
17 Type::List(Box::new(Type::String)),
18 ),
19 (Type::table(), Type::table()),
20 (Type::record(), Type::record()),
21 ])
22 .allow_variants_without_examples(true)
23 .rest(
24 "rest",
25 SyntaxShape::CellPath,
26 "For a data structure input, convert strings at the given cell paths.",
27 )
28 .category(Category::Strings)
29 }
30
31 fn description(&self) -> &str {
32 "Make text uppercase."
33 }
34
35 fn search_terms(&self) -> Vec<&str> {
36 vec!["uppercase", "upper case"]
37 }
38
39 fn is_const(&self) -> bool {
40 true
41 }
42
43 fn run(
44 &self,
45 engine_state: &EngineState,
46 stack: &mut Stack,
47 call: &Call,
48 input: PipelineData,
49 ) -> Result<PipelineData, ShellError> {
50 let column_paths: Vec<CellPath> = call.rest(engine_state, stack, 0)?;
51 operate(engine_state, call, input, column_paths)
52 }
53
54 fn run_const(
55 &self,
56 working_set: &StateWorkingSet,
57 call: &Call,
58 input: PipelineData,
59 ) -> Result<PipelineData, ShellError> {
60 let column_paths: Vec<CellPath> = call.rest_const(working_set, 0)?;
61 operate(working_set.permanent(), call, input, column_paths)
62 }
63
64 fn examples(&self) -> Vec<Example<'_>> {
65 vec![Example {
66 description: "Upcase contents",
67 example: "'nu' | str upcase",
68 result: Some(Value::test_string("NU")),
69 }]
70 }
71}
72
73fn operate(
74 engine_state: &EngineState,
75 call: &Call,
76 input: PipelineData,
77 column_paths: Vec<CellPath>,
78) -> Result<PipelineData, ShellError> {
79 let head = call.head;
80 input.map(
81 move |v| {
82 if column_paths.is_empty() {
83 action(&v, head)
84 } else {
85 let mut ret = v;
86 for path in &column_paths {
87 let r =
88 ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
89 if let Err(error) = r {
90 return Value::error(error, head);
91 }
92 }
93 ret
94 }
95 },
96 engine_state.signals(),
97 )
98}
99
100fn action(input: &Value, head: Span) -> Value {
101 match input {
102 Value::String { val: s, .. } => Value::string(s.to_uppercase(), head),
103 Value::Error { .. } => input.clone(),
104 _ => Value::error(
105 ShellError::OnlySupportsThisInputType {
106 exp_input_type: "string".into(),
107 wrong_type: input.get_type().to_string(),
108 dst_span: head,
109 src_span: input.span(),
110 },
111 head,
112 ),
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119 use super::{StrUpcase, action};
120
121 #[test]
122 fn test_examples() {
123 use crate::test_examples;
124
125 test_examples(StrUpcase {})
126 }
127
128 #[test]
129 fn upcases() {
130 let word = Value::test_string("andres");
131
132 let actual = action(&word, Span::test_data());
133 let expected = Value::test_string("ANDRES");
134 assert_eq!(actual, expected);
135 }
136}