Skip to content

Instantly share code, notes, and snippets.

@mracos
Created July 20, 2022 13:42
Show Gist options
  • Save mracos/924df0a6cb5a64d06dd856496af44fa0 to your computer and use it in GitHub Desktop.
Save mracos/924df0a6cb5a64d06dd856496af44fa0 to your computer and use it in GitHub Desktop.
neovim lspconfig and lsp-installer
-- assuming require("packer").startup({ function(use)
{ "williamboman/nvim-lsp-installer", -- all lsp
requires = { -- everything that needs to be attached manually
{ "neovim/nvim-lspconfig" },
{ "lukas-reineke/lsp-format.nvim", config = function() require("lsp-format").setup() end, },
},
config = function()
local m_lsp = require("m.lsp")
local lsp_format = require("lsp-format")
local m_nvim_lsp_installer = require("m.nvim_lsp_installer")
local nvim_lsp_installer_servers = require("nvim-lsp-installer.servers")
local lspconfig = require("lspconfig")
require("nvim-lsp-installer").setup({})
vim.diagnostic.config({ virtual_text = false, float = { border = "rounded", }, })
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require("cmp_nvim_lsp").update_capabilities(capabilities)
capabilities.textDocument.completion.completionItem.snippetSupport = true
local default_opts = {
capabilities = capabilities,
on_attach = function(client, bufnr)
m_lsp.on_attach_mappings(client, bufnr)
lsp_format.on_attach(client)
end,
handlers = {
["textDocument/hover"] = vim.lsp.with(
m_lsp.normal_highlight_window_handler(vim.lsp.handlers["textDocument/hover"]),
{ border = "rounded", }
),
["textDocument/signatureHelp"] = vim.lsp.with(
m_lsp.normal_highlight_window_handler(vim.lsp.handlers["textDocument/signatureHelp"]),
{ border = "rounded", }
),
},
}
local server_opts = {
elixirls = {
filetypes = { "elixir", "heex", "eelixir" },
on_attach = function(client, bufnr)
default_opts.on_attach(client, bufnr)
require("elixir").on_attach(client, bufnr)
end,
},
}
-- need to compile with same version as elixir language used
-- TODO: until https://github.com/elixir-lsp/elixir-ls/issues/193 is fixed
m_nvim_lsp_installer.use_elixir_ls_fork("https://github.com/elixir-lsp/elixir-ls")
local installed_servers = nvim_lsp_installer_servers.get_installed_servers()
local active_clients = m_lsp.active_clients()
for i = 1, #installed_servers do
local installed_server = installed_servers[i]
local opts = vim.tbl_deep_extend("force", default_opts, server_opts[installed_server.name] or {})
if vim.tbl_contains(vim.tbl_keys(active_clients), installed_server.name) then
vim.lsp.stop_client(active_clients[installed_server.name], false)
end
lspconfig[installed_server.name].setup(opts)
end
Map.add("n", "<leader>xls", { ":lua print(vim.lsp.buf.server_ready())<CR>", "status" })
Map.add("n", "<leader>xli", { ":LspInfo<CR>", "info" })
Map.add("n", "<leader>xlS", { "<cmd>LspStart<cr>", "start" })
Map.add("n", "<leader>xlx", { ":LspStop<CR>", "stop" })
Map.add("n", "<leader>xll", { function() vim.cmd("split " .. vim.lsp.get_log_path()) end, "open log split" })
Map.add("n", "<leader>xlI", { "<cmd>LspInstallInfo<cr>", "lsp install info" })
end
},
-- lua/m/lsp.lua
return {
---@diagnostic disable-next-line: unused-local
on_attach_mappings = function(_client, _bufnr)
Map.add("n", "<leader>c.", { vim.lsp.buf.code_action, "code actions" })
Map.add("n", "<leader>cc", { vim.lsp.buf.incoming_calls, "incoming calls" })
Map.add("n", "<leader>cC", { vim.lsp.buf.outgoing_calls, "outgoing calls" })
Map.add("n", "<leader>c?", {
require("m.vim.diagnostic").normal_highlight_open_float,
"show full line diagnostic"
})
Map.add("n", "<leader>cs", { "<CMD>Telescope lsp_document_symbols<CR>", "document symbols" })
Map.add("n", "<leader>cS", { "<CMD>Telescope lsp_dynamic_workspace_symbols<CR>", "workspace symbols" })
-- TODO: use telescope lsp when it uses the default handlers
-- defined by vim or when it supports something like hooks
-- https://github.com/nvim-telescope/telescope.nvim/blob/b5c63c6329cff8dd8e23047eecd1f581379f1587/lua/telescope/builtin/lsp.lua#L28-L28
Map.add("n", "<leader>cg", { vim.lsp.buf.definition, "definition" })
Map.add("n", "<leader>ci", { vim.lsp.buf.implementation, "implementation" })
Map.add("n", "<leader>cr", { "<cmd>Telescope lsp_references<CR>", "references" })
Map.add("n", "<leader>ct", { vim.lsp.buf.type_definition, "type definition" })
Map.add("n", "<leader>ch", { vim.lsp.buf.hover, "show hover" })
Map.add("n", "<leader>cH", { vim.lsp.buf.signature_help, "show signature help" })
Map.add("i", "<C-h>", { vim.lsp.buf.signature_help, "show signature help" })
Map.add("n", "<leader>cn", { vim.diagnostic.get_next, "next diagnostic" })
Map.add("n", "<leader>cp", { vim.diagnostic.get_prev, "prev diagnostic" })
Map.group("n", "<leader>ce", "+edit")
Map.add("n", "<leader>cer", { vim.lsp.buf.rename, "rename (lsp)" })
Map.add("n", "<leader>cef", { vim.lsp.buf.formatting_sync, "format (lsp)" })
Map.add("v", "<leader>cef", { vim.lsp.buf.range_formatting, "format (lsp)" })
end,
-- @return {client_name = client_id}
-- @treturn table {string = integer}
active_clients = function()
local active_clients = {}
---@diagnostic disable-next-line: unused-local
for _key, client in pairs(vim.lsp.get_active_clients()) do
active_clients[client.name] = client.id
end
return active_clients
end,
}
-- lua/m/nvim_lsp_installer_servers.lua
return {
use_elixir_ls_fork = function(fork_repo)
local is_elixirls_available, elixirls_server = servers.get_server("elixirls")
if is_elixirls_available then
nvim_lsp_installer.register(
server.Server:new({
name = elixirls_server.name,
root_dir = elixirls_server.root_dir,
homepage = fork_repo,
languages = elixirls_server.languages,
async = true,
installer = function(ctx)
git.clone({ fork_repo })
ctx.spawn.mix({ "deps.get", "--force" })
ctx.spawn.mix({ "compile" })
ctx.spawn.mix({ "elixir_ls.release", "-o", "elixir-ls" })
ctx.spawn.chmod({ "+x", "elixir-ls/language_server.sh" })
end,
default_options = elixirls_server._default_options
})
)
end,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment