nu_command/strings/str_/case/
downcase.rs1use nu_engine::command_prelude::*;
2
3#[derive(Clone)]
4pub struct StrDowncase;
5
6impl Command for StrDowncase {
7 fn name(&self) -> &str {
8 "str downcase"
9 }
10
11 fn signature(&self) -> Signature {
12 Signature::build("str downcase")
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 lowercase."
33 }
34
35 fn search_terms(&self) -> Vec<&str> {
36 vec!["lower case", "lowercase"]
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![
66 Example {
67 description: "Downcase contents",
68 example: "'NU' | str downcase",
69 result: Some(Value::test_string("nu")),
70 },
71 Example {
72 description: "Downcase contents",
73 example: "'TESTa' | str downcase",
74 result: Some(Value::test_string("testa")),
75 },
76 Example {
77 description: "Downcase contents",
78 example: "[[ColA ColB]; [Test ABC]] | str downcase ColA",
79 result: Some(Value::test_list(vec![Value::test_record(record! {
80 "ColA" => Value::test_string("test"),
81 "ColB" => Value::test_string("ABC"),
82 })])),
83 },
84 Example {
85 description: "Downcase contents",
86 example: "[[ColA ColB]; [Test ABC]] | str downcase ColA ColB",
87 result: Some(Value::test_list(vec![Value::test_record(record! {
88 "ColA" => Value::test_string("test"),
89 "ColB" => Value::test_string("abc"),
90 })])),
91 },
92 ]
93 }
94}
95
96fn operate(
97 engine_state: &EngineState,
98 call: &Call,
99 input: PipelineData,
100 column_paths: Vec<CellPath>,
101) -> Result<PipelineData, ShellError> {
102 let head = call.head;
103 input.map(
104 move |v| {
105 if column_paths.is_empty() {
106 action(&v, head)
107 } else {
108 let mut ret = v;
109 for path in &column_paths {
110 let r =
111 ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
112 if let Err(error) = r {
113 return Value::error(error, head);
114 }
115 }
116 ret
117 }
118 },
119 engine_state.signals(),
120 )
121}
122
123fn action(input: &Value, head: Span) -> Value {
124 match input {
125 Value::String { val, .. } => Value::string(val.to_lowercase(), head),
126 Value::Error { .. } => input.clone(),
127 _ => Value::error(
128 ShellError::OnlySupportsThisInputType {
129 exp_input_type: "string".into(),
130 wrong_type: input.get_type().to_string(),
131 dst_span: head,
132 src_span: input.span(),
133 },
134 head,
135 ),
136 }
137}
138
139#[cfg(test)]
140mod test {
141 use super::*;
142 #[test]
143 fn test_examples() {
144 use crate::test_examples;
145
146 test_examples(StrDowncase {})
147 }
148}