christoomey / vim-tmux-navigator

Seamless navigation between tmux panes and vim splits
MIT License
5.07k stars 319 forks source link

C-\ not working to switch panes in tmux #298

Open noahmoss opened 3 years ago

noahmoss commented 3 years ago

This is the issue I mentioned in #297.

Basically, C-\ is working to switch to the last pane when I'm in vim, but when I'm in a bash pane it doesn't do anything at all. Nothing is even printed or displayed. My .tmux.conf is set up with the exact commands in the readme. Also tried it in zsh and it exhibits the same behavior.

Thanks for any help you can provide! :)

christoomey commented 3 years ago

Hey @noahmoss, not sure what the issue is, but I've got some questions that might help debug:

  1. What version of Tmux are you on?
  2. Can you try running select-pane -l directly in the tmux command prompt (prefix: to open the prompt, just to be clear there). Does that work as expected? (It should you bounce you back and forth between current and previous pane)
  3. Can you change the tmux binding command:
  if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \
-    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'select-pane -l'"
+    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'display-panes'"
  if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
-    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'select-pane -l'"
+    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'display-panes'"

This'll swap out the pane switching for the display-pane. Now if you hit C-\ and things are wired correctly, you should see the pane numbers briefly flash. Hoping to test if it's the key binding that's mixed up.

noahmoss commented 3 years ago

Hi @christoomey, thanks for the debugging tips!

I'm on tmux 3.2

select-pane -l in the command prompt works as expected.

Changing the commands still doesn't work. I guess that means the key binding itself isn't working? This might be a case of some other config messing with things...

noahmoss commented 3 years ago

I also have vi-mode enabled in bash, which I realized was the root cause of #297. But I tried disabling it and I still wasn't able to get C-\ to work properly, so I guess this is a different problem.

christoomey commented 3 years ago

One other thing worth checking is the output of tmux list-keys. Is it possible that something else is overriding the C-\ mapping?

Based on your testing, it sounds like you're in the murky world of ' and \ escaping in tmux bindings, which is murky at best. The version of the bindings has an extra layer of complexity due to having some version checking logic, but I'd suggest replace them with just the single link you should need. I believe it's the following:

bind-key -n 'C-\\' if-shell "$is_vim" 'send-keys C-\\\\'  'select-pane -l'

Hopefully you can work from that (might have to tweak some ' and " and \\ escapes).

wassimk commented 2 years ago

I had the same problem and this fixed it for me. Escaping $is_vim was needed to make it work on SSH sessions.

bind-key -n C-\\ if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'
jZhangTk commented 2 years ago

I have the same problem. Looks like it is $tmux_version is storing the expression, not the evaluated version number.

❯ echo $tmux_version
^E$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")

Hence echo "$tmux_version >= 3.0" never outputs the right expression 3.2 >= 3.0. I tried a few things but no luck.

Not sure if one of the below could cause the problem.

melbaldove commented 1 year ago

Was able to fix this with

if-shell -b '[ "$(echo "$(eval "echo $tmux_version") < 3.0" | bc)" = 1 ]' \
    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'select-pane -l'"
if-shell -b '[ "$(echo "$(eval "echo $tmux_version") >= 3.0" | bc)" = 1 ]' \
    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'select-pane -l'"
menghuu commented 1 year ago
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?)(diff)?$'"
bind-key -n M-h if-shell "$is_vim" "send-keys M-h" "select-pane -L"
bind-key -n M-j if-shell "$is_vim" "send-keys M-j" "select-pane -D"
bind-key -n M-k if-shell "$is_vim" "send-keys M-k" "select-pane -U"
bind-key -n M-l if-shell "$is_vim" "send-keys M-l" "select-pane -R"
if-shell '[ $(echo $(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p") "<" 3 | bc) -eq 1 ]' \
  "bind-key -n 'M-\\' if-shell \"$is_vim\" 'send-keys M-\\'  'select-pane -l'"
if-shell '[ $(echo $(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p") ">=" 3 | bc) -eq 1 ]' \
  "bind-key -n 'M-\\' if-shell \"$is_vim\" 'send-keys M-\\\\'  'select-pane -l'"

These variables confuse me, maybe writing shell script directly is more intuitive