post

Vim zh-cn:插件

Contents

简介

正如我们前一章看见的,我们可以通过使用脚本来扩展Vim现有的功能。我们将这些能扩展或添加功能的脚本叫做插件(plugins)。

这里列出一些插件的种类:

  • vimrc
  • 全局插件(gloable plugin)
  • 文件类型插件(filetype plugin)
  • 语法高亮插件(syntax highlighting plugin)
  • 编译器插件(compiler plugin)

除了自己写插件还可以下载别人已经写好的插件。

使用vimrc定制

当我每次重新安装一个linux的发行版的时候,或是重新安装windows的时候,我装完vim之后做得第一件事就是取回我备份的vimrc,然后才开始使用vim。为什么这个很重要呢?这是因为vimrc文件包含了好多我自己定制的属性,这些可以使vim更加有用和易用。

要定制vim,有两个文件你可以使用:

  1. vimrc – 用来进行一般的定制
  2. gvimrc – 用来针对GUI进行定制

这些文件存储在:

  • 对于 Windows %HOME%/_vimrc%HOME%/_gvimrc
  • 对于 Linux/BSD/Mac OS X $HOME/.vimrc$HOME/.gvimrc

使用命令 :help vimrc 来查看在你机器上他们存储的确切位置。

vimrc和gvimrc可以包含任何vim命令。习惯上只是将简单的设置写在vimrc文件中,其他高级的特性使用插件完成。

请看一下我的vimrc文件:

" My Vimrc file
" Maintainer: www.swaroopch.com/contact/
" Reference: Initially based on http://dev.gentoo.org/~ciaranm/docs/vim-guide/
" License: www.opensource.org/licenses/bsd-license.php

" Enable syntax highlighting.
syntax on

" Automatically indent when adding a curly bracket, etc.
set smartindent

" Tabs should be converted to a group of 4 spaces.
" This is the official Python convention
" (http://www.python.org/dev/peps/pep-0008/)
" I didn't find a good reason to not use it everywhere.
set shiftwidth=4
set tabstop=4
set expandtab
set smarttab

" Minimal number of screen lines to keep above and below the cursor.
set scrolloff=999

" Use UTF-8.
set encoding=utf-8

" Set color scheme that I like.
if has("gui_running")
    colorscheme desert
else
    colorscheme darkblue
endif

" Status line
set laststatus=2
set statusline=
set statusline+=%-3.3n                      " buffer number
set statusline+=%f                          " filename
set statusline+=%h%m%r%w                     " status flags
set statusline+=[%{strlen(&ft)?&ft:'none'}] " file type
set statusline+=%=                           " right align remainder
set statusline+=0x%-8B                       " character value
set statusline+=%-14(%l,%c%V%)               " line, character
set statusline+=%<%P                         " file position

" Show line number, cursor position.
set ruler

" Display incomplete commands.
set showcmd

" To insert timestamp, press F3.
nmap <F3> a<C-R>=strftime("%Y-%m-%d%a%I:%M%p")<CR><Esc>
imap <F3> <C-R>=strftime("%Y-%m-%d%a%I:%M%p")<CR>

" To save, press ctrl-s.
nmap <c-s> :w<CR>
imap <c-s> <Esc>:w<CR>a

" Search as you type.
set incsearch

" Ignore case when searching.
set ignorecase

" Show autocomplete menus.
set wildmenu

" Show editing mode
set showmode

" Error bells are displayed visually.
set visualbell

请注意这些命令前边都不用加’:'(冒号)。当在文件里书写脚本的时候这些冒号是可选的,因为假定这些命令都是是处在普通模式的命令。

如果你想了解详细上边每一条设置命令的话,使用 :help

截取一部分我的gvimrc文件:

" Size of GVim window
set lines=35 columns=99

" Don't display the menu or toolbar. Just the screen.
set guioptions-=m
set guioptions-=T

" Font. Very important.
if has('win32') || has('win64')
    " set guifont=Monaco:h16
    " http://jeffmilner.com/index.php/2005/07/30/windows-vista-fonts-now-available/
    set guifont=Consolas:h12:cANSI
elseif has('unix')
    let &guifont="Monospace 10"
endif

这里还有好多写好的vimrc文件,你可以仔细看一下,然后学习怎么定制这些功能,当然你也可以选择一个自己喜欢的使用。

我之前发现一些不错的:

通过你使用的vimrc一般都能看出你使用vim有多长时间了。

全局插件

全局插件可以用来提供全局的或是通用的功能。

全局插件一般存放在两个地方:

  1. vim安装时提供的标准插件放在 $VIMRUNTIME/plugin/
  2. 想要安装你自己下载的某些的插件的话,你可以自己建立插件目录:
    • 在 Linux/BSD/Mac OS X 上是 $HOME/.vim/plugin/
    • 在 Windows 上是 %HOME%/vimfiles/plugin/
    • 使用命令 :help runtimepath 来查看更加详细的信息。

接下来我们来看一下怎么使用插件:

一个有用的插件是 highlight_current_line.vim 作者为Ansuman Mohanty,这个插件的功能就像他的名字所说的一样:高亮显示当前行。下载最新的 highlight_current_line.vim 版本然后放入你的插件目录(我们上边提到的)。 现在重启一下vim并且打开一个文件看看是不是当前行的文本已将加亮了呢。

但是如果你不喜欢这个插件的话,很简单,只需要删掉highlight_current_line.vim 这个文件然后重启vim就行了。

类似的,我们可以安装我们自己在上一章写的related.vim 或是 capitalize.vim 到plugin目录,这样就避免了每次使用 :source 的麻烦。最后,任何你写的插件最后都需要放到 .vim/vimfiles 目录下。

文件类型插件

文件类型插件是专门针对特定类型的文件而制作的。比如说,一个c程序员在写程序的时候可以使用他自己的缩进风格,语法高亮甚至是错误类型显示风格等。这种类型的插件并不是通用的,而是针对特定文件类型的。

使用一个文件类型插件

我们先来看一个对应于XML文件的插件。XML是一种标记语言,他使用标签来描述文档自身的结构。比如说,你有一个文档类似于下边这样:

   Iron Gods
   ---------

   Ashok Banker's next book immediately following the Ramayana is said to
   be a novel tentatively titled "Iron Gods" scheduled to be published in
   2007. A contemporary novel, it is an epic hard science fiction story
   about a war between the gods of different faiths. Weary of the
   constant infighting between religious sects and their deities, God
   (aka Allah, Yahweh, brahman, or whatever one chooses to call the
   Supreme Deity) wishes to destroy creation altogether.

   A representation of prophets and holy warriors led by Ganesa, the
   elephant-headed Hindu deity, randomly picks a sample of mortals, five
   of whom are the main protagonists of the book--an American Catholic,
   an Indian Hindu, a Pakistani Muslim, a Japanese Buddhist, and a
   Japanese Shinto follower.  The mortal sampling, called a 'Palimpsest'
   is ferried aboard a vast Dyson's Sphere artifact termed The Jewel,
   which is built around the sun itself, contains retransplanted cities
   and landscapes brought from multiple parallel Earths and is the size
   of 12,000 Earths. It is also a spaceship travelling to the end of
   creation, where the Palimpsest is to present itself before God to
   plead clemency for all creation.

   Meanwhile, it is upto the five protagonists, aided by Ganesa and a few
   concerned individuals, including Lucifer Morningstar, Ali Abu Tarab,
   King David and his son Solomon, and others, to bring about peace among
   the myriad warring faiths.  The question is whether or not they can do
   so before the audience with God, and if they can do so peacefully--for
   pressure is mounting to wage one final War of Wars to end all war
   itself.

   (Excerpt taken from
   http://en.wikipedia.org/w/index.php?title=Ashok_Banker&oldid=86219280
   under the GNU Free Documentation License)

这个文档可以用XML文档格式书写(特别是使用’DocBook XML’格式),如下:

<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
        "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>

    <articleinfo>
        <author><firstname>Wikipedia Contributors</firstname></author>
        <title>Iron Gods</title>
    </articleinfo>

    <para>

        Ashok Banker's next book immediately following the Ramayana is
        said to be a novel tentatively titled "Iron Gods" scheduled to
        be published in 2007. A contemporary novel, it is an epic hard
        science fiction story about a war between the gods of
        different faiths.  Weary of the constant infighting between
        religious sects and their deities, God (aka Allah, Yahweh,
        brahman, or whatever one chooses to call the Supreme Deity)
        wishes to destroy creation altogether.

    </para>

    <para>

        A representation of prophets and holy warriors led by Ganesa,
        the elephant-headed Hindu deity, randomly picks a sample of
        mortals, five of whom are the main protagonists of the
        book--an American Catholic, an Indian Hindu, a Pakistani
        Muslim, a Japanese Buddhist, and a Japanese Shinto follower.
        The mortal sampling, called a 'Palimpsest' is ferried aboard a
        vast Dyson's Sphere artifact termed The Jewel, which is built
        around the sun itself, contains retransplanted cities and
        landscapes brought from multiple parallel Earths and is the
        size of 12,000 Earths.  It is also a spaceship travelling to
        the end of creation, where the Palimpsest is to present itself
        before God to plead clemency for all creation.

    </para>

    <para>

        Meanwhile, it is upto the five protagonists, aided by Ganesa
        and a few concerned individuals, including Lucifer
        Morningstar, Ali Abu Tarab, King David and his son Solomon,
        and others, to bring about peace among the myriad warring
        faiths. The question is whether or not they can do so before
        the audience with God, and if they can do so peacefully--for
        pressure is mounting to wage one final War of Wars to end all
        war itself.

    </para>

    <sidebar>
        <para>

            (Excerpt taken from
            http://en.wikipedia.org/w/index.php?title=Ashok_Banker&amp;oldid=86219280
            under the GNU Free Documentation License)

        </para>
    </sidebar>

</article>

请注意,在xml文档中结构如何定义是比较随意的。这样也就使他更容易通过其他工具转换成其他格式的文档,比如PDF或是其他打印版本。当然也有缺点,这样按照xml的格式书写文档对于人类来说有点困难。那么我们现在来看一下如何通过文件格式化插件如何帮助vim用户书写xml文档。

1. 首先下载 xmledit ftplugin 并且将其放到 ~/.vim/ftplugin/ 目录。

2. 然后在你的 ~/.vimrc 文件中加入下边这一行:

autocmd BufNewFile,BufRead *.xml source ~/.vim/ftplugin/xml.vim

(请确认对应你的操作系统路径的正确)

这样你的vim在打开一个扩展名为 .xml 的文件的时候自动开启xmledit ftplugin。

3. 打开vim并且编辑一个文件 test.xml

4. 输入 <article.

5. 然后输入结束的 > 符号, 你会看到xml ftplugin自动为你加入闭合的标签。现在你的文档应该像是这个样子的:

<article></article>

6. 现在输入另一个 >,你会看到标签展开了,这样你就可以输入更多标签。现在的文档应该像是这个样子:

    <article>

    </article>

7. 你可能已经注意光标的形状变化了,这样你可以整洁的和更加结构化的书写文档。

8. 重复这个过程,知道输入完毕。

请注意通过使用针对xml的插件是如何使得书写xml文档变得如此简单的。这也正是文件类型插件被设计的原因。

编写一个文件类型插件

现在我们来尝试如何自己写一个插件。

在我们之前使用xmledit.vim插件和书写xml文档格式的例子中,我们看见我们不得不为每一个Doc BooK先写一些标准的头部信息。既然这样不如我们让vim使用插件自动生成这些。

我们的xml插件最基本的需求就是要自动添加如下的头部信息到一个新的xml文档中:

<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
          "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">

所以我们将这个新插件,暂且就叫’xmlheader.vim’,运行在’BufNewFile’事件上。添加下面这行到你的 ~/.vimrc(~/.vimrc)文件:

autocmd BufNewFile *.xml source ~/.vim/ftplugin/xmlheader.vim

现在所有我们需要做得就是写入如下两行:

" Vim plugin to add XML header information to a new XML file
call setline(1, '<?xml version="1.0"?>')
call setline(2, '<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">')

好了,我们重启vim,确认’test.xml’文件之前是不存在的,然后输入 :e test.xml. 这时你就能看见头部信息已经出现了。

语法模式

在之前一节中我们写了一个DocBook xml文档。如果能用不同的色彩来显示标签的话,对我们正确的书写标签将会是非常有用的。这是当然是可行的,我们可以输入 :set filetype=docbkxml。vim会找到 $VIMRUNTIME/syntax/docbkxml.vim 文件,并按照语法规则显示。

这个语法文件定义了文件中的每一部分是如何相互关联的。比如说,针对xml的语法文件定义了什么是标签以及标签按照什么颜色显示等。

使用一个语法模式

我们来实际的看一个语法文件。下载 mkd.vim 针对 Markdown syntax 的语法文件。 Markdown是一本基本的格式,使用这种格式编辑的文本可以在之后转换成HTML文档。

  1. 用vim打开一个文件,文件名为test_markdown.txt。
  2. 执行 :set syntax=mkd 命令。
  3. 在文件中输入下边内容:
   # Bengaluru

   The name **Bangalore** is an anglicised version of the city's name in
   the Kannada language, Bengaluru.

   > A popular anecdote (although one contradicted by historical
   > evidence) recounts that the 11th-century Hoysala king Veera Ballala
   > II, while on a hunting expedition, lost his way in the forest. Tired
   > and hungry, he came across a poor old woman who served him boiled
   > beans. The grateful king named the place _"benda kaal-ooru"_
   > (literally, "town of boiled beans"), which was eventually
   > colloquialised to "Bengaluru".

   ***

   (This information has been retrieved from
   [Wikipedia](http://en.wikipedia.org/wiki/Bangalore) under the GNU Free
   Documentation License.)

4. 请注意文件中不同的部分比如头和重点单词是如何自动加亮的。这些可以在maekdown语法中轻易的写出来。

编写一个语法模式

现在我们尝试写一个我们自己的语法文件,它针对于 AmiFormat 文本格式。

语法高亮最基本的就是循环执行两个步骤-其一就是定义我们搜索的文本模式;其二就是定义如何显示。

比如我们要找到所有 <b>any word</b> 这种模式,并将其作为黑体加粗显示。 首先我们需要在文本中比配这个模式,然后将这个模式和显示模式绑定,以便我们之后显示:

:syntax match ourBold /&lt;b&gt;.*&lt;/b&gt;/
:highlight default ourBold term=bold cterm=bold gui=bold

第一行是要基于某个匹配模式新建一个语法,我们将其命名为ourBold,正则表达式生命如上。

第二行我们要高亮显示上边的ourBold语法。我们生命的模式是一种默认的模式,也就是说用户或是其他显示模式可以覆盖掉他。我们可以声明三种不同的方式来表示ourBold,并且以这三种模式在vim中显示-黑白终端,彩色终端和GUI。

有些时候,我们想在文本中写入一些任务列表作为我们的todo列表,为了更加醒目,通常要将TODO大写,但是我们相让他更加醒目的要如何呢?

:syntax keyword ourTodo TODO FIXME XXX
:hi def link ourTodo Todo

首先我们定义’ourTodo’关键字,这是需要高亮显示的简单的文本,我们将这个模式绑定到已经在vim中存在的Todo组。 在vim中有好多已经提前定义好的颜色模式。将我们的语法风格绑定到已经存在的语法风格上是再好不过的了。 输入 :help group-name 来查看更多可用的组。

接下来,我们在闭合的

 ..  

中声明代码块,那我们该如何高亮显示呢?

:syn region amiCode excludenl start=/[code]/ end=/[/code]/
:hi def link amiCode Identifier

首先我们定义一个以开始模式和结束模式包围的文本区域(在我们的例子中很简单),然后绑定到已经存在的模式(Identifier)上。

相同道理,我们将文本其他部分的定义添加到以定义的AmiFormat reference, 最后的脚本差不多是这个样子:

" Vim syntax file for AmiFormat
" Language: AmiFormat
" Version: 1
" Last Change: 2006-12-28 Thu
" Maintainer: www.swaroopch.com/contact/
" License: www.opensource.org/licenses/bsd-license.php
" Reference: http://orangoo.com/labs/AmiNation/AmiFormat/

"""""""""" Initial Checks """"""""""""""""""""""""""""""""""""""""""""

" To be compatible with Vim 5.8. See `:help 44.12`
if version < 600
    syntax clear
elseif exists("b:current_syntax")
    " Quit when a (custom) syntax file was already loaded
    finish
endif

"""""""""" Patterns """"""""""""""""""""""""""""""""""""""""""""""""""

" Emphasis
syn match amiItalic /&lt;i&gt;.{-}</i>/
syn match amiBold /&lt;b&gt;.{-}</b>/

" Todo
syn keyword amiTodo TODO FIXME XXX

" Headings
syn match amiHeading /^h[1-6].s+.{-}$/

" Lists
syn match amiList /^s**s+/
syn match amiList /^s*d+.s+/

" Classes
syn match amiClass /^s*%(w+).*%/
syn match amiClass /^s*%{.*}.*%/

" Code
syn region amiCode excludenl start=/[code]/ end=/[/code]/

" HTML
syn region amiEscape excludenl start=/[escape]/ end=/[/escape]/

" Link
syn match amiLink /".{-}":(.{-})/

" Image
syn match amiImage /!.{-}(.{-})!/

"""""""""" Highlighting """"""""""""""""""""""""""""""""""""""""""""""

hi def amiItalic term=italic cterm=italic gui=italic
hi def amiBold term=bold cterm=bold gui=bold

hi def link amiHeading Title
hi def link amiTodo Todo
hi def link amiList PreProc
hi def link amiClass Statement
hi def link amiCode Identifier
hi def link amiEscape Comment
hi def link amiLink String
hi def link amiImage String

"""""""""" Finish """"""""""""""""""""""""""""""""""""""""""""""""""""

" Set syntax name
let b:current_syntax = "amifmt"

现在这个脚本可以很好的工作了,而且我已经将他上传到了 Vim scripts section 因为这个是我写的:)现在全世界所有的人都可以使用我写的语法高亮的脚本了。

想要了解更多关于语法高亮的内容,参考:

  • :help syntax
  • :help usr_44.txt
  • :help group-name
  • :help pattern-overview
  • :help mysyntaxfile
  • :help new-filetype
注意
以防万一某个语法文件将显示弄乱,你可以按 CTRL-L 来刷新屏幕回到之前的显示。
注意
你可能已经猜到了,当我们之前设置文件类型 filetype 的时候, vim自动使用相同文件名的 syntax 文件。

编译器插件

编译器插件是为了编译不同语言写成的文件而设计的。在任何需要将一个源文件转换成另一种文件格式的情况下编译器插件都是非常有用的,即使是你正在用Markdown格式些一个源文件,然后使用转换成许将其转换成HTML文件。

我们来探索一下针对Python的编译器插件。

1. 下载 compiler/python.vim 脚本,并将其存放在 ~/.vim/compiler/ 目录下。

2. 将下面这一行语句放进你的 ~/.vimrc 文件:

autocmd BufNewFile,BufRead *.py compiler python

3. 重新启动vim并新建一个python文件比如说test.py ,然后输入下面的内容:

#!python
print 'Hello World'

4. 输入 :make ,你就应该能看见编译成功的提示了。

5. 现在我们故意引入一个错误看一下,把 ‘print’ 改成 ‘pritn’:

pritn 'Hello World'

再次输入 :make,注意错误提示出现了,并且vim自动将光标移动到了出错的行上。

6. 输入 :clist 可以查看完整的错误消息列表。

7. 每当修改完一个错误,可以输入 :cnext ,来使光标移动到下一个错误位置上。

当你打开我们下载的编译器脚本 compiler/python.vim 的话,你会发现里边很简单-只有两个变量定义 – 一个是 makeprg 这个是用来定义如何编译这个文件的。第二就是 errorformat,定义了如何显示出错消息。

使用这两个变量,我写了一个针对 Adobe Flex 的编译器插件。

输入 :help write-compiler-plugin:help quickfix 查看更多关于如何编写插件的内容。

作业:编写一个全局插件

为了练习你新掌握的编写插件的技巧,你可以试试下边的练习:

编写一个插件,用来删除文档中的重复行和多余的空行。

你可以使用Vim的脚本语言,也可以使用Vim已经提供借口了的其他语言来编写。

如果你需要找下“灵感”的话,看看这里
this Vim Tip.

那么另一个呢?

编写一个脚本,用来取回与当前光标处单词意义相近或相似的单词。

同样,你需要“灵感”的话,看看这里 lookup.vim plugin.

禁用插件

假如说你某一天发现Vim突然表现的很古怪,而且你怀疑是某个插件导致的,那么你可以使用命令 -u 让Vim有选择的进行初始化。

例如, vim -u NONE
命令将会使Vim启动的时候不初始化任何插件。现在运行的是一个最原始的Vim。使用命令 vim -u your-minimal-initialization.vim,可以使用你特定的脚本来初始化。

对于你当前所遇到的问题或是因为引入新插件而引起的问题,使用这条命令很容易找出错误。

查看更多内容 :help -u:help starting

总结

我们已经看到了Vim的各种各样的插件,并且学会了怎么使用一个插件甚至是怎样自己编写一个插件。我们已经能意识到了Vim超强的可扩展性,而且我们知道了如何通过编写插件来是生活变得更简单。


Advertisements