chezmoiを使って管理しているdotfileのファイルタイプをNeovimにうまく認識させる

by
カテゴリ:

Neovimはファイルの名前や内容を元に、ファイルタイプを決定する機能を持っています。たとえば、拡張子が.shだったらシェルスクリプトだと判断できます。

このルールを改変する機能も備わっており:h vim.filetype.addに記載されています。

これを利用して、chezmoiで管理しているdotfileのファイルタイプ検出を改善してみましょう。

本記事ではchezmoiそのものの解説はしないので、Zennなどの紹介記事をあたってください。

chezmoi で dotfiles を手軽に柔軟にセキュアに管理する by ryo_kawamataさん

chezmoiでは、.configなど.で始まるファイルやディレクトリをdot_configなどとdot_始まりに改名したコピーを別ディレクトリでバージョン管理しています。このため、たとえば.zshrcならfiletype=zshなところ、dot_zshrcなせいでファイルタイプを検出できない、といった事態に陥ります。

そこで、chezmoiで管理しているファイルを編集する時は、そのファイルパス中の/dot_/.に置換した上で、vim.filetype.match関数を使ってファイルタイプを再判定するとよさそうです。といっても、dot_config/nvim/init.luaのように、拡張子でファイルタイプをうまく検出できるケースもあるので、検出失敗時のフォールバックとして設定すると良いでしょう。

~/.config/nvim/filetype.luaに以下を記述するだけで設定できます。

vim.filetype.add({
  -- フルパスを使って判定するので、`pattern`キー内に記述
  pattern = {
    -- フルパスはlua-patternという正規表現っぽいものでマッチでき、環境変数も使える
    ['${HOME}/.local/share/chezmoi/.*'] = {
      -- テーブルの第一要素はフルパスなどを受け取ってファイルタイプを返す関数
      function(
        path,  -- フルパス
        buf    -- buffer number
      )
        -- パスに`/dot_`を含む場合、パスを改変して再判定させる
        if path:match('/dot_') then
          return vim.filetype.match({
            filename = path:gsub('/dot_', '/.'),
            buf = buf,
          })
        end
      end,
      -- テーブルの第二要素でpriorityを最低にしておくと、フォールバック相当になる
      { priority = -math.huge }
    },
  },
})

私は当初、basenameがdot_始まりかだけ確認していましたが、/dot_をすべて.に置換するようにしました。こうしておくと、dot_config/git/configといったファイル名ではなく親ディレクトリに/dot_を含むケースでも、ファイルタイプをgitconfigとして検出できるようになります。

ENJOY!

2023-1-11追記:

chezmoi edit .zshrcなどで編集した場合、ここに書いた方法を使わなくても、適切にファイルタイプを検出できます。 ryoppippiさん、教えてくださってありがとうございます。