Skip to content

Commit fdebd78

Browse files
committed
Add support for repeating previous/next commands
This is useful for mapping it to something convenient like `üü` and `++` on a German keyboard layout, allowing for context-sensitive movement by default (e.g. forwarding to `[c`, `]c` in diff mode), and remembering the last used command group. Other plugins are able to hook into this by setting `g:unimpaired_prevnext`. It uses `:normal` in g:unimpaired_prevnext explicitly. This allows to specify the whole command for `:exe`, and does not require a mapping. The mapping is used internally to handle the `zv`, but that could be included in the command already now. It uses the `g:` namespace, which is important for repeating `[q/]q` across buffers.
1 parent d632599 commit fdebd78

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

plugin/unimpaired.vim

+33-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ function! s:MapNextFamily(map,cmd) abort
4444
let map = '<Plug>unimpaired'.toupper(a:map)
4545
let cmd = '".(v:count ? v:count : "")."'.a:cmd
4646
let end = '"<CR>'.(a:cmd ==# 'l' || a:cmd ==# 'c' ? 'zv' : '')
47-
execute 'nnoremap <silent> '.map.'Previous :<C-U>exe "'.cmd.'previous'.end
48-
execute 'nnoremap <silent> '.map.'Next :<C-U>exe "'.cmd.'next'.end
47+
let prevnext = printf('["normal \%sPrevious", "normal \%sNext"]', map, map)
48+
execute 'nnoremap <silent> '.map.'Previous :<C-U>exe <SID>prevnext("'.a:cmd.'", "previous", '.prevnext.')<CR>'
49+
execute 'nnoremap <silent> '.map.'Next :<C-U>exe <SID>prevnext("'.a:cmd.'", "next", '.prevnext.')<CR>'
4950
execute 'nnoremap <silent> '.map.'First :<C-U>exe "'.cmd.'first'.end
5051
execute 'nnoremap <silent> '.map.'Last :<C-U>exe "'.cmd.'last'.end
5152
call s:map('n', '['. a:map , map.'Previous')
@@ -84,6 +85,36 @@ function! s:entries(path) abort
8485
return files
8586
endfunction
8687

88+
" Handle previous/next movements, storing the last used one.
89+
function! s:prevnext(cmd, dir, prevnext) abort
90+
let g:unimpaired_prevnext = a:prevnext
91+
let cmd = (v:count ? v:count : '').a:cmd.a:dir
92+
if a:cmd ==# 'l' || a:cmd ==# 'c'
93+
let cmd .= '|normal zv'
94+
endif
95+
return cmd
96+
endfunction
97+
function! s:last_prevnext_cmd(dir) abort
98+
let prevnext = get(g:, 'unimpaired_prevnext', [])
99+
if empty(prevnext)
100+
if &diff
101+
let m = 'c'
102+
elseif !empty(getloclist(0))
103+
let m = 'l'
104+
elseif !empty(getqflist())
105+
let m = 'q'
106+
else
107+
let m = 'n'
108+
endif
109+
return 'normal '.(a:dir ==# 'previous' ? '[' : ']').m
110+
endif
111+
return (a:dir ==# 'previous' ? prevnext[0] : prevnext[1])
112+
endfunction
113+
execute 'nnoremap <silent> <Plug>unimpairedRepeatPrevious :<C-U>exe <SID>last_prevnext_cmd("previous")<CR>'
114+
execute 'nnoremap <silent> <Plug>unimpairedRepeatNext :<C-U>exe <SID>last_prevnext_cmd("next")<CR>'
115+
call s:map('n', '[.', '<Plug>unimpairedRepeatPrevious')
116+
call s:map('n', '].', '<Plug>unimpairedRepeatNext')
117+
87118
function! s:FileByOffset(num) abort
88119
let file = expand('%:p')
89120
if empty(file)

0 commit comments

Comments
 (0)