From c422c6cc3d6097050d47f38568462698a77815bf Mon Sep 17 00:00:00 2001 From: goldfish <37319612+ito-hiroki@users.noreply.github.com> Date: Wed, 26 Apr 2023 23:15:27 +0900 Subject: [PATCH] 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 - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :green_circle: `toolkit test` - :green_circle: `toolkit test stdlib` ``` # After Submitting nothing --- .../src/completions/variable_completions.rs | 46 ++++++++- crates/nu-cli/tests/completions.rs | 94 +++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/crates/nu-cli/src/completions/variable_completions.rs b/crates/nu-cli/src/completions/variable_completions.rs index 2eb5b43817..3173d4289f 100644 --- a/crates/nu-cli/src/completions/variable_completions.rs +++ b/crates/nu-cli/src/completions/variable_completions.rs @@ -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>) -> 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, } } diff --git a/crates/nu-cli/tests/completions.rs b/crates/nu-cli/tests/completions.rs index e984698411..d6608975f4 100644 --- a/crates/nu-cli/tests/completions.rs +++ b/crates/nu-cli/tests/completions.rs @@ -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 = 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 = 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 = 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 = vec![ + "any".into(), + "binary".into(), + "bool".into(), + "datetime".into(), + "duration".into(), + "filesize".into(), + "int".into(), + "list".into(), + "list".into(), + "list".into(), + "list".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 = 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 = vec!["name".into(), "type".into(), "value".into()]; + // Match results + match_suggestions(expected, suggestions); + // Test completions for custom var let suggestions = completer.complete("$actor.", 7);