iceberg.vimを壊してしまった話
はじめに
こんにちは、あろーです。
半年前くらいに VSCode から Vim へ移行したばかりの初心者です。
現在は Neovim をメインに使っています。
本来は Vim に入門した話を書こうと思っていたのですが、自戒の念を込めてこの記事を書いています…。
iceberg.vim って?
iceberg.vim はcocoponさんが開発されている、Vim・Neovim 対応のカラースキームです。
ダークブルーを基調としていて視認性がよく、かっこよくてかわいいので愛用しています。
何をしたのか
シンタックスハイライトにnvim-treesitterを使用している環境で、正しく色がつかなくなっていた問題を修正する PR を出しました。
色がつかなくなっている様子
本来はこうなっているべき
原因
原因はシンプルで、最近取り込まれた nvim-treesitter のハイライトグループ名の変更に iceberg.vim が対応できていなかったからでした。
具体的には、TS
から始まっていた名前が @
から始まる名前に変更されています。
詳しい変更内容については以下のリンクをご参照ください。
経緯
「置き換わっただけなら、カラースキームの方でも置き換えればいけそう!」
と思ったので、愚直に置き換えました。
その後、ちょっと調整したりして…
既存のTS*
のハイライトグループを消すと後方互換性が壊れるので戻した
無事にマージしていただけました ✌️
壊れた
と喜んでいたのも束の間、以下のような Issue が立ちました。
「Vim で読み込んだ際に警告 W18: Invalid character in group name happens
が出まくる」という内容です。
どう考えても私の行った変更が原因なので、急いで調査に取り掛かりました…。
なぜ壊れたのか
結論から言うと、原因はVim と Neovim とでハイライトグループ名に使える文字が異なることでした。
Vim で使用できる文字は [a-zA-Z0-9_]
ですが、Neovim v0.8 から .
と @
を足した [a-zA-Z0-9_.@]
が使用できるようになっています。
後にコメントで教えていただいたのですが、リリースノートの Breaking changes にしっかりと記載されていました。
Vim(もしくは Neovim v0.7 以前)では @
が使用できないため Invalid character in group name
という警告が出ていた、という訳です。
修正する
上記の理由から、@*
のハイライトグループを Neovim v0.8 以降の場合にのみ定義するよう修正すれば良さそうです。
iceberg.vim はpgmnt.vimというテンプレートエンジンで生成する形を取っているので、そちらのコードを触る必要があります。
src/iceberg.vim
「今後、Treesitter 以外にも Neovim に依存したハイライトグループ名を使うプラグインがあるかも」と思ったので、追加しやすいよう該当する部分を関数にまとめました。
はじめに出した PR とは異なり、元々定義されていた TS*
のハイライトグループにリンクさせる形を取っています。
function! s:create_neovim_08_links() abort
let links = []
call add(links, pgmnt#hi#link('@attribute', 'TSAttribute'))
call add(links, pgmnt#hi#link('@boolean', 'TSBoolean'))
call add(links, pgmnt#hi#link('@character', 'TSCharacter'))
call add(links, pgmnt#hi#link('@comment', 'TSComment'))
call add(links, pgmnt#hi#link('@constructor', 'TSConstructor'))
call add(links, pgmnt#hi#link('@conditional', 'TSConditional'))
call add(links, pgmnt#hi#link('@constant', 'TSConstant'))
call add(links, pgmnt#hi#link('@constant.builtin', 'TSConstBuiltin'))
call add(links, pgmnt#hi#link('@constant.macro', 'TSConstMacro'))
" 省略...
return links
endfunction
create_context()
の戻り値がテンプレートに埋め込まれるので、ここで先ほど作った関数を呼び、戻り値に追加します。
function! s:create_context() abort
" 省略...
let neovim_08_links = s:create_neovim_08_links()
return {
\ 'modified': strftime('%Y-%m-%d %H:%M%z'),
\ 'dark_rules': d.rules,
\ 'dark_neovim_term_defs': d.neovim_term_defs,
\ 'dark_vim_term_defs': d.vim_term_defs,
\ 'light_rules': l.rules,
\ 'light_neovim_term_defs': l.neovim_term_defs,
\ 'light_vim_term_defs': l.vim_term_defs,
\ 'links': links,
+ \ 'neovim_08_links': neovim_08_links,
\ }
endfunction
src/template.vim
テンプレートへ create_context()
に新しく追加した戻り値の名前を埋め込みます。
has('nvim-0.8')
で Neovim v0.8 以上なのかを取得できる[1]ので、それを使って分岐させています。
" 省略...
{{ links }}
+ if has('nvim-0.8')
+ {{ neovim_08_links }}
+ endif
if !has('nvim')
hi! link SpecialKey Whitespace
endif
これで、今度こそ完了です!
最後に
Neovim について「なんか Vim を強くしたやつ」くらいの認識でいたので、改めて両者の違いを調べる良いきっかけになったなと思います。
また、vim-jpの Slack[2]でも今回のハイライト周りの件が話題にあがっており、Neovim 本体の Issue・PR を読みつつお話されていて、とても勉強になりました。
最後になりますが、今回 PR の対応をしてくださった cocopon さんをはじめ、コメントにてフォローしてくださった方々には頭が上がりません。ありがとうございました…!
-
こちらのコメントで教えていただきました 🙏
https://github.com/cocopon/iceberg.vim/pull/110#issuecomment-1316889285 ↩︎ -
参加はこちらから…!
https://vim-jp.org/docs/chat.html ↩︎
Discussion