Filter the initial completion
This commit is contained in:
parent
40abec80e1
commit
66f26e82ce
5 changed files with 57 additions and 17 deletions
|
@ -234,9 +234,8 @@ impl Application {
|
|||
}
|
||||
|
||||
pub fn handle_idle_timeout(&mut self) {
|
||||
use crate::commands::{completion, Context};
|
||||
use helix_view::document::Mode;
|
||||
use crate::commands::{Context, completion};
|
||||
|
||||
|
||||
if doc_mut!(self.editor).mode != Mode::Insert {
|
||||
return;
|
||||
|
@ -254,6 +253,8 @@ impl Application {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: if completion window was closed with enter (and no selection) we shouldn't retrigger
|
||||
|
||||
let mut cx = Context {
|
||||
selected_register: helix_view::RegisterSelection::default(),
|
||||
editor: &mut self.editor,
|
||||
|
@ -262,9 +263,9 @@ impl Application {
|
|||
callback: None,
|
||||
on_next_key_callback: None,
|
||||
};
|
||||
completion(&mut cx);
|
||||
// TODO: scan backwards for trigger and filter the box
|
||||
self.render();
|
||||
completion(&mut cx);
|
||||
// TODO: scan backwards for trigger and filter the box
|
||||
self.render();
|
||||
}
|
||||
|
||||
pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
|
||||
|
|
|
@ -4090,10 +4090,8 @@ pub fn completion(cx: &mut Context) {
|
|||
};
|
||||
|
||||
let offset_encoding = language_server.offset_encoding();
|
||||
let cursor = doc
|
||||
.selection(view.id)
|
||||
.primary()
|
||||
.cursor(doc.text().slice(..));
|
||||
let text = doc.text().slice(..);
|
||||
let cursor = doc.selection(view.id).primary().cursor(text);
|
||||
|
||||
let pos = pos_to_lsp_pos(doc.text(), cursor, offset_encoding);
|
||||
|
||||
|
@ -4101,6 +4099,15 @@ pub fn completion(cx: &mut Context) {
|
|||
|
||||
let trigger_offset = cursor;
|
||||
|
||||
// TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
|
||||
// completion filtering. For example logger.te| should filter the initial suggestion list with "te".
|
||||
|
||||
use helix_core::chars;
|
||||
let mut iter = text.chars_at(cursor);
|
||||
iter.reverse();
|
||||
let offset = iter.take_while(|ch| chars::char_is_word(*ch)).count();
|
||||
let start_offset = cursor.saturating_sub(offset);
|
||||
|
||||
cx.callback(
|
||||
future,
|
||||
move |editor: &mut Editor,
|
||||
|
@ -4131,7 +4138,7 @@ pub fn completion(cx: &mut Context) {
|
|||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.unwrap();
|
||||
if let Some(ui) = ui.as_any_mut().downcast_mut::<ui::EditorView>() {
|
||||
ui.set_completion(items, offset_encoding, trigger_offset, size);
|
||||
ui.set_completion(editor, items, offset_encoding, start_offset, trigger_offset, size);
|
||||
};
|
||||
},
|
||||
);
|
||||
|
|
|
@ -69,14 +69,17 @@ impl menu::Item for CompletionItem {
|
|||
/// Wraps a Menu.
|
||||
pub struct Completion {
|
||||
popup: Popup<Menu<CompletionItem>>,
|
||||
start_offset: usize,
|
||||
trigger_offset: usize,
|
||||
// TODO: maintain a completioncontext with trigger kind & trigger char
|
||||
}
|
||||
|
||||
impl Completion {
|
||||
pub fn new(
|
||||
editor: &Editor,
|
||||
items: Vec<CompletionItem>,
|
||||
offset_encoding: helix_lsp::OffsetEncoding,
|
||||
start_offset: usize,
|
||||
trigger_offset: usize,
|
||||
) -> Self {
|
||||
// let items: Vec<CompletionItem> = Vec::new();
|
||||
|
@ -175,16 +178,22 @@ impl Completion {
|
|||
};
|
||||
});
|
||||
let popup = Popup::new(menu);
|
||||
Self {
|
||||
let mut completion = Self {
|
||||
popup,
|
||||
start_offset,
|
||||
trigger_offset,
|
||||
}
|
||||
};
|
||||
|
||||
// need to recompute immediately in case start_offset != trigger_offset
|
||||
completion.recompute_filter(editor);
|
||||
|
||||
completion
|
||||
}
|
||||
|
||||
pub fn update(&mut self, cx: &mut commands::Context) {
|
||||
pub fn recompute_filter(&mut self, editor: &Editor) {
|
||||
// recompute menu based on matches
|
||||
let menu = self.popup.contents_mut();
|
||||
let (view, doc) = current!(cx.editor);
|
||||
let (view, doc) = current_ref!(editor);
|
||||
|
||||
// cx.hooks()
|
||||
// cx.add_hook(enum type, ||)
|
||||
|
@ -200,14 +209,18 @@ impl Completion {
|
|||
.selection(view.id)
|
||||
.primary()
|
||||
.cursor(doc.text().slice(..));
|
||||
if self.trigger_offset <= cursor {
|
||||
let fragment = doc.text().slice(self.trigger_offset..cursor);
|
||||
if self.start_offset <= cursor {
|
||||
let fragment = doc.text().slice(self.start_offset..cursor);
|
||||
let text = Cow::from(fragment);
|
||||
// TODO: logic is same as ui/picker
|
||||
menu.score(&text);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, cx: &mut commands::Context) {
|
||||
self.recompute_filter(cx.editor)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.popup.contents().is_empty()
|
||||
}
|
||||
|
|
|
@ -721,12 +721,15 @@ impl EditorView {
|
|||
|
||||
pub fn set_completion(
|
||||
&mut self,
|
||||
editor: &Editor,
|
||||
items: Vec<helix_lsp::lsp::CompletionItem>,
|
||||
offset_encoding: helix_lsp::OffsetEncoding,
|
||||
start_offset: usize,
|
||||
trigger_offset: usize,
|
||||
size: Rect,
|
||||
) {
|
||||
let mut completion = Completion::new(items, offset_encoding, trigger_offset);
|
||||
let mut completion =
|
||||
Completion::new(editor, items, offset_encoding, start_offset, trigger_offset);
|
||||
// TODO : propagate required size on resize to completion too
|
||||
completion.required_size((size.width, size.height));
|
||||
self.completion = Some(completion);
|
||||
|
|
|
@ -44,3 +44,19 @@ macro_rules! view {
|
|||
$( $editor ).+ .tree.get($( $editor ).+ .tree.focus)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! doc {
|
||||
( $( $editor:ident ).+ ) => {{
|
||||
$crate::current_ref!( $( $editor ).+ ).1
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! current_ref {
|
||||
( $( $editor:ident ).+ ) => {{
|
||||
let view = $( $editor ).+ .tree.get($( $editor ).+ .tree.focus);
|
||||
let doc = &$( $editor ).+ .documents[view.doc];
|
||||
(view, doc)
|
||||
}};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue