From fda068600b0f5b32bc7396a1ee5ebc94f89cfb5a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:57:50 +0000 Subject: [PATCH 1/2] perf(search): add fast path for terminal search This avoids slice overhead and zipping iterators for the vast majority of search iterations where the first character does not even match. Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com> --- crates/forktty-ui-gtk/src/gtk_app/terminal_search.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/forktty-ui-gtk/src/gtk_app/terminal_search.rs b/crates/forktty-ui-gtk/src/gtk_app/terminal_search.rs index aec7f6b1..93c9cecc 100644 --- a/crates/forktty-ui-gtk/src/gtk_app/terminal_search.rs +++ b/crates/forktty-ui-gtk/src/gtk_app/terminal_search.rs @@ -75,10 +75,17 @@ fn for_each_char_match_start( return; } let mut index = 0; + let first_needle = needle[0]; while index + needle.len() <= haystack.len() { - let matched = haystack[index..index + needle.len()] + // Fast path: avoid slice slicing and zipping iterator overhead for the vast + // majority of positions where the first character doesn't even match. + if !chars_eq_ignore_case(haystack[index], first_needle) { + index += 1; + continue; + } + let matched = haystack[index + 1..index + needle.len()] .iter() - .zip(needle) + .zip(&needle[1..]) .all(|(a, b)| chars_eq_ignore_case(*a, *b)); if matched { if !visit(index) { From afd09d86fb32ce5a36b793bd4d34e91a28cb800d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:47:26 +0000 Subject: [PATCH 2/2] perf(search): add fast path for terminal search This avoids slice overhead and zipping iterators for the vast majority of search iterations where the first character does not even match. Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com> --- crates/forktty-ui-gtk/src/gtk_app/terminal_input.rs | 13 +++++-------- crates/forktty-ui-gtk/src/socket_cli.rs | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/forktty-ui-gtk/src/gtk_app/terminal_input.rs b/crates/forktty-ui-gtk/src/gtk_app/terminal_input.rs index 35435d3b..3211b614 100644 --- a/crates/forktty-ui-gtk/src/gtk_app/terminal_input.rs +++ b/crates/forktty-ui-gtk/src/gtk_app/terminal_input.rs @@ -140,14 +140,11 @@ pub(super) fn translate_gtk_key( return Some(TerminalInput::Bytes(text.as_bytes().to_vec())); } } - if let Some(ch) = key.to_unicode() { - GhosttyKeySpec { - key: GhosttyKey::Char(ch), - ctrl, - alt, - } - } else { - return None; + let ch = key.to_unicode()?; + GhosttyKeySpec { + key: GhosttyKey::Char(ch), + ctrl, + alt, } } }; diff --git a/crates/forktty-ui-gtk/src/socket_cli.rs b/crates/forktty-ui-gtk/src/socket_cli.rs index 73af6c70..038b6517 100644 --- a/crates/forktty-ui-gtk/src/socket_cli.rs +++ b/crates/forktty-ui-gtk/src/socket_cli.rs @@ -81,6 +81,7 @@ use help::{ use hooks::event::*; #[cfg(test)] use hooks::handle_hooks; +#[cfg(feature = "gtk-ghostty")] pub(crate) use hooks::hook_setup_reminder_message; #[cfg(test)] use hooks::install::*;