diff options
-rw-r--r-- | plugin/command.vim | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/plugin/command.vim b/plugin/command.vim index db18cf3..4101307 100644 --- a/plugin/command.vim +++ b/plugin/command.vim @@ -1,14 +1,53 @@ -" g: is a command to run a vim command around a text object. +" g: last command operator. " -" For example, to do a substitution inside the current block, one can do: +" Runs the last command over the given text object. " -" g:iBs/foo/bar/g<cr> +" By "last command" I mean the last command run with a range. This avoids all those pesky :w and :e +" commands. +" +" so now to join all lines in a text object one could do something like: +" +" vap:join<cr> +" +" now this command can be repeated around a different text object using g:, for example g:ab +" +" what's more is after using g:, it is dot-repeatable. +" +" Note that while this is powerful, it wil only work on line-style selections as that it a +" limitation of ex commands. noremap <silent> g: :set operatorfunc=<SID>do_command_around<cr>g@ +noremap <silent> g:: :set operatorfunc=<SID>do_command_around<cr>g@_ + +function! s:find_cmd() abort + let match_mark = "\\('.\\)\\?[0-9\\-+^$.%]*" + + let i = -1 + while 1 + let ocmd = histget(':', i) + + " Strip the leading range + let ncmd = substitute(ocmd, printf('\(%s\)\(,\(%s\)\)\?', match_mark, match_mark), "", "") + + if ncmd != ocmd + " If this command had a range, use that one. + let cmd = ncmd + break + endif + + let i -= 1 + endwhile + + return cmd +endfunction function! s:do_command_around(str) abort - let [_, lnum0, _, _] = getpos("'[") - let [_, lnum1, _, _] = getpos("']") + call setpos("'<", getpos("'[")) + call setpos("'>", getpos("']")) + + let cmd = s:find_cmd() + - call feedkeys(printf(":silent! %d,%d ", lnum0, lnum1)) + echo printf("'<,'>%s", cmd) + exec printf("'<,'>%s", cmd) endfunction |