Grammar Highlighting and Quick Achievement
We continue to practice Vim skills on earth. Last time we learned how to install plug-ins through vundle, this time we moved quickly towards writing plug-ins.
Let's first learn how to write a simple grammar highlighting plug-in.
Grammar highlighting basically consists of three parts:
- Colour matching scheme
- regular expression
- Rule correspondence between color matching schemes and regular expressions
Simple three-step grammar highlighting
The first step is to write matching regular expressions
Let's take Android's log as an example. The format of Android's log is as follows:
--------- 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
As you can see, the first step is a timestamp, followed by the type of log, followed by Tag, process number and specific content.
In the simplest way, we just take the log type and the following "/" two features, and the regular expression is written as follows:
syn match LogF '\<F/.*' syn match LogE '\<E/.*' syn match LogW '\<W/.*' syn match LogI '\<I/.*' syn match LogD '\<D/.*' syn match LogV '\<V/.*'
Where'<'means the first word that matches a word. Detailed information can be queried by: help<in the help pattern.txt.
The second step is to color the scene.
Next, we need to define colors for these matching scenarios:
There are four attributes that can be used:
- ctermfg: Foreground color for running at the terminal
- ctermbg: Background color at the terminal
- guifg: The Prospect of Graphic Interface
- guibg: The Background of Graphic Interface Definition format: hi def color matching name {color list} hi def is the abbreviation of highlight default
Example:
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
The third step is to map color matching and regular expressions together
Use the hi def link command to link the results of the first and second steps together.
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
Note: The above code is quoted from: https://github.com/serpent7776/vim-logcat/blob/master/syntax/logcat.vim
The copyright belongs to the original author.
A more complex example
Looking at the simplest implementation, we can certainly do something more complicated.
Let's refer to a more complex example: 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
Unlike the previous fully customized color scheme, the author maps regular expressions directly into the predefined color scheme of the language. For example, Comment is a comment, Statement is a statement, Identifier is an identifier, and so on. Specific can be learned through: help syntax, we will also have a detailed introduction in the later promotion of immortals in the course.
In a word, this regular expression is more complex, but the basic principle is the same.
Example three
Now let's strike while the iron is hot. Let's take a more complex and humane example. https://github.com/thinca/vim-logcat/blob/master/syntax/logcat.vim
Let's take a look at the following paragraph. It's very intimate to design two color schemes according to whether the background is dark or not.
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
Summary
To sum up, we only learn three commands in this section:
- syntax match: Regular expression and scene matching
- highlight default: Define color matching for scenarios
- highlight link: Connect the two together, or link to predefined standard color schemes