Using lazy-events.nvim we can create custom events (such as the LazyVim equivalent LazyFile event) based on other events (i.e. a grouping), on globbing files in the current dir, or on arbitrary custom logic. For now, any plugins which require files to be present to work are loaded with the 'LazyFile' event. Any plugins which need to be loaded when opening a directory with vim are loaded with the 'StartWithDir' event (essentially only neo-tree for now). Similarly mini.starter is loaded on the `StartScreen` event. Any plugin which only makes sense to run in a `.git` dir (gitsigns etc) will only run on the `LazyProject:git` event.
229 lines
6.9 KiB
Lua
229 lines
6.9 KiB
Lua
local function get_all_servers()
|
|
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] = vim.tbl_deep_extend("force", servers[name] or {}, conf)
|
|
end
|
|
::continue::
|
|
end
|
|
return servers
|
|
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 = function()
|
|
local to_install = {}
|
|
local not_enabled = {}
|
|
for k, v in pairs(get_all_servers()) do
|
|
table.insert(to_install, k)
|
|
if v["disable"] and v["disable"] == true then
|
|
table.insert(not_enabled, k)
|
|
end
|
|
end
|
|
local tbl = {
|
|
ensure_installed = to_install,
|
|
automatic_enable = { exclude = not_enabled },
|
|
}
|
|
return tbl
|
|
end,
|
|
dependencies = { "williamboman/mason.nvim" },
|
|
cmd = { "LspInstall", "LspUninstall" },
|
|
},
|
|
{ "saghen/blink.cmp", optional = true },
|
|
},
|
|
event = "LazyFile",
|
|
opts = { servers = get_all_servers() },
|
|
init = function()
|
|
if require("core.util").is_available("which-key") then
|
|
require("which-key").add({ "<localleader>l", group = "language" })
|
|
end
|
|
end,
|
|
config = function(_, lspconfig_opts)
|
|
-- 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" })
|
|
|
|
local function register(server_name, config, enabled)
|
|
if vim.fn.has("nvim-0.11") == 1 then
|
|
vim.lsp.config(server_name, config or {})
|
|
if enabled == false or vim.lsp.config[server_name]["autostart"] == false then
|
|
vim.lsp.enable(server_name, false)
|
|
else
|
|
vim.lsp.enable(server_name, true)
|
|
end
|
|
else
|
|
require("lspconfig")[server_name].setup(config)
|
|
end
|
|
end
|
|
|
|
if vim.fn.executable("nu") == 1 then
|
|
register("nushell")
|
|
end
|
|
|
|
-- arduino lsp only works if arduino-cli is installed
|
|
if vim.fn.executable("arduino-cli") == 1 then
|
|
register("arduino_language_server")
|
|
end
|
|
|
|
-- attach ltex for fitting ft only when spell checking becomes enabled
|
|
vim.api.nvim_create_autocmd("User", {
|
|
pattern = "SpellEnable",
|
|
callback = function()
|
|
local mapped = {}
|
|
local lang_map = {
|
|
en_us = "en-US",
|
|
en_gb = "en-GB",
|
|
de_de = "de-DE",
|
|
}
|
|
for _, v in ipairs(vim.opt.spelllang:get()) do
|
|
table.insert(mapped, lang_map[v])
|
|
end
|
|
vim.lsp.config("ltex", {
|
|
settings = { ltex = { language = mapped } },
|
|
})
|
|
-- single-shot setup: Enable for this buffer
|
|
-- but instantly disable again globally
|
|
vim.lsp.enable("ltex")
|
|
vim.lsp.enable("ltex", false)
|
|
end,
|
|
})
|
|
vim.api.nvim_create_autocmd("User", {
|
|
pattern = "SpellDisable",
|
|
callback = function()
|
|
vim.lsp.enable("ltex", false)
|
|
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", "[e", "<cmd>lua vim.diagnostic.goto_prev()<cr>", o({ desc = "Previous diagnostic" }))
|
|
map("n", "]e", "<cmd>lua vim.diagnostic.goto_next()<cr>", o({ desc = "Next diagnostic" }))
|
|
map(
|
|
"n",
|
|
"[E",
|
|
"<cmd>lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})<cr>",
|
|
o({ desc = "Previous error" })
|
|
)
|
|
map(
|
|
"n",
|
|
"]E",
|
|
"<cmd>lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})<cr>",
|
|
o({ desc = "Next error" })
|
|
)
|
|
|
|
map("n", "<localleader>ld", "<cmd>lua vim.diagnostic.open_float()<cr>", o({ desc = "Show line diagnostics" }))
|
|
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>lI", function()
|
|
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled())
|
|
end, o({ desc = "Toggle inlay hints" }))
|
|
map("n", "<localleader>lD", function()
|
|
vim.diagnostic.enable(not vim.diagnostic.is_enabled())
|
|
end, o({ desc = "Toggle Diagnostics" }))
|
|
-- FIXME: Will be re-enabled with insert-mode autocmd above
|
|
map("n", "<localleader>lo", function()
|
|
local c = vim.diagnostic.config() or {}
|
|
vim.diagnostic.config({ virtual_text = not c["virtual_text"] })
|
|
end, o({ desc = "Toggle virtual diag text" }))
|
|
if vim.fn.has("nvim-0.11") == true then -- new feature https://gpanders.com/blog/whats-new-in-neovim-0-11/#virtual-lines
|
|
map("n", "<localleader>lO", function()
|
|
local c = vim.diagnostic.config() or {}
|
|
vim.diagnostic.config({ virtual_lines = not c["virtual_lines"] })
|
|
end, o({ desc = "Toggle virtual diag lines" }))
|
|
end
|
|
|
|
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
|