mirror of
https://github.com/neovim/neovim.git
synced 2026-03-29 20:02:03 +00:00
Problem: - Despite [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) claims to be a "data-only" plugin, in fact it still provides some user-facing commands because they haven't been upstreamed to Nvim. Solution: - Upstream `:LspRestart`, `:LspStart` and `:LspStop` commands as `:lsp restart`, `:lsp start` and `:lsp stop` respectively. Co-authored-by: glepnir <glephunter@gmail.com>
143 lines
3.6 KiB
Lua
143 lines
3.6 KiB
Lua
local lsp = vim.lsp
|
|
|
|
local M = {}
|
|
|
|
--- @param filter? vim.lsp.get_clients.Filter
|
|
--- @return string[]
|
|
local function get_client_names(filter)
|
|
return vim
|
|
.iter(lsp.get_clients(filter))
|
|
:map(function(client)
|
|
return client.name
|
|
end)
|
|
:filter(function(name)
|
|
return vim.lsp.config[name] ~= nil
|
|
end)
|
|
:totable()
|
|
end
|
|
|
|
---@return string[]
|
|
local function get_config_names()
|
|
local config_names = vim
|
|
.iter(vim.api.nvim_get_runtime_file('lsp/*.lua', true))
|
|
---@param path string
|
|
:map(function(path)
|
|
local file_name = path:match('[^/]*.lua$')
|
|
return file_name:sub(0, #file_name - 4)
|
|
end)
|
|
:totable()
|
|
|
|
---@diagnostic disable-next-line: invisible
|
|
vim.list_extend(config_names, vim.tbl_keys(vim.lsp.config._configs))
|
|
return vim.list.unique(config_names)
|
|
end
|
|
|
|
local complete_args = {
|
|
start = get_config_names,
|
|
stop = get_client_names,
|
|
restart = get_client_names,
|
|
}
|
|
|
|
local function ex_lsp_start(servers)
|
|
-- Default to enabling all servers matching the filetype of the current buffer.
|
|
-- This assumes that they've been explicitly configured through `vim.lsp.config`,
|
|
-- otherwise they won't be present in the private `vim.lsp.config._configs` table.
|
|
if #servers == 0 then
|
|
local filetype = vim.bo.filetype
|
|
---@diagnostic disable-next-line: invisible
|
|
for name, _ in pairs(vim.lsp.config._configs) do
|
|
local filetypes = vim.lsp.config[name].filetypes
|
|
if filetypes and vim.tbl_contains(filetypes, filetype) then
|
|
table.insert(servers, name)
|
|
end
|
|
end
|
|
end
|
|
|
|
vim.lsp.enable(servers)
|
|
end
|
|
|
|
---@param clients string[]
|
|
local function ex_lsp_stop(clients)
|
|
-- Default to disabling all servers on current buffer
|
|
if #clients == 0 then
|
|
clients = get_client_names { bufnr = vim.api.nvim_get_current_buf() }
|
|
end
|
|
|
|
for _, name in ipairs(clients) do
|
|
if vim.lsp.config[name] == nil then
|
|
vim.notify(("Invalid server name '%s'"):format(name))
|
|
else
|
|
vim.lsp.enable(name, false)
|
|
end
|
|
end
|
|
end
|
|
|
|
---@param clients string[]
|
|
local function ex_lsp_restart(clients)
|
|
-- Default to restarting all active servers
|
|
if #clients == 0 then
|
|
clients = get_client_names()
|
|
end
|
|
|
|
for _, name in ipairs(clients) do
|
|
if vim.lsp.config[name] == nil then
|
|
vim.notify(("Invalid server name '%s'"):format(name))
|
|
else
|
|
vim.lsp.enable(name, false)
|
|
end
|
|
end
|
|
|
|
local timer = assert(vim.uv.new_timer())
|
|
timer:start(500, 0, function()
|
|
for _, name in ipairs(clients) do
|
|
vim.schedule_wrap(function(x)
|
|
vim.lsp.enable(x)
|
|
end)(name)
|
|
end
|
|
end)
|
|
end
|
|
|
|
local actions = {
|
|
start = ex_lsp_start,
|
|
restart = ex_lsp_restart,
|
|
stop = ex_lsp_stop,
|
|
}
|
|
|
|
local available_subcmds = vim.tbl_keys(actions)
|
|
|
|
--- Use for `:lsp {subcmd} {clients}` command
|
|
---@param args string
|
|
M._ex_lsp = function(args)
|
|
local fargs = vim.api.nvim_parse_cmd('lsp ' .. args, {}).args
|
|
if not fargs then
|
|
return
|
|
end
|
|
local subcmd = fargs[1]
|
|
if not vim.list_contains(available_subcmds, subcmd) then
|
|
vim.notify(("Invalid subcommand '%s'"):format(subcmd), vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local clients = { unpack(fargs, 2) }
|
|
|
|
actions[subcmd](clients)
|
|
end
|
|
|
|
--- Completion logic for `:lsp` command
|
|
--- @param line string content of the current command line
|
|
--- @return string[] list of completions
|
|
function M._ex_lsp_complete(line)
|
|
local splited = vim.split(line, '%s+')
|
|
if #splited == 2 then
|
|
return available_subcmds
|
|
else
|
|
local subcmd = splited[2]
|
|
---@param n string
|
|
return vim.tbl_map(function(n)
|
|
return vim.fn.escape(n, [[" |]])
|
|
end, complete_args[subcmd]())
|
|
end
|
|
end
|
|
|
|
return M
|