分享

VIM进阶索引::高亮

 Rainboy913 2013-12-06

Vim进阶索引[5]::高亮
与以前的教程相比,这一篇做了一些小改变:使用了缩写而不是每次都给出完整的命令。提示使用文档时不同给出完整的命令而是给出“关键字”——你可以用“: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预定义的组、所表示的意义及其使用的颜色与样式:
Comment     注释
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" . ':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/^/\=c{L1}.c{L2}.c{L3}." "/' . "\"
这条命令在文档中新起一行,并用:s命令插入颜色值。关于:s命令的rhs中使用\=在“寄存器”篇中我们已经讲过了(见:sub-replace-special)。当L1、L2、L3分别为1、2、3时,这条命令就成了:
exec "norm o\" . ':s/^/\=c1.c2.c3." "/' . "\"
其结果就是在当前行下插入了“336699 ”。在这三组循环运行完后文档区将会有如下的web色数值表:
000000
000033
...
ffffff
还有就是expand()。这个函数的作用是将一些特殊的符号扩展为该符号所表示的字串。expand("")将返回当前光标所在位置的“词”。常见的用法还有expand("%")、expand("")等。篇幅所限,关于这个函数的用法见*expand()*。
g/./exec 'hi '.expand("").' guifg=grey guibg=#'.expand("") ……
g/./表示对所有非空行执行命令。假设当前行在“336699 ”,对这行执行“exec 'hi…. .expand("")”命令时,expand("")将被扩展为“336699”,这样命令就成了:
hi 336699 guifg=grey guibg=336699
同样的后面的:syn命令就成了syn match 336699 /336699 /。在运行完这组命令后Vim就会刷新屏幕上的颜色了。
提示:这段代码只有在图形介面下能发挥功用,在脚本开头加入这段代码以检测运行环境:
if !has("gui")
    finish
endif
另外,在脚本末尾添加下面代码可以使用web色表更易读一点:
1d " 删除空行
" 格式化颜色表,每行六种颜色。
g/./norm 6gJ
这是运行结果(部分):
660000 660033 660066 660099 6600cc 6600ff
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并,定义更复杂的语法文件。
Footnotes
[
1
] 其实Vim中的颜色文件,配色文件,语法文件,配置文件和插件本质上都是脚本文件都可以用ru或so运行。colors命令可以认为是预设了目录的so命令。
[
2
] 这里用的命令格式与上面修改高亮时的命令格式是一样的,它们的唯一区别在于使用的是否是新的组名。如前所述,Vim并不知道它是修改已有组的颜色设置,还是定义了新的组。要检查特定的组是否已存在可以用:hi mygroup,如出现错误提示则说明在“当前应用的语法文件”中不存在组mygroup
[
3
] 在我读书的会儿老师会要求我们把错的题目抄800-1000遍
[
4
] 没错,你可以按自己的意愿选择组名


本文来自ChinaUnix博客,如果查看原文请点:http://blog./u/12467/showart_229636.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多