Make optional cell paths work with reject (#8697)

This PR makes `?` work with `reject`. For example:

```bash
> {} | reject foo
Error: nu:🐚:column_not_found

  × Cannot find column
   ╭─[entry #2:1:1]
 1 │ {} | reject foo
   ·      ───┬── ─┬─
   ·         │    ╰── cannot find column 'foo'
   ·         ╰── value originates here
   ╰────

> {} | reject foo?
╭──────────────╮
│ empty record │
╰──────────────╯
```

This was prompted by [a user
question](https://discord.com/channels/601130461678272522/614593951969574961/1091466428546306078).
I would like to get this in for 0.78, I think it's low-risk and I want
the `?` feature to be as polished as possible for its debut.
This commit is contained in:
Reilly Wood 2023-03-31 16:40:19 -07:00 committed by GitHub
parent eaea00366b
commit 83ddf0ebe2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 8 deletions

View File

@ -147,3 +147,24 @@ fn reject_large_vec_with_two_identical_elements() {
assert!(actual.out.contains("100"));
assert!(actual.out.contains('2'));
}
#[test]
fn reject_optional_column() {
let actual = nu!("{} | reject foo? | to nuon");
assert_eq!(actual.out, "{}");
let actual = nu!("[{}] | reject foo? | to nuon");
assert_eq!(actual.out, "[{}]");
let actual = nu!("[{} {foo: 2}] | reject foo? | to nuon");
assert_eq!(actual.out, "[{}, {}]");
let actual = nu!("[{foo: 1} {foo: 2}] | reject foo? | to nuon");
assert_eq!(actual.out, "[{}, {}]");
}
#[test]
fn reject_optional_row() {
let actual = nu!("[{foo: 'bar'}] | reject 3? | to nuon");
assert_eq!(actual.out, "[[foo]; [bar]]");
}

View File

@ -1208,7 +1208,7 @@ impl Value {
PathMember::String {
val: col_name,
span,
..
optional,
} => match self {
Value::List { vals, .. } => {
for val in vals.iter_mut() {
@ -1230,7 +1230,7 @@ impl Value {
true
}
});
if !found {
if !found && !optional {
return Err(ShellError::CantFindColumn {
col_name: col_name.to_string(),
span: *span,
@ -1262,7 +1262,7 @@ impl Value {
found = true;
}
}
if !found {
if !found && !optional {
return Err(ShellError::CantFindColumn {
col_name: col_name.to_string(),
span: *span,
@ -1278,12 +1278,16 @@ impl Value {
}),
},
PathMember::Int {
val: row_num, span, ..
val: row_num,
span,
optional,
} => match self {
Value::List { vals, .. } => {
if vals.get_mut(*row_num).is_some() {
vals.remove(*row_num);
Ok(())
} else if *optional {
Ok(())
} else if vals.is_empty() {
Err(ShellError::AccessEmptyContent { span: *span })
} else {
@ -1306,7 +1310,7 @@ impl Value {
PathMember::String {
val: col_name,
span,
..
optional,
} => match self {
Value::List { vals, .. } => {
for val in vals.iter_mut() {
@ -1323,7 +1327,7 @@ impl Value {
col.1.remove_data_at_cell_path(&cell_path[1..])?
}
}
if !found {
if !found && !optional {
return Err(ShellError::CantFindColumn {
col_name: col_name.to_string(),
span: *span,
@ -1356,7 +1360,7 @@ impl Value {
col.1.remove_data_at_cell_path(&cell_path[1..])?
}
}
if !found {
if !found && !optional {
return Err(ShellError::CantFindColumn {
col_name: col_name.to_string(),
span: *span,
@ -1372,11 +1376,15 @@ impl Value {
}),
},
PathMember::Int {
val: row_num, span, ..
val: row_num,
span,
optional,
} => match self {
Value::List { vals, .. } => {
if let Some(v) = vals.get_mut(*row_num) {
v.remove_data_at_cell_path(&cell_path[1..])
} else if *optional {
Ok(())
} else if vals.is_empty() {
Err(ShellError::AccessEmptyContent { span: *span })
} else {