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, {buffer = bufnr}) vim.keymap.set('n', 'gd' , vim.lsp.buf.definition, {buffer = bufnr}) vim.keymap.set('n', 'gR' , vim.lsp.buf.references, {buffer = bufnr}) 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, {buffer = bufnr}) end if client.supports_method('textDocument/rename') then vim.keymap.set('n', 'grr' , vim.lsp.buf.rename, {buffer = bufnr}) wk_register({ ['grr'] = {'rename'}, }, {buffer = bufnr}) end if client.supports_method('signatureHelp') then vim.keymap.set('n', '' , vim.lsp.buf.signature_help, {buffer = bufnr}) -- vim.keymap.set('n', ';s ' , vim.lsp.buf.signature_help, {buffer = bufnr}) 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, {buffer = bufnr}) 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, {buffer = bufnr}) wk_register({ ['gT'] = {'goto typedef'}, }, {buffer = bufnr}) end if client.supports_method('textDocument/declaration') then vim.keymap.set('n', 'gD' , vim.lsp.buf.declaration, {buffer = bufnr}) wk_register({ ['gD'] = {'goto declaration'}, }, {buffer = bufnr}) end if client.supports_method('textDocument/implementation') then vim.keymap.set('n', 'gI' , vim.lsp.buf.implementation, {buffer = bufnr}) 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, {buffer = bufnr}) 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, {buffer = bufnr}) -- end if client.supports_method('textDocument/codeAction') then vim.keymap.set('n', 'ga', vim.lsp.buf.code_action, {buffer = bufnr}) 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 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 local symbols = { -- 󰆼 󱆃 Array = '󰨾 ', Boolean = '󰦍 ', Class = '󰙀 ', Color = '󰉦 ', Constant = ' ', Constructor = '󱇿 ', Enum = ' ', EnumMember = ' ', Event = '󱐋 ', -- Field = '󰽜 ', Field = '󰆈 ', File = '󰈔 ', Folder = '󰝰 ', Function = ' ', Interface = '󱦜 ', Key = '󰌋 ', Keyword = '󰓽 ', Method = '󰒓 ', Module = '󰏖 ', Namespace = '󰆧 ', Null = '󰎣 ', Object = '󰘦 ', Operator = '󱓉 ', Property = '󰐱 ', Package = '󰏗 ', Reference = '󰌹 ', Snippet = '󰯁 ', Struct = '󰙅 ', Text = '󰉿 ', TypeParameter = '󰌨 ', Unit = '󰠱 ', Value = '󰎠 ', Variable = '󱄑 ', } return { my_attach = my_attach, my_exit = my_exit, capabilities = capabilities, setup = setup, format = format, symbols = symbols, }