2020-08-21 21:37:51 +02:00
|
|
|
use crate::completion::{self, Suggestion};
|
2020-07-25 01:39:12 +02:00
|
|
|
use crate::context;
|
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
pub(crate) struct NuCompleter {}
|
2019-05-16 23:43:36 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
impl NuCompleter {}
|
2020-05-24 02:27:52 +02:00
|
|
|
|
2019-08-09 06:51:21 +02:00
|
|
|
impl NuCompleter {
|
2020-08-21 21:37:51 +02:00
|
|
|
pub fn complete(
|
2019-05-16 23:43:36 +02:00
|
|
|
&self,
|
2019-05-18 04:30:57 +02:00
|
|
|
line: &str,
|
|
|
|
pos: usize,
|
2020-07-25 01:39:12 +02:00
|
|
|
context: &completion::Context,
|
2020-08-21 21:37:51 +02:00
|
|
|
) -> (usize, Vec<Suggestion>) {
|
|
|
|
use crate::completion::engine::LocationType;
|
2019-12-08 07:23:31 +01:00
|
|
|
|
2020-08-21 21:37:51 +02: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
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
let location = lite_block
|
|
|
|
.map(|block| nu_parser::classify_block(&block, &nu_context.registry))
|
|
|
|
.and_then(|block| {
|
|
|
|
crate::completion::engine::completion_location(line, &block.block, pos)
|
|
|
|
});
|
2020-07-25 16:41:14 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
if let Some(location) = location {
|
|
|
|
let partial = location.span.slice(line);
|
2020-07-25 16:41:14 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
let suggestions = match location.item {
|
|
|
|
LocationType::Command => {
|
|
|
|
let command_completer = crate::completion::command::Completer {};
|
|
|
|
command_completer.complete(context, partial)
|
2020-05-24 02:27:52 +02:00
|
|
|
}
|
2020-07-25 16:41:14 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
LocationType::Flag(cmd) => {
|
|
|
|
let flag_completer = crate::completion::flag::Completer {};
|
|
|
|
flag_completer.complete(context, cmd, partial)
|
2019-05-18 16:06:01 +02:00
|
|
|
}
|
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
LocationType::Argument(_cmd, _arg_name) => {
|
|
|
|
// TODO use cmd and arg_name to narrow things down further
|
|
|
|
let path_completer = crate::completion::path::Completer::new();
|
|
|
|
path_completer.complete(context, partial)
|
2020-05-24 02:27:52 +02:00
|
|
|
}
|
2020-07-25 01:39:12 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
LocationType::Variable => Vec::new(),
|
2020-05-20 22:32:21 +02:00
|
|
|
}
|
2020-08-21 21:37:51 +02:00
|
|
|
.into_iter()
|
2020-07-25 01:39:12 +02:00
|
|
|
.map(requote)
|
2020-08-21 21:37:51 +02:00
|
|
|
.collect();
|
2020-05-24 02:27:52 +02:00
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
(location.span.start(), suggestions)
|
2020-05-24 02:27:52 +02:00
|
|
|
} else {
|
2020-08-21 21:37:51 +02:00
|
|
|
(pos, Vec::new())
|
2020-07-18 03:59:23 +02:00
|
|
|
}
|
2020-05-24 02:27:52 +02:00
|
|
|
}
|
2020-07-25 01:39:12 +02:00
|
|
|
}
|
|
|
|
|
2020-08-21 21:37:51 +02:00
|
|
|
fn requote(item: Suggestion) -> Suggestion {
|
|
|
|
let unescaped = rustyline::completion::unescape(&item.replacement, Some('\\'));
|
|
|
|
if unescaped != item.replacement {
|
|
|
|
Suggestion {
|
2020-07-25 01:39:12 +02:00
|
|
|
display: item.display,
|
2020-08-21 21:37:51 +02:00
|
|
|
replacement: format!("\"{}\"", unescaped),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
item
|
2020-05-24 02:27:52 +02:00
|
|
|
}
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|