{ pkgs, ... }: { plugins.lspconfig.enable = true; lsp = { enable = true; servers = { lua_ls = { enable = true; package = pkgs.lua-language-server; packageFallback = true; }; nil_ls = { enable = true; package = pkgs.nil; packageFallback = true; }; jsonls = { enable = true; package = pkgs.vscode-langservers-extracted; packageFallback = true; }; astro = { enable = true; package = pkgs.astro-language-server; packageFallback = true; }; eslint = { enable = true; package = pkgs.vscode-langservers-extracted; packageFallback = true; config = { root_markers = [ ".eslintrc" ".eslintrc.js" ".eslintrc.cjs" ".eslintrc.yaml" ".eslintrc.yml" ".eslintrc.json" "eslint.config.js" "eslint.config.mjs" "eslint.config.cjs" "eslint.config.ts" "eslint.config.mts" "eslint.config.cts" "package.json" ]; settings = { validate = "on"; useESLintClass = false; experimental = { useFlatConfig = true; }; codeActionOnSave = { enable = false; mode = "all"; }; format = true; quiet = false; onIgnoredFiles = "off"; rulesCustomizations = { }; run = "onType"; problems = { shortenToSingleLine = false; }; nodePath = ""; workingDirectory = { mode = "location"; }; codeAction = { disableRuleComment = { enable = true; location = "separateLine"; }; showDocumentation = { enable = true; }; }; }; handlers = { "eslint/openDoc".__raw = /* lua */ '' function(_, result) if result then vim.ui.open(result.url) end return {} end ''; "eslint/confirmESLintExecution" = /* lua */ '' function(_, result) if not result then return end return 4 -- approved end ''; "eslint/probeFailed" = /* lua */ '' function() vim.notify("[lspconfig] ESLint probe failed.", vim.log.levels.WARN) return {} end ''; "eslint/noLibrary" = /* lua */ '' function() vim.notify("[lspconfig] Unable to find ESLint library.", vim.log.levels.WARN) return {} end ''; }; on_new_config.__raw = /* lua */ '' function(config, new_root_dir) -- This function is called when LSP attaches to a new buffer -- Set the working directory to the root where eslint config is found config.settings = config.settings or {} config.settings.workspaceFolder = { uri = new_root_dir, name = vim.fn.fnamemodify(new_root_dir, ":t"), } -- Detect flat config local flat_config_files = { "eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", "eslint.config.ts", "eslint.config.mts", "eslint.config.cts", } for _, file in ipairs(flat_config_files) do local config_path = new_root_dir .. "/" .. file if vim.uv.fs_stat(config_path) then config.settings.experimental = config.settings.experimental or {} config.settings.experimental.useFlatConfig = true break end end -- Support Yarn PnP local pnp_cjs = new_root_dir .. "/.pnp.cjs" local pnp_js = new_root_dir .. "/.pnp.js" if vim.uv.fs_stat(pnp_cjs) or vim.uv.fs_stat(pnp_js) then config.cmd = vim.list_extend({ "yarn", "exec" }, config.cmd or {}) end end ''; }; }; biome = { enable = true; package = null; packageFallback = false; }; }; keymaps = [ { key = "ca"; lspBufAction = "code_action"; } { key = "e"; action = "lua vim.diagnostic.open_float()"; } ]; }; # Define diagnostic appearance diagnostic.settings = { virtual_text = false; signs = true; underline = true; update_in_insert = false; severity_sort = false; }; }