Skip to content

Instantly share code, notes, and snippets.

@latentflip
Created April 27, 2012 10:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save latentflip/2508226 to your computer and use it in GitHub Desktop.
Save latentflip/2508226 to your computer and use it in GitHub Desktop.
Fancy split navigation with vim and tmux
  • In vim I have split navigation mapped to ctrl+h/j/k/l.
  • In tmux I navigate splits with prefix + ctrl+h/j/k/l.
  • Ideally I would be able to navigate between vim and tmux splits transparently using only ctrl+h/j/k/l.
  • I haven't figured that out yet, but I have figured out how to jump out of vim into the next tmux split if I am at the boundary of vim and tmux, without having to prefix jump, which is pretty ace. ie:
    *=cursor position
    
    -----------            -----------            -----------                  -----------
    | vim  *  |            | vim     |            | vim     |                  | vim     |
    -----------            -----------            -----------                  -----------
    | vim     |  <c-j> ->  | vim  *  |  <c-j> ->  | vim     |  prefix<c-k> ->  | vim   * | 
    ===========            ===========            ===========                  ===========
    | term    |            | term    |            | term  * |                  | term    |
    -----------            -----------            -----------                  -----------

Help needed:

  • I have no idea how to go from a terminal into vim without using the prefix though. I know I can bind keys without the prefix using -n but that breaks the above behaviour.
  • What I think I need is to for <ctrl-j> in tmux bound to a function which checks if the current pane is running vim, if so it send-keys ctrl-j to vim, otherwise it jumps the pane like normal.
  • But I have no idea how to do that, do you?
func! MoveWithTmux(keypressed,direction)
let k = a:keypressed
let d = a:direction
" I don't exactly know how this works, but it does
" Something like silently move to the next split, and see if we are still in the same split
let oldw = winnr()
silent! exe "normal! \<c-w>" . k
let neww = winnr()
silent! exe oldw.'wincmd w'
" If we are in the same split, we must be at a boundary so tell tmux to switch split
if oldw == neww
exec '!tmux select-pane ' . d
else
exe "normal! \<c-w>" . k
end
endfunction
nnoremap <c-j> :call MoveWithTmux('j', '-D')<cr><cr>
nnoremap <c-k> :call MoveWithTmux('k', '-U')<cr><cr>
nnoremap <c-h> :call MoveWithTmux('h', '-L')<cr><cr>
nnoremap <c-l> :call MoveWithTmux('j', '-R')<cr><cr>
@fnilsen
Copy link

fnilsen commented Aug 24, 2012

Magnificent. I've been using Conque inside vim, but it somehow feels wrong with a terminal in there. Perhaps this will ease my conscience while retaining (nearly) seamless split navigation. Thanks!

@tarruda
Copy link

tarruda commented Mar 13, 2013

Ok, based on your idea I have written a few scripts that do what you want, check it out.

@flipsi
Copy link

flipsi commented Jan 12, 2016

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