nvim-treesitter は Python のインデントを壊す (共存方法まで紹介)
はじめに
nvim-treesitterを導入していると、たまに Python のインデントがバグります。
- oによる改行でのインデントがおかしくなっている様子
仕組み上仕方のないコンフリクトなんですが、初見だと戸惑いますし何が原因か分からないかと思います。
本記事では
- なぜ起きるのか
- どうやって回避するのか
について説明します。
原因
原因になる行はこういうものです。
if s == "(":
文字列の (
なんかが含まれる行ですね。
組み込みや Vimjas/vim-python-pep8-indent による Python のインデント計算は、シンタックスハイライトを参照することがあります。
この辺 とか この辺 とかですね。
Python は ()
などで行継続できるのでインデントに影響しますが、これが文字列中にあるのなら無視するべきです。
これを判断するためにシンタックスハイライトを見ます。
x = (2 +
4 * 10**1)
ところが Treesitter を有効化していると、通常のハイライトが無効化されてしまいます。
色の付け方の仕組みが違うので、synID()
は何も返しません。
そうしてインデント計算が壊れるわけです。
if s == "(":
|ここにカーソル来るはず!
回避方法
最もシンプルな解決方法は、Python で treesitter を無効化することです。
がっかりしましたか?
安心してください、もっと良い解決方法が用意されています。
syntax も動かす
幸いにもこのコンフリクトは nvim-treesitter 開発チームも把握しています。
require("treesitter.configs").setup({
highlight = {
enable = true,
additional_vim_regex_highlighting = { "python" },
},
})
highlight.additional_vim_regex_highlighting
というオプションを有効化することで、裏で syntax も計算してくれます。
これにより、treesitter のハイライトを残しつつ、インデント計算も正常に行なわれるようになります。
なお、処理が増える分重くなることには注意してください。
treesitter にインデント計算させる
experimental な機能ですが nvim-treesitter にインデント計算させることもできます。
使用者によると割と安定してるらしいので、こちらの方がいいかもしれないです。
require("treesitter.configs").setup({
indent = {
enable = true,
-- python だけで有効化したいなら
-- disable = function(lang)
-- return lang ~= "python"
-- end
},
})
おわり
Python のインデントがおかしくなったからって、treesitter 疑うのは難しいですよねぇ。
誰かの助けになれば幸いです。
Discussion