From 9368a4864c3a9e697581ed641eb929bb35976164 Mon Sep 17 00:00:00 2001 From: Rootiest Date: Thu, 20 Aug 2026 00:38:02 -0400 Subject: [PATCH 1/2] fix(bindings): trigger fzf inline picker with a lookbehind @ instead of a @@ chord Binding the raw @@ chord made a lone @ an ambiguous prefix, so fish (with fish_sequence_key_delay_ms unset) held every typed @ indefinitely until a disambiguating keystroke arrived, breaking things like `ssh user@host`. Binding the single @ key instead and checking whether the current token is already a bare @ removes the ambiguity entirely: plain @ always self-inserts instantly, and a second consecutive @ triggers the picker in place, with no forced delimiter before you can keep typing. Vi's normal/visual modes are left unbound, matching their existing (no-op) @ behavior. --- conf.d/key_bindings.fish | 12 ++++++++++-- docs/manual/03-key-bindings.md | 8 +++++--- functions/__fzf_inline_picker.fish | 30 ++++++++++++++++++------------ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/conf.d/key_bindings.fish b/conf.d/key_bindings.fish index 1f9793f..588e073 100644 --- a/conf.d/key_bindings.fish +++ b/conf.d/key_bindings.fish @@ -65,7 +65,6 @@ function fish_user_key_bindings bind ctrl-alt-u _replace_command_token type -q qalc && bind ctrl-alt-= _qalc_eval bind ctrl-enter _smart_execute - bind @@ __fzf_inline_picker bind ctrl-right nextd-or-forward-word bind \e\[1\;5C nextd-or-forward-word @@ -77,8 +76,17 @@ function fish_user_key_bindings bind --mode $mode ctrl-alt-u _replace_command_token type -q qalc && bind --mode $mode ctrl-alt-= _qalc_eval bind --mode $mode ctrl-enter _smart_execute - bind --mode $mode @@ __fzf_inline_picker bind --mode $mode ctrl-right nextd-or-forward-word bind --mode $mode \e\[1\;5C nextd-or-forward-word end + + # @ is Emacs/Vi-insert only. Emacs bindings and Vi's "default" (normal) + # mode share the same bind_mode name, so a mode-less `bind @` would also + # land in Vi normal mode, turning its current no-op @ into a self-insert. + # Register the mode-less form only when Vi bindings aren't the active + # base, and rely on the explicit insert-mode bind otherwise. + if test "$fish_key_bindings" != fish_vi_key_bindings + bind @ __fzf_inline_picker + end + bind --mode insert @ __fzf_inline_picker end diff --git a/docs/manual/03-key-bindings.md b/docs/manual/03-key-bindings.md index 7841c13..4df6c5f 100644 --- a/docs/manual/03-key-bindings.md +++ b/docs/manual/03-key-bindings.md @@ -42,9 +42,11 @@ are active in Insert, Normal, and Visual modes unless noted. pressing Enter a second time for certain fast-path commands (speedtest-fast, etc.). - @@ FZF inline picker. Type @@ anywhere on the command - line to open an fzf picker and insert a selection - at the cursor position. + @@ FZF inline picker. Type @ twice anywhere on the + command line to open an fzf picker and replace the + @@ with the selection. The @@ must be typed as its + own token: "test @@" triggers it, but "test@@" does + not. Ctrl+Right Accept autosuggestion one word/directory segment at a time. (Restores Fish 3.x behavior by binding diff --git a/functions/__fzf_inline_picker.fish b/functions/__fzf_inline_picker.fish index 7913d45..f9e05fb 100644 --- a/functions/__fzf_inline_picker.fish +++ b/functions/__fzf_inline_picker.fish @@ -5,23 +5,29 @@ # __fzf_inline_picker # # DESCRIPTION -# Opens an interactive fzf session and injects the selected item directly -# into the command line at the cursor position. Bound to @@ by default. +# Bound to the @ key. Self-inserts @ normally; on a second consecutive @ +# (detected by looking behind at the current token rather than making fish +# buffer ahead for a chord), opens an interactive fzf session and replaces +# the bare @ with the selected item. Cancelling leaves a literal @@ behind. # Repaints the prompt after selection or cancellation. # # EXIT STATUS -# 0 Always; no-op if fzf is cancelled +# 0 Always # # EXAMPLE -# # Press @@ at the command prompt to open fzf and insert the selected item. +# # Press @ twice at the command prompt to open fzf and insert the +# # selected item in place of the second @, then keep typing to extend it +# # (e.g. a trailing /subdir). function __fzf_inline_picker - # Open fzf and capture selection - set -l selection (fzf) - - if test -n "$selection" - # Injects text instantly at the cursor - commandline -i (string escape -- $selection) + if test (commandline -t) = @ + set -l selection (fzf) + if test -n "$selection" + commandline -t -- (string escape -- $selection) + else + commandline -t -- @@ + end + commandline -f repaint + else + commandline -i @ end - # Refresh the line display - commandline -f repaint end -- 2.54.0 From 27f780e7334a427a2cb05cbdce8274010f35ae69 Mon Sep 17 00:00:00 2001 From: Rootiest Date: Thu, 20 Aug 2026 00:38:22 -0400 Subject: [PATCH 2/2] docs(manual): use cat as the token-boundary example for @@ --- docs/manual/03-key-bindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manual/03-key-bindings.md b/docs/manual/03-key-bindings.md index 4df6c5f..711905c 100644 --- a/docs/manual/03-key-bindings.md +++ b/docs/manual/03-key-bindings.md @@ -45,7 +45,7 @@ are active in Insert, Normal, and Visual modes unless noted. @@ FZF inline picker. Type @ twice anywhere on the command line to open an fzf picker and replace the @@ with the selection. The @@ must be typed as its - own token: "test @@" triggers it, but "test@@" does + own token: "cat @@" triggers it, but "cat@@" does not. Ctrl+Right Accept autosuggestion one word/directory segment -- 2.54.0