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)
+    }};
+}