forked from extern/nushell
Add completion options for custom completions (#4674)
* Add completion options for custom completions * Make clippy happy * Refactor options for clarity * Make return type of filtering explicit
This commit is contained in:
parent
210d25f2a0
commit
13f2048ffb
@ -9,6 +9,22 @@ use reedline::Completer;
|
||||
|
||||
const SEP: char = std::path::MAIN_SEPARATOR;
|
||||
|
||||
pub struct CompletionOptions {
|
||||
case_sensitive: bool,
|
||||
positional: bool,
|
||||
sort: bool,
|
||||
}
|
||||
|
||||
impl Default for CompletionOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
case_sensitive: true,
|
||||
positional: true,
|
||||
sort: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NuCompleter {
|
||||
engine_state: EngineState,
|
||||
@ -192,12 +208,10 @@ impl NuCompleter {
|
||||
prefix.remove(pos - flat.0.start);
|
||||
|
||||
if prefix.starts_with(b"$") {
|
||||
return self.complete_variables(
|
||||
&working_set,
|
||||
&prefix,
|
||||
new_span,
|
||||
offset,
|
||||
);
|
||||
let mut output =
|
||||
self.complete_variables(&working_set, &prefix, new_span, offset);
|
||||
output.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
return output;
|
||||
}
|
||||
if prefix.starts_with(b"-") {
|
||||
// this might be a flag, let's see
|
||||
@ -240,6 +254,7 @@ impl NuCompleter {
|
||||
));
|
||||
}
|
||||
}
|
||||
output.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@ -279,10 +294,12 @@ impl NuCompleter {
|
||||
true,
|
||||
);
|
||||
|
||||
let v: Vec<_> = match result {
|
||||
Ok(pd) => pd
|
||||
.into_iter()
|
||||
.filter_map(move |x| {
|
||||
fn map_completions<'a>(
|
||||
list: impl Iterator<Item = &'a Value>,
|
||||
new_span: Span,
|
||||
offset: usize,
|
||||
) -> Vec<(reedline::Span, String)> {
|
||||
list.filter_map(move |x| {
|
||||
let s = x.as_string();
|
||||
|
||||
match s {
|
||||
@ -296,12 +313,91 @@ impl NuCompleter {
|
||||
Err(_) => None,
|
||||
}
|
||||
})
|
||||
.filter(|x| x.1.as_bytes().starts_with(&prefix))
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
.collect()
|
||||
}
|
||||
|
||||
let (completions, options) = match result {
|
||||
Ok(pd) => {
|
||||
let value = pd.into_value(new_span);
|
||||
match &value {
|
||||
Value::Record { .. } => {
|
||||
let completions = value
|
||||
.get_data_by_key("completions")
|
||||
.and_then(|val| {
|
||||
val.as_list().ok().map(|it| {
|
||||
map_completions(
|
||||
it.iter(),
|
||||
new_span,
|
||||
offset,
|
||||
)
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let options = value.get_data_by_key("options");
|
||||
|
||||
let options =
|
||||
if let Some(Value::Record { .. }) = &options {
|
||||
let options = options.unwrap_or_default();
|
||||
CompletionOptions {
|
||||
case_sensitive: options
|
||||
.get_data_by_key("case_sensitive")
|
||||
.and_then(|val| val.as_bool().ok())
|
||||
.unwrap_or(true),
|
||||
positional: options
|
||||
.get_data_by_key("positional")
|
||||
.and_then(|val| val.as_bool().ok())
|
||||
.unwrap_or(true),
|
||||
sort: options
|
||||
.get_data_by_key("sort")
|
||||
.and_then(|val| val.as_bool().ok())
|
||||
.unwrap_or(true),
|
||||
}
|
||||
} else {
|
||||
CompletionOptions::default()
|
||||
};
|
||||
|
||||
return v;
|
||||
(completions, options)
|
||||
}
|
||||
Value::List { vals, .. } => {
|
||||
let completions =
|
||||
map_completions(vals.iter(), new_span, offset);
|
||||
(completions, CompletionOptions::default())
|
||||
}
|
||||
_ => (vec![], CompletionOptions::default()),
|
||||
}
|
||||
}
|
||||
_ => (vec![], CompletionOptions::default()),
|
||||
};
|
||||
|
||||
let mut completions: Vec<(reedline::Span, String)> = completions
|
||||
.into_iter()
|
||||
.filter(|it| {
|
||||
// Minimise clones for new functionality
|
||||
match (options.case_sensitive, options.positional) {
|
||||
(true, true) => it.1.as_bytes().starts_with(&prefix),
|
||||
(true, false) => it.1.contains(
|
||||
std::str::from_utf8(&prefix).unwrap_or(""),
|
||||
),
|
||||
(false, positional) => {
|
||||
let value = it.1.to_lowercase();
|
||||
let prefix = std::str::from_utf8(&prefix)
|
||||
.unwrap_or("")
|
||||
.to_lowercase();
|
||||
if positional {
|
||||
value.starts_with(&prefix)
|
||||
} else {
|
||||
value.contains(&prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if options.sort {
|
||||
completions.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
FlatShape::Filepath | FlatShape::GlobPattern => {
|
||||
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD") {
|
||||
@ -313,7 +409,8 @@ impl NuCompleter {
|
||||
"".to_string()
|
||||
};
|
||||
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
||||
return file_path_completion(new_span, &prefix, &cwd)
|
||||
let mut output: Vec<_> =
|
||||
file_path_completion(new_span, &prefix, &cwd)
|
||||
.into_iter()
|
||||
.map(move |x| {
|
||||
(
|
||||
@ -325,6 +422,8 @@ impl NuCompleter {
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
output.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
return output;
|
||||
}
|
||||
flat_shape => {
|
||||
let last = flattened
|
||||
@ -394,7 +493,7 @@ impl NuCompleter {
|
||||
};
|
||||
// let prefix = working_set.get_span_contents(flat.0);
|
||||
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
||||
let output = file_path_completion(new_span, &prefix, &cwd)
|
||||
let mut output = file_path_completion(new_span, &prefix, &cwd)
|
||||
.into_iter()
|
||||
.map(move |x| {
|
||||
if flat_idx == 0 {
|
||||
@ -437,6 +536,7 @@ impl NuCompleter {
|
||||
.chain(commands.into_iter())
|
||||
.collect::<Vec<_>>();
|
||||
//output.dedup_by(|a, b| a.1 == b.1);
|
||||
output.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
|
||||
return output;
|
||||
}
|
||||
@ -452,11 +552,7 @@ impl NuCompleter {
|
||||
|
||||
impl Completer for NuCompleter {
|
||||
fn complete(&self, line: &str, pos: usize) -> Vec<(reedline::Span, String)> {
|
||||
let mut output = self.completion_helper(line, pos);
|
||||
|
||||
output.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
|
||||
output
|
||||
self.completion_helper(line, pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user