feat(lsp): hot reload of lsp config

This commit is contained in:
2024-04-19 17:22:03 +02:00
parent 15fdc24c15
commit ad7b8848d1
12 changed files with 4970 additions and 478 deletions
+109 -30
View File
@@ -1,36 +1,114 @@
local module_name = "lsp"
local utils = require("utils")
---@class ServerConfig
local CONFIG_DIR = vim.fn.stdpath("config") .. "/lua/lsp/config"
---@class Server
local Server = require("lsp.server")
local M = {}
---@type table<string, ServerConfig>
local servers = {
bashls = {},
clangd = {},
cmake = {},
diagnosticls = {},
gopls = {},
groovyls = {},
intelephense = {},
pylsp = {},
lemminx = {},
lua_ls = {},
rust_analyzer = {},
zls = {},
}
---@type table<string, Server>
local servers = {}
for name, _ in pairs(servers) do
utils.try_require(
"lsp.config." .. name,
module_name,
---@param cfg ServerConfig
function (cfg)
cfg.name = name
servers[name] = Server:new(cfg)
function M.get_servers()
return servers
end
local function get_module_name(filepath)
return filepath:match("([^/\\]+)%.lua$")
end
local function get_server_config(name)
local module = "lsp.config." .. name
package.loaded[module] = nil
return utils.try_require("lsp.config." .. name)
end
local reload_server_config = utils.debounce_with_id(function(name, events)
utils.debug(("Reloading server %s"):format(name))
---@type Server?
local server = servers[name]
if server and server.config.enable then
server:unload()
servers[name] = nil
end
if events.rename then
local _, _, err_name = vim.uv.fs_stat(("%s/%s.lua"):format(CONFIG_DIR, name))
if err_name == "ENOENT" then
return
end
end
local config = get_server_config(name)
if not config then
return
end
server = Server.new(name, config)
if not server or not server.config.enable then
return
end
if #server:get_ft_buffers() ~= 0 then
server:setup()
else
server:register()
end
servers[name] = server
end, 100)
local function process_change(error, filename, events)
utils.debug(("Got event: %s, %s, %s"):format(filename, vim.inspect(events), error))
if error then
utils.err(("Error on change for %s:\n%s"):format(filename, error), "lsp.on_config_change")
return
end
local name = get_module_name(filename)
if not name or name == "init" then
return
end
reload_server_config(name, name, events)
end
local function load_configs()
local handle = vim.uv.fs_scandir(CONFIG_DIR)
while handle do
local filepath = vim.uv.fs_scandir_next(handle)
if not filepath then
break
end
local name = get_module_name(filepath)
if name == "init" then
goto continue
end
local config = get_server_config(name)
if not config then
goto continue
end
local server = Server.new(name, config)
if server then
servers[name] = server
end
::continue::
end
vim.uv.fs_event_start(
vim.uv.new_fs_event(),
CONFIG_DIR,
{},
vim.schedule_wrap(process_change)
)
end
@@ -42,7 +120,7 @@ local function setup_diagnostics()
signs = true,
virtual_text = {
prefix = "",
format = function (diagnostic)
format = function(diagnostic)
return diagnostic.message
end,
},
@@ -51,25 +129,26 @@ local function setup_diagnostics()
source = true,
border = "single",
focusable = false,
format = function (diagnostic)
format = function(diagnostic)
return string.format("%s", diagnostic.message)
end,
},
update_in_insert = false,
severity_sort = false,
})
local signs = { Error = "󰅚 ", Warn = "󰀪 ", Hint = "󰌶 ", Info = "", }
local signs = { Error = "󰅚 ", Warn = "󰀪 ", Hint = "󰌶 ", Info = "" }
for type, icon in pairs(signs) do
local hl = "DiagnosticSign" .. type
vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl, })
vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
end
end
function M.setup()
load_configs()
setup_diagnostics()
for _, server in pairs(servers) do
if server.enable then
if server.config.enable then
server:register()
end
end