Merge nucleic/sleek-thistle-egret-fyej into dev
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
use nu_ansi_term::{Color, Style};
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
use crate::{completion, refs};
|
||||
|
||||
pub(crate) struct ReedlineCompleter<SE: brush_core::ShellExtensions> {
|
||||
pub shell: refs::ShellRef<SE>,
|
||||
}
|
||||
|
||||
impl<SE: brush_core::ShellExtensions> reedline::Completer for ReedlineCompleter<SE> {
|
||||
fn complete(&mut self, line: &str, pos: usize) -> Vec<reedline::Suggestion> {
|
||||
tokio::task::block_in_place(|| {
|
||||
tokio::runtime::Handle::current().block_on(self.complete_async(line, pos))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<SE: brush_core::ShellExtensions> ReedlineCompleter<SE> {
|
||||
async fn complete_async(&self, line: &str, pos: usize) -> Vec<reedline::Suggestion> {
|
||||
let mut shell_guard = self.shell.lock().await;
|
||||
let shell = shell_guard.borrow_mut().as_mut();
|
||||
let completions = completion::complete_async(shell, line, pos).await;
|
||||
|
||||
// We're done with the shell, so drop it eagerly.
|
||||
drop(shell_guard);
|
||||
|
||||
let insertion_index = completions.insertion_index;
|
||||
let delete_count = completions.delete_count;
|
||||
let options = completions.options;
|
||||
|
||||
completions
|
||||
.candidates
|
||||
.into_iter()
|
||||
.map(|candidate| {
|
||||
Self::to_suggestion(line, candidate, insertion_index, delete_count, &options)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[allow(
|
||||
clippy::string_slice,
|
||||
reason = "all indices + counts are expected to be at char boundaries"
|
||||
)]
|
||||
fn to_suggestion(
|
||||
line: &str,
|
||||
mut candidate: String,
|
||||
mut insertion_index: usize,
|
||||
mut delete_count: usize,
|
||||
options: &brush_core::completion::ProcessingOptions,
|
||||
) -> reedline::Suggestion {
|
||||
let mut style = Style::new();
|
||||
|
||||
// Special handling for filename completions.
|
||||
if options.treat_as_filenames {
|
||||
if brush_core::sys::fs::ends_with_path_separator(&candidate) {
|
||||
style = style.fg(Color::Green);
|
||||
}
|
||||
|
||||
if insertion_index + delete_count <= line.len() {
|
||||
let removed = &line[insertion_index..insertion_index + delete_count];
|
||||
if let Some(last_sep_index) = brush_core::sys::fs::rfind_path_separator(removed) {
|
||||
if candidate.starts_with(removed) {
|
||||
candidate = candidate.split_off(last_sep_index + 1);
|
||||
insertion_index += last_sep_index + 1;
|
||||
delete_count -= last_sep_index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if there's whitespace at the end.
|
||||
let append_whitespace = candidate.ends_with(' ');
|
||||
if append_whitespace {
|
||||
candidate.pop();
|
||||
}
|
||||
|
||||
reedline::Suggestion {
|
||||
value: candidate,
|
||||
description: None,
|
||||
style: Some(style),
|
||||
extra: None,
|
||||
span: reedline::Span {
|
||||
start: insertion_index,
|
||||
end: insertion_index + delete_count,
|
||||
},
|
||||
match_indices: None,
|
||||
display_override: None,
|
||||
append_whitespace,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user