From fdebd7894aa0a37372300712efb248f874914e5b Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 13 Apr 2018 14:50:42 +0200 Subject: [PATCH] Add support for repeating previous/next commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- plugin/unimpaired.vim | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/plugin/unimpaired.vim b/plugin/unimpaired.vim index 02e41a2..cd82769 100644 --- a/plugin/unimpaired.vim +++ b/plugin/unimpaired.vim @@ -44,8 +44,9 @@ function! s:MapNextFamily(map,cmd) abort let map = 'unimpaired'.toupper(a:map) let cmd = '".(v:count ? v:count : "")."'.a:cmd let end = '"'.(a:cmd ==# 'l' || a:cmd ==# 'c' ? 'zv' : '') - execute 'nnoremap '.map.'Previous :exe "'.cmd.'previous'.end - execute 'nnoremap '.map.'Next :exe "'.cmd.'next'.end + let prevnext = printf('["normal \%sPrevious", "normal \%sNext"]', map, map) + execute 'nnoremap '.map.'Previous :exe prevnext("'.a:cmd.'", "previous", '.prevnext.')' + execute 'nnoremap '.map.'Next :exe prevnext("'.a:cmd.'", "next", '.prevnext.')' execute 'nnoremap '.map.'First :exe "'.cmd.'first'.end execute 'nnoremap '.map.'Last :exe "'.cmd.'last'.end call s:map('n', '['. a:map , map.'Previous') @@ -84,6 +85,36 @@ function! s:entries(path) abort return files endfunction +" Handle previous/next movements, storing the last used one. +function! s:prevnext(cmd, dir, prevnext) abort + let g:unimpaired_prevnext = a:prevnext + let cmd = (v:count ? v:count : '').a:cmd.a:dir + if a:cmd ==# 'l' || a:cmd ==# 'c' + let cmd .= '|normal zv' + endif + return cmd +endfunction +function! s:last_prevnext_cmd(dir) abort + let prevnext = get(g:, 'unimpaired_prevnext', []) + if empty(prevnext) + if &diff + let m = 'c' + elseif !empty(getloclist(0)) + let m = 'l' + elseif !empty(getqflist()) + let m = 'q' + else + let m = 'n' + endif + return 'normal '.(a:dir ==# 'previous' ? '[' : ']').m + endif + return (a:dir ==# 'previous' ? prevnext[0] : prevnext[1]) +endfunction +execute 'nnoremap unimpairedRepeatPrevious :exe last_prevnext_cmd("previous")' +execute 'nnoremap unimpairedRepeatNext :exe last_prevnext_cmd("next")' +call s:map('n', '[.', 'unimpairedRepeatPrevious') +call s:map('n', '].', 'unimpairedRepeatNext') + function! s:FileByOffset(num) abort let file = expand('%:p') if empty(file)