Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help wanted: CTRL-G CTRL-H keybinding conflicts with tmux #16

Open
wookayin opened this issue Sep 15, 2022 · 2 comments
Open

Help wanted: CTRL-G CTRL-H keybinding conflicts with tmux #16

wookayin opened this issue Sep 15, 2022 · 2 comments

Comments

@wookayin
Copy link

Hello! Thanks for the great plugin.

I know this is more related to zsh or zsh keybinding rather than fzf-git per se, but I'm asking for help because many of the users may run into the same problem.

CTRL-G CTRL-H for commit Hashes do not work in my environment, because it conflicts with CTRL-H mappings:

❯❯❯ bindkey    # (excerpt)
"^G" fzm
"^G^H" fzf-git-hashes-widget
"^H" backward-delete-char

I pressed ^G^H within the KEYTIMEOUT limit (40 ms) but in this case the fzf-git widget does not appear. However, ^G H or other keys (e.g., ^G ^S) works fine. In a similar vein, ^G ^E seems conflicting with ^E (end-of-line) but ^G ^E works OK. Any idea why ^G ^H is not working for me?

This SuperUser thread seems relevant, but there is no working solution posted there (KEYTIMEOUT does not work).

zsh: zsh 5.9 (arm-apple-darwin21.3.0)

@wookayin
Copy link
Author

wookayin commented Sep 15, 2022

Oops; I found that it is not the zsh-bindkey issue, tmux is eating the CTRL-H sequence (outside tmux it works OK). A similar case as #3.

# tmux.conf

is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"'
bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L"
bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D"
bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U"
bind -n C-l if-shell "$is_vim" "send-keys C-l" "send-keys C-l"

@wookayin wookayin changed the title Help wanted: CTRL-G CTRL-H keybinding conflicts Help wanted: CTRL-G CTRL-H keybinding conflicts with tmux Sep 15, 2022
@wookayin
Copy link
Author

wookayin commented Sep 16, 2022

One workaround here.

To map a sequence keymap in tmux, one could do the following (e.g. CTRL-G CTRL-H):

# tmux.conf
bind-key -n -T root        C-g switch-client -T ctrl_g_mode
bind-key    -T ctrl_g_mode C-h send-keys C-g C-h

However, its downside is that it will eat all the 'CTRL-g' as a prefix, so other commands like C-g C-b will not be passed through unless explicitly specified. One could either enumerate a complete list of all known keymaps:

bind-key -n -T root C-g switch-client -T ctrl_g_mode
bind-key -T ctrl_g_mode C-B send-keys C-g C-B
bind-key -T ctrl_g_mode C-E send-keys C-g C-E
bind-key -T ctrl_g_mode C-F send-keys C-g C-F
bind-key -T ctrl_g_mode C-H send-keys C-g C-H
bind-key -T ctrl_g_mode C-R send-keys C-g C-R 
bind-key -T ctrl_g_mode C-S send-keys C-g C-S
bind-key -T ctrl_g_mode C-T send-keys C-g C-T
bind-key -T ctrl_g_mode b send-keys C-g b 
bind-key -T ctrl_g_mode e send-keys C-g e
bind-key -T ctrl_g_mode f send-keys C-g f 
bind-key -T ctrl_g_mode h send-keys C-g h
bind-key -T ctrl_g_mode r send-keys C-g r
bind-key -T ctrl_g_mode s send-keys C-g s
bind-key -T ctrl_g_mode t send-keys C-g t       

or do some clever scripting as follows.

(1) in your zshrc, we export an environment variable so that TMUX can fetch all the zsh keybindings prefixed with ^g:

+# Export all the known keymaps with prefix CTRL-g so it can be mapped in tmux
+export FZF_GIT_BINDKEYS=$(bindkey -p '^g')

(2) in tmux.conf: Add a run-shell line

 # vim-tmux-navigator
 bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L"  
 bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D"
 bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U"
 bind -n C-l if-shell "$is_vim" "send-keys C-l" "send-keys C-l"

+run-shell '~/.tmux/fzf-git-tmux.sh'

(3) ~/.tmux/fzf-git-tmux.sh:

#!/bin/zsh

# Define <CTRL-G ...> keymaps to make fzf-git-tmux work.
# see ~/.zshrc for export of $FZF_GIT_BINDKEYS

tmux bind-key -n -T root C-g send-keys C-g \; switch-client -T ctrl_g_mode

for i in $(echo $FZF_GIT_BINDKEYS); do
    if [[ "$i" =~ "\"\^G([^\"]+)" ]]; then
        local key=${match[1]/\^/C-}
        tmux bind-key -T ctrl_g_mode "$key" send-keys C-g "$key"
    fi
done

return 0;

What this script does is:

  • Read all the bindkey prefixed with CTRL-g (bindkey -p ^g) from $FZF_GIT_BINDKEYS
  • Parse each line (e.g., "^G^H" fzf-git-hashes-widget) to extract key character that follows ^G (e.g. ^H)
  • Run tmux bind-key with a proper conversion, e.g. send-keys C-g C-H

The $FZF_GIT_BINDKEYS variable are read and processed only when tmux initializes (or reloads the config) from the "parent zsh shell", so tmux bindkeys can go out of sync when keymaps in zshrc change, but this should be practically of no problem if we don't change the setting frequently.

But one downside is CTRL-G is remapped everywhere, so any key other sequence that would follow CTRL-G will be eaten (e.g. if you have a keymappings with CTRL-G in vim)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant