如何在执行ex命令之前使vim的`:global`命令可以确认?

时间:2017-03-22 14:18:34

标签: vim

如何让vim的:global命令询问用户是否要执行ex命令?类似于:substite命令与' c'选项,例如%s:Foo:Fighters:gc

我试过了:

:g/mypattern/.s:.*\n::gc

:g/mypattern/s:.*\n::gc

但如果下面一行有匹配则会跳转。例如:

MATCH
NONMATCH
MATCH

MATCH
MATCH

结果是:

NONMATCH

MATCH  <<-- this should be erased.

提示g/FOO/d将是完美的。

2 个答案:

答案 0 :(得分:3)

没有本地方法可以做到这一点。典型的方法是记录宏并重复宏。确保您在宏的末尾/n前进到下一场比赛。现在跳过@@:Global来执行宏。

自定义:global命令

但是,如果你真的希望confirm()命令带有确认,你可以通过在命令中使用:g/pat/if confirm("&yes\n&no", 2) == 1 | cmd | endif 来模仿它。一般的想法是做这样的事情:

:match

由于以下原因,这不太有效:

  • 您不知道光标在哪里。需要:redraw:Global
  • 之类的内容
  • 不会中止。需要一种方法来抛出异常中止
  • 非常笨拙地输入这个

我已经提出以下确认:G / 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[0] 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 命令

IncSearch

注意:按原样使用。使用\c突出显示并强制:G/foo/d

现在您可以运行:Confirm

自定义:Confirm {cmd}命令

如果您更喜欢使用与提供的@Randy Morris类似的技术,请在执行前使用以下{cmd}命令确认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

:g/foo/Confirm d

这样您就可以使用:h @ :h q :h confirm() :h :exe :h get() :h :match :h :redraw

如需更多帮助,请参阅:

-replace

答案 1 :(得分:2)

据我所知,本机无法做到这一点。我想我已经在一起攻击了一种方法来做到这一点,但它可能是错误的,因为我很长时间没有写过vimscript。在这里我定义了一个命令C,它接受​​一个ex命令作为它的参数。如果按 y Y ,则通过:global返回的每一行都会传递给此ex命令。任何其他键都会导致跳过此行。

let s:GlobalConfirmSignNumber = 42
sign define GlobalConfirmMarker text=>> texthl=Search

function GlobalConfirm(cmd)
    let line = getpos(".")[1]
    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>)

这是一个实际的GIF。在这个gif中,我为包含norm! gUU的每一行运行命令ba。在这种情况下,我通过按 y 三次确认每场比赛。

gif in action

如果有人可以对此进行改进(尤其是标志位),请随意编辑。

相关问题