-
Notifications
You must be signed in to change notification settings - Fork 334
/
Copy pathtmux_navigator.vim
148 lines (128 loc) · 4.92 KB
/
tmux_navigator.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
" Maps <C-h/j/k/l> to switch vim splits in the given direction. If there are
" no more windows in that direction, forwards the operation to tmux.
" Additionally, <C-\> toggles between last active vim splits/tmux panes.
if exists("g:loaded_tmux_navigator") || &cp || v:version < 700
finish
endif
let g:loaded_tmux_navigator = 1
function! s:VimNavigate(direction)
try
execute 'wincmd ' . a:direction
catch
echohl ErrorMsg | echo 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits: wincmd k' | echohl None
endtry
endfunction
if !get(g:, 'tmux_navigator_no_mappings', 0)
nnoremap <silent> <c-h> :<C-U>TmuxNavigateLeft<cr>
nnoremap <silent> <c-j> :<C-U>TmuxNavigateDown<cr>
nnoremap <silent> <c-k> :<C-U>TmuxNavigateUp<cr>
nnoremap <silent> <c-l> :<C-U>TmuxNavigateRight<cr>
nnoremap <silent> <c-\> :<C-U>TmuxNavigatePrevious<cr>
if !get(g:, 'tmux_navigator_disable_netrw_workaround', 0)
if !exists('g:Netrw_UserMaps')
let g:Netrw_UserMaps = [['<C-l>', '<C-U>TmuxNavigateRight<cr>']]
else
echohl ErrorMsg | echo 'vim-tmux-navigator conflicts with netrw <C-l> mapping. See https://github.com/christoomey/vim-tmux-navigator#netrw or add `let g:tmux_navigator_disable_netrw_workaround = 1` to suppress this warning.' | echohl None
endif
endif
endif
if empty($TMUX)
command! TmuxNavigateLeft call s:VimNavigate('h')
command! TmuxNavigateDown call s:VimNavigate('j')
command! TmuxNavigateUp call s:VimNavigate('k')
command! TmuxNavigateRight call s:VimNavigate('l')
command! TmuxNavigatePrevious call s:VimNavigate('p')
finish
endif
command! TmuxNavigateLeft call s:TmuxAwareNavigate('h')
command! TmuxNavigateDown call s:TmuxAwareNavigate('j')
command! TmuxNavigateUp call s:TmuxAwareNavigate('k')
command! TmuxNavigateRight call s:TmuxAwareNavigate('l')
command! TmuxNavigatePrevious call s:TmuxAwareNavigate('p')
if !exists("g:tmux_navigator_save_on_switch")
let g:tmux_navigator_save_on_switch = 0
endif
if !exists("g:tmux_navigator_disable_when_zoomed")
let g:tmux_navigator_disable_when_zoomed = 0
endif
if !exists("g:tmux_navigator_preserve_zoom")
let g:tmux_navigator_preserve_zoom = 0
endif
if !exists("g:tmux_navigator_no_wrap")
let g:tmux_navigator_no_wrap = 0
endif
let s:pane_position_from_direction = {'h': 'left', 'j': 'bottom', 'k': 'top', 'l': 'right'}
function! s:TmuxOrTmateExecutable()
return (match($TMUX, 'tmate') != -1 ? 'tmate' : 'tmux')
endfunction
function! s:TmuxVimPaneIsZoomed()
return s:TmuxCommand("display-message -p '#{window_zoomed_flag}'") == 1
endfunction
function! s:TmuxSocket()
" The socket path is the first value in the comma-separated list of $TMUX.
return split($TMUX, ',')[0]
endfunction
function! s:TmuxCommand(args)
let cmd = s:TmuxOrTmateExecutable() . ' -S ' . s:TmuxSocket() . ' ' . a:args
let l:x=&shellcmdflag
let &shellcmdflag='-c'
let retval=system(cmd)
let &shellcmdflag=l:x
return retval
endfunction
function! s:TmuxNavigatorProcessList()
echo s:TmuxCommand("run-shell 'ps -o state= -o comm= -t ''''#{pane_tty}'''''")
endfunction
command! TmuxNavigatorProcessList call s:TmuxNavigatorProcessList()
let s:tmux_is_last_pane = 0
augroup tmux_navigator
au!
autocmd WinEnter * let s:tmux_is_last_pane = 0
augroup END
function! s:NeedsVitalityRedraw()
return exists('g:loaded_vitality') && v:version < 704 && !has("patch481")
endfunction
function! s:ShouldForwardNavigationBackToTmux(tmux_last_pane, at_tab_page_edge)
if g:tmux_navigator_disable_when_zoomed && s:TmuxVimPaneIsZoomed()
return 0
endif
return a:tmux_last_pane || a:at_tab_page_edge
endfunction
function! s:TmuxAwareNavigate(direction)
let nr = winnr()
let tmux_last_pane = (a:direction == 'p' && s:tmux_is_last_pane)
if !tmux_last_pane
call s:VimNavigate(a:direction)
endif
let at_tab_page_edge = (nr == winnr())
" Forward the switch panes command to tmux if:
" a) we're toggling between the last tmux pane;
" b) we tried switching windows in vim but it didn't have effect.
if s:ShouldForwardNavigationBackToTmux(tmux_last_pane, at_tab_page_edge)
if g:tmux_navigator_save_on_switch == 1
try
update " save the active buffer. See :help update
catch /^Vim\%((\a\+)\)\=:E32/ " catches the no file name error
endtry
elseif g:tmux_navigator_save_on_switch == 2
try
wall " save all the buffers. See :help wall
catch /^Vim\%((\a\+)\)\=:E141/ " catches the no file name error
endtry
endif
let args = 'select-pane -t ' . shellescape($TMUX_PANE) . ' -' . tr(a:direction, 'phjkl', 'lLDUR')
if g:tmux_navigator_preserve_zoom == 1
let l:args .= ' -Z'
endif
if g:tmux_navigator_no_wrap == 1
let args = 'if -F "#{pane_at_' . s:pane_position_from_direction[a:direction] . '}" "" "' . args . '"'
endif
silent call s:TmuxCommand(args)
if s:NeedsVitalityRedraw()
redraw!
endif
let s:tmux_is_last_pane = 1
else
let s:tmux_is_last_pane = 0
endif
endfunction