nu-cli/completions: cache layer for fetching (#5114)

This commit is contained in:
Herlon Aguiar 2022-04-07 21:36:16 +02:00 committed by GitHub
parent 5e177fe8e7
commit e86c1b118e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 16 deletions

View File

@ -9,20 +9,20 @@ use nu_protocol::{
use reedline::Suggestion;
use std::sync::Arc;
pub struct CommandCompletion {
pub struct CommandCompletion<'a> {
engine_state: Arc<EngineState>,
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<EngineState>,
_: &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,

View File

@ -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<EngineState>,
stack: Stack,
config: Option<Value>,
cached_results: Option<(Vec<Suggestion>, CompletionOptions)>,
last_fetch: Option<Instant>,
}
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<T: Completer>(
&self,
&mut self,
completer: &mut T,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
@ -36,9 +41,41 @@ impl NuCompleter {
offset: usize,
pos: usize,
) -> Vec<Suggestion> {
// 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<Suggestion> {
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(