我在 .vimrc 文件中写了以下自定义命令:
command! -nargs=+ Sub :%s/<args>/g
它允许我用一个词替换另一个词,执行方式如下:
:Sub <word>/<new word>
我更喜欢编写带有多个参数的命令,如下所示:
:Sub <word> <new word>
我可以重写命令以接受多个参数吗?
理想情况下我想要这样的东西:
command! -nargs=+ Sub :%s/<arg1>/<arg2>/g
先感谢您。
答案1
自行进行解析
如果你使用:help <q-args>
,你会得到一个带引号的字符串,你可以split()
分成两个用空格分隔的部分:
command! -nargs=+ Sub execute '%substitute/' . split(<q-args>, ' ')[0] . '/' . split(<q-args>, ' ')[1] . '/g'
我们可以使用一些元编程(call()
)来避免两次解析printf()
:
command! -nargs=+ Sub execute call('printf', ['%%substitute/%s/%s/g'] + split(<q-args>, ' '))
这有效,但错误处理仍然不太好(如果你只传递一个参数,它会抱怨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
使用函数,您可以轻松检查参数的数量是否正确:
function! Sub( ... )
if a:0 != 2
echo "Need two arguments"
return
endif
...
函数的缺点是错误(例如模式不匹配、缓冲区不可修改)会导致多行、不友好的错误消息。try...catch
必须使用它来派生出一个很好的单行错误消息。
奖金:接下来该怎么做
- 由于您向用户隐藏了
:s
命令(以及使用的分隔符),我认为不需要对分隔符进行转义。请使用escape(a:1, '/')
而不是a:1
/a:2
。 - 和
:help :command-range
,您仍然可以默认该命令对整个缓冲区起作用,但也允许传递其他范围。
还要考虑命令是否真的发挥了作用。无论使用哪种解析,参数中的空格都是有问题的,这是原始命令:s
没有的缺点。我看到的唯一好处是输入起来更容易一些,但也可以通过使用不完整命令预填充命令行:s
并将光标置于中间的映射来实现相同的效果。