From 17b2bcc1253f771522e7a0604a3271b0ce294944 Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Sun, 23 Oct 2022 02:42:17 -0700 Subject: [PATCH] Support range in str substring (#6867) --- crates/nu-command/src/strings/str_/substring.rs | 15 +++++++++++++-- crates/nu-protocol/src/value/range.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/strings/str_/substring.rs b/crates/nu-command/src/strings/str_/substring.rs index 27ff2b838..b22a98eac 100644 --- a/crates/nu-command/src/strings/str_/substring.rs +++ b/crates/nu-command/src/strings/str_/substring.rs @@ -65,12 +65,18 @@ impl Command for SubCommand { fn examples(&self) -> Vec { vec![ Example { - description: "Get a substring \"nushell\" from the text \"good nushell\"", + description: + "Get a substring \"nushell\" from the text \"good nushell\" using a range", + example: " 'good nushell' | str substring 5..12", + result: Some(Value::test_string("nushell")), + }, + Example { + description: "Alternately, you can pass in a list", example: " 'good nushell' | str substring [5 12]", result: Some(Value::test_string("nushell")), }, Example { - description: "Alternatively, you can use the form", + description: "Or a simple comma-separated string", example: " 'good nushell' | str substring '5,12'", result: Some(Value::test_string("nushell")), }, @@ -199,6 +205,11 @@ fn action(input: &Value, options: &Substring, head: Span) -> Value { fn process_arguments(options: &Arguments, head: Span) -> Result<(isize, isize), ShellError> { let search = match &options.range { + Value::Range { val, .. } => { + let start = val.from()?; + let end = val.to()?; + Ok(SubstringText(start.to_string(), end.to_string())) + } Value::List { vals, .. } => { if vals.len() > 2 { Err(ShellError::UnsupportedInput( diff --git a/crates/nu-protocol/src/value/range.rs b/crates/nu-protocol/src/value/range.rs index 7e7033efe..2a4ca9728 100644 --- a/crates/nu-protocol/src/value/range.rs +++ b/crates/nu-protocol/src/value/range.rs @@ -122,6 +122,19 @@ impl Range { matches!(self.inclusion, RangeInclusion::Inclusive) } + pub fn from(&self) -> Result { + self.from.as_integer() + } + + pub fn to(&self) -> Result { + let to = self.to.as_integer()?; + if self.is_end_inclusive() { + Ok(to) + } else { + Ok(to - 1) + } + } + pub fn contains(&self, item: &Value) -> bool { match (item.partial_cmp(&self.from), item.partial_cmp(&self.to)) { (Some(Ordering::Greater | Ordering::Equal), Some(Ordering::Less)) => self.moves_up(),