diff --git a/crates/nu-cli/src/completions/base.rs b/crates/nu-cli/src/completions/base.rs index ee56d693bf..9c00d679ae 100644 --- a/crates/nu-cli/src/completions/base.rs +++ b/crates/nu-cli/src/completions/base.rs @@ -1,4 +1,4 @@ -use crate::completions::{CompletionOptions, SortBy}; +use crate::completions::SortBy; use nu_protocol::{engine::StateWorkingSet, levenshtein_distance, Span}; use reedline::Suggestion; @@ -12,50 +12,18 @@ pub trait Completer { span: Span, offset: usize, pos: usize, - ) -> (Vec, CompletionOptions); + ) -> Vec; - // Filter results using the completion options - fn filter( - &self, - prefix: Vec, - items: Vec, - options: CompletionOptions, - ) -> Vec { - items - .into_iter() - .filter(|it| { - // Minimise clones for new functionality - match (options.case_sensitive, options.positional) { - (true, true) => it.value.as_bytes().starts_with(&prefix), - (true, false) => it - .value - .contains(std::str::from_utf8(&prefix).unwrap_or("")), - (false, positional) => { - let value = it.value.to_lowercase(); - let prefix = std::str::from_utf8(&prefix).unwrap_or("").to_lowercase(); - if positional { - value.starts_with(&prefix) - } else { - value.contains(&prefix) - } - } - } - }) - .collect() + fn get_sort_by(&self) -> SortBy { + SortBy::Ascending } - // Sort results using the completion options - fn sort( - &self, - items: Vec, - prefix: Vec, - options: CompletionOptions, - ) -> Vec { + fn sort(&self, items: Vec, prefix: Vec) -> Vec { let prefix_str = String::from_utf8_lossy(&prefix).to_string(); let mut filtered_items = items; // Sort items - match options.sort_by { + match self.get_sort_by() { SortBy::LevenshteinDistance => { filtered_items.sort_by(|a, b| { let a_distance = levenshtein_distance(&prefix_str, &a.value); diff --git a/crates/nu-cli/src/completions/command_completions.rs b/crates/nu-cli/src/completions/command_completions.rs index 38f83e2504..32c8407e0e 100644 --- a/crates/nu-cli/src/completions/command_completions.rs +++ b/crates/nu-cli/src/completions/command_completions.rs @@ -1,6 +1,4 @@ -use crate::completions::{ - file_completions::file_path_completion, Completer, CompletionOptions, SortBy, -}; +use crate::completions::{file_completions::file_path_completion, Completer, SortBy}; use nu_parser::{trim_quotes, FlatShape}; use nu_protocol::{ engine::{EngineState, StateWorkingSet}, @@ -154,7 +152,7 @@ impl Completer for CommandCompletion { span: Span, offset: usize, pos: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { let last = self .flattened .iter() @@ -172,9 +170,6 @@ impl Completer for CommandCompletion { }) .last(); - // Options - let options = CompletionOptions::new(true, true, SortBy::LevenshteinDistance); - // The last item here would be the earliest shape that could possible by part of this subcommand let subcommands = if let Some(last) = last { self.complete_commands( @@ -191,7 +186,7 @@ impl Completer for CommandCompletion { }; if !subcommands.is_empty() { - return (subcommands, options); + return subcommands; } let commands = if matches!(self.flat_shape, nu_parser::FlatShape::External) @@ -225,7 +220,8 @@ impl Completer for CommandCompletion { }; // let prefix = working_set.get_span_contents(flat.0); let prefix = String::from_utf8_lossy(&prefix).to_string(); - let output = file_path_completion(span, &prefix, &cwd) + + file_path_completion(span, &prefix, &cwd) .into_iter() .map(move |x| { if self.flat_idx == 0 { @@ -262,13 +258,10 @@ impl Completer for CommandCompletion { }) .chain(subcommands.into_iter()) .chain(commands.into_iter()) - .collect::>(); - - (output, options) + .collect::>() } - // Replace base filter with no filter once all the results are already based in the current path - fn filter(&self, _: Vec, items: Vec, _: CompletionOptions) -> Vec { - items + fn get_sort_by(&self) -> SortBy { + SortBy::LevenshteinDistance } } diff --git a/crates/nu-cli/src/completions/completer.rs b/crates/nu-cli/src/completions/completer.rs index 61af34baed..0309e08ab1 100644 --- a/crates/nu-cli/src/completions/completer.rs +++ b/crates/nu-cli/src/completions/completer.rs @@ -36,14 +36,10 @@ impl NuCompleter { pos: usize, ) -> Vec { // Fetch - let (mut suggestions, options) = - completer.fetch(working_set, prefix.clone(), new_span, offset, pos); - - // Filter - suggestions = completer.filter(prefix.clone(), suggestions, options.clone()); + let mut suggestions = completer.fetch(working_set, prefix.clone(), new_span, offset, pos); // Sort - suggestions = completer.sort(suggestions, prefix, options); + suggestions = completer.sort(suggestions, prefix); suggestions } diff --git a/crates/nu-cli/src/completions/completion_options.rs b/crates/nu-cli/src/completions/completion_options.rs index 19e2469eb7..414c966b39 100644 --- a/crates/nu-cli/src/completions/completion_options.rs +++ b/crates/nu-cli/src/completions/completion_options.rs @@ -1,4 +1,4 @@ -#[derive(Clone)] +#[derive(Copy, Clone)] pub enum SortBy { LevenshteinDistance, Ascending, @@ -12,16 +12,6 @@ pub struct CompletionOptions { pub sort_by: SortBy, } -impl CompletionOptions { - pub fn new(case_sensitive: bool, positional: bool, sort_by: SortBy) -> Self { - Self { - case_sensitive, - positional, - sort_by, - } - } -} - impl Default for CompletionOptions { fn default() -> Self { Self { diff --git a/crates/nu-cli/src/completions/custom_completions.rs b/crates/nu-cli/src/completions/custom_completions.rs index 49df473023..48940c2cd8 100644 --- a/crates/nu-cli/src/completions/custom_completions.rs +++ b/crates/nu-cli/src/completions/custom_completions.rs @@ -13,6 +13,7 @@ pub struct CustomCompletion { stack: Stack, decl_id: usize, line: String, + sort_by: SortBy, } impl CustomCompletion { @@ -22,6 +23,7 @@ impl CustomCompletion { stack, decl_id, line, + sort_by: SortBy::None, } } @@ -55,11 +57,11 @@ impl Completer for CustomCompletion { fn fetch( &mut self, _: &StateWorkingSet, - _: Vec, + prefix: Vec, span: Span, offset: usize, pos: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { // Line position let line_pos = pos - offset; @@ -113,6 +115,10 @@ impl Completer for CustomCompletion { .and_then(|val| val.as_bool().ok()) .unwrap_or(false); + if should_sort { + self.sort_by = SortBy::Ascending; + } + CompletionOptions { case_sensitive: options .get_data_by_key("case_sensitive") @@ -144,6 +150,32 @@ impl Completer for CustomCompletion { _ => (vec![], CompletionOptions::default()), }; - (suggestions, options) + filter(&prefix, suggestions, options) + } + + fn get_sort_by(&self) -> SortBy { + self.sort_by } } + +fn filter(prefix: &[u8], items: Vec, options: CompletionOptions) -> Vec { + items + .into_iter() + .filter(|it| { + // Minimise clones for new functionality + match (options.case_sensitive, options.positional) { + (true, true) => it.value.as_bytes().starts_with(prefix), + (true, false) => it.value.contains(std::str::from_utf8(prefix).unwrap_or("")), + (false, positional) => { + let value = it.value.to_lowercase(); + let prefix = std::str::from_utf8(prefix).unwrap_or("").to_lowercase(); + if positional { + value.starts_with(&prefix) + } else { + value.contains(&prefix) + } + } + } + }) + .collect() +} diff --git a/crates/nu-cli/src/completions/dotnu_completions.rs b/crates/nu-cli/src/completions/dotnu_completions.rs index 89044f01ba..e6310de70b 100644 --- a/crates/nu-cli/src/completions/dotnu_completions.rs +++ b/crates/nu-cli/src/completions/dotnu_completions.rs @@ -1,6 +1,4 @@ -use crate::completions::{ - file_path_completion, partial_from, Completer, CompletionOptions, SortBy, -}; +use crate::completions::{file_path_completion, partial_from, Completer, SortBy}; use nu_protocol::{ engine::{EngineState, StateWorkingSet}, Span, @@ -21,11 +19,6 @@ impl DotNuCompletion { } impl Completer for DotNuCompletion { - // Replace base filter with no filter once all the results are already filtered - fn filter(&self, _: Vec, items: Vec, _: CompletionOptions) -> Vec { - items - } - fn fetch( &mut self, _: &StateWorkingSet, @@ -33,7 +26,7 @@ impl Completer for DotNuCompletion { span: Span, offset: usize, _: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { let prefix_str = String::from_utf8_lossy(&prefix).to_string(); let mut search_dirs: Vec = vec![]; let (base_dir, mut partial) = partial_from(&prefix_str); @@ -118,9 +111,10 @@ impl Completer for DotNuCompletion { }) .collect(); - // Options - let options = CompletionOptions::new(false, true, SortBy::LevenshteinDistance); + output + } - (output, options) + fn get_sort_by(&self) -> SortBy { + SortBy::LevenshteinDistance } } diff --git a/crates/nu-cli/src/completions/file_completions.rs b/crates/nu-cli/src/completions/file_completions.rs index b515d9b6ab..b6ed7c2e22 100644 --- a/crates/nu-cli/src/completions/file_completions.rs +++ b/crates/nu-cli/src/completions/file_completions.rs @@ -1,4 +1,4 @@ -use crate::completions::{Completer, CompletionOptions}; +use crate::completions::Completer; use nu_protocol::{ engine::{EngineState, StateWorkingSet}, levenshtein_distance, Span, @@ -28,7 +28,7 @@ impl Completer for FileCompletion { span: Span, offset: usize, _: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD") { match d.as_string() { Ok(s) => s, @@ -51,19 +51,11 @@ impl Completer for FileCompletion { }) .collect(); - // Options - let options = CompletionOptions::default(); - - (output, options) + output } // Sort results prioritizing the non hidden folders - fn sort( - &self, - items: Vec, - prefix: Vec, - _: CompletionOptions, // Ignore the given options, once it's a custom sorting - ) -> Vec { + fn sort(&self, items: Vec, prefix: Vec) -> Vec { let prefix_str = String::from_utf8_lossy(&prefix).to_string(); // Sort items @@ -97,11 +89,6 @@ impl Completer for FileCompletion { non_hidden } - - // Replace base filter with no filter once all the results are already based in the current path - fn filter(&self, _: Vec, items: Vec, _: CompletionOptions) -> Vec { - items - } } pub fn partial_from(input: &str) -> (String, String) { diff --git a/crates/nu-cli/src/completions/flag_completions.rs b/crates/nu-cli/src/completions/flag_completions.rs index 7d378c4171..34c56bfd6d 100644 --- a/crates/nu-cli/src/completions/flag_completions.rs +++ b/crates/nu-cli/src/completions/flag_completions.rs @@ -1,4 +1,4 @@ -use crate::completions::{Completer, CompletionOptions}; +use crate::completions::Completer; use nu_protocol::{ ast::{Expr, Expression}, engine::StateWorkingSet, @@ -26,7 +26,7 @@ impl Completer for FlagCompletion { span: Span, offset: usize, _: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { // Check if it's a flag if let Expr::Call(call) = &self.expression.expr { let decl = working_set.get_decl(call.decl_id); @@ -73,9 +73,9 @@ impl Completer for FlagCompletion { } } - return (output, CompletionOptions::default()); + return output; } - (vec![], CompletionOptions::default()) + vec![] } } diff --git a/crates/nu-cli/src/completions/variable_completions.rs b/crates/nu-cli/src/completions/variable_completions.rs index ee66b7fe42..30796fc118 100644 --- a/crates/nu-cli/src/completions/variable_completions.rs +++ b/crates/nu-cli/src/completions/variable_completions.rs @@ -1,4 +1,4 @@ -use crate::completions::{Completer, CompletionOptions}; +use crate::completions::Completer; use nu_protocol::{ engine::{EngineState, Stack, StateWorkingSet}, Span, Value, @@ -35,7 +35,7 @@ impl Completer for VariableCompletion { span: Span, offset: usize, _: usize, - ) -> (Vec, CompletionOptions) { + ) -> Vec { let mut output = vec![]; let builtins = ["$nu", "$in", "$config", "$env", "$nothing"]; let var_str = std::str::from_utf8(&self.var_context.0) @@ -52,15 +52,17 @@ impl Completer for VariableCompletion { // Completion for $env. if var_str.as_str() == "$env" { for env_var in self.stack.get_env_vars(&self.engine_state) { - output.push(Suggestion { - value: env_var.0, - description: None, - extra: None, - span: current_span, - }); + if env_var.0.as_bytes().starts_with(&prefix) { + output.push(Suggestion { + value: env_var.0, + description: None, + extra: None, + span: current_span, + }); + } } - return (output, CompletionOptions::default()); + return output; } // Completion other variable types @@ -96,11 +98,11 @@ impl Completer for VariableCompletion { }); } - return (output, CompletionOptions::default()); + return output; } _ => { - return (output, CompletionOptions::default()); + return output; } } } @@ -149,7 +151,7 @@ impl Completer for VariableCompletion { output.dedup(); - (output, CompletionOptions::default()) + output } }