sublime - PackageDev自定義語法高亮規則
這幾天為sublime-syntax的語法簡直傷透了腦筋,網上能找到的教程都非常淺顯,而官方英文文檔的一時半會看不懂,中文文檔翻譯又實在糟心,糾結到最後還是下決心將英文文檔整個看了一遍,並翻譯成了我能看懂的文字。就以此作為我的第一篇正式博客吧!
使用步驟
1.安裝PackageDev插件
2.新建語法文件
Tools | Packages | Package Development | New Syntax Definition
3.定義語法高亮規則
見後文。
4.保存文件
保存完點擊 Tools | Build System | Convert to
編譯。
(感覺好像可以不用這一步,直接保存在user文件夾下就行,因為新版本已支持.sublime-syntax後綴文件。當然我也沒試過,只是猜想。)
5.修改語法文件
修改並保存可直接產生效果,不用等狀態欄100%。但最終要等100%才能退出sublime,以後會自動加載。
語法規則
Header
name -> 語法名稱。可選,如果不寫,將從文件名派生 file_extensions -> 此語法應使用的文件擴展名 first_line_match -> 沒有可識別的擴展名時,將對文件第一行進行匹配識別 scope -> 分配給文件中所有文本的默認scope hidden -> 隱藏的語法定義,不會顯示在菜單中,但仍可以通過插件分配
Contexts
Contexts中通常有多種匹配文本
ctrl+alt+shift+p -> 查看當前文本所使用的scope
當內容能匹配多個context時,使用最左邊的一個;當多種context在同一位置生效時,使用先定義的一個。
push -> 使用push入棧,將文本匹配切換到另一種context中, => 剩下的將不再使用當前context,直到使用pop從棧中彈出 meta_scope -> 為當前棧context的所有文本分配scope pop -> 從棧中彈出,繼續使用之前的scope main -> 每個語法必須定義一個main context, 它應用於文本最開始的位置.
Meta
meta_scope -> 為當前棧context的所有文本分配scope, 包括觸發push和pop的文本
meta_content_scope -> 同上,但是不應用於觸發push和pop的文本
meta_include_prototype -> false, 阻止當前文本自動應用prototype匹配.
clear_scopes -> 移除當前棧中應用的scope,可以是整數或true.
=> 應用於meta_scope和meta_content_scope之前.
=> 通常僅在將一種語法嵌入另一種語法時使用。
meta 必須列在任何match或include之前。
Match
match -> 用正則表達式來匹配文本。一次只針對一行文本匹配
=> 可以不使用‘‘,但當正則中有# : - { [ 或 > 時必須用引號
scope -> 分配給匹配文本的著色類型
captures -> group數字對scope的映射,將匹配的內容按gruop分別著色
push -> 推入堆棧的context,可以是context名及其列表,或者內聯的匿名context
pop -> 彈出堆棧中的當前context。此鍵唯一可接受的值是true
set -> 類似push,但先退出當前context,然後將給定的context推送到棧中
embed -> 此鍵接受context名,類似push,但當escape時彈出所有嵌套的context。
=> 是將一種語法嵌入另一種語法的理想工具
escape -> 與embed配套使用,用於退出嵌入的context
=> 此內的所有反向引用與match中的group關聯
embed_scope -> 為escape前match的所有文本分配scope
escape_capture -> escape中group數字對scope的映射,0表示所有匹配文本
push, pop, set 和 embed互斥。
Include
用於將一個context的內容包含在另一個context中。
例如註釋,可以使用include將其包含在內,而不用將它的內容復制到每個context中。
include的內容會被插入到當前位置,仍然可以通過調整插入位置來指定先後順序。
include的內容中定義的meta語句會被忽略。
prototype
對於諸如註釋之類的元素,經常會用include來使它們在每個context中自動插入,但每次都寫include太過繁瑣。
可以使用prototype來完成此操作,它自動將內容插入到每個context的頂部,除非在context頂部用meta_include_prototype: false
用標明。
Including Other Files
Sublime Syntax 支持一個語法嵌套另一個語法。
例如HTML嵌套Javascript。
main:
- match: <script>
push: Packages/JavaScript/JavaScript.sublime-syntax
with_prototype:
- match: (?=</script>)
pop: true
with_prototype -> 類似prototype, 將匹配應用於上面引入的所有context中。
=> 但是它會忽略meta_include_prototype設置。
此處(?=</script>)
,當匹配到上面的內容後跟</script>
時將JS從棧中彈出,並按原HTML規則匹配
雖然.sublime-syntax 和.tmLanguage語法都支持,但是在此不能混用。
例2:HTML模板語言的實現
scope: text.jinja
contexts:
main:
- match: ""
push: "Packages/HTML/HTML.sublime-syntax"
with_prototype:
- match: "{{"
push: expr
expr:
- match: "}}"
pop: true
- match: \b(if|else)\b
scope: keyword.control
與HTML中嵌入JavaScript不同的是,模板語言傾向於從內到外操作:默認使用HTML,只有某些特殊語句轉義為模板語言
match: ""
默認匹配所有的文本,通過with_prototype語句,當遇到 {{ ... }}
時使用新的匹配.
Variables
幾個正則表達式中有部分完全相同的情況並不少見,為避免重復,可以使用變量代替。
variables:
ident: ‘[A-Za-z_][A-Za-z_0-9]*‘
contexts:
main:
- match: ‘\b{{ident}}\b‘
scope: keyword.control
變量必須在.sublime-syntax文件頂層定義,並通過{{varname}}
在正則表達式中引用。
Variables may themselves include other variables. Note that any text that doesn‘t match {{[A-Za-z0-9_]+}} won‘t be considered as a variable, so regexes can still include literal {{ characers, for example.
實例
嵌套循環匹配
例:括號自動匹配, 高亮顯示單獨的閉括號)
contexts:
main:
- match: \(
push: brackets
- match: \)
scope: invalid.illegal.stray-bracket-end
brackets:
- match: \)
pop: true
- include: main
高級棧的使用
例:匹配typedef的兩種定義
typedef int coordinate_t;
typedef struct
{
int x;
int y;
} point_t;
匹配代碼:
main:
- match: \btypedef\b
scope: keyword.control.c
set: [typedef_after_typename, typename]
typename:
- match: \bstruct\b
set:
- match: "{"
set:
- match: "}"
pop: true
- match: \b[A-Za-z_][A-Za-z_0-9]*\b
pop: true
typedef_after_typename:
- match: \b[A-Za-z_][A-Za-z_0-9]*\b
scope: entity.name.type
pop: true
main中使用匹配將兩個context推入堆棧,最右邊的處於棧的最頂層,先匹配,當最右邊彈出後,才開始匹配左邊的。
為了簡潔起見,typename中使用了context的匿名寫法。
對正則表達式中group的引用
例:PHP與 Heredocs語法
contexts:
main:
- match: <<<([A-Za-z][A-Za-z0-9_]*)
push: heredoc
heredoc:
- meta_scope: string.unquoted.heredoc
- match: ^\1;
pop: true
此處使用了 \1
符號代指之前匹配的group
語法測試
可以定義一個語法測試文本來自動檢測,而不需要手動通過show_scope_name
命令檢測
具體見官方文檔。
關於scope的語法容日後再行研究
引用:
非官方文檔(推薦)
官方文檔
中文版百度快照
sublime - PackageDev自定義語法高亮規則