1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

nvim-treesitter の main ブランチ移行でハイライトが効かなくなり格闘した記録(原因は灯台下暗しでした

Posted at

はじめに

前回、自作の Tree-sitter パーサー (tree-sitter-unreal-cpp) の構文解析はうまくいったのに、どうしてもハイライトが効かない…というポエムのような記事を投稿しました。

あれから一日、リベンジを誓って再びデバッグに挑んだ結果、ついにハイライトを有効にすることに成功しました。しかし、その原因はあまりにも単純なケアレスミス。この恥ずかしさと、ついに解決した安堵が入り混じった気持ちをここに記します。
image.png

長く険しいデバッグの旅路

今回も、問題の切り分けからスタートしました。

1. クエリファイルは正しく読み込まれているか?

nvim-treesittermain ブランチでは、デバッグ用のコマンドが整理され、Neovim 本体の API を直接叩くのが確実です。まずは、現在のファイルタイプ (cpp) に対して、どの highlights.scm が読み込まれているかを確認しました。

-- コマンドモードで実行
:lua print(vim.inspect(vim.treesitter.query.get_files(vim.bo.filetype, "highlights")))

結果として、自作のクエリファイル (.../queries/cpp/highlights_unreal.scm など) のパスがきちんと表示されました。クエリファイルの読み込みは成功している、ということが確定しました。


2. ハイライトグループは適用されているか?

次に、ハイライトさせたいキーワード(Blueprintable など)の上で、どのハイライトグループが適用されているかを確認します。

:Inspect

しかし、結果は Syntax - cParen のような無関係なものだけ。Tree-sitter 由来のハイライトグループは何も適用されていませんでした


3. ドキュメントの再読と深まる謎

クエリは読み込まれている。パーサーも :InspectTree で見る限り正しく動いている。それなのにハイライトが適用されない...。

Neovim の Tree-sitter 公式ドキュメントを何度も読み返しましたが、.scm ファイルの構文に間違いは見当たりません。
master ブランチでは動いていたのに、なぜ...?」という気持ちが強くなり、今回も諦めムードが漂い始めた、まさにその時でした。ふと、あることに気が付きます。

「そういえば、Unreal C++ 以外のハイライトも効いていない…?」


灯台下暗し!すべての原因

ensure_installed を設定しているはずなのに、なぜ cpp 以外のパーサーがインストールされていないのか?
その疑問をきっかけに main ブランチの README を改めて熟読した結果、自分の思い込みに愕然としました。

main ブランチは master ブランチとは全くの別物になっていたのです。

  • setup テーブルに記述していた ensure_installed廃止
  • 同じく highlight = { enable = true }indent = { enable = true } といった機能の自動有効化スイッチも廃止

nvim-treesitter はもはや多機能フレームワークではなく、パーサー管理とクエリ提供に特化した、よりシンプルなプラグインへと役割を変えていました。そして、ハイライトなどの機能を有効にするのは、ユーザー自身の責任となっていたのです。

まさに灯台下暗し。部品(クエリファイル)ばかりを調べていましたが、そもそも電源スイッチが入っていなかったのでした。

最終的な設定コード

README を読み、これまでのデバッグで得た知見をすべて反映した最終的な設定コードがこちらです。

-- lazy.nvim での設定例
{
  'nvim-treesitter/nvim-treesitter',
  branch = 'main',
  build = ':TSUpdate', -- プラグイン更新時にパーサーも更新する
  config = function()
    -- インストールしたいパーサーのリスト
    local langs = { "c", "cpp", "c_sharp", "lua", "vim", "vimdoc" }

    -- 1. パーサーをインストールする
    -- buildステップで自動化されるが、手動実行も可能
    require("nvim-treesitter").install(langs)

    -- 2. 機能の有効化 (ここが最重要ポイント!)
    -- autocmdでファイルタイプごとにTreesitterの機能を起動する
    local group = vim.api.nvim_create_augroup('MyTreesitterSetup', { clear = true })
    vim.api.nvim_create_autocmd('FileType', {
      group = group,
      pattern = langs,
      callback = function(args)
        -- ハイライトを有効にする
        vim.treesitter.start(args.buf)

        -- インデントを有効にする
        vim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
      end,
    })
  end,
}

この設定を適用したことで、長かった戦いに終止符が打たれ、無事にすべてのハイライトが正しく表示されるようになりました。


まとめ

image.png

nvim-treesittermain ブランチへ移行する際は、master ブランチの知識は一度忘れる必要があります。

  • setup テーブルは大幅に簡素化されました。
  • パーサーのインストールは require("nvim-treesitter").install() で行います。
  • ハイライトやインデントなどの機能は、自分で autocmd を設定して vim.treesitter.start() などを呼び出す必要があります

最新のプラグインを追いかけるのは大変ですが、その分 Neovim 本体の進化を直接感じられる良い機会になりました。何より、自分のケアレスミスに気づけて本当に良かったです(とても恥ずかしいですが…)。
この記事が、同じように main ブランチで迷子になった誰かの助けになれば幸いです。


さて今回もgemini proに下書きを正書してもらって記事を投稿しています。
今回はアメリカン感がすくなく下書きの雰囲気がすこーしのこっているので画像の追加以外一切の加筆&修正なし純度100%のgeimini文章です
treesitterのデバッグをしていたチャット部屋で文章も書いてもらったので私がわすれていたデバッグの章も加筆してくれました。これを思うに用途で部屋を分けるよりかは一つのチャット部屋で完結したほうがいいのか?と思いつつ、大量のソースコードのやり取りをしているとgemini側がどのソースが最新の状態なのか?がだんだんわからなくなっていくような挙動もするので見極めつつ今後も geminiを使っていこうと思います。
(copilotも課金してますがなんか性格が好きになれない)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?