From e867ab7ec24ae61f437b2dc928aff095c2ac4022 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Thu, 15 Sep 2022 12:14:32 -0600 Subject: command.vim: change g: semantics instead of starting a command around a text object, repeat the last ranged command around that text object. So one can now do something like vip:sort to sort the current paragraph, and then that command can be repeated on a different paragraph with g:ip, and then the command is dot-repeatable. --- plugin/command.vim | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file 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 +" 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 +" +" 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 g: :set operatorfunc=do_command_aroundg@ +noremap g:: :set operatorfunc=do_command_aroundg@_ + +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 -- cgit