{ 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; }; ts_ls = { enable = true; package = pkgs.typescript-language-server; 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" ]; settings = { validate = "on"; useESLintClass = false; experimental = { useFlatConfig = false; }; codeActionOnSave = { enable = false; mode = "all"; }; format = true; quiet = false; onIgnoredFiles = "off"; rulesCustomizations = { }; run = "onType"; problems = { shortenToSingleLine = false; }; nodePath = ""; workingDirectory = { mode = "auto"; }; 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 ''; }; before_init.__raw = /* lua */ '' function(_, config) local eslint_config_files = { ".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", } -- The "workspaceFolder" is a VSCode concept. It limits how far the -- server will traverse the file system when locating the ESLint config -- file (e.g., .eslintrc). local root_dir = config.root_dir if root_dir then config.settings = config.settings or {} config.settings.workspaceFolder = { uri = root_dir, name = vim.fn.fnamemodify(root_dir, ":t"), } -- Support flat config files -- They contain 'config' in the file name local flat_config_files = vim.tbl_filter(function(file) return file:match("config") end, eslint_config_files) for _, file in ipairs(flat_config_files) do local found_files = vim.fn.globpath(root_dir, file, true, true) -- Filter out files inside node_modules local filtered_files = {} for _, found_file in ipairs(found_files) do if string.find(found_file, "[/\\]node_modules[/\\]") == nil then table.insert(filtered_files, found_file) end end if #filtered_files > 0 then config.settings.experimental = config.settings.experimental or {} config.settings.experimental.useFlatConfig = true break end end -- Support Yarn2 (PnP) projects local pnp_cjs = root_dir .. "/.pnp.cjs" local pnp_js = root_dir .. "/.pnp.js" if vim.uv.fs_stat(pnp_cjs) or vim.uv.fs_stat(pnp_js) then local cmd = config.cmd config.cmd = vim.list_extend({ "yarn", "exec" }, cmd) end end end ''; }; }; biome = { enable = true; package = pkgs.biome; packageFallback = true; }; }; 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; }; }