はじめに
本エントリは Vim Advent Calendar 209 日目の記事になります。
Qt で UI 記述言語の QML 使ってアプリケーション作るのが簡単すぎて、他の環境で作れない身体になって来ました。そんな QML では CSS の文法のように各要素を配置する QML 部分、ロジックを書く JavaScript 部分、またシェーダを扱う GLSL 部分が存在します。これらを Vim Advent Calendar 194 日目で紹介されていました precious.vim を使って、シンタックスハイライト及び補完を切り分ける処理を拡張として書いてみました。
デモ
QML のコンテキストでは QML のシンタックスハイライト及び補完を、JavaScript / GLSL のコンテキストでもそれぞれの filetype にあったシンタックスハイライトと補完を行なってくれるようになります。
設定
if !exists('g:context_filetype#filetypes') let g:context_filetype#filetypes = {} endif " context_filetype.vim の filetype 毎の設定を拡張 let g:context_filetype#filetypes = { \ 'qml' : [ \ { \ 'filetype' : 'javascript', \ 'start' : '^\(\s*\)\h\w*:\s*{$', \ 'end' : '^\1}' \ }, \ { \ 'filetype' : 'glsl', \ 'start' : ':\s*"', \ 'end' : '"' \ } \ ], \ 'html' : [ \ { \ 'filetype' : 'glsl', \ 'start' : '<script[^>]*shader[^>]*>', \ 'end' : '<\/script>' \ } \ ], \ } " 保存時に補完が誤作動しないように切っておく augroup PreciousMySettings autocmd! autocmd User PreciousFileType :echo precious#context_filetype() autocmd User PreciousFiletype_javascript \ :let g:watchdogs_check_BufWritePost_enables['javascript'] = 0 augroup END
カーソル位置からコンテキストに応じた filetype を判定してくれる plugin である context_filetype.vim の設定を拡張します。QML のついでに HTML のシェーダ部分も拡張しておきました。
JavaScript は「: {」で開始して「}」で終了するのですが終了の波括弧は JavaScript 内でも使われるため、ここではいインデントの一致を見ています。GLSL の方は単純で、単に複数行にまたがる「: "」〜「"」を見ています。HTML では script タグに「shader」が含まれるときに切り替えるようにしました。
また、WatchDogs や Syntastic といった保存時に文法をチェックしてくれるプラグインに関しては、他のコンテキストをエラーとして判別してしまうため明示的に切るようにしています。
(本当はチェックをかけたいのですが、precious#quickrun_operator を拡張すれば可能?と思ったけど巧くいっていないので出来たら追記します)
おわりに
複数の言語が同一のソース内で交じり合う状況では必須のプラギンだと思います。すごい便利です。後はコンテキスト内の文法チェックが出来れば良いのですが、外側のコンテキスト依存の要素(QML なら QML の id や、HTML なら別ソースの変数など)が絡んでくるので難しそうです。