Vim - 我可以在不编写函数的情况下将多个参数传递给自定义命令吗

Ale*_*kay 3 linux bash vim command-line vimscript

我在我的 .vimrc 文件中编写了以下自定义命令:

command! -nargs=+ Sub :%s/<args>/g
Run Code Online (Sandbox Code Playgroud)

它允许我用一个词替换另一个词并执行如下:

:Sub <word>/<new word>
Run Code Online (Sandbox Code Playgroud)

我更喜欢用多个参数编写命令,如下所示:

:Sub <word> <new word>
Run Code Online (Sandbox Code Playgroud)

我可以重写命令以接受多个参数吗?

理想情况下,我想要这样的东西:

command! -nargs=+ Sub :%s/<arg1>/<arg2>/g
Run Code Online (Sandbox Code Playgroud)

先感谢您。

Ing*_*kat 5

自己做解析

如果你使用:help <q-args>,你会得到一个带引号的字符串,你可以把它split()分成两个空格分隔的部分:

command! -nargs=+ Sub execute '%substitute/' . split(<q-args>, ' ')[0] . '/' . split(<q-args>, ' ')[1] . '/g'
Run Code Online (Sandbox Code Playgroud)

我们可以通过一些元编程 ( call()) 和printf()

command! -nargs=+ Sub execute call('printf', ['%%substitute/%s/%s/g'] + split(<q-args>, ' '))
Run Code Online (Sandbox Code Playgroud)

这有效,但错误处理仍然不好(如果你只传递一个参数,它会抱怨E766: Insufficient arguments for printf())。通过将代码提取到:function.

Vim 可以解析参数

一个单独的:function也允许 Vim 为你做参数解析,通过:help <f-args>.

command! -nargs=+ Sub call Sub(<f-args>)
function! Sub( ... )
    execute printf('%%substitute/%s/%s/g', a:1, a:2)
endfunction
Run Code Online (Sandbox Code Playgroud)

使用函数,您可以轻松检查参数的正确数量:

function! Sub( ... )
    if a:0 != 2
        echo "Need two arguments"
        return
    endif
    ...
Run Code Online (Sandbox Code Playgroud)

函数的缺点是错误(例如模式不匹配、缓冲区不可修改)会导致多行、不友好的错误消息。try...catch必须用于派生出漂亮的单行错误消息。

奖励:从那里拿它

  • 当您:s向用户隐藏命令(和使用的分隔符)时,我认为不需要对分隔符进行转义。使用escape(a:1, '/')代替a:1/ a:2
  • 使用:help :command-range,您仍然可以默认命令在整个缓冲区上工作,但也允许传递其他范围。

还要考虑该命令是否真的很重要。不管使用什么解析,参数中的空格都是有问题的,这是原始:s没有的缺点。我看到的唯一好处是它更容易输入,但也可以通过使用不完整:s命令预先填充命令行并将光标定位在中间的映射来实现相同的效果。