🌚

Vim自定义命令的参数自动补全

Posted at — Jun 11, 2011
#Vim #编程

UltraBlog.vim起初的几个版本采用增加命令个数的方式减少每个命令的参数个数,目的是降低命令格式记忆的难度。从2.3.0版本起,开始采用Vim自定义命令的一些高级特性,精简命令个数,虽然参数个数增加了,但由于实现了参数补全,反而更加直观。

Vim对自定义命令提供了多种补全参数的方式,详见:h command-complete。其中,最常用的当属custom

```vim command! -nargs=? -complete=custom,StatusCmpl UBSend exec('py ub_send_item()') ```

以上代码定义了一个自定义命令UBSend,它可以获得一个或零个参数(-nargs=?),如果指定参数,则补全方式采用custom,该方式调用一个名为StatusCmpl的函数并以其返回值作为补全的值域:

```vim function! StatusCmpl(ArgLead, CmdLine, CursorPos) return "draft\npublish\nprivate\npending\n" endfunction ```

从以上代码可以看出,该函数需要接受三个参数,返回值应该是一个用换行符“\n”分割的字符串,在执行补全时,Vim自动使用正则表达式匹配备选项。对于只有一个参数的情况,这种实现方式简单高效。

对于参数较多的情况,customlist补全方式最为适用:

```vim command! -nargs=* -complete=customlist,UBNewCmpl UBNew exec('py ub_new_item()') ```

以上代码定义了命令UBNewcustomlist补全方式调用函数UBNewCmpl获取补全的值域:

```vim function! UBNewCmpl(ArgLead, CmdLine, CursorPos) let lst = split(a:CmdLine) if len(a:ArgLead)>0 let lst = lst[0:-2] endif let results = [] " For the first argument, complete the object type if len(lst)==1 let objects = ['post','page','tmpl'] for obj in objects if stridx(obj,a:ArgLead)==0 call add(results,obj) endif endfor " For the second argument, complete the syntax for :UBNew post or :UBNew " page elseif len(lst)==2 && count(['post', 'page'], lst[1])==1 let syntaxes = ['markdown','html','rst','textile','latex'] for synx in syntaxes if stridx(synx,a:ArgLead)==0 call add(results,synx) endif endfor endif return results endfunction ```

这时侯,前面提到的三个参数就派上用场了。ArgLead是进行补全时,已输入的参数部分,例如输入:UBNew p,然后按Tab键,则ArgLead的值就是“p”;CmdLine是已经输入的命令的全部,按上例,这个参数的值就是“UBNew p”;CursorPost是当前光标距离命令行开头的字符数。利用这三个参数,就可以判断正在补全命令的第几个参数,进而利用ArgLead筛选该参数的值域。

custom调用的函数不同,customlist调用的函数的返回值应该是一个list类型的值。

Posted via UltraBlog.vim.