From bf82417d524646fb6124487016ef19d726f57924 Mon Sep 17 00:00:00 2001 From: onthebridgetonowhere <71919805+onthebridgetonowhere@users.noreply.github.com> Date: Fri, 3 Dec 2021 03:00:32 +0100 Subject: [PATCH] Port str upcase (#404) * Port str upcase * Switch to to_uppercase to support more characters than only ASCII --- crates/nu-command/src/default_context.rs | 1 + crates/nu-command/src/strings/str_/mod.rs | 2 + crates/nu-command/src/strings/str_/upcase.rs | 109 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 crates/nu-command/src/strings/str_/upcase.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 5b9ec0238b..22779d8a9b 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -148,6 +148,7 @@ pub fn create_default_context() -> EngineState { StrStartsWith, StrReverse, StrSubstring, + StrUpcase, StrTrim, Sys, Table, diff --git a/crates/nu-command/src/strings/str_/mod.rs b/crates/nu-command/src/strings/str_/mod.rs index ca32976905..1d1d39911b 100644 --- a/crates/nu-command/src/strings/str_/mod.rs +++ b/crates/nu-command/src/strings/str_/mod.rs @@ -13,6 +13,7 @@ mod rpad; mod starts_with; mod substring; mod trim; +mod upcase; pub use capitalize::SubCommand as StrCapitalize; pub use case::*; @@ -29,3 +30,4 @@ pub use rpad::SubCommand as StrRpad; pub use starts_with::SubCommand as StrStartsWith; pub use substring::SubCommand as StrSubstring; pub use trim::Trim as StrTrim; +pub use upcase::SubCommand as StrUpcase; diff --git a/crates/nu-command/src/strings/str_/upcase.rs b/crates/nu-command/src/strings/str_/upcase.rs new file mode 100644 index 0000000000..9f64c74eaa --- /dev/null +++ b/crates/nu-command/src/strings/str_/upcase.rs @@ -0,0 +1,109 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::ast::CellPath; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Value}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "str upcase" + } + + fn signature(&self) -> Signature { + Signature::build("str upcase").rest( + "rest", + SyntaxShape::CellPath, + "optionally upcase text by column paths", + ) + } + + fn usage(&self) -> &str { + "upcases text" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + operate(engine_state, stack, call, input) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Upcase contents", + example: "'nu' | str upcase", + result: Some(Value::test_string("NU")), + }] + } +} + +fn operate( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let head = call.head; + let column_paths: Vec = call.rest(engine_state, stack, 0)?; + input.map( + move |v| { + if column_paths.is_empty() { + action(&v, head) + } else { + let mut ret = v; + for path in &column_paths { + let r = + ret.update_cell_path(&path.members, Box::new(move |old| action(old, head))); + if let Err(error) = r { + return Value::Error { error }; + } + } + ret + } + }, + engine_state.ctrlc.clone(), + ) +} + +fn action(input: &Value, head: Span) -> Value { + match input { + Value::String { val: s, .. } => Value::String { + val: s.to_uppercase(), + span: head, + }, + other => { + let got = format!("Expected string but got {}", other.get_type()); + Value::Error { + error: ShellError::UnsupportedInput(got, head), + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::{action, SubCommand}; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } + + #[test] + fn upcases() { + let word = Value::test_string("andres"); + + let actual = action(&word, Span::unknown()); + let expected = Value::test_string("ANDRES"); + assert_eq!(actual, expected); + } +}