fix inspect and explore panics on empty records (#13893)

# Description

Fixes a couple panics:

```
> {} | inspect
Error:   x Main thread panicked.
  |-> at crates/nu-command/src/debug/inspect_table.rs:87:15
  `-> attempt to divide by zero
```

```
> {} | explore
# see an empty column, press Down
Error:   x Main thread panicked.
  |-> at crates/nu-explore/src/views/cursor/mod.rs:39:9
  `-> attempt to subtract with overflow
```

# User-Facing Changes

`{} | inspect` now outputs an empty table:

```
╭─────────────┬────────╮
│ description │ record │
├─────────────┴────────┤
│                      │
├──────────────────────┤
```

`{} | explore` opens the help menu.

Both match the empty list behavior.

# Tests

I'm not sure how to test `explore`, as it waits for interaction.
This commit is contained in:
Solomon 2024-09-25 12:48:16 +00:00 committed by GitHub
parent 08a241f763
commit 071faae772
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 6 deletions

View File

@ -152,7 +152,7 @@ fn truncate_data(
let left_space = expected_width - width; let left_space = expected_width - width;
let has_space_for_truncation_column = left_space > PAD; let has_space_for_truncation_column = left_space > PAD;
if !has_space_for_truncation_column { if !has_space_for_truncation_column {
peak_count -= 1; peak_count = peak_count.saturating_sub(1);
} }
remove_columns(data, peak_count); remove_columns(data, peak_count);
@ -201,11 +201,18 @@ mod util {
Value::Record { val: record, .. } => { Value::Record { val: record, .. } => {
let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip(); let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
( (
cols, match cols.is_empty() {
vec![vals true => vec![String::from("")],
false => cols,
},
match vals
.into_iter() .into_iter()
.map(|s| debug_string_without_formatting(&s)) .map(|s| debug_string_without_formatting(&s))
.collect()], .collect::<Vec<String>>()
{
vals if vals.is_empty() => vec![],
vals => vec![vals],
},
) )
} }
Value::List { vals, .. } => { Value::List { vals, .. } => {

View File

@ -5,3 +5,15 @@ fn inspect_with_empty_pipeline() {
let actual = nu!("inspect"); let actual = nu!("inspect");
assert!(actual.err.contains("no input value was piped in")); assert!(actual.err.contains("no input value was piped in"));
} }
#[test]
fn inspect_with_empty_list() {
let actual = nu!("[] | inspect");
assert!(actual.out.contains("empty list"));
}
#[test]
fn inspect_with_empty_record() {
let actual = nu!("{} | inspect");
assert!(actual.out.contains("empty record"));
}

View File

@ -92,8 +92,15 @@ pub fn collect_input(value: Value) -> Result<(Vec<String>, Vec<Vec<Value>>)> {
let span = value.span(); let span = value.span();
match value { match value {
Value::Record { val: record, .. } => { Value::Record { val: record, .. } => {
let (key, val) = record.into_owned().into_iter().unzip(); let (key, val): (_, Vec<Value>) = record.into_owned().into_iter().unzip();
Ok((key, vec![val]))
Ok((
key,
match val.is_empty() {
true => vec![],
false => vec![val],
},
))
} }
Value::List { vals, .. } => { Value::List { vals, .. } => {
let mut columns = get_columns(&vals); let mut columns = get_columns(&vals);