Vimscript编程指南

实例分析:Grep操作符,第三部分

我们的新grep操作符工作的很好,但是有些Vimscript可以改善一下,使得我的操作符更加体贴,更加方便用户去使用。我们可以再做两件事情来让我们的操作符在vim系统里工作的更好。

保存寄存器

通过把文本保存到未名的寄存器里,我们把之前存在里面的内容给覆盖了。

这个对于我们的用户而言,是很不友好的,所以我们需要在复制文本并保存到寄存器里之前把寄存器里的内容先存下来,然后再我们的操作完成之后进行保存。编辑之前的代码,使得和下面相似:

 
nnoremap g :set operatorfunc=GrepOperatorg@
vnoremap g :call GrepOperator(visualmode())

function! GrepOperator(type)
    let saved_unnamed_register = @@

    if a:type ==# 'v'
        normal! `y
    elseif a:type ==# 'char'
        normal! `[v`]y
    else
        return
    endif

    silent execute "grep! -R " . shellescape(@@) . " ."
    copen

    let @@ = saved_unnamed_register
endfunction

我们在函数的开始处和结束处分别加了一个let语句。第一个是用来保存@@里的内容,第二个则是恢复它里面的内容。

写入脚本,并且加载文件。检查它是否正常工作,首先复制一些文本,然后按giw来触发我们的操作符,然后按p来粘贴你之前复制的文本。

在写Vim插件的时候,你都要保存和恢复你的代码修改的任何用户配置以及寄存器的内容。

命名空间

我们的脚本在全局命令空间里创建了一个GrepOperator。这个或许没什么大不了的,但是当你在写vimscript的时候保证安全绝对比时候后悔要强。

我们可以通过对代码稍微做一些调整来防止污染全局命令空间。编辑代码,使得和下面相似:

  
nnoremap g :set operatorfunc=GrepOperatorg@
vnoremap g :call GrepOperator(visualmode())

function! s:GrepOperator(type)
    let saved_unnamed_register = @@

    if a:type ==# 'v'
        normal! `y
    elseif a:type ==# 'char'
        normal! `[v`]y
    else
        return
    endif

    silent execute "grep! -R " . shellescape(@@) . " ."
    copen

    let @@ = saved_unnamed_register
endfunction

代码的前三行都有了一点变化。首先,我们用:s来修饰函数名称,这样就可以把它放在当前脚本的命名空间里了。

同时我们也修改了映射,我们在GrepOperator函数名的前面加上了,,这样就可以保证它们可以找到对应的函数了。如果我们不这样做的话,vim就会在全局命名空间里来找这个函数,这样肯定是不行的。

庆祝一下,我们的grep-operator.vim脚本现在非常有用了,现在可以把他当作vim内置的操作符来使用了。

练习

  • 阅读:help
  • 给自己买一些零食,这是你该得的。