Skip to content

Instantly share code, notes, and snippets.

@mislav
Last active March 28, 2024 00:47
Show Gist options
  • Save mislav/5189704 to your computer and use it in GitHub Desktop.
Save mislav/5189704 to your computer and use it in GitHub Desktop.
tmux-vim integration to transparently switch between tmux panes and vim split windows

I use tmux splits (panes). Inside one of these panes there's a Vim process, and it has its own splits (windows).

In Vim I have key bindings C-h/j/k/l set to switch windows in the given direction. (Vim default mappings for windows switching are the same, but prefixed with C-W.) I'd like to use the same keystrokes for switching tmux panes.

An extra goal that I've solved with a dirty hack is to toggle between last active panes with C-\.

Here's how it should work:

  1. If I'm in "vim window 2", going in left (C-h) or down (C-j) direction should switch windows inside vim.
  2. However, if I'm in "vim window 3", going right (C-l) or down (C-j) should select the next tmux pane in that direction.

The solution

The solution has 3 parts:

  1. In ~/.tmux.conf, I bind the keys I want to execute a custom tmux-vim-select-pane command;
  2. tmux-vim-select-pane checks if the foreground process in the current tmux pane is Vim, then forwards the original keystroke to the vim process. Otherwise it simply switches tmux panes.
  3. In Vim, I set bindings for the same keystrokes to a custom function. The function tries to switch windows in the given direction. If the window didn't change, that means there are no more windows in the given direction inside vim, and it forwards the pane switching command to tmux by shelling out to tmux select-pane.

Installation

  • check tmux -V that you have v1.8

  • get the vim-tmux-navigator plugin

  • additional ~/.tmux.conf config & tmux-vim-select-pane script:

    curl -fsSL https://gist.github.com/mislav/5189704/raw/install.sh | bash -e
curl -fsSL https://gist.github.com/mislav/5189704/raw/tmux.conf \
>> ~/.tmux.conf
curl -fsSL https://raw.github.com/mislav/dotfiles/1500cd2/bin/tmux-vim-select-pane \
-o /usr/local/bin/tmux-vim-select-pane
chmod +x /usr/local/bin/tmux-vim-select-pane
# Smart pane switching with awareness of vim splits
bind -n C-k run-shell 'tmux-vim-select-pane -U'
bind -n C-j run-shell 'tmux-vim-select-pane -D'
bind -n C-h run-shell 'tmux-vim-select-pane -L'
bind -n C-l run-shell 'tmux-vim-select-pane -R'
bind -n "C-\\" run-shell 'tmux-vim-select-pane -l'
# Bring back clear screen under tmux prefix
bind C-l send-keys 'C-l'
@007kevin
Copy link

Sharing my emacs version with variable pane_current_command (e.g emacs, Emacs, Emacs-v1)

bind -n C-p if "[[ $(tmux display -p '#{pane_current_command}') = [Ee]macs* ]]" "send-keys C-p" "copy-mode; send-keys C-p"
bind -n C-n if "[[ $(tmux display -p '#{pane_current_command}') = [Ee]macs* ]]" "send-keys C-n" "copy-mode; send-keys C-n"
bind -n M-v if "[[ $(tmux display -p '#{pane_current_command}') = [Ee]macs* ]]" "send-keys M-v" "copy-mode; send-keys M-v"
bind -n C-Space if "[[ $(tmux display -p '#{pane_current_command}') = [Ee]macs* ]]" "send-keys C-Space" "copy-mode; send-keys C-Space"

When emacs is the current pane, movement keys will behave as normal. When pane is not emacs, you navigate in copy-mode with the same emacs bindings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment