mirror of
https://github.com/nushell/nushell.git
synced 2025-07-01 07:00:37 +02:00
Refactor completion trait (#2555)
* Remove completion code from help/value shells * Tweak the `Completer` trait for nushell. Previously, this trait was built around rustyline's completion traits, and for `Shell` instances. Now it is built for individual completers inside of nushell that will complete a specific location based on a partial string. For example, for completing a partially typed command in the command position.
This commit is contained in:
@ -1,5 +1,7 @@
|
||||
use crate::completion::path::PathSuggestion;
|
||||
use crate::completion::{self, Suggestion};
|
||||
use crate::completion::command::CommandCompleter;
|
||||
use crate::completion::flag::FlagCompleter;
|
||||
use crate::completion::path::{PathCompleter, PathSuggestion};
|
||||
use crate::completion::{self, Completer, Suggestion};
|
||||
use crate::context;
|
||||
|
||||
pub(crate) struct NuCompleter {}
|
||||
@ -13,7 +15,7 @@ impl NuCompleter {
|
||||
pos: usize,
|
||||
context: &completion::Context,
|
||||
) -> (usize, Vec<Suggestion>) {
|
||||
use crate::completion::engine::LocationType;
|
||||
use completion::engine::LocationType;
|
||||
|
||||
let nu_context: &context::Context = context.as_ref();
|
||||
let lite_block = match nu_parser::lite_parse(line, 0) {
|
||||
@ -23,7 +25,7 @@ impl NuCompleter {
|
||||
|
||||
let locations = lite_block
|
||||
.map(|block| nu_parser::classify_block(&block, &nu_context.registry))
|
||||
.map(|block| crate::completion::engine::completion_location(line, &block.block, pos))
|
||||
.map(|block| completion::engine::completion_location(line, &block.block, pos))
|
||||
.unwrap_or_default();
|
||||
|
||||
if locations.is_empty() {
|
||||
@ -36,17 +38,17 @@ impl NuCompleter {
|
||||
let partial = location.span.slice(line);
|
||||
match location.item {
|
||||
LocationType::Command => {
|
||||
let command_completer = crate::completion::command::Completer;
|
||||
let command_completer = CommandCompleter;
|
||||
command_completer.complete(context, partial)
|
||||
}
|
||||
|
||||
LocationType::Flag(cmd) => {
|
||||
let flag_completer = crate::completion::flag::Completer;
|
||||
flag_completer.complete(context, cmd, partial)
|
||||
let flag_completer = FlagCompleter { cmd };
|
||||
flag_completer.complete(context, partial)
|
||||
}
|
||||
|
||||
LocationType::Argument(cmd, _arg_name) => {
|
||||
let path_completer = crate::completion::path::Completer;
|
||||
let path_completer = PathCompleter;
|
||||
|
||||
const QUOTE_CHARS: &[char] = &['\'', '"', '`'];
|
||||
|
||||
@ -71,7 +73,7 @@ impl NuCompleter {
|
||||
partial
|
||||
};
|
||||
|
||||
let completed_paths = path_completer.path_suggestions(context, partial);
|
||||
let completed_paths = path_completer.path_suggestions(partial);
|
||||
match cmd.as_deref().unwrap_or("") {
|
||||
"cd" => select_directory_suggestions(completed_paths),
|
||||
_ => completed_paths,
|
||||
|
@ -6,7 +6,6 @@ use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::completion;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::shell::Shell;
|
||||
|
||||
@ -230,56 +229,3 @@ impl Shell for HelpShell {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl completion::Completer for HelpShell {
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
pos: usize,
|
||||
_ctx: &completion::Context<'_>,
|
||||
) -> Result<(usize, Vec<completion::Suggestion>), ShellError> {
|
||||
let mut possible_completion = vec![];
|
||||
let commands = self.commands();
|
||||
for cmd in commands {
|
||||
let Value { value, .. } = cmd;
|
||||
for desc in value.data_descriptors() {
|
||||
possible_completion.push(desc);
|
||||
}
|
||||
}
|
||||
|
||||
let line_chars: Vec<_> = line.chars().collect();
|
||||
let mut replace_pos = pos;
|
||||
while replace_pos > 0 {
|
||||
if line_chars[replace_pos - 1] == ' ' {
|
||||
break;
|
||||
}
|
||||
replace_pos -= 1;
|
||||
}
|
||||
|
||||
let mut completions = vec![];
|
||||
for command in possible_completion.iter() {
|
||||
let mut pos = replace_pos;
|
||||
let mut matched = true;
|
||||
if pos < line_chars.len() {
|
||||
for chr in command.chars() {
|
||||
if line_chars[pos] != chr {
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
pos += 1;
|
||||
if pos == line_chars.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
completions.push(completion::Suggestion {
|
||||
display: command.to_string(),
|
||||
replacement: command.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok((replace_pos, completions))
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ use crate::commands::ls::LsArgs;
|
||||
use crate::commands::mkdir::MkdirArgs;
|
||||
use crate::commands::move_::mv::Arguments as MvArgs;
|
||||
use crate::commands::rm::RemoveArgs;
|
||||
use crate::completion;
|
||||
use crate::prelude::*;
|
||||
use crate::shell::shell::Shell;
|
||||
use crate::utils::ValueStructure;
|
||||
@ -76,6 +75,8 @@ impl ValueShell {
|
||||
shell_entries
|
||||
}
|
||||
|
||||
// TODO make use of this in the new completion engine
|
||||
#[allow(dead_code)]
|
||||
fn members(&self) -> VecDeque<Value> {
|
||||
self.members_under(Path::new("."))
|
||||
}
|
||||
@ -255,56 +256,3 @@ impl Shell for ValueShell {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl completion::Completer for ValueShell {
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
pos: usize,
|
||||
_ctx: &completion::Context<'_>,
|
||||
) -> Result<(usize, Vec<completion::Suggestion>), ShellError> {
|
||||
let mut possible_completion = vec![];
|
||||
let members = self.members();
|
||||
for member in members {
|
||||
let Value { value, .. } = member;
|
||||
for desc in value.data_descriptors() {
|
||||
possible_completion.push(desc);
|
||||
}
|
||||
}
|
||||
|
||||
let line_chars: Vec<_> = line.chars().collect();
|
||||
let mut replace_pos = pos;
|
||||
while replace_pos > 0 {
|
||||
if line_chars[replace_pos - 1] == ' ' {
|
||||
break;
|
||||
}
|
||||
replace_pos -= 1;
|
||||
}
|
||||
|
||||
let mut completions = vec![];
|
||||
for command in possible_completion.iter() {
|
||||
let mut pos = replace_pos;
|
||||
let mut matched = true;
|
||||
if pos < line_chars.len() {
|
||||
for chr in command.chars() {
|
||||
if line_chars[pos] != chr {
|
||||
matched = false;
|
||||
break;
|
||||
}
|
||||
pos += 1;
|
||||
if pos == line_chars.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
completions.push(completion::Suggestion {
|
||||
display: command.to_string(),
|
||||
replacement: command.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok((replace_pos, completions))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user