本身寫VIM語法高亮插件

實習以後發現,一切代碼活動都侷限在一個終端界面了。因爲一些安全緣由和開發環境的方便,開發都是經過遠程ssh到開發機上開發,天然也就只有終端界面了。VNC由於安全緣由不讓用,因此就別妄想使用Clion等IDE來開發了。在這樣的背景下,人們大多使用VIM或者EMACS等編輯器來開發。html

在調試過程當中,服務端日誌是一個重要的參考依據。可是這類文本並非某種編程語言,一般查閱的時候是沒有語法高亮的,並且爲了對grep命令友好,一般會將一條日誌打在一行裏,這就使得日誌信息很是密集,分辯關鍵信息的時候很是不方便。因而我便有了這樣一個想法,編寫VIM插件,對日誌中的關鍵信息如時間戳、代碼行號、錯誤碼進行語法高亮。正則表達式

爲了敘述的方便,咱們的目標是爲下面這段日誌進行高亮,將日誌級別、時間戳、代碼行號標識出來。編程

[ERROR][2017-10-01 08:08:08][example.go:231]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
[DEBUG][2017-10-01 08:08:10][example.go:233]Lorem ipsum dolor sit amet
[INFO][2017-10-01 08:09:09][example.go:2333]Lorem ipsum dolor sit amet

語法高亮插件

語法高亮插件須要兩個.vim文件。一個是語法檢測文件(ftdetect),這是爲了讓VIM可以將指定語法應用於指定後綴的文件。一個是語法文件(syntax),這裏定義了高亮的語法和着色方案。vim

插件的目錄結構以下:安全

/Users/zhuangqh/.vim
├── ftdetect
│   └── log.vim
└── syntax
    └── log.vim

這些文件在類UNIX系統上要放到$HOME/.vim目錄下,Windows系統是$HOME/vimfiles/下。ssh

語法檢測

當buffer讀取或建立時,將.log後綴的文件類型設置爲log,以後使用log類型的語法高亮方案進行着色。編程語言

" ftdetect/log.vim
au BufNewFile,BufRead *.log set filetype=log

語法高亮

這是文本的重點,該文件告訴VIM該怎麼着色。編輯器

關鍵字高亮

syn keyword ${group} ${keyword}

大多數編程語言都有關鍵字。規則設置的時候,先給他一個組名,後面再接着一些關鍵字,以後再根據這個組名設置顏色。關鍵字高亮的匹配優先級是最高的,若是有其它高亮規則匹配上了也會按關鍵字的規則來高亮。.net

這個規則對咱們此次任務沒什麼用,由於咱們只想高亮日誌開頭的那個特定的ERROR字樣,存在上下文,實際上並非關鍵字。插件

匹配字高亮

syn match ${name} ${pattern}

這個命令提供了一種強大的匹配方法,用正則表達式來匹配。咱們能夠用來匹配咱們的時間戳,如:syn match logDate '\d\{4}-\d\d-\d\d'

高亮嵌套

對某個匹配的字符串高亮以後,對子字符應用不一樣的規則。

好比上述日誌中的代碼行號 example2.go:233,咱們先總體匹配了這個模式,而後但願行號能有不同的顏色。這能夠理解成匹配的上下文,規則只在指定上下文中有效。

syn match logFile '\w*\.go:\d*' contains=logLineNum
syn match logLineNum '\d*' contained

contains告訴VIM這個token會包含其餘哪些token。contained告訴VIM,只有在被其餘token包含時,該規則纔有效。

匹配偏移

在高亮行號時,\d*規則會將全部的數字高亮,而事實上,只有冒號右邊的數字纔是行號,這就要用到匹配偏移的規則了。

syn match logLineNum ':\d*'ms=s+1 contained

匹配偏移用來調整實際匹配的值。ms(me)表示的是實際匹配的起始(終止)下標,s(e)表示的是原匹配字符的起始(終止)下標。咱們用:\d*匹配後,將下標向右調整一位便可。

記得偏移命令要緊跟模式項,不然會報錯。

區域高亮

syn region ${name} start=${pattern} end=${pattern} skip=${pattern}

區域匹配最多見的是匹配一個字符串,用引號包裹的字符串,能夠經過skip來跳過轉義字符如\"

在咱們的日誌高亮任務裏,想匹配的是包含特定token的中括號,咱們只高亮中括號,其餘的交由其餘規則來匹配。

syn region logBlock matchgroup=logParen start=/\[/ end=/\]/ fold

配色

hi ${name} ctermfg=${color}

爲前面定義的語法token設定着色樣式,ctermfg是彩色終端的前景色,其餘選項詳見:highlight

結果

把全部規則集結起來以下:

if exists("b:current_syntax")
  finish
endif

syn match logLevelError 'ERROR' contained
syn match logLevelDebug 'DEBUG' contained
syn match logLevelInfo 'INFO' contained

syn match logFile '\w*\.go:\d*' contains=logLineNum
syn match logLineNum ':\d*'ms=s+1 contained

syn match logDate '\d\{4}-\d\d-\d\d' contained
syn match logTime '\d\d:\d\d:\d\d' contained
syn region logBlock matchgroup=logParen start=/\[/ end=/\]/ fold
 \ contains=logLevelError,logLevelDebug,logLevelInfo,logFile,logDate,logTime

hi logLevelError ctermfg=red
hi logLevelDebug ctermfg=yellow
hi logLevelInfo ctermfg=green
hi logFile ctermfg=yellow
hi logLineNum ctermfg=blue
hi logDate ctermfg=yellow
hi logTime ctermfg=blue
hi logBlock ctermfg=white
hi logParen ctermfg=grey

let b:current_syntax = "log"

參考資料

相關文章
相關標籤/搜索