My tmux session for a given project typically has two horizontal tmux panes with Vim occupying the top 80% of the screen and a shell running below that occupying the remainder. For the most part I stay in Vim, splitting often, and moving amongst those splits with ease.
Then I’ll decide to pop down to the shell split for a moment and confidently hit
<C-j>
… nothing. Hmph. Let’s try again. <C-j>
… nothing. Oh, right,
that’s not a Vim split, it’s a tmux split. <C-a>j
.
I’m constantly stumbling over the disconnect between Vim and tmux splits. There’s a little mental hurdle I have to clear each time and I fail at that more often than I’d care to admit. It’s 2013; Shouldn’t the computer be able to figure out what I meant and just do that? As it turns out, yes.
Vim and tmux, Together in Harmony
Mislav Marohnić devised a solution that allows for using
the same key strokes to switch between Vim and tmux splits. With this in place,
I can use <C-h/j/k/l>
to seamlessly navigate all my splits, be they from tmux
or Vim.
Mislav’s post has an installation script, but a few of us at thoughtbot had trouble getting those exact scripts running successfully. We’ve been able to simplify and generalize the solution some.
Installation
To get the whole thing running, follow these two steps:
- Install the vim-tmux-navigator
Vim plugin from Chris Toomey.
With vundle, that’s as simple as adding
the following to your ~/.vimrc file:
Bundle 'christoomey/vim-tmux-navigator'
Add the following to your
~/.tmux.conf
configuration file to conditionally bind the movement keys depending on the active command:# smart pane switching with awareness of vim splits bind -n C-h run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-h) || tmux select-pane -L" bind -n C-j run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-j) || tmux select-pane -D" bind -n C-k run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-k) || tmux select-pane -U" bind -n C-l run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys C-l) || tmux select-pane -R" bind -n C-\ run "(tmux display-message -p '#{pane_current_command}' | grep -iq vim && tmux send-keys 'C-\\') || tmux select-pane -l"
Note: An earlier version of this post included more steps and dependencies. Thanks to readers Chis Eskow and Christopher Sexton for helping simplify the setup.
What’s next
If you found this useful, you might also enjoy: