-
-
Save randymorris/825937 to your computer and use it in GitHub Desktop.
| This setup is very ugly and will hopefully get better when some of the TODOs | |
| for tmux get implemented. | |
| --- | |
| 1. Add the stuff from the vimrc file to your .vimrc or some file that is sorced | |
| from your .vimrc. | |
| - This just adds a few maps and functions to escape vim with ^w<motion> | |
| when you are on an edge window in vim. | |
| 2. Add the stuff from the tmux.conf to your .tmux.conf, making changes to the | |
| prefix as you wish. Just be sure to leave ^w as a prefix. | |
| - This sets _almost_ all of the vim ^W commands to use our new shell script | |
| to determine whether or not we are currently in a vim session. The | |
| exceptions are the g* commands which rely on chaining. Chaining afaict | |
| is not possible with this approach. | |
| 3. Add tmux_vim_integration.sh somewhere in your $PATH. | |
| - NOTE: You will *need* to edit this file to set any tmux keybinds that | |
| conflict with vim ^w commands. | |
| - This is an ugly artifact of tmux not being able to set a second key-table | |
| like ratpoison can. Once that is possible we will be able to only map | |
| motion commands using ^w as a prefix for a different key-table. | |
| --- | |
| You should now be able to move around between vim splits and tmux panes with | |
| the same hjkl keybinds. |
| # global settings | |
| set -g prefix C-a,C-w | |
| # Vim passthrough keys. | |
| # for the rest of the tmux keybinds, see tmux_vim_integration.sh. This will | |
| # be a lot prettier once tmux supports multiple key-tables. | |
| bind-key C-w run-shell "tmux_vim_integration.sh 'w'" | |
| bind-key w run-shell "tmux_vim_integration.sh 'w'" | |
| bind-key + run-shell "tmux_vim_integration.sh '+'" | |
| bind-key - run-shell "tmux_vim_integration.sh '-'" | |
| bind-key < run-shell "tmux_vim_integration.sh '<'" | |
| bind-key = run-shell "tmux_vim_integration.sh '='" | |
| bind-key > run-shell "tmux_vim_integration.sh '>'" | |
| bind-key H run-shell "tmux_vim_integration.sh 'H'" | |
| bind-key J run-shell "tmux_vim_integration.sh 'J'" | |
| bind-key K run-shell "tmux_vim_integration.sh 'K'" | |
| bind-key L run-shell "tmux_vim_integration.sh 'L'" | |
| bind-key P run-shell "tmux_vim_integration.sh 'P'" | |
| bind-key R run-shell "tmux_vim_integration.sh 'R'" | |
| bind-key S run-shell "tmux_vim_integration.sh 'S'" | |
| bind-key T run-shell "tmux_vim_integration.sh 'T'" | |
| bind-key W run-shell "tmux_vim_integration.sh 'W'" | |
| bind-key ] run-shell "tmux_vim_integration.sh ']'" | |
| bind-key ^ run-shell "tmux_vim_integration.sh '^'" | |
| bind-key _ run-shell "tmux_vim_integration.sh '_'" | |
| bind-key b run-shell "tmux_vim_integration.sh 'b'" | |
| bind-key c run-shell "tmux_vim_integration.sh 'c'" | |
| bind-key d run-shell "tmux_vim_integration.sh 'd'" | |
| bind-key f run-shell "tmux_vim_integration.sh 'f'" | |
| bind-key F run-shell "tmux_vim_integration.sh 'F'" | |
| bind-key h run-shell "tmux_vim_integration.sh 'h'" | |
| bind-key i run-shell "tmux_vim_integration.sh 'i'" | |
| bind-key j run-shell "tmux_vim_integration.sh 'j'" | |
| bind-key k run-shell "tmux_vim_integration.sh 'k'" | |
| bind-key l run-shell "tmux_vim_integration.sh 'l'" | |
| bind-key n run-shell "tmux_vim_integration.sh 'n'" | |
| bind-key o run-shell "tmux_vim_integration.sh 'o'" | |
| bind-key p run-shell "tmux_vim_integration.sh 'p'" | |
| bind-key q run-shell "tmux_vim_integration.sh 'q'" | |
| bind-key r run-shell "tmux_vim_integration.sh 'r'" | |
| bind-key s run-shell "tmux_vim_integration.sh 's'" | |
| bind-key t run-shell "tmux_vim_integration.sh 't'" | |
| bind-key v run-shell "tmux_vim_integration.sh 'v'" | |
| bind-key w run-shell "tmux_vim_integration.sh 'w'" | |
| bind-key x run-shell "tmux_vim_integration.sh 'x'" | |
| bind-key z run-shell "tmux_vim_integration.sh 'z'" | |
| bind-key | run-shell "tmux_vim_integration.sh '|'" | |
| bind-key } run-shell "tmux_vim_integration.sh '}'" |
| #!/bin/bash | |
| # | |
| # This script sets up vim<->tmux integration. | |
| # | |
| # It allows one to use a single set of keybinds to navigate between | |
| # vim windows and tmux panes. This makes it feel like vim has a | |
| # terminal emulator built in. | |
| [ -z $1 ] && exit | |
| log(){ | |
| # echo $@ | |
| # echo $@ >> ~/tmp/log | |
| return | |
| } | |
| passthrough=$1 | |
| tmux=( $(tmux display -p "#S #I #P") ) | |
| log ${tmux[@]} | |
| sedstr="1,/^Sessions:/ d | |
| :session | |
| /^ ${tmux[0]}:/{ :window; n; | |
| /^ ${tmux[1]}:/{ :pane; n | |
| /^ ${tmux[2]}:/{ s/[^:]\+:\s\S\+ \([[:digit:]]\+\).*/\1/; p; q | |
| } | |
| b pane | |
| } | |
| b window | |
| }; | |
| n | |
| /^$/q | |
| b session" | |
| pid=$(tmux info | sed -n "$sedstr") | |
| log $pid | |
| if ps --ppid $pid | grep -q vim; then | |
| log 'Current app is `vim`' | |
| # pass any key through to vim | |
| exec tmux send-keys C-w $passthrough | |
| else | |
| log 'Current app is `tmux`' | |
| # this list is pulled from `tmux list-keys`. once tmux supports multiple | |
| # key-tables, this should be a lot prettier. | |
| case $passthrough in | |
| 'L') passthrough="switch-client -l";; | |
| 'R') passthrough="kill-pane";; | |
| 'S') passthrough="split-window -h";; | |
| 'c') passthrough="new-window";; | |
| 'd') passthrough="detach-client";; | |
| 'f') passthrough="command-prompt \"find-window '%%'\"";; | |
| 'h') passthrough="select-pane -L";; | |
| 'i') passthrough="display-message";; | |
| 'j') passthrough="select-pane -D";; | |
| 'k') passthrough="select-pane -U";; | |
| 'l') passthrough="select-pane -R";; | |
| 'n') passthrough="next-window";; | |
| 'o') passthrough="select-pane -t :.+";; | |
| 'p') passthrough="previous-window";; | |
| 'q') passthrough="display-panes";; | |
| 'r') passthrough="refresh-client";; | |
| 's') passthrough="split-window";; | |
| 't') passthrough="clock-mode";; | |
| 'w') passthrough='last-pane';; | |
| 'x') passthrough="confirm-before kill-pane";; | |
| esac | |
| tmux $passthrough | |
| # explicitly exit 0 to hush tmux in the case $passthrough isn't a | |
| # tmux command | |
| exit 0 | |
| fi |
| nnoremap <silent> <C-w>h :call WindowMotion('h')<cr> | |
| nnoremap <silent> <C-w>j :call WindowMotion('j')<cr> | |
| nnoremap <silent> <C-w>k :call WindowMotion('k')<cr> | |
| nnoremap <silent> <C-w>l :call WindowMotion('l')<cr> | |
| function WindowMotion(dir) "{{{ | |
| let dir = a:dir | |
| let old_winnr = winnr() | |
| execute "wincmd " . dir | |
| if old_winnr != winnr() | |
| return | |
| endif | |
| if dir == 'h' | |
| let dir = '-L' | |
| elseif dir == 'j' | |
| let dir = '-D' | |
| elseif dir == 'k' | |
| let dir = '-U' | |
| elseif dir == 'l' | |
| let dir = '-R' | |
| endif | |
| call system('tmux select-pane ' . dir) | |
| endfunction |
@str1ngs: even with screen you can't use the same keybind to move within vim windows and within screen windows, unless I'm missing something. This allows me to (say) have tmux up with two panes. One is running a shell and one is running vim with some splits in it. I can freely move around inside of vim and also between vim and the shell all via ^w. I'm very open to a better solution. Multiple keybinds for the "same" action sucks.
Maybe this could use an abstraction layer that would give a unified API for both tmux and screen. Possible?
@rson you mean slits in screen and tmux? because I dont use those just tabs. same with vim and I use dwm to handle all my window splitting.
@str1ngs I suppose I do mean splits in screen. tmux calls them panes. vim calls them windows.
@Daenyth It would be nice. I'd really like to get a bit to sit down with this and get the ugly parts cleaner somehow but I'm not sure the best way to go about it. If you have any ideas or suggestions, feel free to hack on it and let me know if you come up with anything. When I have free time I'll be doing the same.
My main points of hate with this is #3. It just sucks, but I don't see a better way. I don't remember if screen supports multiple key-tables or not (ratpoison was based largely on screen so it may) but that would make this a bit better anyway. Still wouldn't be perfect.
Dunno. My free time is really limited for the foreseeable future. :(
this is why I use screen or use screen bindings in tmux. :P