Repository: alacritty/alacritty (language: rust)

Issue:
Searching for uppercase, accented letters, and symbols doesn't work in inline vi mode search (f/F/t/T)
Hi, searching for lowercase ascii [a-z] characters in inline vi mode search (f/F/t/T) works fine, but it doesn't work for:

  - Uppercase characters.
  - Accented letters (i.e: í, é, á, ü, ...) gets inserted instead of being searched.
  - Symbol characters (i.e.: :, ?, ¿, ¡, ¿), and / starts a search instead of being searched.

### System

OS: GNU/Linux Debian trixie/sid
Version: `alacritty 0.13.2`
Linux/BSD: X11 with awesomewm

Thanks for this great terminal!


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9d8d3ff892..7dff2d54ee5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,6 +50,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its
 - Alacritty not being properly activated with startup notify
 - Invalid URL highlights after terminal scrolling
 - Hollow block cursor not spanning multiple chars being edited inside the IME preview
+- Vi inline search only working for direct key input without modifiers
 
 ## 0.13.2
 
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index a8501da67f0..d0044f8bf15 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -884,8 +884,11 @@ impl Display {
             },
             None => {
                 let num_lines = self.size_info.screen_lines();
-                term::point_to_viewport(display_offset, cursor_point)
-                    .filter(|point| point.line < num_lines)
+                match vi_cursor_viewport_point {
+                    None => term::point_to_viewport(display_offset, cursor_point)
+                        .filter(|point| point.line < num_lines),
+                    point => point,
+                }
             },
         };
 
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index 46e9433c1ac..23575e21eb1 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -1218,6 +1218,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
             for c in text.chars() {
                 self.search_input(c);
             }
+        } else if self.inline_search_state.char_pending {
+            self.inline_search_input(text);
         } else if bracketed && self.terminal().mode().contains(TermMode::BRACKETED_PASTE) {
             self.on_terminal_input_start();
 
@@ -1291,6 +1293,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
         self.inline_search_state.stop_short = stop_short;
         self.inline_search_state.direction = direction;
         self.inline_search_state.char_pending = true;
+        self.inline_search_state.character = None;
     }
 
     /// Jump to the next matching character in the line.
@@ -1305,6 +1308,22 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
         self.inline_search(direction);
     }
 
+    /// Process input during inline search.
+    fn inline_search_input(&mut self, text: &str) {
+        // Ignore input with empty text, like modifier keys.
+        let c = match text.chars().next() {
+            Some(c) => c,
+            None => return,
+        };
+
+        self.inline_search_state.char_pending = false;
+        self.inline_search_state.character = Some(c);
+        self.window().set_ime_allowed(false);
+
+        // Immediately move to the captured character.
+        self.inline_search_next();
+    }
+
     fn message(&self) -> Option<&Message> {
         self.message_buffer.message()
     }
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs
index 4bc3ffee098..147555940bd 100644
--- a/alacritty/src/input/keyboard.rs
+++ b/alacritty/src/input/keyboard.rs
@@ -1,5 +1,4 @@
 use std::borrow::Cow;
-use std::mem;
 
 use winit::event::{ElementState, KeyEvent};
 #[cfg(target_os = "macos")]
@@ -29,6 +28,9 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
         let mods = self.ctx.modifiers().state();
 
         if key.state == ElementState::Released {
+            if self.ctx.inline_search_state().char_pending {
+                self.ctx.window().set_ime_allowed(true);
+            }
             self.key_release(key, mode, mods);
             return;
         }
@@ -45,15 +47,8 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
 
         // First key after inline search is captured.
         let inline_state = self.ctx.inline_search_state();
-        if mem::take(&mut inline_state.char_pending) {
-            if let Some(c) = text.chars().next() {
-                inline_state.character = Some(c);
-
-                // Immediately move to the captured character.
-                self.ctx.inline_search_next();
-            }
-
-            // Ignore all other characters in `text`.
+        if inline_state.char_pending {
+            self.ctx.inline_search_input(text);
             return;
         }
 
diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs
index c10777f23c6..bbd8673f7bb 100644
--- a/alacritty/src/input/mod.rs
+++ b/alacritty/src/input/mod.rs
@@ -127,6 +127,7 @@ pub trait ActionContext<T: EventListener> {
     fn inline_search_state(&mut self) -> &mut InlineSearchState;
     fn start_inline_search(&mut self, _direction: Direction, _stop_short: bool) {}
     fn inline_search_next(&mut self) {}
+    fn inline_search_input(&mut self, _text: &str) {}
     fn inline_search_previous(&mut self) {}
     fn hint_input(&mut self, _character: char) {}
     fn trigger_hint(&mut self, _hint: &HintMatch) {}


Test patch: