📄 usr_44.cnx
字号:
*usr_44.txt* For Vim version 6.3. 最近更新:2004年6月 VIM 用户手册 - by Bram Moolenaar (译者: wandys http://vimcdoc.sf.net) 自定义语法加亮Vim 对上百种文件都有自动语法加亮。如果你所编辑的文件类型没有被包括,通过阅读本章,你可以掌握对这种文件类型自定义语法加亮的方法。同时请参考 |:syn-define|。|44.1| 基本语法命令|44.2| 关键字|44.3| 匹配|44.4| 区域|44.5| 嵌套条目|44.6| 跟随组|44.7| 其它参数|44.8| 群组|44.9| 包含其它语法文件|44.10| 同步|44.11| 安装语法文件|44.12| 可移植语法文件格式 后一章: |usr_45.txt| 选择你的语言 前一章: |usr_43.txt| 使用文件类型 目录: |usr_toc.txt|==============================================================================*44.1* 基本语法命令利用一个已经存在的语法文件可以节省很多时间。首先看 $VIMRUNTIME/syntax 目录下是否存在一种类似语言的语法文件。为进一步理解,你需要阅读以下的部分。让我们先从简单的命令开始。在定义新的语法之前,我们需要清除旧的定义: > :syntax clear这在最终的语法文件中不是必须的,但在我们试验时却很有用。本章有很多简便的方法。如果你要编写一个供别人使用的语法文件,请从头到尾阅读本章以找到有关细节。列 出 已 定 义 的 条 目要查看现在已定义的条目,用这个命令: > :syntax你可以用此命令查看哪些命令确实已被定义。这在调试新的语法文件时很有用。它还会显示每个条目所用的颜色,可以更好的区分彼此。 列出某个特定语法组的条目,用: > :syntax list {group-name}这还可以用来列出群组(在 |44.8| 有解释)。只需要在名字中包含 '@'。匹 配 大 小 写一些语言不是大小写敏感,比如 Pascal 。另外一些,比如 C ,是大小写敏感。你需要用以下命令指出你的类型: > :syntax case match :syntax case ignore参数 "match" 意味着 Vim 区分语法元素的大小写,这样 "int" 和 "Int" 与 "INT"不同。如果指定 "ignore" 参数,"Procedure", "PROCEDURE" 和 "procedure" 均视为相同。 ":syncat case" 命令可以出现在语法文件的任何地方,并对其后的语法定义产生效用。在大多数情况下,你只需要一个 ":syntax case" 命令;但如果你使用一种不常见的语言,这种语言既包括大小写敏感的元素又包括大小写不敏感的元素,你需要在文件中使用多个 ":syntax case" 命令。==============================================================================*44.2* 关键字最基本的语法元素是关键字。要定义一个关键字,用以下命令: > :syntax keyword {group} {keyword} ...{group} 是语法组的名字。用 ":highlight" 命令,你可以对 {group} 设定颜色。{keyword} 参数是关键字。这里有一些例子: > :syntax keyword xType int long char :syntax keyword xStatement if then else endif这个例子中用到了两个名为 "xType" 和 "xStatement" 的语法组。按惯例,每个组名都用所定义语言的文件类型作为前缀。本例中是为 x 语言(样例语言,无特殊含义)定义语法。在为 "csh" 脚本建立的语法文件中,将用到类似 "cshType" 的名字。这样,前缀和'filetype' 的值相同。 这些命令使 "int","long","char" 以一种方式被高亮显示,而 "if", "then","else", 和 "endif" 则以另一种方式被高亮显示。现在你需要将 x 组名和标准的 Vim名字联系起来: > :highlight link xType Type :highlight link xStatement Statement这告诉 Vim 以 "Type" 的方式高亮显示 "xType",以 "Statement" 的方式高亮显示"xStatement"。关于标准名,参考 |group-name|。非 常 见 关 键 字在关键字里用到的字符必须在 'iskeyword' 选项内。如果你使用其它的字符,关键字将不被匹配。Vim 对此并不给出警告信息。 x 语言在关键字中用到了 '-' 字符。使用的方法如下: >> :setlocal iskeyword+=- :syntax keyword xStatement when-not"setlocal" 命令用来指定只对当前缓冲区改变 'iskeyword'。但仍会对 "w" 和 "*" 等命令造成影响。如果这不是所期望的,不要定义关键字而使用匹配(在下一节内解释)。x 语言允许缩写。比如,"next" 可以缩写成 "n", "ne", 或者 "nex"。你可以用这个命令来定义: >> :syntax keyword xStatement n[ext]这并不会匹配 "nextone",关键字只匹配它本身。==============================================================================*44.3* 匹配试想一下定义更复杂的东西。你想要匹配普通的标识符。对此,你定义一个匹配语法条目。它会匹配任意一个只由小写字母组成的单词: > :syntax match xIdentifier /\<\l\+\>/< Note: 关键字会使其它的语法条目无效。这样 "if", "then" 等关键字将以上面的 ":syntax keyword" 命令定义的方式被视为关键字,即使它们匹配 xIdentifier 的模式。最后一部分是一个模式(类似查找中的模式)。"//" 用来包含模式(像 ":substitude"命令中的一样)。你也可以用其它的字符,比如加号或者引号。现在定义一个注释的匹配。在 x 语言中注释是以 '#' 开头的行: > :syntax match xComment /#.*/你可以用任意的查找模式。因此通过一个匹配条目,你可以高亮显示非常复杂的项目。关于查找模式,参考 |pattern|。==============================================================================*44.4* 区域在 x 样例语言中,字符串用双引号 (") 来包含。要高亮一个字符串,你需要定义一个区域。你需要一个区域的开头(双引号)和一个区域的结尾(双引号)。定义如下所示:> :syntax region xString start=/"/ end=/"/"start" 和 "end" 指示定义要寻找模式的开头和结尾。但如果一个有这样的字符串该怎么办呢? "A string with a double quote (\") in it" ~这会带来一个问题:字符串中间的双引号会结束区域。你需要告诉 Vim 忽略任何转义之后的双引号: > :syntax region xString start=/"/ skip=/\\"/ end=/"/用两个反斜杠匹配单个反斜杠,因为反斜杠在字符串中是一个特殊字符。什么时候用区域而不用匹配?两者主要的区别是匹配是单个的模式,它必须作为整体来匹配;而区域是只要区域的 "开头" 匹配便开始匹配, "结尾" 匹配是否找到并不重要。这样当一个条目倚赖于 "结尾" 匹配时,你不能用区域。区域定义起来更简单些,当使用嵌套条目时就更加方便,这将在下一节中解释。==============================================================================*44.5* 嵌套条目看一下这个注释: %Get input TODO: Skip white space ~你想将 "TODO" 高亮显示成黄色字符,即使它在一个蓝色高亮显示的注释中。要使 Vim了解到这些,你需要定义以下的语法组: > :syntax keyword xTodo TODO contained :syntax match xComment /%.*/ contains=xTodo在第一行中,"contained" 参数告诉 Vim 这个关键字只能存在于另一个语法条目中。下一行指定 "contains=xTodo", 这说明 "xTodo" 语法元素存在其中。结果就是注释行作为整体匹配 "xComment" 并被显示成蓝色。而其中的 "TODO" 单词匹配 "xTodo" 将被显示成黄色。递 归 套 嵌x 语言用大括号定义代码块。而且一个代码块中可以包含其它的代码块。这可以用以下方式定义: > :syntax region xBlock start=/{/ end=/}/ contains=xBlock假设你有这样的代码: while i < b { ~ if a { ~ b = c; ~ } ~ } ~首先一个 "xBlock" 开始于第一行的 '{'。第二行中有另一个 '{'。因为我们已经在一个"xBlock" 之内,因此一个套嵌的 "xBlock" 在此处开始。这样 "b = c" 那一行在第二级的 "xBlock" 区域之内。下一行有一个 '}',这将和区域的结尾相匹配。它会结束套嵌的"xBlock"。因为这个 '}' 存在于套嵌的区域,它将隐藏于第一个 'xBlock' 区域。因此最后一行的 '}' 结束第一个 'xBlock' 区域。保 留 结 尾考虑下面的两个语法条目: > :syntax region xComment start=/%/ end=/$/ contained :syntax region xPreProc start=/#/ end=/$/ contains=xComment你定义注释是以 '%' 开始的任意行,而预处理命令是以 '#' 开始的任意行。因为注释可以存在于预处理中,预处理的定义包含一个 "contains=xComment" 参数。现在看一下下面的代码会发生什么情况: #define X = Y % Comment text ~ int foo = 1; ~你看到的是第二行也被当作预处理高亮显示。预处理命令应该在行结尾处结束。这也是你要使用 "end=/$/" 的原因。但到底是哪里错了呢? 问题在于包含的注释。注释以 '%' 开始,在行尾结束。注释结束后,预处理语法继续,这是在行尾已被处理之后进行的,因此下一行也被认为是预处理命令。 为避免这个问题,避免一个包含的语法条目吃掉一个必需的行尾,使用 "keepend" 参数。这样就会解决两个行结尾的匹配问题: > :syntax region xComment start=/%/ end=/$/ contained :syntax region xPreProc start=/#/ end=/$/ contains=xComment keepend包 含 多 个 条 目你可以用 'contains' 参数来指定任何条目都能被包含。比如: > :syntax region xList start=/\[/ end=/\]/ contains=ALL所有的条目都包含在此项中。它也包含它自己本身,但不是在同一位置(这是为了避免无限循环)。 你可以指定不被包括的组,这样就包含除了指定组之外的所有组:> :syntax region xList start=/\[/ end=/\]/ contains=ALLBUT,xString使用 "TOP" 条目,你可以包含所有那些没有 "contained" 参数的条目。"CONTAINED" 用来只包含那些使用了 "contained" 参数的条目。更多信息,参考 |:syn-contains|。==============================================================================*44.6* 跟随组x 语言有这种形式的语句: if (condition) then ~你想对这三种条目使用不同的高亮。但是 "(condintion)" 和 "then" 可能在其它地方有其它的高亮显示方式。这时你需要这样做: > :syntax match xIf /if/ nextgroup=xIfCondition skipwhite :syntax match xIfCondition /([^)]*)/ contained nextgroup=xThen skipwhite :syntax match xThen /then/ contained"nextgroup" 参数指定跟随的条目。这并不是必须的。如果指定的条目都没找到,什么事情都不会发生。比如,在下面的代码中: if not (condition) then ~"if" 匹配 "xIf"。"not" 并不匹配指定的跟随组 "xIfCondition",这样只有 "if" 被高亮显示。"skipwhite" 参数告诉 Vim 空白字符(空格和制表符)可以出现在条目之间。相似地,"skipnl" 参数允许条目之间存在换行符;"skipempty" 允许存在空白行。注意 "skipnl"并不忽略一个空白行。==============================================================================*44.7* 其它参数MATCHGROUP当你定义一个区域时,整个区域将根据指定的组名被高亮显示。比如,要高亮显示"xInside" 组被小括号 "()" 包含的部分,用下面的命令: > :syntax region xInside start=/(/ end=/)/假设,你要以不同方式显示括号。你可以用很多复杂的区域语句来完成,或者你可以使用"matchgroup" 参数。它将告诉 Vim 用另外一个组的方式来显示区域的开头和结尾(在本例中是 xParen 组): > :syntax region xInside matchgroup=xParen start=/(/ end=/)/<"matchgroup" 参数适用于它之后的区域开头或结尾。在前一例中,开头和结尾都以"xParen" 方式高亮显示。如果要用 "xParenEnd" 显示结尾: > :syntax region xInside matchgroup=xParen start=/(/ \ matchgroup=xParenEnd end=/)/用 "matchgroup" 的一个副作用是被包含的条目不会在区域的开头或结尾匹配。"transparent" 的例子中用到此作用。TRANSPARENT在 C 语言文件中你想要以不同方式高亮显示 "while" 和 "for" 后面的小括号。这两者中均会出现套嵌的小括号,它们会以相同的方式显示。你必须保证括号的高亮显示在匹配的 ')' 处结束。下面是一种可用的方法:> :syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -