Support range in str substring (#6867)

This commit is contained in:
Reilly Wood 2022-10-23 02:42:17 -07:00 committed by GitHub
parent 24a98f8999
commit 17b2bcc125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 2 deletions

View File

@ -65,12 +65,18 @@ impl Command for SubCommand {
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {
vec![ vec![
Example { 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]", example: " 'good nushell' | str substring [5 12]",
result: Some(Value::test_string("nushell")), result: Some(Value::test_string("nushell")),
}, },
Example { Example {
description: "Alternatively, you can use the form", description: "Or a simple comma-separated string",
example: " 'good nushell' | str substring '5,12'", example: " 'good nushell' | str substring '5,12'",
result: Some(Value::test_string("nushell")), 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> { fn process_arguments(options: &Arguments, head: Span) -> Result<(isize, isize), ShellError> {
let search = match &options.range { 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, .. } => { Value::List { vals, .. } => {
if vals.len() > 2 { if vals.len() > 2 {
Err(ShellError::UnsupportedInput( Err(ShellError::UnsupportedInput(

View File

@ -122,6 +122,19 @@ impl Range {
matches!(self.inclusion, RangeInclusion::Inclusive) matches!(self.inclusion, RangeInclusion::Inclusive)
} }
pub fn from(&self) -> Result<i64, ShellError> {
self.from.as_integer()
}
pub fn to(&self) -> Result<i64, ShellError> {
let to = self.to.as_integer()?;
if self.is_end_inclusive() {
Ok(to)
} else {
Ok(to - 1)
}
}
pub fn contains(&self, item: &Value) -> bool { pub fn contains(&self, item: &Value) -> bool {
match (item.partial_cmp(&self.from), item.partial_cmp(&self.to)) { match (item.partial_cmp(&self.from), item.partial_cmp(&self.to)) {
(Some(Ordering::Greater | Ordering::Equal), Some(Ordering::Less)) => self.moves_up(), (Some(Ordering::Greater | Ordering::Equal), Some(Ordering::Less)) => self.moves_up(),