local lsp = require('lspconfig') local lspstatus = require('lsp-status') local navic = require('nvim-navic') local my_attach = function(client, bufnr) if vim.opt.diff:get() then vim.notify('not running LSP client in diff mode', vim.log.levels.WARN) vim.lsp.stop_client() return end local group = vim.api.nvim_create_augroup('LspOnAttach', {}) vim.api.nvim_create_autocmd('CursorHold', { buffer = bufnr, group = group, callback = function() if not _G.diagnostic_hidden then vim.diagnostic.open_float(nil, { focusable = false, close_events = {'BufLeave', 'CursorMoved', 'InsertEnter', 'FocusLost'}, border = _G.floating_win_border, source = 'always', prefix = ' ', scope = 'cursor', }) end end, }) lspstatus.on_attach(client) if client.supports_method('textDocument/symbols') then navic.attach(client, bufnr) end if client.supports_method('textDocument/definition') then vim.keymap.set('n', '' , vim.lsp.buf.definition) vim.keymap.set('n', 'gd' , vim.lsp.buf.definition) vim.keymap.set('n', 'gR' , vim.lsp.buf.references) wk_register({ ['gd'] = {'goto definition'}, ['gR'] = {'goto references'}, }, { buffer = bufnr }) end if client.supports_method('textDocument/hover') then vim.keymap.set('n', 'K' , vim.lsp.buf.hover) end if client.supports_method('textDocument/rename') then vim.keymap.set('n', 'grr' , vim.lsp.buf.rename) wk_register({ ['grr'] = {'rename'}, }, { buffer = bufnr }) end if client.supports_method('signatureHelp') then vim.keymap.set('n', '' , vim.lsp.buf.signature_help) -- vim.keymap.set('n', ';s ' , vim.lsp.buf.signature_help) end if client.supports_method('textDocument/formatting') then vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr()') vim.keymap.set('n', 'f' , vim.lsp.buf.format) wk_register({ ['f'] = {'format'}, }, { buffer = bufnr }) vim.api.nvim_create_autocmd('BufWritePre', { buffer = bufnr, group = group, callback = function() require('lsp').format(vim.fn.expand(':p')) end, }) end if client.supports_method('textDocument/typeDefinition') then vim.keymap.set('n', 'gT' , vim.lsp.buf.type_definition) wk_register({ ['gT'] = {'goto typedef'}, }, { buffer = bufnr }) end if client.supports_method('textDocument/declaration') then vim.keymap.set('n', 'gD' , vim.lsp.buf.declaration) wk_register({ ['gD'] = {'goto declaration'}, }, { buffer = bufnr }) end if client.supports_method('textDocument/implementation') then vim.keymap.set('n', 'gI' , vim.lsp.buf.implementation) wk_register({ ['gI'] = {'goto implementation'}, }, { buffer = bufnr }) end if client.supports_method('workspace/symbol') then vim.keymap.set('n', 'gW' , vim.lsp.buf.workspace_symbol) wk_register({ ['gW'] = {'goto symbol'}, }, { buffer = bufnr }) end -- if client.resolved_capabilities.document_symbol then -- vim.keymap.set('n', 'g0', vim.lsp.buf.document_symbol) -- end if client.supports_method('textDocument/codeAction') then vim.keymap.set('n', 'ga', vim.lsp.buf.code_action) wk_register({['ga'] = {'code action'}}, {buffer = bufnr}) end end local my_exit = function(_, _, _) end local capabilities = function() local caps = vim.lsp.protocol.make_client_capabilities() -- enable lsp-based snippets caps.textDocument.completion.completionItem.snippetSupport = true caps.textDocument.completion.completionItem.resolveSupport = { properties = { 'documentation', 'detail', 'additionalTextEdits', } } -- add window/workDoneProgress capability caps = vim.tbl_extend('keep', caps or {}, lspstatus.capabilities) return caps end -- vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(vim.lsp.handlers.hover, {border = border}), -- vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(vim.lsp.handlers.signatureHelp, {border = border}), local servers = { ccls = { disabled = true, root_dir = lsp.util.root_pattern('.ccls','meson.build','.git'), init_options = { compilationDatabaseDirectory = "build", index = { threads = 0 }, completion = { filterAndSort = false, }, clang = { excludeArgs = { '-frounding-math' } }, }, }, clangd = { root_dir = lsp.util.root_pattern('.ccls','meson.build','.git'), }, elixirls = { cmd = { 'elixir-ls' }, settings = { elixirLS = { dialyzerEnabled = false, } } }, gopls = { settings = { gopls = { analyses = { -- composites = false, fieldalignment = true, nilness = true, shadow = false, unusedparams = true, unusedwrite = true, }, gofumpt = true, -- hoverKind = 'Structured', } } }, sumneko_lua = { cmd = { 'lua-language-server' }, settings = { Lua = { runtime = { version = 'LuaJIT', path = vim.split(package.path, ';'), }, diagnostics = { globals = { '_G', 'error', 'os', 'package', 'pairs', 'ipairs', 'pcall', 'require', 'string', 'table', 'type', 'vim', }, neededFileStatus = { ['code-style-check'] = 'Any', } }, format = { enable = true, defaultConfig = { indent_style = 'space', indent_size = '2', } }, workspace = { -- library = vim.api.nvim_get_runtime_file("", true), library = { [vim.env.VIMRUNTIME .. '/lua'] = true, [vim.env.VIMRUNTIME .. '/lua/vim/lsp'] = true, } }, telemetry = { enable = false, }, }, }, }, rust_analyzer = { cmd = { 'env', 'CARGO_TARGET_DIR=/tmp', 'RUST_SRC_PATH=/usr/src/rustlib/library', 'rust-analyzer' }, settings = { ['rust-analyzer'] = { checkOnSave = { command = 'clippy' } } }, }, tsserver = { disabled = true, cmd = { 'toolbox', 'run', '--', 'sh', '-c', '. /etc/profile.d/nvm.sh && typescript-language-server --stdio' }, }, zls = { disabled = true, }, zk = { disabled = true, root_dir = lsp.util.root_pattern('.zk'), }, } local setup = function() local caps = capabilities() for server, opts in pairs(servers) do if not opts.disabled then opts = vim.tbl_extend('error', opts, { on_attach = my_attach, on_exit = my_exit, capabilities = caps, }) -- lsp-status custom handlers local ok, lspstatus_ext = pcall(lspstatus.extensions[server]) if ok then opts = vim.tbl_extend('error', opts, { handlers = lspstatus_ext.setup(), }) end lsp[server].setup(opts) end end end local format = function(afile) if vim.g.nofmt then return end if not string.match(afile, '^/home/robert/devel/upstream') then vim.lsp.buf.format() if string.match(afile, '.go$') then vim.lsp.buf.code_action({ only = {'source.organizeImports'} }) end -- vim.notify('%#MoreMsg#󰃢%#Italic# fmt') vim.notify('%#MoreMsg#󰃢%#Italic# fmt') end end return { my_attach = my_attach, my_exit = my_exit, capabilities = capabilities, setup = setup, format = format, symbols = symbols, }