1
0
Fork 0
chezmoi/dot_config/nvim/lua/configs/packages/lsp.lua
2024-08-08 21:23:25 +02:00

405 lines
15 KiB
Lua

local server_configs = function()
return {
ansiblels = {},
powershell_es = {},
gopls = {},
templ = {},
clangd = {},
zls = {},
-- hls = {},
tsserver = {},
-- perlls = {},
cssls = {},
html = {},
lemminx = {
--{{{
settings = {
xml = {
format = {
enabled = true,
splitAttributes = true,
formatComments = true,
joinCDATALines = false,
joinCommentLines = false,
joinContentLines = false,
spaceBeforeEmptyCloseTag = true,
},
},
},
}, -- }}}
nixd = {},
omnisharp = {
-- {{{
handlers = {
['textDocument/definition'] = require('omnisharp_extended').handler,
},
settings = {
FormattingOptions = {
EnableEditorConfigSupport = true,
OrganizeImportsOnFormat = true
},
RoslynExtensionsOptions = {
EnableAnalyzersSupport = true,
EnableImportCompletion = true,
AnalyzeOpenDocumentsOnly = true,
},
},
cmd = { 'omnisharp', 'RoslynExtensionsOptions:EnableDecompilationSupport=true' },
}, -- }}}
lua_ls = {
-- {{{
settings = {
Lua = {
workspace = { checkThirdParty = false, },
telemetry = { enable = false },
completion = { callSnippet = 'Replace', },
},
},
}, -- }}}
phpactor = {
-- {{{
cmd = { vim.env.HOME .. '/devel/phpactor/bin/phpactor', 'language-server' },
root_dir = function(startpath)
local u = require('lspconfig.util')
return u.search_ancestors(startpath, function(path)
return not string.find(path, '/vendor/') and (
u.path.exists(u.path.join(path, 'composer.json'))
or u.path.exists(u.path.join(path, 'sharedLibs'))
or u.path.exists(u.path.join(path, '.git'))
)
end)
end,
}, -- }}}
yamlls = require('yaml-companion').setup {
-- {{{
settings = {
yaml = {
completion = { enable = true },
keyOrdering = false,
schemas = require('schemastore').yaml.schemas(),
},
},
}, -- }}}
jsonls = {
-- {{{
settings = {
validate = { enable = true },
json = {
schemas = require('schemastore').json.schemas {
replace = {
['openapi.json'] = {
description = 'A JSON schema for Open API documentation files',
fileMatch = { 'openapi.json', 'openapi.yml', 'openapi.yaml', 'openapi/*.json' },
name = 'openapi.json',
url = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json',
versions = {
['3.1'] = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.1/schema.json',
['3.0'] = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.json',
},
},
},
},
},
},
}, -- }}}
jsonnet_ls = {},
regal = {},
}
end
local function formatting_filter(c)
local bl = {
'phpactor',
}
for _, name in ipairs(bl) do
if c.name == name then
return false;
end
end
return true
end
local function navic_attach(client, bufnr)
require('nvim-navic').attach(client, bufnr)
vim.wo.winbar = "%{%v:lua.require'nvim-navic'.get_location()%}"
vim.api.nvim_create_autocmd('LspDetach', {
pattern = vim.api.nvim_buf_get_name(bufnr),
once = true,
callback = function()
vim.cmd.setlocal('winbar<')
end,
})
end
local function update_attached(bufnr)
local attached = '';
for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do
attached = attached .. ',' .. client.name
end
vim.b[bufnr].attached_lsps = attached
end
local function on_attach(args) -- {{{
local bufnr = args.buf
local client = vim.lsp.get_client_by_id(args.data.client_id)
if client == nil then
return
end
-- if (client.server_capabilities.documentSymbolProvider) then
-- navic_attach(client, bufnr)
-- end
-- Mappings.
local function mkOpts(desc)
return { noremap = true, silent = true, buffer = args.buf, desc = desc }
end
if client.name == 'yamlls' then
vim.keymap.set('n', '<Leader>os', function()
require('yaml-companion').open_ui_select()
end, mkOpts('Select yaml schema'))
end
-- null-ls has mostly no hover and therefore trashes manpages for shell
if client.supports_method('textDocument/hover') and client.name ~= 'null-ls' then
vim.keymap.set('n', 'K', vim.lsp.buf.hover, mkOpts('LSP hover'))
end
if client.server_capabilities.signatureHelpProvider then
require('lsp-overloads').setup(client, {
-- UI options are mostly the same as those passed to vim.lsp.util.open_floating_preview
ui = {
border = 'none', -- The border to use for the signature popup window. Accepts same border values as |nvim_open_win()|.
height = nil, -- Height of the signature popup window (nil allows dynamic sizing based on content of the help)
width = nil, -- Width of the signature popup window (nil allows dynamic sizing based on content of the help)
wrap = true, -- Wrap long lines
wrap_at = nil, -- Character to wrap at for computing height when wrap enabled
max_width = nil, -- Maximum signature popup width
max_height = nil, -- Maximum signature popup height
-- Events that will close the signature popup window: use {"CursorMoved", "CursorMovedI", "InsertCharPre"} to hide the window when typing
close_events = { 'CursorMoved', 'BufHidden', 'InsertLeave' },
focusable = true, -- Make the popup float focusable
focus = false, -- If focusable is also true, and this is set to true, navigating through overloads will focus into the popup window (probably not what you want)
offset_x = 0, -- Horizontal offset of the floating window relative to the cursor position
offset_y = 0, -- Vertical offset of the floating window relative to the cursor position
floating_window_above_cur_line = false, -- Attempt to float the popup above the cursor position
-- (note, if the height of the float would be greater than the space left above the cursor, it will default
-- to placing the float below the cursor. The max_height option allows for finer tuning of this)
},
display_automatically = true,
silent = true,
keymaps = {
next_signature = '<M-j>',
previous_signature = '<M-k>',
next_parameter = '<M-l>',
previous_parameter = '<M-h>',
close_signature = '<M-y>',
},
})
vim.keymap.set('n', '<A-k>', '<Cmd>LspOverloadsSignature<CR>', mkOpts('LSP signature help'))
vim.keymap.set('i', '<A-k>', '<Cmd>LspOverloadsSignature<CR>', mkOpts('LSP signature help'))
end
if client.server_capabilities.codeLensProvider then
vim.api.nvim_create_autocmd(
{ 'BufEnter', 'CursorHold', 'InsertLeave' }, {
callback = vim.lsp.codelens.refresh,
buffer = bufnr,
})
end
vim.keymap.set('n', '<leader>cl', vim.lsp.codelens.run, mkOpts('LSP Run code lens'))
vim.keymap.set('n', '<leader>ci', vim.lsp.buf.implementation, mkOpts('LSP implementation'))
vim.keymap.set('n', '<leader>cd', vim.lsp.buf.type_definition, mkOpts('LSP type definition'))
vim.keymap.set('n', '<leader>cD', vim.lsp.buf.declaration, mkOpts('LSP declaration'))
vim.keymap.set('n', '<leader>cR', vim.lsp.buf.rename, mkOpts('LSP rename'))
vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, mkOpts('LSP Code action'))
vim.keymap.set('v', '<leader>ca', vim.lsp.buf.code_action, mkOpts('LSP Code action'))
vim.keymap.set('n', '<leader>cci', vim.lsp.buf.incoming_calls, mkOpts('LSP incoming calls'))
vim.keymap.set('n', '<leader>cco', vim.lsp.buf.outgoing_calls, mkOpts('LSP outgoing calls'))
-- vim.keymap.set('n', 'gr', vim.lsp.buf.references, mkOpts('LSP references'))
vim.keymap.set('n', '<leader>cr', '<Cmd>Trouble lsp_references<CR>', mkOpts('LSP references'))
vim.keymap.set('n', '<leader>cs', '<Cmd>Telescope lsp_document_symbols<CR>', mkOpts('LSP document symbols'))
-- fix omnisharp {{{
if client.name == 'omnisharp' then
client.server_capabilities.semanticTokensProvider.legend = {
tokenModifiers = { 'static' },
tokenTypes = {
'comment', -- "comment",
'comment', -- "excluded_code",
'identifier', -- "identifier",
'keyword', -- "keyword",
'keyword', -- "keyword_control",
'number', -- "number",
'operator', -- "operator",
'operator', -- "operator_overloaded",
'preproc', -- "preprocessor_keyword",
'string', -- "string",
'whitespace', -- "whitespace",
'text', -- "text",
'static', -- "static_symbol",
'preproc', -- "preprocessor_text",
'punctuation', -- "punctuation",
'string.escape', -- "string_verbatim",
'character.special', -- "string_escape_character",
'class', -- "class_name",
'type', -- "delegate_name",
'enum', -- "enum_name",
'interface', -- "interface_name",
'namespace', -- "module_name",
'struct', -- "struct_name",
'typeParameter', -- "type_parameter_name",
'field', -- "field_name",
'enumMember', -- "enum_member_name",
'constant', -- "constant_name",
'variable', -- "local_name",
'parameter', -- "parameter_name",
'method', -- "method_name",
'method', -- "extension_method_name",
'property', -- "property_name",
'event', -- "event_name",
'namespace', -- "namespace_name",
'label', -- "label_name",
'text.literal', -- "xml_doc_comment_attribute_name",
'text.literal', -- "xml_doc_comment_attribute_quotes",
'text.literal', -- "xml_doc_comment_attribute_value",
'text.literal', -- "xml_doc_comment_cdata_section",
'text.literal', -- "xml_doc_comment_comment",
'text.literal', -- "xml_doc_comment_delimiter",
'text.literal', -- "xml_doc_comment_entity_reference",
'text.literal', -- "xml_doc_comment_name",
'text.literal', -- "xml_doc_comment_processing_instruction",
'text.literal', -- "xml_doc_comment_text",
'text.literal', -- "xml_literal_attribute_name",
'text.literal', -- "xml_literal_attribute_quotes",
'text.literal', -- "xml_literal_attribute_value",
'text.literal', -- "xml_literal_cdata_section",
'text.literal', -- "xml_literal_comment",
'text.literal', -- "xml_literal_delimiter",
'text.literal', -- "xml_literal_embedded_expression",
'text.literal', -- "xml_literal_entity_reference",
'text.literal', -- "xml_literal_name",
'text.literal', -- "xml_literal_processing_instruction",
'text.literal', -- "xml_literal_text",
'regexp', -- "regex_comment",
'regexp', -- "regex_character_class",
'regexp', -- "regex_anchor",
'regexp', -- "regex_quantifier",
'regexp', -- "regex_grouping",
'regexp', -- "regex_alternation",
'regexp', -- "regex_text",
'regexp', -- "regex_self_escaped_character",
'regexp', -- "regex_other_escape",
},
}
end
-- }}}
update_attached(bufnr)
end -- }}}
local function make_client_capabilities()
local caps = require('cmp_nvim_lsp').default_capabilities()
local def = vim.lsp.protocol.make_client_capabilities()
caps = vim.tbl_deep_extend('keep', caps, def)
-- caps.workspace.didChangeWatchedFiles.dynamicRegistration = false
return caps
end
local function config()
vim.api.nvim_create_autocmd('LspAttach', {
callback = on_attach,
})
vim.api.nvim_create_autocmd('LspDetach', {
callback = function(ev)
-- vim.print(ev)
update_attached(ev.buf)
end,
})
local capabilities = make_client_capabilities()
local nvim_lsp = require('lspconfig')
nvim_lsp.util.default_config = vim.tbl_extend('force',
nvim_lsp.util.default_config,
{
capabilities = capabilities,
}
)
local servers = server_configs();
for name, conf in pairs(servers) do
nvim_lsp[name].setup(conf)
end
end
local function config_mason_lsp()
local mlsp = require('mason-lspconfig')
local servers = server_configs()
local available = mlsp.get_available_servers()
local ensure = {}
for name, _ in pairs(servers) do
if vim.tbl_contains(available, name) and name ~= 'phpactor' and name ~= 'nixd' then
ensure[#ensure + 1] = name
end
end
mlsp.setup({ ensure_installed = ensure })
end
return {
{
'neovim/nvim-lspconfig',
event = 'BufRead',
config = config,
cmd = { 'LspInfo', 'LspLog', 'LspStart' },
dependencies = {
{ 'folke/neodev.nvim', config = true },
{ 'j-hui/fidget.nvim', config = true, tag = 'legacy' },
{
'ray-x/lsp_signature.nvim',
opts = {
hint_prefix = '',
floating_window = false,
hint_scheme = 'Identifier',
},
},
{
'williamboman/mason-lspconfig.nvim',
lazy = true,
dependencies = { 'williamboman/mason.nvim' },
config = config_mason_lsp,
},
{
'simrat39/rust-tools.nvim',
dependencies = { 'williamboman/mason.nvim' },
build = ':MasonInstall rust-analyzer',
config = true,
},
},
keys = {
{ '<leader>li', '<Cmd>LspInfo<CR>', desc = 'Lsp info' },
{ '<leader>ll', '<Cmd>LspLog<CR>', desc = 'Lsp log' },
},
},
{ 'SmiteshP/nvim-navic', lazy = true },
{ 'Hoffs/omnisharp-extended-lsp.nvim', lazy = true },
{ 'b0o/schemastore.nvim', lazy = true },
{ 'Issafalcon/lsp-overloads.nvim', lazy = true },
{
'vlada-dudr/yaml-companion.nvim',
lazy = true,
dependencies = {
{ 'neovim/nvim-lspconfig' },
{ 'nvim-lua/plenary.nvim' },
},
},
}