oeasy教您玩轉(zhuǎn)vim - 90 - # 語法定義syntax
內(nèi)容查找 grep
回憶
我們這次研究了一下配色方案
murphy雖然配色好看
但是對(duì)于java的支持并不好
我們對(duì)于murphy進(jìn)行了修改
增加了
String
、StorageClass
顏色的定義整體思路是在syntax中定義組
然后在配色方案中對(duì)于組進(jìn)行顏色設(shè)置
可是syntax中如何定義組的呢???
語法文件
vi /usr/share/vim/vim81/syntax/java.vim
先把配色方案設(shè)置為murphy
:colorscheme murphy

我們可以看見這個(gè)java語法文件的:
作者
github地址
修改時(shí)間
然后就是大量的syn定義

什么是
syn
呢?
syntax語法
h syn

syntax
就是語法:syntax list
可以列出syntax item 語法項(xiàng)
syntax group 語法組
syntax cluster 集群
我們來試試
syntax list 語法列表
:syntax list

語法項(xiàng)目都是用help打頭的
為什么呢?
先q跳出去
:set filetype?
可以知道目前的文件是help文件
所以語法項(xiàng)目都是用help開頭的
:q
跳出help文件回到java.vim
java.vim
在打開java.vim的情況下運(yùn)行
:syntax list

因?yàn)楫?dāng)前打開的是.vim文件
所以得到的語法項(xiàng)都是和vim有關(guān)
如果我們打開一個(gè)java文件呢?
oeasy.java
:e oeasy.java
:syntax list

為什么打開不同的文件就會(huì)有不同的語法項(xiàng)列表呢?
語法文件
語法列表是由語法文件來決定的
語法文件位于語法文件夾中
/usr/share/vim/vim81/syntax/

help的語法文件
/usr/share/vim/vim81/syntax/help.vim
vim的語法文件
/usr/share/vim/vim81/syntax/vim.vim
java的語法文件
/usr/share/vim/vim81/syntax/java
我們繼續(xù)來看java的語法文件
關(guān)鍵字keyword
/\<public\>

syntax keyword javaScopeDecl public protected private abstract
java的
Scope可見性
Declaration描述
syntax 語法
keyword 關(guān)鍵字
javaScopeDecl
public protected private abstract 具體的關(guān)鍵字
vi oeasy.java
:colorscheme murphy
:hi javaScopeDecl ctermfg=brown

這樣設(shè)置了public protected private abstract 這些關(guān)鍵字的顏色了
試驗(yàn)成功
我們可以自定義的一個(gè)屬于自己的關(guān)鍵字么?
自定義關(guān)鍵字
:h syntax

這里是定義syntax語法項(xiàng)的地方
第一種語法項(xiàng)就是keyword
我們?nèi)ザx一個(gè)自己的關(guān)鍵字
sudo vi /usr/share/vim/vim81/syntax/java.vim
自己的關(guān)鍵字keyword
syn keyword oeasy System
把System定義為oeasy這個(gè)類型的關(guān)鍵字
然后保存退出

重新打開
oeasy.java
:syntax list

可以發(fā)現(xiàn)在oeasy.java文件打開后
已經(jīng)有了一個(gè)叫做oeasy的關(guān)鍵字類別
里面包含著System這個(gè)詞
那如何給oeasy這個(gè)類別上色呢?
給oeasy列別上色
顏色模式設(shè)置為murphy
:hi oeasy ctermfg=yellow

試驗(yàn)成功
但是public對(duì)應(yīng)的這個(gè)javaScope
又是如何與StorageClass掛上關(guān)系的呢?
層層關(guān)聯(lián)
回到syntax中的
java.vim
/\<javaScopeDecl\>
9個(gè)匹配

這里有個(gè)
hi def link

就是對(duì)于高亮hilight組的鏈接

把javaScopeDecl、javaClassDecl、javaMethodDecl鏈接到了javaStorageClass上
這樣,
:hi javaStorageClass cterm=white
就可以用到三組上面但是上圖最上的一句話又是什么意思呢?
hi def link javaStorageClass StorageClass
組名通用化
:e /usr/share/vim/vim81/syntax/c.vim

我們可以看到不同語言有不同的語言的StorageClass
java的叫做javaStorageClass
c的叫做cStorageClass
rust叫做rustStorageClass
不管他們?cè)瓉淼拿秩绾?,都映射到StorageClass
這樣murphy、morning、blue等顏色方案只要設(shè)置StorageClass的高亮
就可以映射到不同語言的不同組里面了
像StorageClass這樣的通用組名還有很多

如果我們做一門叫做oeasy的語言
就需要把關(guān)鍵字定義到oeasyStorageClass中
然后把oeasyStorageClass映射到StorageClass上
只要顏色方案中有關(guān)于StorageClass的定義
我們相關(guān)關(guān)鍵字就可以顯示出來
除了keyword之外,還有什么樣的高亮item的定義呢?
match 匹配模式

match顧名思義就是匹配模式
比如
syntax match javaComment /#.*/
/
是模式匹配的開始和結(jié)束#
代表#
如果是#開頭的行,^#
如果是#開頭的單詞,\<#
.
任意字符*
代表任意字符.
的數(shù)量是0到任意多個(gè)javaComment
是高亮項(xiàng)名稱/#.*/
/match

javaBraces 對(duì)應(yīng)的是左右大括號(hào)
"[{}]"
""里面是pattern
[]里面是或的關(guān)系
{}是左或右大括號(hào)
匹配import 或者 import static
這里怎么引號(hào)外面還有東西呢?
偏移量 offset
"\.\s*\<class\>"
\.
開頭有任意字符\s*
然后有0到任意多個(gè)空格或tab然后是獨(dú)立單詞class
ms的意思是Match Start匹配頭
ms=s+1是什么意思
s是start
ms=s+1
就是把
\s*
前面的\.
去掉開始定義匹配的開始我們?cè)倏匆粋€(gè)
javaCommentStar
match 的思路是匹配一個(gè)模式
^\s* 行開頭有空格或者tab
然后后面有一個(gè)不是/的字符
這個(gè)時(shí)候要把結(jié)尾的位置me
設(shè)置為e-1
也就是不包含這個(gè)非/的字符
:hi javaCommentStar ctermbg=red
紅色的就是對(duì)應(yīng)的javaCommentStart的區(qū)域
匹配了就進(jìn)入組
除了match直接匹配之外
還有什么定義高亮組的方法么?
region 區(qū)域
最重要的有三個(gè)屬性
start開頭
end結(jié)尾
skip 跳過的
start=+"+
+是分隔符號(hào)相當(dāng)于/
pattern是"
以"為開頭
end=+"+"
同上
以"為結(jié)尾
skip=+\"+
分割符還是+
中間如果有\(zhòng)"就跳過
不作為結(jié)尾
echo "i say \"oeasy\"" #echo sth
匹配
"i say \"oeasy\""
region帶偏移量
高亮開始
hs highlight start 高亮開始位置
e 是end 指的是start開始模式
/\*
的結(jié)束位置e+1指的是
/*
后面一個(gè)字符的位置hs=e+1 高亮開始于開始模式末尾后一個(gè)字符
高亮結(jié)束
he highlight end 高亮結(jié)束位置
s 是 start 指的是end結(jié)束模式
\*/
的開始位置s-1 指的是
*/
前面一個(gè)字符的位置he=s-1 高亮結(jié)束于結(jié)束模式開頭前一個(gè)字符

匹配模式match的是
mmm...mmm
的位置匹配高亮的region是
rrr
對(duì)應(yīng)的位置除了region之外,還有什么高亮組的定義方法么?
嵌入的高亮組

xComment
x語言的注釋
%開始的都是注釋
注釋里面可以包含TODO
xTODO
x語言的TODO
TODO高亮組只能存在于注釋里面
不在注釋里面的不是TODO高亮組
遞歸嵌入

xBlock
x語言的Block塊
大括號(hào)包起來的都是Block
Block可以自身遞歸嵌套
統(tǒng)一截行 keepend

xComment
x語言的注釋,從%到結(jié)尾$
xPreProc
x語言的預(yù)處理,從#到結(jié)尾$
可以包含xComment
藍(lán)色部分把第二行也認(rèn)為是預(yù)處理
因?yàn)榈谝恍械慕Y(jié)尾回車給了xComment
xPreProc就把第二行的結(jié)尾回車當(dāng)作自己的了
為了避免這個(gè)情況
keepend

排除元素ALLBUT

contains里面可以放具體的高亮組
也可以放所有東西
如果要排除某些東西怎么辦呢?

下一組nextgroup

這三個(gè)東西必須挨著
在一起
各自才能成立
匹配組 matchgroup

第一種模式定義了一個(gè)組
包括括號(hào)和括號(hào)里面的內(nèi)容
第二種模式生成了兩個(gè)組
xInside
xParen
可以分別上色
透明transparent
如果你想要while和for循環(huán)的條件有不同顏色
可以這樣試試

for、while各有一套
cCondNest本身是透明的
跟著上一層高亮組走
行內(nèi)oneline

oneline就是一行
保證這個(gè)匹配的模式必須在一行以內(nèi)
有一行那有沒有多行呢?
多行

多行里面包含了xLineContinue
xLineContinue包含了
\\$
換行符被包含在了高亮組里
于是高亮組可以換行了
集群cluster

contains里面的東西是重復(fù)的
可以定一個(gè)集群cluster

然后contains里面就用集群

集群本質(zhì)上是高亮組的列表
這個(gè)列表可以添加和刪除

更多語法
比如你打開一個(gè)cpp文件
文件緩沖被解析為cpp的高亮組
但是我同時(shí)想用c的高亮組
怎么辦?

什么是runtime呢?
運(yùn)行時(shí)環(huán)境
syntax/c.vim
在運(yùn)行時(shí)環(huán)境里面找syntax/c.vim
運(yùn)行時(shí)環(huán)境是什么?
:echo $VIMRUNTIME
/usr/share/vim/vim81
這是一切的來源
語法文件的來源
高亮顏色模式的來源
縮進(jìn)的來源
如果出現(xiàn)了問題
可以去看看這里是不是正確
總結(jié)
這次我們徹底研究了vim高亮的原理
各種語法項(xiàng)syntax item
關(guān)鍵字keyword
匹配模式match
區(qū)域region
定義好了之后還可以設(shè)置鏈接成組
hi def link javaComment Comment
然后就可以在顏色文件中具體配色了
比如murphy中對(duì)于Comment的定義
hi Comment ctermfg=yellow
不同的語言可以有不同的語法定義
其實(shí),vim也是門語言
vimscript也是可以編程的
怎么玩呢???
下次再說!