How do I make the vim `: global` command asserted before executing the ex command?
How do I make the vim command
ask the user if they want to execute the ex command? Similar to what happens with a command
with the 'c' option, for example
but if there is a match on the line below, it bounces. For example:
MATCH NONMATCH MATCH MATCH MATCH
NONMATCH MATCH <<-- this should be erased.
will be perfect.
source to share
There is no native way to do this. The typical method would be to record a macro and repeat the macro. Make sure you are
at the end of the macro to go to the next match. Skipping now simply
to execute the macro.
However, if you really want to have a command
with acknowledgment, you can emulate that by using
within your command. The general idea is to do something like this:
:g/pat/if confirm("&yes\n&no", 2) == 1 | cmd | endif
This does not work for the following reasons:
- You don't know where your cursor is. You need something like
- Doesn't stop. Need a way to throw an exception to cancel
- It is very inconvenient to type all this.
I got the following confirmation command
command! -nargs=+ -range=% -complete=command Global <line1>,<line2>call <SID>global_confirm(<q-args>) command! -nargs=+ -range=% -complete=command G <line1>,<line2>call <SID>global_confirm(<q-args>) function! s:global_confirm(args) range let args = a:args let sep = args let [pat, cmd; _] = split(args[1:], '\v([^\\](\\\\)*\\)@<!%d' . char2nr(sep), 1) + ['', ''] match none let options = ['throw "Global: Abort"', cmd, '', 'throw "Global: Abort"'] let cmd = 'exe ''match IncSearch /\c\%''.line(''.'').''l''.@/.''/''' let cmd .= '| redraw' let cmd .= '| exe get(options, confirm("Execute?", "&yes\n&no\n&abort", 2))' try execute a:firstline . ',' . a:lastline . 'g'.sep.pat.sep.cmd catch /Global: Abort/ finally match none endtry endfunction
Note. Use it as is. Uses
for emphasis and strength
Now you can run
If you'd rather use a similar technique to what @Randy Morris provided and use the following command
command! -nargs=+ -complete=command Confirm execute <SID>confirm(<q-args>) | match none function! s:confirm(cmd) let abort = 'match none | throw "Confirm: Abort"' let options = [abort, a:cmd, '', abort] match none execute 'match IncSearch /\c\%' . line('.') . 'l' . @/ . '/' redraw return get(options, confirm('Execute?', "&yes\n&no\n&abort", 2), abort) endfunction
This will allow you to use
For more help see:
:h @ :h q :h confirm() :h :exe :h get() :h :match :h :redraw
source to share
As far as I know, there is no way to do this natively. I think I hacked a way to do this, but it was probably wrong as I haven't written vimscript in a long time. In this I have defined a command
that takes the ex command as its arguments. Each line returned through
is then passed to this ex command if you press yor y. Any other key causes this line to be skipped.
let s:GlobalConfirmSignNumber = 42 sign define GlobalConfirmMarker text=>> texthl=Search function GlobalConfirm(cmd) let line = getpos(".") execute "sign place " . s:GlobalConfirmSignNumber . " line=" . line . " name=GlobalConfirmMarker file=" . expand("%:p") redraw! echomsg "Execute? (y/N) " try let char = nr2char(getchar()) if (char == "y" || char == "Y") execute a:cmd endif finally " Ensure signs are cleaned up if execution is aborted. execute "sign unplace " . s:GlobalConfirmSignNumber endtry redraw! endfunction command -nargs=* C call GlobalConfirm(<q-args>)
Here's a gif of it in action. In this gif, I am running a command
for each line containing
. In this case, I confirmed each match by clicking ythree times.
If anyone can improve on this (especially the sign bit), edit it as you see fit.
source to share