nix-config/modules/nixvim/lsp.nix
2026-02-06 10:13:06 +01:00

207 lines
6 KiB
Nix

{ 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 = "<leader>ca";
lspBufAction = "code_action";
}
{
key = "<leader>e";
action = "<cmd>lua vim.diagnostic.open_float()<cr>";
}
];
};
# Define diagnostic appearance
diagnostic.settings = {
virtual_text = false;
signs = true;
underline = true;
update_in_insert = false;
severity_sort = false;
};
}