summaryrefslogtreecommitdiff
path: root/helix-term/src/ui
diff options
context:
space:
mode:
authorBlaž Hrastnik2021-10-17 04:51:56 +0000
committerBlaž Hrastnik2021-10-17 04:51:56 +0000
commit0a6b60085a56876068bf652c9491c435e9cca229 (patch)
tree8681db55d1a7707421f98d81a108d6438459536a /helix-term/src/ui
parentbc0084d071ac53fa460370667cdd8740e7499c76 (diff)
parente216e9621e73cda1968632cd20595231af5e07be (diff)
Merge branch 'master' into debug
Diffstat (limited to 'helix-term/src/ui')
-rw-r--r--helix-term/src/ui/completion.rs30
-rw-r--r--helix-term/src/ui/editor.rs16
-rw-r--r--helix-term/src/ui/menu.rs8
-rw-r--r--helix-term/src/ui/picker.rs6
4 files changed, 52 insertions, 8 deletions
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index 6c9e3a80..c75b24f1 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -69,14 +69,18 @@ impl menu::Item for CompletionItem {
/// Wraps a Menu.
pub struct Completion {
popup: Popup<Menu<CompletionItem>>,
+ start_offset: usize,
+ #[allow(dead_code)]
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 +179,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 +210,22 @@ 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);
+ } else {
+ // we backspaced before the start offset, clear the menu
+ // this will cause the editor to remove the completion popup
+ menu.clear();
}
}
+ 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()
}
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 128fe948..037f04b8 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -37,7 +37,7 @@ pub struct EditorView {
keymaps: Keymaps,
on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
last_insert: (commands::Command, Vec<KeyEvent>),
- completion: Option<Completion>,
+ pub(crate) completion: Option<Completion>,
spinners: ProgressSpinners,
autoinfo: Option<Info>,
}
@@ -984,12 +984,21 @@ 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);
+
+ if completion.is_empty() {
+ // skip if we got no completion results
+ return;
+ }
+
// TODO : propagate required size on resize to completion too
completion.required_size((size.width, size.height));
self.completion = Some(completion);
@@ -1211,6 +1220,7 @@ impl Component for EditorView {
EventResult::Consumed(None)
}
Event::Key(key) => {
+ cxt.editor.reset_idle_timer();
let mut key = KeyEvent::from(key);
canonicalize_key(&mut key);
// clear status
@@ -1245,6 +1255,7 @@ impl Component for EditorView {
if callback.is_some() {
// assume close_fn
self.completion = None;
+ cxt.editor.clear_idle_timer(); // don't retrigger
}
}
}
@@ -1258,6 +1269,7 @@ impl Component for EditorView {
completion.update(&mut cxt);
if completion.is_empty() {
self.completion = None;
+ cxt.editor.clear_idle_timer(); // don't retrigger
}
}
}
diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs
index dab0c34f..055593fd 100644
--- a/helix-term/src/ui/menu.rs
+++ b/helix-term/src/ui/menu.rs
@@ -90,6 +90,14 @@ impl<T: Item> Menu<T> {
self.recalculate = true;
}
+ pub fn clear(&mut self) {
+ self.matches.clear();
+
+ // reset cursor position
+ self.cursor = None;
+ self.scroll = 0;
+ }
+
pub fn move_up(&mut self) {
let len = self.matches.len();
let pos = self.cursor.map_or(0, |i| (i + len.saturating_sub(1)) % len) % len;
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index ee1ec177..341235ee 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -271,12 +271,18 @@ impl<T> Picker<T> {
}
pub fn move_up(&mut self) {
+ if self.matches.is_empty() {
+ return;
+ }
let len = self.matches.len();
let pos = ((self.cursor + len.saturating_sub(1)) % len) % len;
self.cursor = pos;
}
pub fn move_down(&mut self) {
+ if self.matches.is_empty() {
+ return;
+ }
let len = self.matches.len();
let pos = (self.cursor + 1) % len;
self.cursor = pos;