All additional languages features (LSPs, treesitter parsers, linters and formatters) are now defined in a single place in 'core/languages'. This file simply sets up a big table which contains all the enabled programs and parsers, divided by type. They adhere to the structure given by the respective plugin. HACK: We are still cheating a bit currently for treesitter parsers since I have not had the heart to go through all of them to activate/deactivate what I could need. Most of them are simply still loaded, not connected to a specific language. Will have to be sorted out at some point but it is good enough for now.
273 lines
8.5 KiB
Lua
273 lines
8.5 KiB
Lua
local servers = {}
|
|
for _, lang in pairs(Languages) do
|
|
if not lang.lsp then
|
|
goto continue
|
|
end
|
|
for name, conf in pairs(lang.lsp) do
|
|
servers[name] = conf
|
|
end
|
|
::continue::
|
|
end
|
|
|
|
local lsp = {
|
|
{ -- pretty lsp 'peek' menus
|
|
"DNLHC/glance.nvim",
|
|
opts = { border = { enable = true }, theme = { enable = true, mode = "auto" } },
|
|
cmd = { "Glance" },
|
|
},
|
|
{
|
|
"neovim/nvim-lspconfig",
|
|
dependencies = {
|
|
{
|
|
"williamboman/mason-lspconfig.nvim",
|
|
opts = { automatic_installation = true },
|
|
dependencies = { "williamboman/mason.nvim" },
|
|
cmd = { "LspInstall", "LspUninstall" },
|
|
},
|
|
{ "saghen/blink.cmp", optional = true },
|
|
},
|
|
event = { "BufReadPost", "BufNewFile", "BufWritePre" },
|
|
opts = { servers = servers },
|
|
config = function(_, lspconfig_opts)
|
|
local lspconfig = require("lspconfig")
|
|
|
|
-- Display diagnostics as virtual text only if not in insert mode
|
|
-- /r/neovim/comments/12inp4c/disable_diagnostics_virtual_text_when_in_insert/jqqifwk/
|
|
vim.diagnostic.config({ virtual_text = true })
|
|
vim.api.nvim_create_autocmd("InsertEnter", {
|
|
callback = function()
|
|
vim.diagnostic.config({ virtual_text = false })
|
|
end,
|
|
})
|
|
vim.api.nvim_create_autocmd("InsertLeave", {
|
|
callback = function()
|
|
vim.diagnostic.config({ virtual_text = true })
|
|
end,
|
|
})
|
|
|
|
vim.fn.sign_define("DiagnosticSignError", { text = "✘", texthl = "DiagnosticSignError" })
|
|
vim.fn.sign_define("DiagnosticSignWarn", { text = "", texthl = "DiagnosticSignWarn" })
|
|
vim.fn.sign_define("DiagnosticSignInfo", { text = "", texthl = "DiagnosticSignInfo" })
|
|
vim.fn.sign_define("DiagnosticSignHint", { text = "", texthl = "DiagnosticSignHint" })
|
|
|
|
for server, config in pairs(lspconfig_opts.servers) do
|
|
-- TODO: Check if it actually can be ignored in Nvim 0.11+, see https://cmp.saghen.dev/installation.html#lazy-nvim
|
|
if vim.fn.has("nvim-0.11") == false then
|
|
config.capabilities = require("blink.cmp").get_lsp_capabilities(config.capabilities)
|
|
end
|
|
lspconfig[server].setup(config)
|
|
end
|
|
|
|
lspconfig.nushell.setup({})
|
|
|
|
lspconfig.marksman.setup({
|
|
filetypes = { "markdown", "quarto" },
|
|
on_attach = function(client, _)
|
|
-- TODO: for some reason this stays true even after rootdir switch?
|
|
if client.config.in_zk_notebook then
|
|
local default_handler = vim.diagnostic.handlers.virtual_text
|
|
vim.diagnostic.handlers.virtual_text = {
|
|
show = function(namespace, bufnrr, diagnostics, opts)
|
|
for i, diagnostic in ipairs(diagnostics) do
|
|
if
|
|
diagnostic.source
|
|
== "Marksman" -- You need to check what the correct value should be here
|
|
then
|
|
table.remove(diagnostics, i)
|
|
end
|
|
end
|
|
default_handler.show(namespace, bufnrr, diagnostics, opts)
|
|
end,
|
|
hide = function(...)
|
|
default_handler.hide(...)
|
|
end,
|
|
}
|
|
default_handler = vim.diagnostic.handlers.signs
|
|
vim.diagnostic.handlers.signs = {
|
|
show = function(namespace, bufnrr, diagnostics, opts)
|
|
for i, diagnostic in ipairs(diagnostics) do
|
|
if
|
|
diagnostic.source
|
|
== "Marksman" -- You need to check what the correct value should be here
|
|
then
|
|
table.remove(diagnostics, i)
|
|
end
|
|
end
|
|
default_handler.show(namespace, bufnrr, diagnostics, opts)
|
|
end,
|
|
hide = function(...)
|
|
default_handler.hide(...)
|
|
end,
|
|
}
|
|
end
|
|
end,
|
|
on_new_config = function(conf, new_root)
|
|
if require("lspconfig.util").root_pattern(".zk")(new_root) then
|
|
conf.in_zk_notebook = true
|
|
else
|
|
conf.in_zk_notebook = false
|
|
end
|
|
end,
|
|
})
|
|
|
|
local python_path
|
|
-- ensure python virtualenv is determined automatically on lsp start
|
|
-- we primarily use pyright for cmp lsp completion & hover info
|
|
lspconfig.basedpyright.setup({
|
|
on_attach = function(client, _)
|
|
require("core.util").set_python_env()
|
|
if python_path == nil then
|
|
python_path, _ = vim.fn.expand(require("core.util").get_python_venv_bin(client.config.root_dir))
|
|
end
|
|
client.config.settings.python = {} or client.config.settings.python
|
|
client.config.settings.python.pythonPath = python_path
|
|
end,
|
|
settings = {
|
|
-- disable imports and linting since, using ruff for it
|
|
pyright = {
|
|
disableOrganizeImports = true,
|
|
},
|
|
python = {
|
|
analysis = {
|
|
-- ignore all files, use ruff for linting
|
|
ignore = { "*" },
|
|
},
|
|
},
|
|
},
|
|
})
|
|
lspconfig.ruff.setup({
|
|
on_attach = function(client, _)
|
|
require("core.util").set_python_env()
|
|
client.server_capabilities.hoverProvider = false -- we use pyright for hover info
|
|
if python_path == nil then
|
|
python_path, _ = vim.fn.expand(require("core.util").get_python_venv_bin(client.config.root_dir))
|
|
end
|
|
client.config.settings.python = {} or client.config.settings.python
|
|
client.config.settings.python.pythonPath = python_path
|
|
end,
|
|
})
|
|
|
|
-- set up arduino with the help of arduino.nvim plugin
|
|
if require("core.util").is_available("arduino") then
|
|
lspconfig.arduino_language_server.setup({
|
|
on_new_config = require("arduino").on_new_config,
|
|
})
|
|
end
|
|
|
|
-- attach ltex for fitting ft only when spell checking becomes enabled
|
|
vim.api.nvim_create_autocmd("User", {
|
|
pattern = "SpellEnable",
|
|
callback = function()
|
|
lspconfig.ltex.setup({
|
|
on_attach = function(_, _)
|
|
if require("core.util").is_available("ltex_extra") then
|
|
require("ltex_extra").setup()
|
|
end
|
|
end,
|
|
settings = {
|
|
ltex = {
|
|
language = vim.opt.spelllang:get(),
|
|
},
|
|
},
|
|
})
|
|
vim.cmd("LspStart ltex")
|
|
end,
|
|
})
|
|
end,
|
|
keys = { { "<leader>vs", ":LspInfo<cr>", desc = "LspInfo" } },
|
|
},
|
|
}
|
|
|
|
vim.api.nvim_create_autocmd("LspAttach", {
|
|
desc = "LSP actions",
|
|
callback = function(event)
|
|
local o = function(add_opts)
|
|
return vim.tbl_extend("force", { buffer = event.buf }, add_opts)
|
|
end
|
|
|
|
local map = vim.keymap.set
|
|
map("n", "K", "<cmd>lua vim.lsp.buf.hover()<cr>", o({ desc = "Hover definition" }))
|
|
map("n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<cr>", o({ desc = "Previous diagnostic" }))
|
|
map("n", "]d", "<cmd>lua vim.diagnostic.goto_next()<cr>", o({ desc = "Next diagnostic" }))
|
|
map(
|
|
"n",
|
|
"[D",
|
|
"<cmd>lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})<cr>",
|
|
o({ desc = "Previous error" })
|
|
)
|
|
map(
|
|
"n",
|
|
"]D",
|
|
"<cmd>lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})<cr>",
|
|
o({ desc = "Next error" })
|
|
)
|
|
|
|
if require("core.util").is_available("which-key") then
|
|
require("which-key").add({ "<localleader>l", group = "language" })
|
|
end
|
|
map("n", "<localleader>ld", "<cmd>lua vim.diagnostic.open_float()<cr>", o({ desc = "Show line diagnostics" }))
|
|
map("n", "<localleader>lI", function()
|
|
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled())
|
|
end, o({ desc = "Toggle inlay hints" }))
|
|
map("n", "<localleader>la", "<cmd>lua vim.lsp.buf.code_action()<cr>", o({ desc = "Codeactions" }))
|
|
map("n", "<localleader>ln", "<cmd>lua vim.lsp.buf.rename()<cr>", o({ desc = "Rename element" }))
|
|
map("n", "<localleader>lc", "<cmd>lua vim.lsp.buf.declaration()<cr>", o({ desc = "Declaration" }))
|
|
map("n", "<localleader>ls", "<cmd>lua vim.lsp.buf.signature_help()<cr>", o({ desc = "Signature help" }))
|
|
map("n", "<localleader>lo", function()
|
|
vim.diagnostic.enable(not vim.diagnostic.is_enabled())
|
|
end, o({ desc = "Toggle Diagnostics" }))
|
|
|
|
local pref = function(glances, telescope, fallback)
|
|
if glances and vim.fn.exists(":Glance") > 0 then
|
|
return glances
|
|
elseif telescope and vim.fn.exists(":Telescope") > 0 then
|
|
return telescope
|
|
else
|
|
return fallback
|
|
end
|
|
end
|
|
|
|
map(
|
|
"n",
|
|
"<localleader>lr",
|
|
pref(
|
|
"<cmd>Glance references<cr>",
|
|
"<cmd>Telescope lsp_references<cr>",
|
|
"<cmd>lua vim.lsp.buf.references()<cr>"
|
|
),
|
|
o({ desc = "References" })
|
|
)
|
|
map(
|
|
"n",
|
|
"<localleader>lf",
|
|
pref(
|
|
"<cmd>Glance definitions<cr>",
|
|
"<cmd>Telescope lsp_definitions<cr>",
|
|
"<cmd>lua vim.lsp.buf.definition()<cr>"
|
|
),
|
|
o({ desc = "Definition" })
|
|
)
|
|
map(
|
|
"n",
|
|
"<localleader>lt",
|
|
pref(
|
|
"<cmd>Glance type_definitions<cr>",
|
|
"<cmd>Telescope lsp_type_definitions<cr>",
|
|
"<cmd>lua vim.lsp.buf.type_definition()<cr>"
|
|
),
|
|
o({ desc = "Type definition" })
|
|
)
|
|
map(
|
|
"n",
|
|
"<localleader>lm",
|
|
pref(
|
|
"<cmd>Glance implementations<cr>",
|
|
"<cmd>Telescope lsp_implementations<cr>",
|
|
"<cmd>lua vim.lsp.buf.implementation()<cr>"
|
|
),
|
|
o({ desc = "Implementation" })
|
|
)
|
|
end,
|
|
})
|
|
|
|
return lsp
|