Fix completion on $nu to show correct menus (#8919)

I'm still new to nushell and Rust, so please let me know if there are
any omissions and/or mistakes.

# Description

fixed #8863
`$nu` completion shows wrong completion menus at this time.
This PR fixes the problem to show the correct ones.

# User-Facing Changes

Users can use the correct menus on `$nu` completion like this
[recording](https://asciinema.org/a/KCwfpdAoMFsQODFBnb3NwmufC).

# Tests + Formatting

```
$ use toolkit.nu
$ toolkit check pr

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
```

# After Submitting

nothing
This commit is contained in:
goldfish 2023-04-26 23:15:27 +09:00 committed by GitHub
parent e251f3a0b4
commit c422c6cc3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 139 additions and 1 deletions

View File

@ -1,5 +1,5 @@
use crate::completions::{Completer, CompletionOptions};
use nu_engine::eval_variable;
use nu_engine::{column::get_columns, eval_variable};
use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet},
Span, Value,
@ -267,7 +267,19 @@ fn nested_suggestions(
output
}
Value::List { vals, span: _ } => {
for column_name in get_columns(vals.iter()) {
output.push(Suggestion {
value: column_name,
description: None,
extra: None,
span: current_span,
append_whitespace: false,
});
}
output
}
_ => output,
}
}
@ -295,6 +307,38 @@ fn recursive_value(val: Value, sublevels: Vec<Vec<u8>>) -> Value {
span: Span::unknown(),
};
}
Value::LazyRecord { val, span: _ } => {
for col in val.column_names() {
if col.as_bytes().to_vec() == next_sublevel {
return recursive_value(
val.get_column_value(col).unwrap_or_default(),
sublevels.into_iter().skip(1).collect(),
);
}
}
// Current sublevel value not found
return Value::Nothing {
span: Span::unknown(),
};
}
Value::List { vals, span } => {
for col in get_columns(vals.iter()) {
if col.as_bytes().to_vec() == next_sublevel {
return recursive_value(
Value::List { vals, span }
.get_data_by_key(&col)
.unwrap_or_default(),
sublevels.into_iter().skip(1).collect(),
);
}
}
// Current sublevel value not found
return Value::Nothing {
span: Span::unknown(),
};
}
_ => return val,
}
}

View File

@ -556,6 +556,100 @@ fn variables_completions() {
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.os-info
let suggestions = completer.complete("$nu.os-info.", 12);
assert_eq!(4, suggestions.len());
let expected: Vec<String> = vec![
"arch".into(),
"family".into(),
"kernel_version".into(),
"name".into(),
];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.scope
let suggestions = completer.complete("$nu.scope.", 10);
assert_eq!(5, suggestions.len());
let expected: Vec<String> = vec![
"aliases".into(),
"commands".into(),
"engine_state".into(),
"modules".into(),
"vars".into(),
];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.scope.commands
let suggestions = completer.complete("$nu.scope.commands.", 19);
assert_eq!(15, suggestions.len());
let expected: Vec<String> = vec![
"category".into(),
"creates_scope".into(),
"examples".into(),
"extra_usage".into(),
"is_builtin".into(),
"is_custom".into(),
"is_extern".into(),
"is_keyword".into(),
"is_plugin".into(),
"is_sub".into(),
"module_name".into(),
"name".into(),
"search_terms".into(),
"signatures".into(),
"usage".into(),
];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.scope.commands.signatures
let suggestions = completer.complete("$nu.scope.commands.signatures.", 30);
assert_eq!(17, suggestions.len());
let expected: Vec<String> = vec![
"any".into(),
"binary".into(),
"bool".into(),
"datetime".into(),
"duration".into(),
"filesize".into(),
"int".into(),
"list<any>".into(),
"list<binary>".into(),
"list<number>".into(),
"list<string>".into(),
"nothing".into(),
"number".into(),
"range".into(),
"record".into(),
"string".into(),
"table".into(),
];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.scope.engine_state
let suggestions = completer.complete("$nu.scope.engine_state.", 23);
assert_eq!(6, suggestions.len());
let expected: Vec<String> = vec![
"num_blocks".into(),
"num_decls".into(),
"num_env_vars".into(),
"num_modules".into(),
"num_vars".into(),
"source_bytes".into(),
];
// Match results
match_suggestions(expected, suggestions);
// Test completions for $nu.scope.vars
let suggestions = completer.complete("$nu.scope.vars.", 15);
assert_eq!(3, suggestions.len());
let expected: Vec<String> = vec!["name".into(), "type".into(), "value".into()];
// Match results
match_suggestions(expected, suggestions);
// Test completions for custom var
let suggestions = completer.complete("$actor.", 7);