monorepoでnull-ls.nvimをいい感じにしたい
nvim
はじめに
私はnull-ls.nvim(以後null-ls)を使ってformatやlintをしています。
例えば、普段開発しているプロジェクトではPrettierとESLintを使ってlintやformatをしています。
問題
上記のプロジェクトはmonorepo構成になっており、workspaceによってESLintの設定が違ったり、そもそもESLintがなかったりします。
例えば以下のような場合です。
. ├── packageA │ ├── .eslintrc.js │ └── src/ ├── packageB │ ├── .eslintrc.js │ └── src/ └── packageC └── src/
このようなプロジェクトで例えばpackageA
内のファイルを編集するとします。
packageA
には.eslintrc.js
があるのでnull-lsのESLintが有効になります。
しかし、この状態でpackageC
のファイルを編集しようとするとESLintが有効になったままで、色々と不便です。
これはnull-lsがESLintなどのsourceを有効にするかどうかは最初のsetup関数実行時にのみ判定されます。
解決
これを解決するためにruntime_conditionというものがあります。
これを使うことで新規にファイルを開いたタイミングやファイルを保存したタイミングでnull-lsのsourceを実行するかどうかを決めることができます。
私は以下のように対象ファイルの親ディレクトリ内に設定ファイルがあるかどうかで判定するようにしています。
local b = null_ls.builtins local h = require("null-ls.helpers") local M = {} M.eslint_setting_files = { ".eslintrc", ".eslintrc.js", ".eslintrc.cjs", ".eslintrc.json" } local generate_runtime_condition = function(root_pattern, target_file) return h.cache.by_bufnr(function(params) local root_path = require("lspconfig").util.root_pattern(root_pattern)(params.bufname) if root_path == nil then return false end local condition = false for _, file in pairs(target_file) do condition = condition or vim.fn.findfile(file, root_path .. ";") ~= "" end return condition end) end local apply_eslint = function(setting) return setting.with({ runtime_condition = generate_runtime_condition(M.root_dir, M.eslint_setting_files), }) end local sources = { apply_eslint(b.code_actions.eslint_d), apply_eslint(b.diagnostics.eslint_d), apply_eslint(b.formatting.eslint_d), }
runtime_conditionはかなりの頻度で実行されるものになっているので、なるべくcacheするようにしています。
https://github.com/jose-elias-alvarez/null-ls.nvim/issues/509
さいごに
この記事は IPFactory Advent Calendar 2022 の 10日目の記事です。