Filter the initial completion

pull/821/head
Blaž Hrastnik 3 years ago
parent 40abec80e1
commit 66f26e82ce

@ -234,9 +234,8 @@ impl Application {
} }
pub fn handle_idle_timeout(&mut self) { pub fn handle_idle_timeout(&mut self) {
use crate::commands::{completion, Context};
use helix_view::document::Mode; use helix_view::document::Mode;
use crate::commands::{Context, completion};
if doc_mut!(self.editor).mode != Mode::Insert { if doc_mut!(self.editor).mode != Mode::Insert {
return; return;
@ -254,6 +253,8 @@ impl Application {
return; return;
} }
// TODO: if completion window was closed with enter (and no selection) we shouldn't retrigger
let mut cx = Context { let mut cx = Context {
selected_register: helix_view::RegisterSelection::default(), selected_register: helix_view::RegisterSelection::default(),
editor: &mut self.editor, editor: &mut self.editor,
@ -262,9 +263,9 @@ impl Application {
callback: None, callback: None,
on_next_key_callback: None, on_next_key_callback: None,
}; };
completion(&mut cx); completion(&mut cx);
// TODO: scan backwards for trigger and filter the box // TODO: scan backwards for trigger and filter the box
self.render(); self.render();
} }
pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) { 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 offset_encoding = language_server.offset_encoding();
let cursor = doc let text = doc.text().slice(..);
.selection(view.id) let cursor = doc.selection(view.id).primary().cursor(text);
.primary()
.cursor(doc.text().slice(..));
let pos = pos_to_lsp_pos(doc.text(), cursor, offset_encoding); 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; 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( cx.callback(
future, future,
move |editor: &mut Editor, move |editor: &mut Editor,
@ -4131,7 +4138,7 @@ pub fn completion(cx: &mut Context) {
.find(std::any::type_name::<ui::EditorView>()) .find(std::any::type_name::<ui::EditorView>())
.unwrap(); .unwrap();
if let Some(ui) = ui.as_any_mut().downcast_mut::<ui::EditorView>() { 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. /// Wraps a Menu.
pub struct Completion { pub struct Completion {
popup: Popup<Menu<CompletionItem>>, popup: Popup<Menu<CompletionItem>>,
start_offset: usize,
trigger_offset: usize, trigger_offset: usize,
// TODO: maintain a completioncontext with trigger kind & trigger char // TODO: maintain a completioncontext with trigger kind & trigger char
} }
impl Completion { impl Completion {
pub fn new( pub fn new(
editor: &Editor,
items: Vec<CompletionItem>, items: Vec<CompletionItem>,
offset_encoding: helix_lsp::OffsetEncoding, offset_encoding: helix_lsp::OffsetEncoding,
start_offset: usize,
trigger_offset: usize, trigger_offset: usize,
) -> Self { ) -> Self {
// let items: Vec<CompletionItem> = Vec::new(); // let items: Vec<CompletionItem> = Vec::new();
@ -175,16 +178,22 @@ impl Completion {
}; };
}); });
let popup = Popup::new(menu); let popup = Popup::new(menu);
Self { let mut completion = Self {
popup, popup,
start_offset,
trigger_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 // recompute menu based on matches
let menu = self.popup.contents_mut(); let menu = self.popup.contents_mut();
let (view, doc) = current!(cx.editor); let (view, doc) = current_ref!(editor);
// cx.hooks() // cx.hooks()
// cx.add_hook(enum type, ||) // cx.add_hook(enum type, ||)
@ -200,14 +209,18 @@ impl Completion {
.selection(view.id) .selection(view.id)
.primary() .primary()
.cursor(doc.text().slice(..)); .cursor(doc.text().slice(..));
if self.trigger_offset <= cursor { if self.start_offset <= cursor {
let fragment = doc.text().slice(self.trigger_offset..cursor); let fragment = doc.text().slice(self.start_offset..cursor);
let text = Cow::from(fragment); let text = Cow::from(fragment);
// TODO: logic is same as ui/picker // TODO: logic is same as ui/picker
menu.score(&text); menu.score(&text);
} }
} }
pub fn update(&mut self, cx: &mut commands::Context) {
self.recompute_filter(cx.editor)
}
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.popup.contents().is_empty() self.popup.contents().is_empty()
} }

@ -721,12 +721,15 @@ impl EditorView {
pub fn set_completion( pub fn set_completion(
&mut self, &mut self,
editor: &Editor,
items: Vec<helix_lsp::lsp::CompletionItem>, items: Vec<helix_lsp::lsp::CompletionItem>,
offset_encoding: helix_lsp::OffsetEncoding, offset_encoding: helix_lsp::OffsetEncoding,
start_offset: usize,
trigger_offset: usize, trigger_offset: usize,
size: Rect, 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 // TODO : propagate required size on resize to completion too
completion.required_size((size.width, size.height)); completion.required_size((size.width, size.height));
self.completion = Some(completion); self.completion = Some(completion);

@ -44,3 +44,19 @@ macro_rules! view {
$( $editor ).+ .tree.get($( $editor ).+ .tree.focus) $( $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…
Cancel
Save