diff --git a/crates/nu-cli/src/completions/command_completions.rs b/crates/nu-cli/src/completions/command_completions.rs index 503e3b566b..b09e128c63 100644 --- a/crates/nu-cli/src/completions/command_completions.rs +++ b/crates/nu-cli/src/completions/command_completions.rs @@ -9,20 +9,20 @@ use nu_protocol::{ use reedline::Suggestion; use std::sync::Arc; -pub struct CommandCompletion { +pub struct CommandCompletion<'a> { engine_state: Arc, - flattened: Vec<(Span, FlatShape)>, + flattened: &'a [(Span, FlatShape)], flat_idx: usize, - flat_shape: FlatShape, + flat_shape: &'a FlatShape, } -impl CommandCompletion { +impl<'a> CommandCompletion<'a> { pub fn new( engine_state: Arc, _: &StateWorkingSet, - flattened: Vec<(Span, FlatShape)>, + flattened: &'a [(Span, FlatShape)], flat_idx: usize, - flat_shape: FlatShape, + flat_shape: &'a FlatShape, ) -> Self { Self { engine_state, @@ -146,7 +146,7 @@ impl CommandCompletion { } } -impl Completer for CommandCompletion { +impl<'a> Completer for CommandCompletion<'a> { fn fetch( &mut self, working_set: &StateWorkingSet, diff --git a/crates/nu-cli/src/completions/completer.rs b/crates/nu-cli/src/completions/completer.rs index c8272fe974..7a80bb653a 100644 --- a/crates/nu-cli/src/completions/completer.rs +++ b/crates/nu-cli/src/completions/completer.rs @@ -1,20 +1,23 @@ use crate::completions::{ - CommandCompletion, Completer, CustomCompletion, FileCompletion, FlagCompletion, - VariableCompletion, + CommandCompletion, Completer, CompletionOptions, CustomCompletion, FileCompletion, + FlagCompletion, VariableCompletion, }; use nu_parser::{flatten_expression, parse, FlatShape}; use nu_protocol::{ engine::{EngineState, Stack, StateWorkingSet}, Span, Value, }; -use reedline::{Completer as ReedlineCompleter, Suggestion}; +use reedline::{Completer as ReedlineCompleter, Span as ReedlineSpan, Suggestion}; use std::sync::Arc; +use std::time::{Duration, Instant}; #[derive(Clone)] pub struct NuCompleter { engine_state: Arc, stack: Stack, config: Option, + cached_results: Option<(Vec, CompletionOptions)>, + last_fetch: Option, } impl NuCompleter { @@ -23,12 +26,14 @@ impl NuCompleter { engine_state, stack, config, + cached_results: None, + last_fetch: None, } } // Process the completion for a given completer fn process_completion( - &self, + &mut self, completer: &mut T, working_set: &StateWorkingSet, prefix: Vec, @@ -36,9 +41,41 @@ impl NuCompleter { offset: usize, pos: usize, ) -> Vec { + // Cleanup the result cache if it's old + if let Some(instant) = self.last_fetch { + if instant.elapsed() > Duration::from_millis(1000) { + self.cached_results = None; + } + } + // Fetch - let (mut suggestions, options) = - completer.fetch(working_set, prefix.clone(), new_span, offset, pos); + let (mut suggestions, options) = match self.cached_results.clone() { + Some((suggestions, options)) => { + // Update cached spans + let suggestions = suggestions + .into_iter() + .map(|suggestion| Suggestion { + value: suggestion.value, + description: suggestion.description, + extra: suggestion.extra, + span: ReedlineSpan { + start: new_span.start - offset, + end: new_span.end - offset, + }, + }) + .collect(); + + (suggestions, options) + } + None => { + let result = completer.fetch(working_set, prefix.clone(), new_span, offset, pos); + + // Update cache results + self.cached_results = Some(result.clone()); + + result + } + }; // Filter suggestions = completer.filter(prefix.clone(), suggestions, options.clone()); @@ -46,11 +83,15 @@ impl NuCompleter { // Sort suggestions = completer.sort(suggestions, prefix, options); + // Update last fetch + self.last_fetch = Some(Instant::now()); + suggestions } fn completion_helper(&mut self, line: &str, pos: usize) -> Vec { - let mut working_set = StateWorkingSet::new(&self.engine_state); + let engine_state = self.engine_state.clone(); + let mut working_set = StateWorkingSet::new(&engine_state); let offset = working_set.next_span_start(); let mut line = line.to_string(); line.insert(pos, 'a'); @@ -143,9 +184,9 @@ impl NuCompleter { let mut completer = CommandCompletion::new( self.engine_state.clone(), &working_set, - flattened.clone(), + &flattened, flat_idx, - flat_shape.clone(), + flat_shape, ); return self.process_completion(