fix(completion): inline defined custom completion (#15318)

Fixes #6001 

# Description

<img width="485" alt="image"
src="https://github.com/user-attachments/assets/5aad23ee-07ec-4f1b-8410-a484c2210cd3"
/>

# User-Facing Changes

# Tests + Formatting

+1

# After Submitting
This commit is contained in:
zc he 2025-03-20 23:44:41 +08:00 committed by GitHub
parent 8b80ceac32
commit 2b4914608e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 23 deletions

View File

@ -5,7 +5,7 @@ use nu_engine::eval_call;
use nu_protocol::{
ast::{Argument, Call, Expr, Expression},
debugger::WithoutDebug,
engine::{Stack, StateWorkingSet},
engine::{EngineState, Stack, StateWorkingSet},
DeclId, PipelineData, Span, Type, Value,
};
use std::collections::HashMap;
@ -42,28 +42,37 @@ impl<T: Completer> Completer for CustomCompletion<T> {
) -> Vec<SemanticSuggestion> {
// Call custom declaration
let mut stack_mut = stack.clone();
let result = eval_call::<WithoutDebug>(
working_set.permanent_state,
&mut stack_mut,
&Call {
decl_id: self.decl_id,
head: span,
arguments: vec![
Argument::Positional(Expression::new_unknown(
Expr::String(self.line.clone()),
Span::unknown(),
Type::String,
)),
Argument::Positional(Expression::new_unknown(
Expr::Int(self.line_pos as i64),
Span::unknown(),
Type::Int,
)),
],
parser_info: HashMap::new(),
},
PipelineData::empty(),
);
let mut eval = |engine_state: &EngineState| {
eval_call::<WithoutDebug>(
engine_state,
&mut stack_mut,
&Call {
decl_id: self.decl_id,
head: span,
arguments: vec![
Argument::Positional(Expression::new_unknown(
Expr::String(self.line.clone()),
Span::unknown(),
Type::String,
)),
Argument::Positional(Expression::new_unknown(
Expr::Int(self.line_pos as i64),
Span::unknown(),
Type::Int,
)),
],
parser_info: HashMap::new(),
},
PipelineData::empty(),
)
};
let result = if self.decl_id.get() < working_set.permanent_state.num_decls() {
eval(working_set.permanent_state)
} else {
let mut engine_state = working_set.permanent_state.clone();
let _ = engine_state.merge_delta(working_set.delta.clone());
eval(&engine_state)
};
let mut completion_options = orig_options.clone();
let mut should_sort = true;

View File

@ -350,6 +350,21 @@ fn custom_arguments_vs_subcommands() {
match_suggestions(&expected, &suggestions);
}
#[test]
fn custom_completions_defined_inline() {
let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let completion_str = "def animals [] { [cat dog] }
export def say [
animal: string@animals
] { }; say ";
let suggestions = completer.complete(completion_str, completion_str.len());
// including only subcommand completions
let expected: Vec<_> = vec!["cat", "dog"];
match_suggestions(&expected, &suggestions);
}
/// External command only if starts with `^`
#[test]
fn external_commands_only() {