refactor(completion, parser): move custom_completion info from Expression to Signature (#15613)

Restricts custom completion from universal to internal arguments only.

Pros:
1. Less memory
2. More flexible for later customizations, e.g. #14923 

Cons:
1. limited customization capabilities, but at least covers all currently
existing features in nushell.

# Description

Mostly vibe coded by [Zed AI](https://zed.dev/ai) with a single prompt.
LGTM, but I'm not so sure @ysthakur 

# User-Facing Changes

Hopefully none.

# Tests + Formatting

+3

# After Submitting

---------

Co-authored-by: Yash Thakur <45539777+ysthakur@users.noreply.github.com>
This commit is contained in:
zc he
2025-07-25 02:21:58 +08:00
committed by GitHub
parent 1b01625e1e
commit 71baeff287
12 changed files with 194 additions and 144 deletions

View File

@ -97,8 +97,11 @@ fn extern_completer() -> NuCompleter {
// Add record value as example
let record = r#"
def animals [] { [ "cat", "dog", "eel" ] }
def fruits [] { [ "apple", "banana" ] }
extern spam [
animal: string@animals
fruit?: string@fruits
...rest: string@animals
--foo (-f): string@animals
-b: string@animals
]
@ -2261,6 +2264,22 @@ fn extern_custom_completion_positional(mut extern_completer: NuCompleter) {
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_optional(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam foo -f bar ", 16);
let expected: Vec<_> = vec!["apple", "banana"];
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_rest(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam foo -f bar baz ", 20);
let expected: Vec<_> = vec!["cat", "dog", "eel"];
match_suggestions(&expected, &suggestions);
let suggestions = extern_completer.complete("spam foo -f bar baz qux ", 24);
match_suggestions(&expected, &suggestions);
}
#[rstest]
fn extern_custom_completion_long_flag_1(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam --foo=", 11);
@ -2289,6 +2308,17 @@ fn extern_custom_completion_short_flag(mut extern_completer: NuCompleter) {
match_suggestions(&expected, &suggestions);
}
/// When we're completing the flag name itself, not its value,
/// custom completions should not be used
#[rstest]
fn custom_completion_flag_name_not_value(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam --f", 8);
match_suggestions(&vec!["--foo"], &suggestions);
// Also test with partial short flag
let suggestions = extern_completer.complete("spam -f", 7);
match_suggestions(&vec!["-f"], &suggestions);
}
#[rstest]
fn extern_complete_flags(mut extern_completer: NuCompleter) {
let suggestions = extern_completer.complete("spam -", 6);