nushell/crates/nu-cli/src/completions/base.rs
Fernando Herrera 3ceb39c82c
use arc to avoid cloning entire engine for menus (#5104)
* use arc to avoid cloning entire engine for menus

* remove complete import path

* remove stack clone

* reference in completer
2022-04-06 13:25:02 +01:00

75 lines
2.4 KiB
Rust

use crate::completions::{CompletionOptions, SortBy};
use nu_protocol::{engine::StateWorkingSet, levenshtein_distance, Span};
use reedline::Suggestion;
// Completer trait represents the three stages of the completion
// fetch, filter and sort
pub trait Completer {
fn fetch(
&mut self,
working_set: &StateWorkingSet,
prefix: Vec<u8>,
span: Span,
offset: usize,
pos: usize,
) -> (Vec<Suggestion>, CompletionOptions);
// Filter results using the completion options
fn filter(
&self,
prefix: Vec<u8>,
items: Vec<Suggestion>,
options: CompletionOptions,
) -> Vec<Suggestion> {
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()
}
// Sort results using the completion options
fn sort(
&self,
items: Vec<Suggestion>,
prefix: Vec<u8>,
options: CompletionOptions,
) -> Vec<Suggestion> {
let prefix_str = String::from_utf8_lossy(&prefix).to_string();
let mut filtered_items = items;
// Sort items
match options.sort_by {
SortBy::LevenshteinDistance => {
filtered_items.sort_by(|a, b| {
let a_distance = levenshtein_distance(&prefix_str, &a.value);
let b_distance = levenshtein_distance(&prefix_str, &b.value);
a_distance.cmp(&b_distance)
});
}
SortBy::Ascending => {
filtered_items.sort_by(|a, b| a.value.cmp(&b.value));
}
SortBy::None => {}
};
filtered_items
}
}