語法高亮速成
我們繼續(xù)在人間修行Vim技能之旅哗戈。上一次我們學(xué)習(xí)了如何通過vundle安裝插件,這次我們迅速向?qū)懖寮姆较蛲M(jìn)。
我們先學(xué)習(xí)一個(gè)最簡(jiǎn)單的語法高亮插件的寫法淆党。
語法高亮基本上是由三部分組成:
- 配色方案
- 正則表達(dá)式
- 配色方案和正則表達(dá)式的規(guī)則對(duì)應(yīng)關(guān)系
簡(jiǎn)單的三步法寫語法高亮
第一步,寫匹配的正則表達(dá)式
我們舉個(gè)最簡(jiǎn)單的例子讶凉,以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
從中可以看到,前面先是一個(gè)時(shí)間戳懂讯,然后是log的類型荷憋,接著是Tag,進(jìn)程號(hào)和具體內(nèi)容褐望。
最簡(jiǎn)單的做法勒庄,我們就只取log類型和后面的"/"這兩個(gè)特征串前,正則表達(dá)式這樣寫:
syn match LogF '\<F/.*'
syn match LogE '\<E/.*'
syn match LogW '\<W/.*'
syn match LogI '\<I/.*'
syn match LogD '\<D/.*'
syn match LogV '\<V/.*'
其中,'<'表示匹配一個(gè)單詞的詞首锅铅。詳細(xì)信息可以通過:help \<
來查詢酪呻,在幫助的pattern.txt中。
第二步盐须,為場(chǎng)景配色
下面玩荠,我們需要為這些匹配的場(chǎng)景定義顏色:
有四種屬性可以使用:
- ctermfg: 在終端時(shí)運(yùn)行的前景色
- ctermbg: 終端時(shí)的背景色
- 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
第三步,將配色和正則表達(dá)式映射在一起
使用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
非作者原創(chuàng),版權(quán)歸原作者所有塑径。
更復(fù)雜一點(diǎn)的例子
看了最簡(jiǎn)單的一個(gè)實(shí)現(xiàn)女坑,我們當(dāng)然還可以做得更復(fù)雜一些:
我們參考一個(gè)更復(fù)雜一些的例子: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
與上一個(gè)完全自定義顏色不同,這位作者直接將正則表達(dá)式映射到語言的預(yù)定義配色方案中统舀。比如Comment是注釋匆骗,Statement是語句,Identifier是標(biāo)識(shí)符等等誉简。具體可以通過:help syntax來學(xué)習(xí)碉就,我們后面晉階上仙的教程里也會(huì)有詳細(xì)介紹。
總而言之闷串,這個(gè)的正則表達(dá)式更復(fù)雜了瓮钥,但是基本原理還是一樣的。
例三
下面我們?cè)俪脽岽蜩F烹吵,來看一個(gè)更復(fù)雜碉熄,也更人性化的例子:https://github.com/thinca/vim-logcat/blob/master/syntax/logcat.vim
我們來看下面一段,根據(jù)背景是不是暗的配色而設(shè)計(jì)兩套配色方案肋拔,非常貼心:
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
小結(jié)
小結(jié)一下锈津,我們這節(jié)只學(xué)習(xí)三個(gè)命令:
- syntax match: 正則表達(dá)式和場(chǎng)景匹配
- highlight default: 為場(chǎng)景定義配色
- highlight link: 將上兩者聯(lián)系在一起,也可以鏈接到預(yù)定義的一些標(biāo)準(zhǔn)配色方案上