与以前的教程相比,这一篇做了一些小改变:使用了缩写而不是每次都给出完整的命令。提示使用文档时不同给出完整的命令而是给出“关键字”——你可以用“:h 关键字”的方式找到Vim文档中的相应内容。
–
hq00e
在语法高亮相信大家在使用Vim的文档时就已经见过了,Vim提供了一个测试用的脚本。输入下面的命令:
:e $VIMRUNTIME/syntax/colortest.vim :so %
这个脚本除了让你知道Vim是可以显示许多颜色的外,它还是一个实时定义颜色的脚本实例。在本文的末尾我们会用同样的技巧生成一个Web色表。
Vim中与色彩有关的设定大致可以分为两部分:
- Vim编辑环境配色。如Vim编辑区的前景背景颜色(文本的默认颜色)、状态栏颜色、错误提示颜色、光标、圈选区(可视区)、行号、折叠的颜色等。这些都属于编辑器的环境设定。
- 文件使用的所使用的色彩。即所谓的语法高亮/语法着色,如Vim文档中索引标签使用粉红色,示例使用蓝色、链接使用青色。或是当你打开C语言文件时,注释蓝色、数据类型青色、字串粉红、关键字赭色。都是Vim根据文件类型启用相应的语法文件,对该应用颜色的部分进行识别并着色。
本文将通过对这些色彩进行设置的实例,让用户逐步了解与色彩相关的命令。
1 环境配色
Vim的环境配色决定了用户编辑环境的基本风格。语法高亮可以关闭但环境配色是始终存在的,下面我们将逐步地改造并定义属于自已的配色风格。
1.1 使用预置的配色风格
要改变Vim的编辑环境的配色很容易因为Vim提供了多种预置的配色风格(颜色主题)。比如要使用'evening'风格:在菜单中选择“编辑-调色板-evening”。或者在命令行中使用:colorscheme命令1:
:colors evening
可以看到编辑环境包括编辑区的前景背景的颜色都发生了变化。命令行下Vim默认是黑底白字,图形下的Vim是白底黑字,在应用了上面的命令后都成了深灰的背景,银灰的前景。
提示:在菜单中选择“default”或使用命令:colors default,换回默认的配色。关键字::colorscheme
1.2 修改环境配色
如果你不满足于使用现成的颜色主题的话,那我们来看一下如何修改环境配色。首先要掌握的命令是:highlight。
" 使用默认的高亮(移除用户定义的高亮,即根据'ft'重新载入语法文件) :hi clear " guifg表示图型介面(gui)下的前景色(ForeGround) " guibg表示图型介面(gui)下的背景色(BackGround) :hi {组} guifg={值} guibg={值} " 进行颜色关联。 " 这条命令使{组1}使用与{组2}一样的颜色设置 :hi link {组1} {组2}
例如,要将“组”为“c_name”的组在图形介面下的颜色设置为背景黑色,前景灰色可用如下命令:
:hi c_name guifg=gray guibg=black
让组“c_blah”使用与“c_name”一样的颜色设置:
:hi link c_blah c_name
注意:目前我们只涉及图形介面下Vim(gVim)的色彩控制。所以本文接下来的例子,在我们讲到命令行下的颜色设置之前,所有例子都是在gVim环境中完成的。
忘了解释一下“组”(高亮组)是什么?有什么用?Vim中“组”被用来表示一组颜色设置(前景、背景、字体、风格)。当某个介面元素(或是编辑区中的文本)应用了特定的“组”后,它就根据“组”表示的颜色设置来显示。应用了同样“组”的介面元素或文本会有一样的颜色显示。有:hi为“组”分配颜色时,如果组已存在则覆盖原有的设置,否则定义新组。
现在我们知道通过赋于guifg和guibg颜色值为组分配颜色。哪到底可以使用哪些颜色呢?图形介面下的颜色有“名称”或“数值”两种表示方式。名称如上面所用的gray、black还有大家熟悉的red、white、yellow,更多可以使用的颜色名称见文档:gui-colors。颜色还可以用“数值”来表示,方法是用三个分别表示“红、黄、蓝”的十六进制数值表示。如red还可以表示为#ff0000。记得数值前要加上#号。没错,这与html文件中颜色的表示方法是一样的。用这种方法我们可以表示更多的颜色:
" 将前景改为淡紫色 :hi c_name guifg=#E6E6FA
提示:此外guifg/guibg还支持三个特殊的值:none、fg、bg,分别表示无颜色、编辑区一般文本的前景色、一般文本的背景色。
要改变Vim的配色我们需要知道都有哪些组可以改。下面表中是Vim环境配色中介面元素所应用的“组”(组名在前):
Cursor
- 光标
ErrorMsg
- 命令行中的错误提示
Folded
- 折叠行
LineNr
- 行号
NonText
- 非文本区(控制字符和一些特殊字符和编辑器空白区等)
Normal
- 编辑区一般文本的前景和背景色
Search
- 搜索
StatusLine
- 状态行
Visual
- 圈选区
提示:完整的列表见highlight-groups。非Windows用户还可以设置菜单、滚动条和提示框的颜色。见hl-menu。
现在做个实验,打开一个文档并依次输入下面的命令,观察变化:
:se ft= "关闭高亮 " 分别改变编辑区的前景色(guifg)和背景色(guibg)为灰色和红色 :hi Normal guifg=gray guibg=red " 修改背景色为暗灰色,上面设置的前景色将被保留 :hi Normal guibg=#333333 "显示状态行 :se laststatus=2 " 设置状态行的颜色。 " 如果没“gui=none”会发现状态行的前/背景色颠倒了。 " 关于gui我们稍后再说 :hi Statusline guifg=green guibg=gray gui=None " 状态栏的默认颜色 :hi statusline gui=bold,inverse guifg=fg guibg=bg " 使错误提示使用与状态栏一样的颜色设置(默认是红色) " 用hi link对已定义颜色的组重新定义颜色要加“!” :hi! link ErrorMsg statusline " 下面的命令会出错,错误提示成了绿色的 :hi link " 清除颜色。 :hi! link ErrorMsg none " 无颜色的错误提示 :echoerr "abc" " 恢复默认的颜色 :hi clear
注:“:hi link {组} NONE”是:hi link的一种用法,用来清除组的颜色关联。
2 语法高亮
前面我们讲了如何更改Vim环境配色,如光标,状态行,错误提示的颜色。并没有涉及到如何根据编辑的文件来显示不同颜色,即语法高亮。与更改配色相比设置语法高亮要更复杂一些:配色中更改的组是确定的,因为编辑器中的介面元素是固定的,而语法高亮中所打开文件中那些需要高亮那些不需要,以及对不同类型的文件应用不同的语法高亮都要视具体的文件而定。很多时候我们还需要“创造”(自定义)出一些组来。但与配色一样在语法高亮中颜色的显示依然是由:hi命令控制。
2.1 修改当前的高亮设置
这一节我们将对当前文本中的语法高亮进行修改,你会发现这与修改环境配色相似——所不同的只是“组”名。这是一组实验:
:h syntax.txt "打开Vim文档 :hi helpHyperTextJump guifg=darkblue "改变文档中链接的颜色 :hi clear "清除自定义颜色——包括上面的颜色 :hi! link helpHyperTextJump Identifier "恢复颜色
所以要定义颜色只要对相应的组名的颜色进行设置就行了。那你要问了,这个helpHyperTextJump是从哪来的我怎么会知道哪个的组名是哪个?如果我要定义自已的组名呢?
要查看当前的语法文件中定义了哪些组名可以用不带参数的:hi查看。此外,还可以用:
" 查看当前的文件类型(假设是texinfo文件)。 :se ft texinfo " 知道是texinfo文件后,使用以下命令打开相应的语法文件 " 在语法文件中,:syn命令后跟的就是组名。 :e $vimruntime/syntax/texinfo.vim
那用户该怎么定义自已的组呢?继续往下看吧……
2.2 定义新的高亮
在定义新的高亮组时我们要先回答这个问题:为什么要定义新的组呢?有很多可能的原因:其中之一是我们想在不修改原来的高亮的情况下增加一种色彩,为些我们需要定义新的高亮组,并分配适当的颜色。
现在我们要定义自已的组了,首先要为我们自定义的组取个名字,组的命名与变量一样只能由字符下划线和数字组成(虽然我们前面的例子中使用了不同的大小写,但组名是不区分大小写的)。下面的命令中我们定义了一个组名为“mygroup”的组2。
:hi mygroup guifg=#ff9999
这条命令告诉Vim将mygroup组的字串颜色定义为淡红色(lightred)。但Vim现在还不知道哪些字串属于mygroup,所以我们得告诉Vim——方法是使用:match命令:
:match mygroup /xxx/
这条命令告诉Vim凡匹配式样的xxx的字串都属于mygroup。这样当前文件中所有匹配“xxx”的字串都会变成淡红色。定义自己的颜色是不是很容易呢?先用:hi命令定义组及其使用的颜色。再用:match告诉Vim编辑区文本中哪些部分是属于自定义组的。最后,Vim会根据:match设置的规则将当前编辑区文本分为许多不同的组(如果有定义多个组的话),并对不同的组应用:hi为其分配的颜色
下面我们要用一个更实际的例子来加深对语法高亮的印象。
看一下这个简单的表格:
王小明 数学 46 李阿月 数学 72 林小丽 数学 91
这是某个班主任手中的成绩单。他/她的班级有25个学生,这是其中的三条数据。这个班级经常有考试,这个老师希望考试的结果更直接明了一点:不及格(少于60分)的成绩显示为红色,90分以上的成绩有显示为青色,这样他/她就可以很快知道哪些学生该补课3,而哪些学生该表扬。当科目为数学时将科目显示为蓝色,这个班主任教数学的!学生名字显示为粉红色——看来这个班主任是女的。最后全班最高分的颜色反白显示。
我们先取几个不同的组名4:“u_student、u_subject、u_mark_fail、u_mark_a”分别表示“学生、科目、不及格、优秀”等。将这个表格另存为文本文件并用gVim打开,使用下面的命令:
:hi u_student guifg=#ff9999 guibg=white :hi u_subject guifg=lightblue guibg=white :hi u_mark_fail guifg=red guibg=white :hi u_mark_a guifg=darkcyan guibg=white " 上面的命令定义了不同的组及其对应的颜色 " 现在我们要用match告诉Vim怎么分辨不同的组, " 我们要用到一些的正则表达式 "行头开始至第一个空白字符 :syn match u_student /^\S*/ :syn match u_subject /数学/ :syn match u_mark_fail /\s[1-5]\=.$/ :syn match u_mark_a /\s100\|\s9.$/
你可能发现了每条match命令前面都多了:syn。这是因为使用match命令时前一个match定义的组的颜色会丢失。用match命令你没办法同时显示多种颜色。在上面的match命令前加上syn就行了,就可以显示所有自定义的颜色了。
提示:其实:syntax match与:match是不同的命令,不过“目前为止”它们的语法是一样的,我们在下一篇会讲到:syntax命令。
现在我们为成绩单加上颜色了,但下一次呢?我们可不希望每次打开都手动设置,我们可以将之放进单独文件中。将上面的命令复制到单独的文件中,然后用:so命令运行就可以了。
2.3 写语法文件
我们在前面写的脚本,保存起来就成了一语法文件。我们使用:so命令就可以运行了,不过你也许还希望它像其他语法文件一样能自动加载。要做到这一点也很简单。
在我们继续之前我简单描述一下语法文件加载的机制。Vim读入/新建文件时根据后缀名判断文件类型(或者根据模式行中设置的'filetype'设置项判断文件类型),然后在$VIMRUNTIME/syntax/和$VIM/vimfiles/syntax/中查找以文件类型为文件名,.vim为后缀的文件。找到的话加载该文件。
所以语法文件我们已经有了,我们只需要再选择合适的文件类型名。假设我们使用的文件类型名是'u_mark',将上面的脚本命名为u_mark.vim放到这个目录中:$VIM/vimfiles/syntax/。然后要让Vim打开成绩单时知道自动应用语法文件。在学习autocmd和filetype的内容之前,在这里我们可以简单地使用模式行,来达到这个目的。在成绩单文件的末尾加入模式行:
vim:ft=u_mark
现在打开成绩单文件时Vim就会自动加载语法文件。如果打开成绩单时还是没出现语法高亮请确定已经开启了语法高亮。使用:syn on开启高亮,必要的话将之放到.vimrc中。
3 :highlight命令详解
现在是对:hi进一步挖掘的时候了。
3.1 命令行下的颜色设置
在前面的内容中,我们讲:hi命令时一直都是以图形介面(gui)为例设置前景和背景色。由于命令终端对颜色显示的限制,Vim在命令行下可以使用的颜色相对gui要少得多,所以使用:hi命令时图形介面和命令行介面的颜色是分开设置的。对于黑白终端来说就无所谓颜色了,而彩色终端用cterm来表示,前景色就是“ctermfg”,而背景色是“ctermbg”。下面是一个表格:
终端类型 前景色 背景色 注释 term - - 黑白终端 cterm ctermfg ctermgb 彩色终端 gui guifg guibg 图形介面
在前面我们对编辑区文本的颜色进行了定义:
:hi Normal guifg=gray guibg=red
现在我们对其命令行下的颜色进行定义
:hi Normal ctermfg=gray ctermbg=red
我们可以简单地写成一行:
:hi Normal guifg=gray guibg=red ctermfg=gray ctermbg=red
有哪些颜色可以使用?见cterm-colors。
3.2 显示样式
:hi命令除控制颜色外还可以控制文字的显示样式。term、cterm和gui分别控制三种不同终端下的字体式样。这些字体样式包括了粗体、下划线、斜体、反显。使用多种样式时将样式用逗号隔开。详细样式见attr-list。
" 设置错误提示在不同终端下的显示样式 :hi ErrorMsg term=bold,reverse cterm=bold,reverse gui=reverse " 将某项的值设为NONE,可清除该项的样式设定 :hi ErrorMsg term=NONE
需要注意的是gui下不支持粗体的样式,但gui下多了一个字体的设置项font,用以指定字体::hi tung_poem font=……
另外因为Normal组是做为Vim的基准设定,所以对Normal进行的字体样式设定将被忽略。
3.3 关于link
在使用:hi link命令时有几个细节要注意一下。文档中都有(hi-link),这里简单提一下。仍是以命令“:hi link {组1} {组2}”为例:
- 如果在关联之前{组1}组已经定义过了了,则要使用加!号的形式:hi! link否则提示错误。
- 当{组1}关联到{组2}后,{组1}组使用与{组2}一样的颜色设置。如果此时再用:hi对{组1}定义颜色,则关联被取消。{组1}回复到设置关联前的颜色设置(如果有的话),再应用新定义的颜色。
- default开关项。由于Vim有多个配置文件,又有语法文件定义颜色。所以一组颜色可能被多次定义,为了让某一组颜色只在未定义时关联到其他组。可以使用开关项default:
:hi default link {组1} {组2}
一般而言,后定义(关联)的颜色总是覆盖先定义(关联)的颜色。在使用了这个开关项时,设置了default开关的总是被覆盖。仅当其他地方未定义{组1}时,才使用该关联。这主要是用在语法文件中,语法文件的加载要晚于配置文件。当在配置文件中定义颜色时,由于语法文件较晚加载自定义的颜色总是被覆盖。如果在语法文件中使用了default,则配置文件中自定义的颜色就能被显示出来。
使用:hi link还能节省大量的时间,减少重复的劳动。完整的颜色定义通常较长,因为要兼顾各种终端的显示能力。这是Vim中对Comment组的颜色定义:
:hi Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE
如果每定义一种颜色都要写这么长就太折腾人了。避免这种情况的最好方法是利用好预定义的颜色。这些是Vim预定义的组、所表示的意义及其使用的颜色与样式:
Constant 常量
Identifier 变量名
Statement 语句
PreProc 预处理器
Type 数据类型
Special 特殊符号
Underlined 突出显示的文本
Ignore 无设置
Error 语法错误
Todo 待做事项
Vim的语法文件本身就大量地使用了:hi link命令,它们大部就是关联到上面所列的组。在上面成绩单的例子中我们定义了u_subject在gui下的颜色为蓝色,但使用下面这条命令我们除了达到同样的效果外,还定义在其他终端下的颜色:
:hi! link u_subject Comment
所以在定义新的颜色时,先在上面的列表中看一看有没有你需要的颜色,如果有的话又可以节省很多时间了。
4 综合
现在看一下与语法高亮相关的几个例子。
4.1 高亮tags
见文档:tag-highlight
4.2 生成web色索引
使用:hi命令和:syn match命令就可以让Vim显示出斑斓的色彩。现在我们要更进一步结合上面的两个命令与Vim脚本写出一个217色的Web安全色表。
" 生成Web色表 " 用法:so web_color_gen.vim " 限制:只能在gui中使用 " 注意:这个脚本在Vim6.3/6.4中有时会出现颜色渲染错误的情况。 " 在Vim7中则没发现类似情况。 " 关闭搜索高亮 se nohls " 定义数组 " 在Vim7中定义数组就不会这么累了 let c0="00" let c1="33" let c2="66" let c3="99" let c4="cc" let c5="ff" " 生成web色的数值表 let L1=0 while L1<6 let L2=0 while L2<6 let L3=0 while L3<6 exec "norm o\" . ':s/^/\=c{L1}.c{L2}.c{L3}." "/' . "\ " let L3=L3+1 endw let L2=L2+1 endw let L1=L1+1 endw g/./exec 'hi '.expand(" ").' guifg=grey guibg=#'.expand(" ") | \ exec 'syn match '.expand(" ").' /'.expand(" ").' /'
新建空文档,然后运行脚本就可以看到web色表了。
这里有几个地方我解释一下。
exec "norm o\
这条命令在文档中新起一行,并用:s命令插入颜色值。关于:s命令的rhs中使用\=在“寄存器”篇中我们已经讲过了(见:sub-replace-special)。当L1、L2、L3分别为1、2、3时,这条命令就成了:
exec "norm o\
其结果就是在当前行下插入了“336699 ”。在这三组循环运行完后文档区将会有如下的web色数值表:
000000 000033 ... ffffff
还有就是expand()。这个函数的作用是将一些特殊的符号扩展为该符号所表示的字串。expand("
g/./exec 'hi '.expand("").' guifg=grey guibg=#'.expand(" ") ……
g/./表示对所有非空行执行命令。假设当前行在“336699 ”,对这行执行“exec 'hi…. .expand("
hi 336699 guifg=grey guibg=336699
同样的后面的:syn命令就成了syn match 336699 /336699 /。在运行完这组命令后Vim就会刷新屏幕上的颜色了。
提示:这段代码只有在图形介面下能发挥功用,在脚本开头加入这段代码以检测运行环境:
if !has("gui") finish endif
另外,在脚本末尾添加下面代码可以使用web色表更易读一点:
1d " 删除空行 " 格式化颜色表,每行六种颜色。 g/./norm 6gJ
这是运行结果(部分):
663300 663333 663366 663399 6633cc 6633ff
666600 666633 666666 666699 6666cc 6666ff
669900 669933 669966 669999 6699cc 6699ff
66cc00 66cc33 66cc66 66cc99 66cccc 66ccff
4.3 其他应用
Vim定义的高亮还可以用以生成彩色的html文档或打印彩色文档。
- 要生成html文档,只要先开启高亮然后简单的输入:TOhtml命令就可以生成使用与当前颜色设置一样的html文档了。TOhtml其实是一个插件,除了简单的用法,它其实还支持许多高级的控制选项如编码,CSS等。这是非常值得用户花点时间了解的命令——关键字“:TOhtml”。
- :hardcopy命令会根据当前的色彩设定打印文档。此外在Linux/Unix中这个命令还可以用来生成PostScript文档。关键字“:hardcopy”。
5 小结
至此对于给定的组我们已经能决定它颜色的显示了。然而,依赖:syn match加正则表达式的方式定义组仍有局限——它不能针对组与组之间的关系作出调整,注释的嵌套便是一例。这解决这些问题或者说要定义有更复杂规则的组我们需要对:syntax命令有进一步的了解。下一篇我们将深入高亮的另一重要命令:syntax并,定义更复杂的语法文件。