Pass Stack ref to Completer::fetch (#12783)

# Description
Adds an additional `&Stack` parameter to `Completer::fetch` so that the
completers don't have to store a `Stack` themselves. I also removed
unnecessary `EngineState`s from the completers, since the same
`EngineState` is available in the `working_set.permanent_state` also
passed to `Completer::fetch`.
This commit is contained in:
Ian Manske 2024-05-09 05:38:24 +00:00 committed by GitHub
parent 3b3f48202c
commit 7271ad7909
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 146 additions and 183 deletions

View File

@ -1,13 +1,18 @@
use crate::completions::{CompletionOptions, SortBy}; use crate::completions::{CompletionOptions, SortBy};
use nu_protocol::{engine::StateWorkingSet, levenshtein_distance, Span}; use nu_protocol::{
engine::{Stack, StateWorkingSet},
levenshtein_distance, Span,
};
use reedline::Suggestion; use reedline::Suggestion;
// Completer trait represents the three stages of the completion // Completer trait represents the three stages of the completion
// fetch, filter and sort // fetch, filter and sort
pub trait Completer { pub trait Completer {
#[allow(clippy::too_many_arguments)]
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,

View File

@ -4,16 +4,14 @@ use crate::{
}; };
use nu_parser::FlatShape; use nu_parser::FlatShape;
use nu_protocol::{ use nu_protocol::{
engine::{CachedFile, EngineState, StateWorkingSet}, engine::{CachedFile, Stack, StateWorkingSet},
Span, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::sync::Arc;
use super::SemanticSuggestion; use super::SemanticSuggestion;
pub struct CommandCompletion { pub struct CommandCompletion {
engine_state: Arc<EngineState>,
flattened: Vec<(Span, FlatShape)>, flattened: Vec<(Span, FlatShape)>,
flat_shape: FlatShape, flat_shape: FlatShape,
force_completion_after_space: bool, force_completion_after_space: bool,
@ -21,14 +19,11 @@ pub struct CommandCompletion {
impl CommandCompletion { impl CommandCompletion {
pub fn new( pub fn new(
engine_state: Arc<EngineState>,
_: &StateWorkingSet,
flattened: Vec<(Span, FlatShape)>, flattened: Vec<(Span, FlatShape)>,
flat_shape: FlatShape, flat_shape: FlatShape,
force_completion_after_space: bool, force_completion_after_space: bool,
) -> Self { ) -> Self {
Self { Self {
engine_state,
flattened, flattened,
flat_shape, flat_shape,
force_completion_after_space, force_completion_after_space,
@ -37,13 +32,14 @@ impl CommandCompletion {
fn external_command_completion( fn external_command_completion(
&self, &self,
working_set: &StateWorkingSet,
prefix: &str, prefix: &str,
match_algorithm: MatchAlgorithm, match_algorithm: MatchAlgorithm,
) -> Vec<String> { ) -> Vec<String> {
let mut executables = vec![]; let mut executables = vec![];
// os agnostic way to get the PATH env var // os agnostic way to get the PATH env var
let paths = self.engine_state.get_path_env_var(); let paths = working_set.permanent_state.get_path_env_var();
if let Some(paths) = paths { if let Some(paths) = paths {
if let Ok(paths) = paths.as_list() { if let Ok(paths) = paths.as_list() {
@ -52,7 +48,10 @@ impl CommandCompletion {
if let Ok(mut contents) = std::fs::read_dir(path.as_ref()) { if let Ok(mut contents) = std::fs::read_dir(path.as_ref()) {
while let Some(Ok(item)) = contents.next() { while let Some(Ok(item)) = contents.next() {
if self.engine_state.config.max_external_completion_results if working_set
.permanent_state
.config
.max_external_completion_results
> executables.len() as i64 > executables.len() as i64
&& !executables.contains( && !executables.contains(
&item &item
@ -114,7 +113,7 @@ impl CommandCompletion {
if find_externals { if find_externals {
let results_external = self let results_external = self
.external_command_completion(&partial, match_algorithm) .external_command_completion(working_set, &partial, match_algorithm)
.into_iter() .into_iter()
.map(move |x| SemanticSuggestion { .map(move |x| SemanticSuggestion {
suggestion: Suggestion { suggestion: Suggestion {
@ -161,6 +160,7 @@ impl Completer for CommandCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
_stack: &Stack,
_prefix: Vec<u8>, _prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
@ -266,6 +266,8 @@ pub fn is_passthrough_command(working_set_file_contents: &[CachedFile]) -> bool
#[cfg(test)] #[cfg(test)]
mod command_completions_tests { mod command_completions_tests {
use super::*; use super::*;
use nu_protocol::engine::EngineState;
use std::sync::Arc;
#[test] #[test]
fn test_find_non_whitespace_index() { fn test_find_non_whitespace_index() {

View File

@ -22,10 +22,10 @@ pub struct NuCompleter {
} }
impl NuCompleter { impl NuCompleter {
pub fn new(engine_state: Arc<EngineState>, stack: Stack) -> Self { pub fn new(engine_state: Arc<EngineState>, stack: Arc<Stack>) -> Self {
Self { Self {
engine_state, engine_state,
stack: stack.reset_out_dest().capture(), stack: Stack::with_parent(stack).reset_out_dest().capture(),
} }
} }
@ -52,8 +52,15 @@ impl NuCompleter {
}; };
// Fetch // Fetch
let mut suggestions = let mut suggestions = completer.fetch(
completer.fetch(working_set, prefix.clone(), new_span, offset, pos, &options); working_set,
&self.stack,
prefix.clone(),
new_span,
offset,
pos,
&options,
);
// Sort // Sort
suggestions = completer.sort(suggestions, prefix); suggestions = completer.sort(suggestions, prefix);
@ -175,11 +182,8 @@ impl NuCompleter {
// Variables completion // Variables completion
if prefix.starts_with(b"$") || most_left_var.is_some() { if prefix.starts_with(b"$") || most_left_var.is_some() {
let mut completer = VariableCompletion::new( let mut completer =
self.engine_state.clone(), VariableCompletion::new(most_left_var.unwrap_or((vec![], vec![])));
self.stack.clone(),
most_left_var.unwrap_or((vec![], vec![])),
);
return self.process_completion( return self.process_completion(
&mut completer, &mut completer,
@ -224,8 +228,6 @@ impl NuCompleter {
|| (flat_idx == 0 && working_set.get_span_contents(new_span).is_empty()) || (flat_idx == 0 && working_set.get_span_contents(new_span).is_empty())
{ {
let mut completer = CommandCompletion::new( let mut completer = CommandCompletion::new(
self.engine_state.clone(),
&working_set,
flattened.clone(), flattened.clone(),
// flat_idx, // flat_idx,
FlatShape::String, FlatShape::String,
@ -253,10 +255,7 @@ impl NuCompleter {
|| prev_expr_str == b"overlay use" || prev_expr_str == b"overlay use"
|| prev_expr_str == b"source-env" || prev_expr_str == b"source-env"
{ {
let mut completer = DotNuCompletion::new( let mut completer = DotNuCompletion::new();
self.engine_state.clone(),
self.stack.clone(),
);
return self.process_completion( return self.process_completion(
&mut completer, &mut completer,
@ -267,10 +266,7 @@ impl NuCompleter {
pos, pos,
); );
} else if prev_expr_str == b"ls" { } else if prev_expr_str == b"ls" {
let mut completer = FileCompletion::new( let mut completer = FileCompletion::new();
self.engine_state.clone(),
self.stack.clone(),
);
return self.process_completion( return self.process_completion(
&mut completer, &mut completer,
@ -288,7 +284,6 @@ impl NuCompleter {
match &flat.1 { match &flat.1 {
FlatShape::Custom(decl_id) => { FlatShape::Custom(decl_id) => {
let mut completer = CustomCompletion::new( let mut completer = CustomCompletion::new(
self.engine_state.clone(),
self.stack.clone(), self.stack.clone(),
*decl_id, *decl_id,
initial_line, initial_line,
@ -304,10 +299,7 @@ impl NuCompleter {
); );
} }
FlatShape::Directory => { FlatShape::Directory => {
let mut completer = DirectoryCompletion::new( let mut completer = DirectoryCompletion::new();
self.engine_state.clone(),
self.stack.clone(),
);
return self.process_completion( return self.process_completion(
&mut completer, &mut completer,
@ -319,10 +311,7 @@ impl NuCompleter {
); );
} }
FlatShape::Filepath | FlatShape::GlobPattern => { FlatShape::Filepath | FlatShape::GlobPattern => {
let mut completer = FileCompletion::new( let mut completer = FileCompletion::new();
self.engine_state.clone(),
self.stack.clone(),
);
return self.process_completion( return self.process_completion(
&mut completer, &mut completer,
@ -335,8 +324,6 @@ impl NuCompleter {
} }
flat_shape => { flat_shape => {
let mut completer = CommandCompletion::new( let mut completer = CommandCompletion::new(
self.engine_state.clone(),
&working_set,
flattened.clone(), flattened.clone(),
// flat_idx, // flat_idx,
flat_shape.clone(), flat_shape.clone(),
@ -369,10 +356,7 @@ impl NuCompleter {
} }
// Check for file completion // Check for file completion
let mut completer = FileCompletion::new( let mut completer = FileCompletion::new();
self.engine_state.clone(),
self.stack.clone(),
);
out = self.process_completion( out = self.process_completion(
&mut completer, &mut completer,
&working_set, &working_set,
@ -557,7 +541,7 @@ mod completer_tests {
result.err().unwrap() result.err().unwrap()
); );
let mut completer = NuCompleter::new(engine_state.into(), Stack::new()); let mut completer = NuCompleter::new(engine_state.into(), Arc::new(Stack::new()));
let dataset = [ let dataset = [
("sudo", false, "", Vec::new()), ("sudo", false, "", Vec::new()),
("sudo l", true, "l", vec!["ls", "let", "lines", "loop"]), ("sudo l", true, "l", vec!["ls", "let", "lines", "loop"]),

View File

@ -6,14 +6,13 @@ use nu_engine::eval_call;
use nu_protocol::{ use nu_protocol::{
ast::{Argument, Call, Expr, Expression}, ast::{Argument, Call, Expr, Expression},
debugger::WithoutDebug, debugger::WithoutDebug,
engine::{EngineState, Stack, StateWorkingSet}, engine::{Stack, StateWorkingSet},
PipelineData, Span, Type, Value, PipelineData, Span, Type, Value,
}; };
use nu_utils::IgnoreCaseExt; use nu_utils::IgnoreCaseExt;
use std::{collections::HashMap, sync::Arc}; use std::collections::HashMap;
pub struct CustomCompletion { pub struct CustomCompletion {
engine_state: Arc<EngineState>,
stack: Stack, stack: Stack,
decl_id: usize, decl_id: usize,
line: String, line: String,
@ -21,10 +20,9 @@ pub struct CustomCompletion {
} }
impl CustomCompletion { impl CustomCompletion {
pub fn new(engine_state: Arc<EngineState>, stack: Stack, decl_id: usize, line: String) -> Self { pub fn new(stack: Stack, decl_id: usize, line: String) -> Self {
Self { Self {
engine_state, stack,
stack: stack.reset_out_dest().capture(),
decl_id, decl_id,
line, line,
sort_by: SortBy::None, sort_by: SortBy::None,
@ -35,7 +33,8 @@ impl CustomCompletion {
impl Completer for CustomCompletion { impl Completer for CustomCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
_: &StateWorkingSet, working_set: &StateWorkingSet,
_stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
@ -47,7 +46,7 @@ impl Completer for CustomCompletion {
// Call custom declaration // Call custom declaration
let result = eval_call::<WithoutDebug>( let result = eval_call::<WithoutDebug>(
&self.engine_state, working_set.permanent_state,
&mut self.stack, &mut self.stack,
&Call { &Call {
decl_id: self.decl_id, decl_id: self.decl_id,

View File

@ -8,25 +8,16 @@ use nu_protocol::{
levenshtein_distance, Span, levenshtein_distance, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::{ use std::path::{Path, MAIN_SEPARATOR as SEP};
path::{Path, MAIN_SEPARATOR as SEP},
sync::Arc,
};
use super::SemanticSuggestion; use super::SemanticSuggestion;
#[derive(Clone)] #[derive(Clone, Default)]
pub struct DirectoryCompletion { pub struct DirectoryCompletion {}
engine_state: Arc<EngineState>,
stack: Stack,
}
impl DirectoryCompletion { impl DirectoryCompletion {
pub fn new(engine_state: Arc<EngineState>, stack: Stack) -> Self { pub fn new() -> Self {
Self { Self::default()
engine_state,
stack,
}
} }
} }
@ -34,10 +25,11 @@ impl Completer for DirectoryCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
_: usize, _pos: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<SemanticSuggestion> { ) -> Vec<SemanticSuggestion> {
let AdjustView { prefix, span, .. } = adjust_if_intermediate(&prefix, working_set, span); let AdjustView { prefix, span, .. } = adjust_if_intermediate(&prefix, working_set, span);
@ -47,10 +39,10 @@ impl Completer for DirectoryCompletion {
let output: Vec<_> = directory_completion( let output: Vec<_> = directory_completion(
span, span,
&prefix, &prefix,
&self.engine_state.current_work_dir(), &working_set.permanent_state.current_work_dir(),
options, options,
self.engine_state.as_ref(), working_set.permanent_state,
&self.stack, stack,
) )
.into_iter() .into_iter()
.map(move |x| SemanticSuggestion { .map(move |x| SemanticSuggestion {

View File

@ -1,39 +1,31 @@
use crate::completions::{file_path_completion, Completer, CompletionOptions, SortBy}; use crate::completions::{file_path_completion, Completer, CompletionOptions, SortBy};
use nu_protocol::{ use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet}, engine::{Stack, StateWorkingSet},
Span, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::{ use std::path::{is_separator, Path, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR};
path::{is_separator, Path, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR},
sync::Arc,
};
use super::SemanticSuggestion; use super::SemanticSuggestion;
#[derive(Clone)] #[derive(Clone, Default)]
pub struct DotNuCompletion { pub struct DotNuCompletion {}
engine_state: Arc<EngineState>,
stack: Stack,
}
impl DotNuCompletion { impl DotNuCompletion {
pub fn new(engine_state: Arc<EngineState>, stack: Stack) -> Self { pub fn new() -> Self {
Self { Self::default()
engine_state,
stack,
}
} }
} }
impl Completer for DotNuCompletion { impl Completer for DotNuCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
_: &StateWorkingSet, working_set: &StateWorkingSet,
stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
_: usize, _pos: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<SemanticSuggestion> { ) -> Vec<SemanticSuggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).replace('`', ""); let prefix_str = String::from_utf8_lossy(&prefix).replace('`', "");
@ -49,8 +41,7 @@ impl Completer for DotNuCompletion {
let mut is_current_folder = false; let mut is_current_folder = false;
// Fetch the lib dirs // Fetch the lib dirs
let lib_dirs: Vec<String> = let lib_dirs: Vec<String> = if let Some(lib_dirs) = working_set.get_env_var("NU_LIB_DIRS") {
if let Some(lib_dirs) = self.engine_state.get_env_var("NU_LIB_DIRS") {
lib_dirs lib_dirs
.as_list() .as_list()
.into_iter() .into_iter()
@ -85,7 +76,7 @@ impl Completer for DotNuCompletion {
} else { } else {
// Fetch the current folder // Fetch the current folder
#[allow(deprecated)] #[allow(deprecated)]
let current_folder = self.engine_state.current_work_dir(); let current_folder = working_set.permanent_state.current_work_dir();
is_current_folder = true; is_current_folder = true;
// Add the current folder and the lib dirs into the // Add the current folder and the lib dirs into the
@ -104,8 +95,8 @@ impl Completer for DotNuCompletion {
&partial, &partial,
&search_dir, &search_dir,
options, options,
self.engine_state.as_ref(), working_set.permanent_state,
&self.stack, stack,
); );
completions completions
.into_iter() .into_iter()

View File

@ -9,25 +9,16 @@ use nu_protocol::{
}; };
use nu_utils::IgnoreCaseExt; use nu_utils::IgnoreCaseExt;
use reedline::Suggestion; use reedline::Suggestion;
use std::{ use std::path::{Path, MAIN_SEPARATOR as SEP};
path::{Path, MAIN_SEPARATOR as SEP},
sync::Arc,
};
use super::SemanticSuggestion; use super::SemanticSuggestion;
#[derive(Clone)] #[derive(Clone, Default)]
pub struct FileCompletion { pub struct FileCompletion {}
engine_state: Arc<EngineState>,
stack: Stack,
}
impl FileCompletion { impl FileCompletion {
pub fn new(engine_state: Arc<EngineState>, stack: Stack) -> Self { pub fn new() -> Self {
Self { Self::default()
engine_state,
stack,
}
} }
} }
@ -35,10 +26,11 @@ impl Completer for FileCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
_: usize, _pos: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<SemanticSuggestion> { ) -> Vec<SemanticSuggestion> {
let AdjustView { let AdjustView {
@ -52,10 +44,10 @@ impl Completer for FileCompletion {
readjusted, readjusted,
span, span,
&prefix, &prefix,
&self.engine_state.current_work_dir(), &working_set.permanent_state.current_work_dir(),
options, options,
self.engine_state.as_ref(), working_set.permanent_state,
&self.stack, stack,
) )
.into_iter() .into_iter()
.map(move |x| SemanticSuggestion { .map(move |x| SemanticSuggestion {

View File

@ -1,7 +1,7 @@
use crate::completions::{Completer, CompletionOptions}; use crate::completions::{Completer, CompletionOptions};
use nu_protocol::{ use nu_protocol::{
ast::{Expr, Expression}, ast::{Expr, Expression},
engine::StateWorkingSet, engine::{Stack, StateWorkingSet},
Span, Span,
}; };
use reedline::Suggestion; use reedline::Suggestion;
@ -23,10 +23,11 @@ impl Completer for FlagCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
_stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
_: usize, _pos: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<SemanticSuggestion> { ) -> Vec<SemanticSuggestion> {
// Check if it's a flag // Check if it's a flag

View File

@ -3,30 +3,20 @@ use crate::completions::{
}; };
use nu_engine::{column::get_columns, eval_variable}; use nu_engine::{column::get_columns, eval_variable};
use nu_protocol::{ use nu_protocol::{
engine::{EngineState, Stack, StateWorkingSet}, engine::{Stack, StateWorkingSet},
Span, Value, Span, Value,
}; };
use reedline::Suggestion; use reedline::Suggestion;
use std::{str, sync::Arc}; use std::str;
#[derive(Clone)] #[derive(Clone)]
pub struct VariableCompletion { pub struct VariableCompletion {
engine_state: Arc<EngineState>, // TODO: Is engine state necessary? It's already a part of working set in fetch()
stack: Stack,
var_context: (Vec<u8>, Vec<Vec<u8>>), // tuple with $var and the sublevels (.b.c.d) var_context: (Vec<u8>, Vec<Vec<u8>>), // tuple with $var and the sublevels (.b.c.d)
} }
impl VariableCompletion { impl VariableCompletion {
pub fn new( pub fn new(var_context: (Vec<u8>, Vec<Vec<u8>>)) -> Self {
engine_state: Arc<EngineState>, Self { var_context }
stack: Stack,
var_context: (Vec<u8>, Vec<Vec<u8>>),
) -> Self {
Self {
engine_state,
stack,
var_context,
}
} }
} }
@ -34,10 +24,11 @@ impl Completer for VariableCompletion {
fn fetch( fn fetch(
&mut self, &mut self,
working_set: &StateWorkingSet, working_set: &StateWorkingSet,
stack: &Stack,
prefix: Vec<u8>, prefix: Vec<u8>,
span: Span, span: Span,
offset: usize, offset: usize,
_: usize, _pos: usize,
options: &CompletionOptions, options: &CompletionOptions,
) -> Vec<SemanticSuggestion> { ) -> Vec<SemanticSuggestion> {
let mut output = vec![]; let mut output = vec![];
@ -54,7 +45,7 @@ impl Completer for VariableCompletion {
if !var_str.is_empty() { if !var_str.is_empty() {
// Completion for $env.<tab> // Completion for $env.<tab>
if var_str == "$env" { if var_str == "$env" {
let env_vars = self.stack.get_env_vars(&self.engine_state); let env_vars = stack.get_env_vars(working_set.permanent_state);
// Return nested values // Return nested values
if sublevels_count > 0 { if sublevels_count > 0 {
@ -110,8 +101,8 @@ impl Completer for VariableCompletion {
if var_str == "$nu" { if var_str == "$nu" {
// Eval nu var // Eval nu var
if let Ok(nuval) = eval_variable( if let Ok(nuval) = eval_variable(
&self.engine_state, working_set.permanent_state,
&self.stack, stack,
nu_protocol::NU_VARIABLE_ID, nu_protocol::NU_VARIABLE_ID,
nu_protocol::Span::new(current_span.start, current_span.end), nu_protocol::Span::new(current_span.start, current_span.end),
) { ) {
@ -133,7 +124,7 @@ impl Completer for VariableCompletion {
// Completion other variable types // Completion other variable types
if let Some(var_id) = var_id { if let Some(var_id) = var_id {
// Extract the variable value from the stack // Extract the variable value from the stack
let var = self.stack.get_var(var_id, Span::new(span.start, span.end)); let var = stack.get_var(var_id, Span::new(span.start, span.end));
// If the value exists and it's of type Record // If the value exists and it's of type Record
if let Ok(value) = var { if let Ok(value) = var {
@ -207,7 +198,11 @@ impl Completer for VariableCompletion {
// Permanent state vars // Permanent state vars
// for scope in &self.engine_state.scope { // for scope in &self.engine_state.scope {
for overlay_frame in self.engine_state.active_overlays(&removed_overlays).rev() { for overlay_frame in working_set
.permanent_state
.active_overlays(&removed_overlays)
.rev()
{
for v in &overlay_frame.vars { for v in &overlay_frame.vars {
if options.match_algorithm.matches_u8_insensitive( if options.match_algorithm.matches_u8_insensitive(
options.case_sensitive, options.case_sensitive,

View File

@ -389,7 +389,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) {
.with_completer(Box::new(NuCompleter::new( .with_completer(Box::new(NuCompleter::new(
engine_reference.clone(), engine_reference.clone(),
// STACK-REFERENCE 2 // STACK-REFERENCE 2
Stack::with_parent(stack_arc.clone()), stack_arc.clone(),
))) )))
.with_quick_completions(config.quick_completions) .with_quick_completions(config.quick_completions)
.with_partial_completions(config.partial_completions) .with_partial_completions(config.partial_completions)

View File

@ -6,7 +6,10 @@ use nu_parser::parse;
use nu_protocol::{debugger::WithoutDebug, engine::StateWorkingSet, PipelineData}; use nu_protocol::{debugger::WithoutDebug, engine::StateWorkingSet, PipelineData};
use reedline::{Completer, Suggestion}; use reedline::{Completer, Suggestion};
use rstest::{fixture, rstest}; use rstest::{fixture, rstest};
use std::path::{PathBuf, MAIN_SEPARATOR}; use std::{
path::{PathBuf, MAIN_SEPARATOR},
sync::Arc,
};
use support::{ use support::{
completions_helpers::{new_partial_engine, new_quote_engine}, completions_helpers::{new_partial_engine, new_quote_engine},
file, folder, match_suggestions, new_engine, file, folder, match_suggestions, new_engine,
@ -22,7 +25,7 @@ fn completer() -> NuCompleter {
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
NuCompleter::new(std::sync::Arc::new(engine), stack) NuCompleter::new(Arc::new(engine), Arc::new(stack))
} }
#[fixture] #[fixture]
@ -36,7 +39,7 @@ fn completer_strings() -> NuCompleter {
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
NuCompleter::new(std::sync::Arc::new(engine), stack) NuCompleter::new(Arc::new(engine), Arc::new(stack))
} }
#[fixture] #[fixture]
@ -56,7 +59,7 @@ fn extern_completer() -> NuCompleter {
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
NuCompleter::new(std::sync::Arc::new(engine), stack) NuCompleter::new(Arc::new(engine), Arc::new(stack))
} }
#[fixture] #[fixture]
@ -79,14 +82,14 @@ fn custom_completer() -> NuCompleter {
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
NuCompleter::new(std::sync::Arc::new(engine), stack) NuCompleter::new(Arc::new(engine), Arc::new(stack))
} }
#[test] #[test]
fn variables_dollar_sign_with_varialblecompletion() { fn variables_dollar_sign_with_varialblecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "$ "; let target_dir = "$ ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -138,7 +141,7 @@ fn dotnu_completions() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test source completion // Test source completion
let completion_str = "source-env ".to_string(); let completion_str = "source-env ".to_string();
@ -217,7 +220,7 @@ fn file_completions() {
let (dir, dir_str, engine, stack) = new_engine(); let (dir, dir_str, engine, stack) = new_engine();
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the current folder // Test completions for the current folder
let target_dir = format!("cp {dir_str}{MAIN_SEPARATOR}"); let target_dir = format!("cp {dir_str}{MAIN_SEPARATOR}");
@ -265,7 +268,7 @@ fn partial_completions() {
let (dir, _, engine, stack) = new_partial_engine(); let (dir, _, engine, stack) = new_partial_engine();
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for a folder's name // Test completions for a folder's name
let target_dir = format!("cd {}", file(dir.join("pa"))); let target_dir = format!("cd {}", file(dir.join("pa")));
@ -363,7 +366,7 @@ fn partial_completions() {
fn command_ls_with_filecompletion() { fn command_ls_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "ls "; let target_dir = "ls ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -397,7 +400,7 @@ fn command_ls_with_filecompletion() {
fn command_open_with_filecompletion() { fn command_open_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "open "; let target_dir = "open ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -432,7 +435,7 @@ fn command_open_with_filecompletion() {
fn command_rm_with_globcompletion() { fn command_rm_with_globcompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "rm "; let target_dir = "rm ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -467,7 +470,7 @@ fn command_rm_with_globcompletion() {
fn command_cp_with_globcompletion() { fn command_cp_with_globcompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "cp "; let target_dir = "cp ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -502,7 +505,7 @@ fn command_cp_with_globcompletion() {
fn command_save_with_filecompletion() { fn command_save_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "save "; let target_dir = "save ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -537,7 +540,7 @@ fn command_save_with_filecompletion() {
fn command_touch_with_filecompletion() { fn command_touch_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "touch "; let target_dir = "touch ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -572,7 +575,7 @@ fn command_touch_with_filecompletion() {
fn command_watch_with_filecompletion() { fn command_watch_with_filecompletion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "watch "; let target_dir = "watch ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -607,7 +610,7 @@ fn command_watch_with_filecompletion() {
fn file_completion_quoted() { fn file_completion_quoted() {
let (_, _, engine, stack) = new_quote_engine(); let (_, _, engine, stack) = new_quote_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "open "; let target_dir = "open ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -645,7 +648,7 @@ fn flag_completions() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the 'ls' flags // Test completions for the 'ls' flags
let suggestions = completer.complete("ls -", 4); let suggestions = completer.complete("ls -", 4);
@ -680,7 +683,7 @@ fn folder_with_directorycompletions() {
let (dir, dir_str, engine, stack) = new_engine(); let (dir, dir_str, engine, stack) = new_engine();
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for the current folder // Test completions for the current folder
let target_dir = format!("cd {dir_str}{MAIN_SEPARATOR}"); let target_dir = format!("cd {dir_str}{MAIN_SEPARATOR}");
@ -709,7 +712,7 @@ fn variables_completions() {
assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(record.as_bytes(), &mut engine, &mut stack, dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Test completions for $nu // Test completions for $nu
let suggestions = completer.complete("$nu.", 4); let suggestions = completer.complete("$nu.", 4);
@ -815,7 +818,7 @@ fn alias_of_command_and_flags() {
let alias = r#"alias ll = ls -l"#; let alias = r#"alias ll = ls -l"#;
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let suggestions = completer.complete("ll t", 4); let suggestions = completer.complete("ll t", 4);
#[cfg(windows)] #[cfg(windows)]
@ -834,7 +837,7 @@ fn alias_of_basic_command() {
let alias = r#"alias ll = ls "#; let alias = r#"alias ll = ls "#;
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let suggestions = completer.complete("ll t", 4); let suggestions = completer.complete("ll t", 4);
#[cfg(windows)] #[cfg(windows)]
@ -856,7 +859,7 @@ fn alias_of_another_alias() {
let alias = r#"alias lf = ll -f"#; let alias = r#"alias lf = ll -f"#;
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let suggestions = completer.complete("lf t", 4); let suggestions = completer.complete("lf t", 4);
#[cfg(windows)] #[cfg(windows)]
@ -890,7 +893,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec<Suggestion> {
assert!(engine_state.merge_env(&mut stack, &dir).is_ok()); assert!(engine_state.merge_env(&mut stack, &dir).is_ok());
// Instantiate a new completer // Instantiate a new completer
let mut completer = NuCompleter::new(std::sync::Arc::new(engine_state), stack); let mut completer = NuCompleter::new(Arc::new(engine_state), Arc::new(stack));
completer.complete(input, input.len()) completer.complete(input, input.len())
} }
@ -899,7 +902,7 @@ fn run_external_completion(completer: &str, input: &str) -> Vec<Suggestion> {
fn unknown_command_completion() { fn unknown_command_completion() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let target_dir = "thiscommanddoesnotexist "; let target_dir = "thiscommanddoesnotexist ";
let suggestions = completer.complete(target_dir, target_dir.len()); let suggestions = completer.complete(target_dir, target_dir.len());
@ -962,7 +965,7 @@ fn flagcompletion_triggers_after_cursor_piped(mut completer: NuCompleter) {
fn filecompletions_triggers_after_cursor() { fn filecompletions_triggers_after_cursor() {
let (_, _, engine, stack) = new_engine(); let (_, _, engine, stack) = new_engine();
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
let suggestions = completer.complete("cp test_c", 3); let suggestions = completer.complete("cp test_c", 3);
@ -1071,7 +1074,7 @@ fn alias_offset_bug_7648() {
let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#; let alias = r#"alias ea = ^$env.EDITOR /tmp/test.s"#;
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Issue #7648 // Issue #7648
// Nushell crashes when an alias name is shorter than the alias command // Nushell crashes when an alias name is shorter than the alias command
@ -1090,7 +1093,7 @@ fn alias_offset_bug_7754() {
let alias = r#"alias ll = ls -l"#; let alias = r#"alias ll = ls -l"#;
assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok()); assert!(support::merge_input(alias.as_bytes(), &mut engine, &mut stack, dir).is_ok());
let mut completer = NuCompleter::new(std::sync::Arc::new(engine), stack); let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
// Issue #7754 // Issue #7754
// Nushell crashes when an alias name is shorter than the alias command // Nushell crashes when an alias name is shorter than the alias command

View File

@ -552,8 +552,8 @@ impl LanguageServer {
&params.text_document_position.text_document.uri, &params.text_document_position.text_document.uri,
)?; )?;
let stack = Stack::new(); let mut completer =
let mut completer = NuCompleter::new(Arc::new(engine_state.clone()), stack); NuCompleter::new(Arc::new(engine_state.clone()), Arc::new(Stack::new()));
let location = let location =
Self::lsp_position_to_location(&params.text_document_position.position, rope_of_file); Self::lsp_position_to_location(&params.text_document_position.position, rope_of_file);

View File

@ -606,8 +606,7 @@ pub fn hover(engine_state: &mut EngineState, file_path: &str, location: &Value)
} }
pub fn complete(engine_reference: Arc<EngineState>, file_path: &str, location: &Value) { pub fn complete(engine_reference: Arc<EngineState>, file_path: &str, location: &Value) {
let stack = Stack::new(); let mut completer = NuCompleter::new(engine_reference, Arc::new(Stack::new()));
let mut completer = NuCompleter::new(engine_reference, stack);
let file = std::fs::read(file_path) let file = std::fs::read(file_path)
.into_diagnostic() .into_diagnostic()