From f99bea404f43ea0e373fd9fe54616d3282e8364b Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Sun, 22 Aug 2021 15:28:45 +0900
Subject: idle timer wip

---
 helix-term/src/application.rs | 5 +++++
 helix-term/src/ui/editor.rs   | 1 +
 2 files changed, 6 insertions(+)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 6206e6f2..dbd8755d 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -199,6 +199,11 @@ impl Application {
                     self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
                     self.render();
                 }
+                _ = &mut self.editor.idle_timer => {
+                    self.editor.clear_idle_timer();
+                    println!("idle!")
+                 // idle timeout
+                }
             }
         }
     }
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 0605e2c7..aa2d6636 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -901,6 +901,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
-- 
cgit v1.2.3-70-g09d2


From 40abec80e1062503d70055ed9e968cd4b31411a7 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Thu, 26 Aug 2021 11:14:46 +0900
Subject: Experiment with autocompletion on idle

---
 helix-term/src/application.rs | 38 ++++++++++++++++++++++++++++++++++++--
 helix-term/src/commands.rs    |  2 +-
 helix-term/src/ui/editor.rs   |  2 +-
 3 files changed, 38 insertions(+), 4 deletions(-)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index dbd8755d..ab268041 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -200,9 +200,9 @@ impl Application {
                     self.render();
                 }
                 _ = &mut self.editor.idle_timer => {
+                    // idle timeout
                     self.editor.clear_idle_timer();
-                    println!("idle!")
-                 // idle timeout
+                    self.handle_idle_timeout();
                 }
             }
         }
@@ -233,6 +233,40 @@ impl Application {
         }
     }
 
+    pub fn handle_idle_timeout(&mut self) {
+        use helix_view::document::Mode;
+        use crate::commands::{Context, completion};
+
+
+        if doc_mut!(self.editor).mode != Mode::Insert {
+            return;
+        }
+        let editor_view = self
+            .compositor
+            .find(std::any::type_name::<ui::EditorView>())
+            .expect("expected at least one EditorView");
+        let editor_view = editor_view
+            .as_any_mut()
+            .downcast_mut::<ui::EditorView>()
+            .unwrap();
+
+        if editor_view.completion.is_some() {
+            return;
+        }
+
+        let mut cx = Context {
+            selected_register: helix_view::RegisterSelection::default(),
+            editor: &mut self.editor,
+            jobs: &mut self.jobs,
+            count: None,
+            callback: None,
+            on_next_key_callback: None,
+        };
+       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>>) {
         let mut cx = crate::compositor::Context {
             editor: &mut self.editor,
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index ec76c81d..1dbb5616 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -4045,7 +4045,7 @@ fn remove_primary_selection(cx: &mut Context) {
     doc.set_selection(view.id, selection);
 }
 
-fn completion(cx: &mut Context) {
+pub fn completion(cx: &mut Context) {
     // trigger on trigger char, or if user calls it
     // (or on word char typing??)
     // after it's triggered, if response marked is_incomplete, update on every subsequent keypress
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index aa2d6636..ee3b3c65 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -33,7 +33,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>,
 }
-- 
cgit v1.2.3-70-g09d2


From 66f26e82ceaf4b81dfeb429dcb840a3242e8f254 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Fri, 27 Aug 2021 10:44:12 +0900
Subject: Filter the initial completion

---
 helix-term/src/application.rs   | 11 ++++++-----
 helix-term/src/commands.rs      | 17 ++++++++++++-----
 helix-term/src/ui/completion.rs | 25 +++++++++++++++++++------
 helix-term/src/ui/editor.rs     |  5 ++++-
 helix-view/src/macros.rs        | 16 ++++++++++++++++
 5 files changed, 57 insertions(+), 17 deletions(-)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index ab268041..79921268 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -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>>) {
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 1dbb5616..3798c99a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -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);
             };
         },
     );
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index 6c9e3a80..72b03274 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -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()
     }
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index ee3b3c65..fda6a6d3 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -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);
diff --git a/helix-view/src/macros.rs b/helix-view/src/macros.rs
index c9a04270..0bebd02f 100644
--- a/helix-view/src/macros.rs
+++ b/helix-view/src/macros.rs
@@ -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)
+    }};
+}
-- 
cgit v1.2.3-70-g09d2


From 8ca91891d1f8f6df8073a4cc4af4132f8c6695ce Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Tue, 5 Oct 2021 22:35:38 +0900
Subject: fix compilation

---
 helix-term/src/application.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 79921268..8019b839 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -256,7 +256,7 @@ impl Application {
         // 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(),
+            register: None,
             editor: &mut self.editor,
             jobs: &mut self.jobs,
             count: None,
-- 
cgit v1.2.3-70-g09d2


From f692ede2b7af9ee3c0a83642c0e169ac2db90ca5 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Thu, 7 Oct 2021 10:37:35 +0900
Subject: fix: Don't crash on empty completion, don't retrigger on close

---
 helix-term/src/ui/editor.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

(limited to 'helix-term')

diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index fda6a6d3..9234bb96 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -730,6 +730,12 @@ impl EditorView {
     ) {
         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);
@@ -939,6 +945,7 @@ impl Component for EditorView {
                                     if callback.is_some() {
                                         // assume close_fn
                                         self.completion = None;
+                                        cxt.editor.clear_idle_timer(); // don't retrigger
                                     }
                                 }
                             }
@@ -952,6 +959,7 @@ impl Component for EditorView {
                                     completion.update(&mut cxt);
                                     if completion.is_empty() {
                                         self.completion = None;
+                                        cxt.editor.clear_idle_timer(); // don't retrigger
                                     }
                                 }
                             }
-- 
cgit v1.2.3-70-g09d2


From 9f27be429d0b4848a01876cd0eb192f2db8a830b Mon Sep 17 00:00:00 2001
From: Ethan Frei
Date: Thu, 7 Oct 2021 21:08:10 -0500
Subject: relative paths showing active file in global search (#803)

---
 helix-term/src/commands.rs | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

(limited to 'helix-term')

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index ec76c81d..c1fd7bfe 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1291,7 +1291,8 @@ fn global_search(cx: &mut Context) {
 
     cx.push_layer(Box::new(prompt));
 
-    let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
+    let current_path = doc_mut!(cx.editor).path().cloned();
+
     let show_picker = async move {
         let all_matches: Vec<(usize, PathBuf)> =
             UnboundedReceiverStream::new(all_matches_rx).collect().await;
@@ -1301,14 +1302,19 @@ fn global_search(cx: &mut Context) {
                     editor.set_status("No matches found".to_string());
                     return;
                 }
+
                 let picker = FilePicker::new(
                     all_matches,
                     move |(_line_num, path)| {
-                        path.strip_prefix(&root)
-                            .unwrap_or(path)
+                        let relative_path = helix_core::path::get_relative_path(path)
                             .to_str()
                             .unwrap()
-                            .into()
+                            .to_owned();
+                        if current_path.as_ref().map(|p| p == path).unwrap_or(false) {
+                            format!("{} (*)", relative_path).into()
+                        } else {
+                            relative_path.into()
+                        }
                     },
                     move |editor: &mut Editor, (line_num, path), action| {
                         match editor.open(path.into(), action) {
-- 
cgit v1.2.3-70-g09d2


From a6852fb88f72ea6bb41b19e65b531c17662ba57d Mon Sep 17 00:00:00 2001
From: Leoi Hung Kin
Date: Sat, 9 Oct 2021 19:34:10 +0800
Subject: Picker: Don't panick at move_up/move_down when matches is empty
 (#818)

---
 helix-term/src/ui/picker.rs | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'helix-term')

diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index c5b90a9c..9be2a73e 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -270,12 +270,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;
-- 
cgit v1.2.3-70-g09d2


From c7f3a971c0e42d1ecb8b91f075b2300040b656fa Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Sun, 10 Oct 2021 12:22:11 +0900
Subject: Remove resolved TODOs

---
 helix-term/src/application.rs | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 8019b839..c39a9173 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -253,8 +253,6 @@ impl Application {
             return;
         }
 
-        // TODO: if completion window was closed with enter (and no selection) we shouldn't retrigger
-
         let mut cx = Context {
             register: None,
             editor: &mut self.editor,
@@ -264,7 +262,6 @@ impl Application {
             on_next_key_callback: None,
         };
         completion(&mut cx);
-        // TODO: scan backwards for trigger and filter the box
         self.render();
     }
 
-- 
cgit v1.2.3-70-g09d2


From 633b981db22bb30c601b838eaaeb814a64156125 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Sun, 10 Oct 2021 12:32:06 +0900
Subject: Make idle-timeout configurable

---
 book/src/configuration.md  |  1 +
 helix-term/src/commands.rs | 11 +++++++++--
 helix-view/src/editor.rs   | 12 ++++++++++++
 3 files changed, 22 insertions(+), 2 deletions(-)

(limited to 'helix-term')

diff --git a/book/src/configuration.md b/book/src/configuration.md
index 60b12bfd..f30146dd 100644
--- a/book/src/configuration.md
+++ b/book/src/configuration.md
@@ -19,6 +19,7 @@ To override global configuration parameters, create a `config.toml` file located
 | `line-number` | Line number display (`absolute`, `relative`) | `absolute` |
 | `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` |
 | `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
+| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
 
 ## LSP
 
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 3798c99a..f005e376 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -4130,7 +4130,7 @@ pub fn completion(cx: &mut Context) {
             };
 
             if items.is_empty() {
-                editor.set_error("No completion available".to_string());
+                // editor.set_error("No completion available".to_string());
                 return;
             }
             let size = compositor.size();
@@ -4138,7 +4138,14 @@ 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(editor, items, offset_encoding, start_offset, trigger_offset, size);
+                ui.set_completion(
+                    editor,
+                    items,
+                    offset_encoding,
+                    start_offset,
+                    trigger_offset,
+                    size,
+                );
             };
         },
     );
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 5362acc8..5af6dbf3 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -26,6 +26,14 @@ use helix_core::Position;
 
 use serde::Deserialize;
 
+fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result<Duration, D::Error>
+where
+    D: serde::Deserializer<'de>,
+{
+    let millis = u64::deserialize(deserializer)?;
+    Ok(Duration::from_millis(millis))
+}
+
 #[derive(Debug, Clone, PartialEq, Deserialize)]
 #[serde(rename_all = "kebab-case", default)]
 pub struct Config {
@@ -45,6 +53,9 @@ pub struct Config {
     pub smart_case: bool,
     /// Automatic insertion of pairs to parentheses, brackets, etc. Defaults to true.
     pub auto_pairs: bool,
+    /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
+    #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
+    pub idle_timeout: Duration,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
@@ -72,6 +83,7 @@ impl Default for Config {
             middle_click_paste: true,
             smart_case: true,
             auto_pairs: true,
+            idle_timeout: Duration::from_millis(400),
         }
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 76b1bbc23ad5fc47765472cd9e83727a43c97ff3 Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Sun, 10 Oct 2021 12:33:22 +0900
Subject: Allow trigger_offset to be unused for now

---
 helix-term/src/ui/completion.rs | 1 +
 1 file changed, 1 insertion(+)

(limited to 'helix-term')

diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index 72b03274..ba009c50 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -70,6 +70,7 @@ impl menu::Item for CompletionItem {
 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
 }
-- 
cgit v1.2.3-70-g09d2


From 4d07eaa48bc4fc0c75e0346406fb6dedfc7db743 Mon Sep 17 00:00:00 2001
From: Leoi Hung Kin
Date: Fri, 15 Oct 2021 16:36:39 +0800
Subject: Prevent LSP Messages from displaying when a prompt is presented
 (#824)

* Prevent LSP Messages from displaying when a prompt is presented

* use match guard---
 helix-term/src/application.rs | 33 ++++++++++++++++++++++++---------
 helix-term/src/compositor.rs  |  6 ++++++
 2 files changed, 30 insertions(+), 9 deletions(-)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index c39a9173..7667441b 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -295,14 +295,6 @@ impl Application {
         server_id: usize,
     ) {
         use helix_lsp::{Call, MethodCall, Notification};
-        let editor_view = self
-            .compositor
-            .find(std::any::type_name::<ui::EditorView>())
-            .expect("expected at least one EditorView");
-        let editor_view = editor_view
-            .as_any_mut()
-            .downcast_mut::<ui::EditorView>()
-            .unwrap();
 
         match call {
             Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
@@ -412,7 +404,19 @@ impl Application {
                     Notification::LogMessage(params) => {
                         log::info!("window/logMessage: {:?}", params);
                     }
-                    Notification::ProgressMessage(params) => {
+                    Notification::ProgressMessage(params)
+                        if !self
+                            .compositor
+                            .has_component(std::any::type_name::<ui::Prompt>()) =>
+                    {
+                        let editor_view = self
+                            .compositor
+                            .find(std::any::type_name::<ui::EditorView>())
+                            .expect("expected at least one EditorView");
+                        let editor_view = editor_view
+                            .as_any_mut()
+                            .downcast_mut::<ui::EditorView>()
+                            .unwrap();
                         let lsp::ProgressParams { token, value } = params;
 
                         let lsp::ProgressParamsValue::WorkDone(work) = value;
@@ -487,6 +491,9 @@ impl Application {
                             self.editor.set_status(status);
                         }
                     }
+                    Notification::ProgressMessage(_params) => {
+                        // do nothing
+                    }
                 }
             }
             Call::MethodCall(helix_lsp::jsonrpc::MethodCall {
@@ -521,6 +528,14 @@ impl Application {
                     MethodCall::WorkDoneProgressCreate(params) => {
                         self.lsp_progress.create(server_id, params.token);
 
+                        let editor_view = self
+                            .compositor
+                            .find(std::any::type_name::<ui::EditorView>())
+                            .expect("expected at least one EditorView");
+                        let editor_view = editor_view
+                            .as_any_mut()
+                            .downcast_mut::<ui::EditorView>()
+                            .unwrap();
                         let spinner = editor_view.spinners_mut().get_or_create(server_id);
                         if spinner.is_stopped() {
                             spinner.start();
diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index 36e54ede..cad1df05 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -171,6 +171,12 @@ impl Compositor {
         (None, CursorKind::Hidden)
     }
 
+    pub fn has_component(&self, type_name: &str) -> bool {
+        self.layers
+            .iter()
+            .any(|component| component.type_name() == type_name)
+    }
+
     pub fn find(&mut self, type_name: &str) -> Option<&mut dyn Component> {
         self.layers
             .iter_mut()
-- 
cgit v1.2.3-70-g09d2


From c71b49497d8fc8ee487b7cfeafb7392b71a13d17 Mon Sep 17 00:00:00 2001
From: Omnikar
Date: Fri, 15 Oct 2021 21:04:26 -0400
Subject: Set CWD when editor is started with a directory (#849)

---
 helix-term/src/application.rs | 1 +
 1 file changed, 1 insertion(+)

(limited to 'helix-term')

diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 7667441b..b3fa79ee 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -100,6 +100,7 @@ impl Application {
         if !args.files.is_empty() {
             let first = &args.files[0]; // we know it's not empty
             if first.is_dir() {
+                std::env::set_current_dir(&first)?;
                 editor.new_file(Action::VerticalSplit);
                 compositor.push(Box::new(ui::file_picker(first.clone())));
             } else {
-- 
cgit v1.2.3-70-g09d2


From 2c0468ffd16de1f835ac9c4e39692a682273fb7b Mon Sep 17 00:00:00 2001
From: Blaž Hrastnik
Date: Sat, 16 Oct 2021 18:43:07 +0900
Subject: fix: If backspacing past the start offset, cancel completion

Refs #822
---
 helix-term/src/ui/completion.rs | 4 ++++
 helix-term/src/ui/menu.rs       | 8 ++++++++
 2 files changed, 12 insertions(+)

(limited to 'helix-term')

diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index ba009c50..c75b24f1 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -215,6 +215,10 @@ impl Completion {
             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();
         }
     }
 
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;
-- 
cgit v1.2.3-70-g09d2


From 89707a858f593c99d44af173e9fb2c0d72b8697e Mon Sep 17 00:00:00 2001
From: Ivan Tham
Date: Sat, 16 Oct 2021 21:57:41 +0800
Subject: Make auto-completion a config (#853)

---
 book/src/configuration.md     | 1 +
 helix-term/src/application.rs | 2 +-
 helix-view/src/editor.rs      | 5 ++++-
 3 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'helix-term')

diff --git a/book/src/configuration.md b/book/src/configuration.md
index f30146dd..d47f95d9 100644
--- a/book/src/configuration.md
+++ b/book/src/configuration.md
@@ -19,6 +19,7 @@ To override global configuration parameters, create a `config.toml` file located
 | `line-number` | Line number display (`absolute`, `relative`) | `absolute` |
 | `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` |
 | `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
+| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
 | `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
 
 ## LSP
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index b3fa79ee..0e7d0e55 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -238,7 +238,7 @@ impl Application {
         use crate::commands::{completion, Context};
         use helix_view::document::Mode;
 
-        if doc_mut!(self.editor).mode != Mode::Insert {
+        if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
             return;
         }
         let editor_view = self
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index d0ea6653..90e3bf47 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -47,12 +47,14 @@ pub struct Config {
     pub shell: Vec<String>,
     /// Line number mode.
     pub line_number: LineNumber,
-    /// Middle click paste support. Defaults to true
+    /// Middle click paste support. Defaults to true.
     pub middle_click_paste: bool,
     /// Smart case: Case insensitive searching unless pattern contains upper case characters. Defaults to true.
     pub smart_case: bool,
     /// Automatic insertion of pairs to parentheses, brackets, etc. Defaults to true.
     pub auto_pairs: bool,
+    /// Automatic auto-completion, automatically pop up without user trigger. Defaults to true.
+    pub auto_completion: bool,
     /// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
     #[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
     pub idle_timeout: Duration,
@@ -83,6 +85,7 @@ impl Default for Config {
             middle_click_paste: true,
             smart_case: true,
             auto_pairs: true,
+            auto_completion: true,
             idle_timeout: Duration::from_millis(400),
         }
     }
-- 
cgit v1.2.3-70-g09d2