Vim技能修煉教程(2) - 語法高亮速成
語法高亮速成
我們繼續在人間修行Vim技能之旅。上一次我們學習了如何通過vundle安裝插件,這次我們迅速向寫插件的方向挺進。
我們先學習一個最簡單的語法高亮插件的寫法。
語法高亮基本上是由三部分組成:
- 配色方案
- 正則表達式
- 配色方案和正則表達式的規則對應關係
簡單的三步法寫語法高亮
第一步,寫匹配的正則表達式
我們舉個最簡單的例子,以Android的log為例,Android的log格式如下:
--------- beginning of system
05-05 17:55:48.909 I/ActivityManager( 2454): Start proc 15530:com.ss.android.article.lite:pushservice/u0a69 for service com.ss.android.article.lite/com.xiaomi.push.service.XMPushService
05-05 17:55:48.920 V/Build (15530): clr
05-05 17:55:48.933 D/CompatibilityInfo( 2454): mCompatibilityFlags - 0
05-05 17:55:48.933 D/CompatibilityInfo( 2454): applicationDensity - 640
05-05 17:55:48.933 D/CompatibilityInfo( 2454): applicationScale - 1.0
從中可以看到,前麵先是一個時間戳,然後是log的類型,接著是Tag,進程號和具體內容。
最簡單的做法,我們就隻取log類型和後麵的"/"這兩個特征,正則表達式這樣寫:
syn match LogF '\<F/.*'
syn match LogE '\<E/.*'
syn match LogW '\<W/.*'
syn match LogI '\<I/.*'
syn match LogD '\<D/.*'
syn match LogV '\<V/.*'
其中,'<'表示匹配一個單詞的詞首。詳細信息可以通過:help \<
來查詢,在幫助的pattern.txt中。
第二步,為場景配色
下麵,我們需要為這些匹配的場景定義顏色:
有四種屬性可以使用:
- ctermfg: 在終端時運行的前景色
- ctermbg: 終端時的背景色
- guifg: 圖形界麵的前景色
- guibg: 圖形界麵的背景色 定義格式:hi def 配色名 {顏色列表} hi def是highlight default的縮寫
例:
hi def LogF_color ctermfg=white guifg=white ctermbg=red guibg=red
hi def LogE_color ctermfg=red guifg=red
hi def LogW_color ctermfg=brown guifg=brown
hi def LogI_color ctermfg=grey guifg=grey
hi def LogD_color ctermfg=darkcyan guifg=darkcyan
hi def LogV_color ctermfg=grey guifg=grey
第三步,將配色和正則表達式映射在一起
使用hi def link命令,將第一步和第二步的成果鏈接在一起就好了。
hi def link LogF LogF_color
hi def link LogE LogE_color
hi def link LogW LogW_color
hi def link LogI LogI_color
hi def link LogD LogD_color
hi def link LogV LogV_color
注:上述代碼引用自:https://github.com/serpent7776/vim-logcat/blob/master/syntax/logcat.vim
非作者原創,版權歸原作者所有。
更複雜一點的例子
看了最簡單的一個實現,我們當然還可以做得更複雜一些:
我們參考一個更複雜一些的例子:https://github.com/gburca/vim-logcat/blob/master/syntax/logcat.vim
" Vim syntax file
" Language: Android LogCat and aplogd log file syntax
" Maintainer: Gabriel Burca <gburca dash vim at ebixio dot com>
"
" adb logcat -v time *:V
" 06-09 14:36:00.000 V/AlarmManager( 1484): sending alarm {957ff72 type 3 *alarm*:android.intent.action.TIME_TICK}
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
"
" Or for aplogd logs (syntax group names end with '2'):
" 06-08 16:17:56.101 566 566 E NEW_BHD : Open /sys/class/power_supply/gb_battery
" 06-08 16:17:55.183 18677 20835 D ACDB-LOADER: ACDB -> ACDB_CMD_GET_AFE_COMMON_TABLE
" 06-08 16:17:55.183 18677 20835 D : ACDBFILE_MGR:Read the devices count as zero, please check the acdb file
if exists("b:current_syntax")
finish
endif
...
syn match lcBegin display '^' nextgroup=lcDate
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^
syn match lcDate '[0-1]\d-[0-3]\d '
\ nextgroup=lcTime
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^^^^^^^^
syn match lcTime '[0-1]\d:[0-5]\d:[0-5]\d\.\d\d\d '
\ nextgroup=lcTag,lcThread2
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^
syn match lcPriority '\(V\|D\|I\|W\|E\|F\)[\/ ]'me=e-1
\ containedin=lcTag nextgroup=lcTag2
" Must come after lcPriority so it has higher match priority
syn match lcTagError 'E\/[[:alnum:]_-]\+'
\ containedin=lcTag
" Example:
" 06-08 16:17:56.101 566 566 E NEW_BHD : Open /sys/class/power_supply/gb_battery
syn match lcTagError2 'E [^:]\+:'
\ nextgroup=lcMsgBody
" The component may be empty in some cases
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^
syn match lcComponent '\/[^[:space:](]\+'ms=s+1
\ containedin=lcTag
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^^^^^
" 06-09 10:42:06.729 I/ ( 1484): Message with empty component
" ^^^^^^^^^^
syn match lcTag '\w\/[^(]*\s*'
\ nextgroup=lcThread contains=lcTagError,lcPriority,lcComponent,myTags
" Example:
" 06-08 16:17:55.183 18677 20835 D ACDB-LOADER: ACDB -> ACDB_CMD_GET_AFE_COMMON_TABLE
" ^^^^^^^^^^^^
" 06-08 16:17:55.183 18677 20835 D : ACDBFILE_MGR:Read the devices count as zero, please check the acdb file
" ^^^^^^^^^
syn match lcTag2 ' [^:]*\s*:'
\ nextgroup=lcMsgBody contains=myTags
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^^^
syn match lcThread '(\s*\d\+):'he=e-1
\ nextgroup=lcMsgBody contains=lcNumber
" Example:
" 06-08 16:17:55.183 18677 20835 D ACDB-LOADER: ACDB -> ACDB_CMD_GET_AFE_COMMON_TABLE
" ^^^^^^^^^^^^
syn match lcThread2 '\s*\d\+\s\+\d\+ '
\ nextgroup=lcPriority,lcTagError2 contains=lcNumber
" Example:
" 06-09 10:42:06.729 I/chatty ( 1484): uid=1000(system) Binder:1484_5 expire 1 line
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
syn match lcMsgBody contained ' .*'
\ contains=myKeywords
syn match lcNumber contained '0x[0-9a-fA-F]*\|\[<[0-9a-f]\+>\]\|\<\d[0-9a-fA-F]*'
hi def link lcDate Comment
hi def link lcTime SpecialComment
hi def link lcTag Statement
hi def link lcTag2 Statement
hi def link lcPriority Identifier
hi def link lcTagError Error
hi def link lcTagError2 Error
hi def link lcComponent Normal
hi def link lcThread Special
hi def link lcThread2 Special
hi def link lcMsgBody Normal
hi def link lcNumber Number
hi def link myTags Function
hi def link myKeywords Function
與上一個完全自定義顏色不同,這位作者直接將正則表達式映射到語言的預定義配色方案中。比如Comment是注釋,Statement是語句,Identifier是標識符等等。具體可以通過:help syntax來學習,我們後麵晉階上仙的教程裏也會有詳細介紹。
總而言之,這個的正則表達式更複雜了,但是基本原理還是一樣的。
例三
下麵我們再趁熱打鐵,來看一個更複雜,也更人性化的例子:https://github.com/thinca/vim-logcat/blob/master/syntax/logcat.vim
我們來看下麵一段,根據背景是不是暗的配色而設計兩套配色方案,非常貼心:
function! s:define_color()
if &background is 'dark'
highlight default logcatLevelVerbose guifg=Gray ctermfg=Gray
highlight default logcatLevelDebug guifg=Cyan ctermfg=Cyan
highlight default logcatLevelInfo guifg=Green ctermfg=Green
highlight default logcatLevelWarning guifg=Yellow ctermfg=Yellow
highlight default logcatLevelError guifg=Red ctermfg=Red
else
highlight default logcatLevelVerbose guifg=DarkGray ctermfg=DarkGray
highlight default logcatLevelDebug guifg=DarkCyan ctermfg=DarkCyan
highlight default logcatLevelInfo guifg=DarkGreen ctermfg=DarkGreen
highlight default logcatLevelWarning guifg=DarkYellow ctermfg=DarkYellow
highlight default logcatLevelError guifg=DarkRed ctermfg=DarkRed
endif
highlight default logcatLevelFatal guifg=White ctermfg=White guibg=Red ctermbg=Red
endfunction
小結
小結一下,我們這節隻學習三個命令:
- syntax match: 正則表達式和場景匹配
- highlight default: 為場景定義配色
- highlight link: 將上兩者聯係在一起,也可以鏈接到預定義的一些標準配色方案上
最後更新:2017-06-27 14:31:48