nushell/crates/nu-cli/src/shell/completer.rs

91 lines
3.0 KiB
Rust
Raw Normal View History

use crate::completion::{self, Suggestion};
use crate::context;
use std::fs::metadata;
pub(crate) struct NuCompleter {}
2019-05-16 23:43:36 +02:00
impl NuCompleter {}
2019-08-09 06:51:21 +02:00
impl NuCompleter {
pub fn complete(
2019-05-16 23:43:36 +02:00
&self,
line: &str,
pos: usize,
context: &completion::Context,
) -> (usize, Vec<Suggestion>) {
use crate::completion::engine::LocationType;
2019-12-08 07:23:31 +01:00
let nu_context: &context::Context = context.as_ref();
let lite_block = match nu_parser::lite_parse(line, 0) {
Ok(block) => Some(block),
Err(result) => result.partial,
};
2019-12-08 06:58:53 +01:00
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))
.unwrap_or_default();
if locations.is_empty() {
(pos, Vec::new())
} else {
let pos = locations[0].span.start();
let suggestions = locations
.into_iter()
.flat_map(|location| {
let partial = location.span.slice(line);
match location.item {
LocationType::Command => {
let command_completer = crate::completion::command::Completer;
command_completer.complete(context, partial)
}
LocationType::Flag(cmd) => {
let flag_completer = crate::completion::flag::Completer;
flag_completer.complete(context, cmd, partial)
}
2019-05-18 16:06:01 +02:00
LocationType::Argument(cmd, _arg_name) => {
let path_completer = crate::completion::path::Completer;
let completed_paths = path_completer.complete(context, partial);
match cmd.as_deref().unwrap_or("") {
"cd" => select_directory_suggestions(completed_paths),
_ => completed_paths,
}
}
LocationType::Variable => Vec::new(),
}
.into_iter()
.map(requote)
})
.collect();
(pos, suggestions)
}
}
}
fn select_directory_suggestions(completed_paths: Vec<Suggestion>) -> Vec<Suggestion> {
completed_paths
.into_iter()
.filter(|suggestion| {
metadata(&suggestion.replacement)
.map(|md| md.is_dir())
.unwrap_or(false)
})
.collect()
}
fn requote(item: Suggestion) -> Suggestion {
let unescaped = rustyline::completion::unescape(&item.replacement, Some('\\'));
if unescaped != item.replacement {
Suggestion {
display: item.display,
replacement: format!("\"{}\"", unescaped),
}
} else {
item
}
2019-05-16 23:43:36 +02:00
}