第三章 Vim 常用命令
在第二章已经介绍了 VimL 语言的基本语法,理论上来说,就可以据此写出让 vim 解释 执行的合法脚本了。然而,能写什么的脚本呢?除了打印“Hello World!”,以及高级点的 用循环计算诸如“1+2+...+100”这样人家好像也能心算的题目外,还能干嘛呢?
所以,如果要让 vim 脚本真正有实用价值,还得掌握 vim 提供的内置命令,用以控制 Vim 或定制 Vim。本章就来介绍一些主要的、常用用的命令。
Vim 是个极高自由度的文本编辑软件,它在以下几个层级上给用户提供了自由度:
option
选项。预设了一个很庞大的选项集,用户可以按自己的喜好设置每个选项的 值(当然很多选项也可以接受默认址而假装当它们不存在),这可能改变 Vim 的很多 基础表现与行为。map
(快捷键)映射。一个非常简单但非常强大的机制。用户可以根据自己的习惯 来重新映射各种模式下不同按键(及按键序列)的解释意义。初入门的 Vimer 很容易 沉迷于折腾各种快捷键。command
自定义命令。Vim 是基于 ex 命令的,然后允许又你自定义 Ex 命令。可 见这是比简单映射更灵活强大的利器,当然它的使用要求也比映射要高一些。VimL
脚本。进一步将命令升级为脚本语言,据此开发插件,使得 Vim 的扩展性具 有无限可能。在 Vim 社区已经涌现了很多优秀插件,大多可以直接拿来用。当自己掌 握了 VimL 语言后,也就可以自己写些插件来满足自己的特殊需求或癖好。
本教程虽是旨在 VimL 脚本语言,但还是有必要从简单的选项说起吧。
3.1 选项设置
选项分类与设置命令
设置选项的命令是 set
。根据选项值的不同情况,可以将选项分为以下三类:
- 不需要值的选项,或者说是 bool 型的开关切换状态的选项。这种选项有两个相对立 的选项名,分别用命令
:set option
表示开启选项,:set nooption
表示关闭选 项。例如:set number
是设置显示行号,:set nonumber
是设置不显示行号。 - 选项有一个值。用命令
:set option=value
设定该类选项的值。选项值可以是数字 或字符串,但字符串的值也不能加引号,就按字面字符串理解。也就是说,:set
后 面的参数,不是 VimL 的表达式,与:let
命令有根本的不同。这个命令更像是shell
设置变量的语法,=
前后也最好不要用空格。 - 选项允许有多个值,值之间用逗号分隔。设置命令形如
:set option=val1,val2
。 此外还支持+=
增量与-=
减量语法,如:set option+=val3
或:set option-=val2
,表示在原来的“值集合”的基础上增加某个值或移除某个值。
选项值变量
在选项名前面加个 &
符号,就将一个选项变成了相应的选项值变量。例如,以下两条 命令是等效的:
: set option=value
: let &option = value
与普通变量赋一样,=
前后的空格是可选的,这里的空格只是一种编程习惯,为增加 可读性。另外有以下几点要注意:
- 第一类选项,在用
:set
命令时不需要等号,但是用:let &
命令时也要用等号将 其值赋为 1 或 0,分别表示开启选项与关闭选项。同时&
只允许作用在没有no
前缀的选项之前。比如:let &nonumber = 1
是非法的,只能用:let &number = 0
表示相同意图。 - 第二类选项,如果值是字符串,用
:let &
命令时要将值用引号括起来,也就像普 通变量赋值一样,要求等号后面是合法的表达式。 - 第三类选项,它的值也是一个由逗号分隔的(长)字符串,比如
:echo &rtp
。并不 能由于这类选项支持多个值就将 VimL 的列表赋给它,不过很容易通过split()
函 数从这类选项值中分隔出一个列表。
备注:选项设置 :set
应是历史渊源最早的命令之一吧。而 :let
是后来 VimL 语言 发展丰富起来提供的命令。两者有不一样的语法,所以又提供了这种等价转换方法。
vimrc 配置全局选项
严格地说,:set
是设置全局选项的命令。既是影响全局的选项,一般是要第一时间在 vimrc
中配置的。最重要的是以下两条配置:
: set nocompatible
: filetype plugin indent on
第一条配置是说不要兼容 vi
,否则可能有很多 vim
的高级功能用不了。第二条配置 (虽然不是 set
选项)是用 Vim 编写程序源代码必要的,意思是自动检测文件类型, 加载插件,自动缩进的意思。除非在很老旧的机器上,或为了研究需要,一般都没理由不 加上这两条至关重要的配置。
下面再介绍一些比较重要的几类配置选项,当然这远远不够全面。查看选项的帮助命令是 :help options
,查看某一个选项的帮助是在用单引号括起选项名作为帮助参数,例如 :help 'option'
。查看某个选项的当前值是命令 :set option?
或 :echo &option
。
编码相关:encoding fileencodings fileencoding
- encoding 是 Vim 内部使用的编码。建议
:set encoding=utf-8
。 - fileencodings 是打开文件时,Vim 用于猜测检测文件编码的一个编码列表。对中文 用户,建议
:set fileencodings=ucs-bom,utf-8,gb18030,cp936,latin1
。 - fileencoding (局部选项),当前文件的编码,如果与 encoding 不同,在写入时 自动转码。用户一般不必手动设这个选项,除非你想用另外一种编码保存文件。
- encoding 是 Vim 内部使用的编码。建议
外观相关:number/relativenumber wrap statusline/tabline
- number 是在窗口左侧加一列区域显示行号,relativenumber 显示相对行号,即相对 光标所在的行的行号,当前行是 0,上面的行是负数,下面的行是正数。
- wrap 是指很长的文本行折行显示。一般良好风格的程序源文件不应出现长行,但 Vim 作为通用文件编辑器,不一定只用于编辑程序。
- statusline 是定制状态栏,格式比较复杂,建议查看文档,也有些插件提供了很炫 酷的状态栏。tabline 的定制格式与状态栏一样,在开多个标签页时才生效。
- laststatus 什么时候显示状态栏,建议用值
2
表示始终显示状态栏。 - cmdheight 命令行的高度,默认只有 1 行太少,当命令行有输出时可能经常要多按 一个回车才回到普通模式。建议 2 行,更多就浪费空间了。
- wildmenu 这是在编辑命令行时,按补全键后,会临时在状态栏位置显示补全提示。
GUI外观:只在 gVim 或有 GUI 版本的 Vim 有效
- guioptions 设置 GUI 各部件(菜单工具栏滚动条等)是否显示。
- clipboard 设置剪切板与 Vim 的哪个寄存器关联。
颜色主题:
- colorscheme 这是个单独的命令,不是
set
选项。选择一个颜色主题。颜色主题 是放在运行时各路径的colors/
子目录的*.vim
文件。 - background 背景是深色
dark
或浅色light
。有的 colorscheme 只适于深色或 浅色背景,有的则分别为不同背景色定义不同的颜色主题。 - term 与 t_Co 有的颜色主题可能还与终端与终端色数量有关。
- cursorline 与 cursorcolumn 用不格式高亮当前行与当前列,具体高亮格式由颜色 主题定义。个人建议只高亮 cursorline 。
- hlsearch 高亮搜索结果。
- colorscheme 这是个单独的命令,不是
格式控制:
- formatoptions 控制自动格式化文本的许多选项,建议看文档。
- textwidth 文本行宽度,超过该宽度(默认78)时自动加回车换回。在编辑程序源文 件时可用上个 formatoptions 选项控制只在注释中自动换行但代码行不自动换行。
- autoindent smartindent 插入模式下回车自动缩进。
- shiftwidth 缩进宽度。
- tabstop softtabstop 制表符宽度,软制表符是行首按制符缩进的宽度。一般建议 硬制表符宽度 tabstop 保持 8 不变,用 shiftwidth softtabstop 表示缩进。
- expandtab 插入制表符自动转为合适数量的空格。
- paste 将 Vim 的插入模式置于“粘贴”模式,从外部复制文本进 Vim 开启该选项可避 免一些副作用。但只建议临时开启该选项。
路径相关:
- runtimepath 运行时路径,简称(rtp)。vim 在运行时搜索脚本的一组路径。一般 不手动设置该值,如果有插件管理器管理插件的话。插件必须放在某个
&rtp
路径 下,现在流行的是将插件工程主目录添加至 Vim 的&rtp
中。 - packpath (Vim8开始才支持)动态加载插件的搜索路径,默认是
~/.vim/pack
。 插件主目录可置于{packpath}/{packname}/opt/{plugin}
。然后用:packadd
启用插件。 - path 这是 vim 在寻找编辑文件,如
gf
:find
等命令时所要搜索的一组目录。 - tags 这是 vim 按标签跳转
Ctrl-]
或:tag
等命令所依据的标签文件,默认是./tags,tags
(相对路径)。一般不建议修改默认值,但可以默认值基础上添加更 多的标签文件,比如编辑一个工程时,将工程主目录下的 tags 文件也加进来。 - autochdir 将当前路径自动切换到当前编辑的文件所在的目录。当你依赖一些管理工 程类的插件时,可能要求当前路径锁定在工程主目录,不宜开启该选项。但是个人喜 欢开启这插件,这样在用
:e
命令打开同目录下的其他文件时很方便。
- runtimepath 运行时路径,简称(rtp)。vim 在运行时搜索脚本的一组路径。一般 不手动设置该值,如果有插件管理器管理插件的话。插件必须放在某个
Vim 所支持的选项实在是太多了。初学者建议参考前人经验成熟的配置,用 :help
查 看每个选项的具体含义,然后决定这种选项是否适合自己。另外注意有些选项可能要配合 起来才能发挥更好的效果。
VimL 控制局部选项
局部选项是只影响当前缓冲文件或窗口(buffer/window)的选项。严格来说是局部选项 值,而不是有另外一类选项。默认情况下每个新文件或窗口都继承选项的全局值,但对于 一些选项,可以为该文件或窗口设定一个不同与全局的局部值。然而并不是所有选项都有 局部值意义,在每个选项的帮助文档中,会指明该选项是全局(global)或局部的( local to buffer 或 local to window)。
设置局部选项(值)用 :setlocal
命令。如果目标选项没有局部值,则等效 :set
命令设置全局值。但是最好不要混用,避免误解。局部选项值变量用 &l:option
表示 。比如 number
行号就是个局部选项:
: set nonumber
: setlocal number
: echo &number
: echo &l:number
: echo &g:number
你可以将 vim 分裂出两个窗口(:split
或 :vsplit
),在其中一个窗口上执行以上 语句,试试看结果。需要注意的是,虽然局部选项值借用了变量的局部作用域前缀 l:
,但它的默认规则又有点不同。看这里的 &number
是默认的 &l:number
而不是 &g:number
。事实上,普通的局部变量 l:var
根本不能在函数外的命令行使用。
当用 VimL 写脚本时,如果要改变选项设置,且该选项支持局部值,最好用 :setlocal
只改变局部值。这也是编程的一大原则,尽量将影响局部化。下面介绍一些比较重要的局 部选项设置:
- 文件类型:filetype
- 大部分情况下,这个选项不用手写设,也不用脚本显式地设,打开自动检测就可以自 动根据后缀名设置相应的文件类型。不过在创建新的文件类型时,可能需要自己设置 这个选项。
- 文件类型插件,如
~/.vim/ftplugin/*.vim
脚本内若涉及选项更改,也尽量用:setlocal
只设局部选项。
- 缓冲类型:buftype
- "buffer type" 与 "file type" 是两个不同的概念。缓冲类型更加抽象,是 vim 内 部用于管理缓冲一些控制属性,而文件类型是着眼于文件内容性质的。
buftype
的两个重要的选项值是nofile
与nowrite
,表示特殊的不用写文件 的 buffer,而这两者又还有细微差别,具体请读文档。
- 其他 buffer 属性:
- buflisted 是否将当前缓冲记录在缓冲列表中。
- bufhidden 当缓冲不再任一窗口展示,如何处理该缓冲,有几种不同的选项值。
- modifiable 当前缓冲是否可修改,包括更改编码与换行符格式也算种修改。
由于在 Vim 中,最主要的可见(可编辑)对象就只是 buffer,所以在一些复杂而细致的 插件中,经常会开辟一个辅助窗口,仅为展示辅助内容,这就往往要设置一个特殊的 buftype
及其他一些 buffer 属性。
此外,在脚本中,可能有需求只临时改变某个选项值,处理完毕后再恢复原选项设置,这 就要借且选项值变量了。处理流程大致如下:
: let l:save_option = &l:option
: let &l:option = ? |" 或者 setlocal option = ?
: " do something
: let &l:option = l:save_option