This repository has been archived on 2022-08-21. You can view files and clone it, but cannot push or open issues or pull requests.
dotfiles/home/.config/nvim/lua/modules/lsp.lua

491 lines
20 KiB
Lua

local M = {}
function M.lsp_conf()
local lspconf = require('lspconfig')
local on_attach = function(client, bufnr)
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local opts = {noremap = true, silent = true}
buf_set_keymap('n', 'gD', ':lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', ':lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', ':lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', ':lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<leader>lx', ':lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<leader>la', ':lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<leader>lr', ':lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<leader>lw', ':lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<leader>ld', ':lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<leader>ln', ':lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', 'gr', ':lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<leader>le', ':lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', ':lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', ':lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<leader>ll', ':lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
if client.resolved_capabilities.document_formatting then
buf_set_keymap('n', '<leader>lo', ':lua vim.lsp.buf.formatting()<CR>', opts)
-- vim.api.nvim_command('autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()')
elseif client.resolved_capabilities.document_range_formatting then
buf_set_keymap('n', '<leader>lo', ':lua vim.lsp.buf.range_formatting({},{0,0},{vim.fn.line("$"),0})<CR>', opts)
buf_set_keymap('v', '<leader>lo', ':lua vim.lsp.buf.range_formatting()<CR>', opts)
-- vim.api.nvim_command('autocmd BufWritePre <buffer> lua vim.lsp.buf.range_formatting({},{0,0},{vim.fn.line("$"),0})')
end
-- Attach lsp_signature.nvim
require('lsp_signature').on_attach({
bind = true, -- This is mandatory, otherwise border config doesn't work
floating_window = true,
fix_pos = true,
hint_prefix = '',
transpancy = 5,
handler_opts = {border = 'none'},
zindex = 50, -- set to 200 to make the float window on top of others
toggle_key = '<M-x>'
}, bufnr)
end
local capabilities = vim.lsp.protocol.make_client_capabilities()
-- Add additional capabilities supported by nvim-cmp
local completionItem = capabilities.textDocument.completion.completionItem
completionItem.documentationFormat = {'markdown', 'plaintext'}
completionItem.snippetSupport = true
completionItem.preselectSupport = true
completionItem.insertReplaceSupport = true
completionItem.labelDetailsSupport = true
completionItem.deprecatedSupport = true
completionItem.commitCharactersSupport = true
completionItem.tagSupport = {valueSet = {1}}
completionItem.resolveSupport = {
properties = {
'documentation',
'detail',
'additionalTextEdits',
}
}
-- Replace the default lsp diagnostic letters with prettier symbols
vim.fn.sign_define('LspDiagnosticsSignError', {text = ''})
vim.fn.sign_define('LspDiagnosticsSignWarning', {text = ''})
vim.fn.sign_define('LspDiagnosticsSignInformation', {text = ''})
vim.fn.sign_define('LspDiagnosticsSignHint', {text = ''})
---------------------------
-- Server configurations --
---------------------------
-- https://github.com/neovim/nvim-lspconfig/blob/master/CONFIG.md
local servers_path = vim.fn.stdpath('data') .. '/lsp'
-- C/C++
lspconf.clangd.setup {
on_attach = on_attach,
capabilities = capabilities,
filetypes = {'c', 'cpp'},
init_options = {
usePlaceholders = true,
completeUnimported = true,
clangdFileStatus = true
},
cmd = {
'clangd',
'-j=2',
'--background-index',
'--clang-tidy',
'--completion-style=detailed',
'--pch-storage=memory',
'--header-insertion=iwyu',
'--header-insertion=decorators'
}
}
-- Lua
local lua_lib_path = {}
local lua_runtime_path = {}
-- lua_lib_path[vim.fn.expand('~/.luarocks/share/lua/5.3')] = true
-- lua_lib_path[vim.fn.expand('/usr/share/lua/5.3')] = true
lua_lib_path[os.getenv('VIMRUNTIME') .. '/lua'] = true
-- local function add(lib)
-- for _, p in pairs(vim.fn.expand(lib .. '/lua', false, true)) do
-- p = vim.loop.fs_realpath(p)
-- if p then lua_lib_path[p] = true end
-- end
-- end
-- for _, site in pairs(vim.split(vim.opt.packpath:get(), ',')) do
-- add(site .. '/pack/*/opt/*')
-- add(site .. '/pack/*/start/*')
-- end
table.insert(lua_runtime_path, 'lua/?.lua')
table.insert(lua_runtime_path, 'lua/?/init.lua')
-- table.insert(lua_runtime_path, '?.lua')
-- table.insert(lua_runtime_path, '?/?.lua')
-- table.insert(lua_runtime_path, '?/init.lua')
for lib, _ in pairs(lua_lib_path) do
table.insert(lua_runtime_path, lib .. '/?.lua')
table.insert(lua_runtime_path, lib .. '/?/init.lua')
end
lspconf.sumneko_lua.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {
servers_path .. '/sumneko_lua/bin/Linux/lua-language-server',
'-E', '-e', 'LANG=en',
servers_path .. '/sumneko_lua/main.lua'
},
settings = {
Lua = {
diagnostics = {globals = {'vim'}},
runtime = {version = 'LuaJIT', path = lua_runtime_path},
workspace = {
library = lua_lib_path,
maxPreload = 1000,
preloadFileSize = 150
},
completion = {callSnippet = 'Replace'},
hint = {enable = true},
telemetry = {enable = false}
}
}
}
-- Go
lspconf.gopls.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {servers_path .. '/gopls/gopls', '--remote=auto'},
init_options = {
usePlaceholders = true,
completeUnimported = true
}
}
-- Yaml
lspconf.yamlls.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {servers_path .. '/yamlls/node_modules/.bin/yaml-language-server', '--stdio'},
settings = {
redhat = {telemetry = {enabled = false}},
yaml = {
format = {
bracketSpacing = true,
printWidth = 80,
-- proseWrap = 'always', -- default is 'preserve'
-- singleQuote = true,
-- editor.formatOnType = true
}
}
}
}
-- Ansible
lspconf.ansiblels.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {'node', servers_path .. '/ansiblels/out/server/src/server.js', '--stdio'},
filetypes = {'yaml', 'yaml.ansible'},
settings = {
-- python = {interpreterPath = 'python3'},
executionEnvironment = {enabled = false}
}
}
-- Tailwind
-- lspconf.tailwindcss.setup {
-- on_attach = on_attach,
-- capabilities = capabilities,
-- cmd = {servers_path .. '/tailwindcss/node_modules/.bin/tailwindcss-language-server', '--stdio'},
-- settings = {
-- tailwindCSS = {
-- emmetCompletions = true
-- }
-- }
-- }
-- Emmet
lspconf.emmet_ls.setup {
cmd = {servers_path .. '/emmet_ls/node_modules/.bin/emmet-ls', '--stdio'},
filetypes = {
'html', 'xml', 'css', 'scss', 'sass',
'javascript', 'javascriptreact'
},
capabilities = capabilities
}
-- HTML
lspconf.html.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {servers_path .. '/vscode/node_modules/.bin/vscode-html-language-server', '--stdio'},
filetypes = {'html', 'markdown'}
}
-- JSON
lspconf.jsonls.setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = {servers_path .. '/vscode/node_modules/.bin/vscode-json-language-server', '--stdio'},
settings = {
json = {
-- Schema catalog: https://www.schemastore.org/api/json/catalog.json
schemas = {
{
fileMatch = {'package.json'},
url = 'https://json.schemastore.org/package.json'
}, {
fileMatch = {'tsconfig*.json'},
url = 'https://json.schemastore.org/tsconfig.json'
}, {
fileMatch = {
'.prettierrc', '.prettierrc.json',
'prettier.config.json'
},
url = 'https://json.schemastore.org/prettierrc.json'
}, {
fileMatch = {'.eslintrc', '.eslintrc.json'},
url = 'https://json.schemastore.org/eslintrc.json'
}, {
fileMatch = {
'.babelrc', '.babelrc.json', 'babel.config.json'
},
url = 'https://json.schemastore.org/babelrc.json'
},
{
fileMatch = {'lerna.json'},
url = 'https://json.schemastore.org/lerna.json'
}, {
fileMatch = {'now.json', 'vercel.json'},
url = 'https://json.schemastore.org/now.json'
}, {
fileMatch = {
'.stylelintrc', '.stylelintrc.json',
'stylelint.config.json'
},
url = 'http://json.schemastore.org/stylelintrc.json'
}
}
}
}
}
-- Others
local servers = {
rust_analyzer = {'rust-analyzer'},
sqls = {servers_path .. '/sqls/sqls'},
cmake = {servers_path .. '/cmake/venv/bin/cmake-language-server'},
bashls = {servers_path .. '/bashls/node_modules/.bin/bash-language-server', 'start'},
dockerls = {servers_path .. '/dockerls/node_modules/.bin/docker-langserver', '--stdio'},
cssls = {servers_path .. '/vscode/node_modules/.bin/vscode-css-language-server', '--stdio'},
pyright = {servers_path .. '/pyright/node_modules/.bin/pyright-langserver', '--stdio'},
-- vimls = {servers_path .. '/vimls/node_modules/.bin/vim-language-server', '--stdio'},
tsserver = {servers_path .. '/tsserver/node_modules/.bin/typescript-language-server', '--stdio'}
}
for server, _ in pairs(servers) do
lspconf[server].setup {
on_attach = on_attach,
capabilities = capabilities,
cmd = servers[server]
}
end
------------------------
-- Linters/Formatters --
------------------------
-- TODO: efm-langserver as another option
local null_ls = require('null-ls')
-- Register sources
null_ls.config {
sources = {
-- Formatters
null_ls.builtins.formatting.stylua.with {
condition = function(utils)
return utils.root_has_file('stylua.toml')
end
},
null_ls.builtins.formatting.clang_format.with {
filetypes = {'c', 'cpp'}
}
-- Linters
}
}
lspconf['null-ls'].setup {
on_attach = on_attach
}
end
function M.sqls_conf()
require('sqls').setup {
picker = 'telescope'
}
end
function M.lightbulb_conf()
vim.api.nvim_command [[
autocmd CursorHold * lua require('nvim-lightbulb').update_lightbulb({sign = {enabled = false}, status_text = {enabled = true, text = ' Code action', text_unavailable = ''}})
]]
end
function M.trouble_conf()
require('trouble').setup {
mode = 'lsp_workspace_diagnostics',
fold_open = '',
fold_closed = '',
action_keys = {
open_split = {'<c-h>'},
open_vsplit = {'<c-v>'},
open_tab = {'<c-t>'}
},
signs = {
error = '',
warning = '',
information = '',
hint = '',
other = ''
}
}
end
-- function M.comments_conf()
-- require('todo-comments').setup {
-- signs = false,
-- -- sign_priority = 8,
-- keywords = {
-- FIX = {
-- icon = ' ', -- icon used for the sign, and in search results
-- color = 'error', -- can be a hex color, or a named color (see below)
-- alt = {'FIXME', 'BUG', 'FIXIT', 'ISSUE'}, -- a set of other keywords that all map to this FIX keywords
-- -- signs = false, -- configure signs for some keywords individually
-- },
-- TODO = {icon = ' ', color = 'info'},
-- HACK = {icon = ' ', color = 'warning'},
-- WARN = {icon = ' ', color = 'warning', alt = {'WARNING', 'XXX'}},
-- PERF = {icon = ' ', alt = {'OPTIM', 'PERFORMANCE', 'OPTIMIZE'}},
-- NOTE = {icon = ' ', color = 'hint', alt = {'INFO'}},
-- },
-- merge_keywords = true,
-- highlight = {
-- before = '', -- 'fg' or 'bg' or empty
-- keyword = 'fg', -- 'fg', 'bg', 'wide' or empty. (wide is the same as bg, but will also highlight surrounding characters)
-- after = '', -- 'fg' or 'bg' or empty
-- pattern = [[.*<(KEYWORDS)\s*:]], -- pattern or table of patterns, used for highlightng (vim regex)
-- comments_only = true, -- uses treesitter to match keywords in comments only
-- max_line_len = 400, -- ignore lines longer than this
-- exclude = {'org'}, -- list of file types to exclude highlighting
-- },
-- colors = {
-- error = {'LspDiagnosticsDefaultError', 'TSDanger', 'Red'},
-- warning = {'LspDiagnosticsDefaultWarning', 'TSWarning', 'Yellow'},
-- info = {'LspDiagnosticsDefaultInformation', 'TSNote', 'Blue'},
-- hint = {'LspDiagnosticsDefaultHint', 'Cyan'},
-- default = {'Normal', 'White'}
-- },
-- search = {
-- command = 'rg',
-- args = {
-- '--hidden',
-- '--color=never',
-- '--no-heading',
-- '--with-filename',
-- '--line-number',
-- '--column',
-- },
-- -- regex that will be used to match keywords.
-- -- don't replace the (KEYWORDS) placeholder
-- pattern = [[\b(KEYWORDS):]] -- ripgrep regex
-- -- pattern = [[\b(KEYWORDS)\b]] -- match without the extra colon. You'll likely get false positives
-- }
-- }
-- end
function M.outline_conf()
vim.g.symbols_outline = {
highlight_hovered_item = false,
show_guides = false
}
end
function M.dap_conf()
local dap = require('dap')
vim.fn.sign_define('DapBreakpoint', {text='', texthl='Orange'})
vim.fn.sign_define('DapLogPoint', {text='', texthl='Orange'})
vim.fn.sign_define('DapStopped', {text='', texthl='Orange'})
vim.fn.sign_define('DapBreakpointRejected', {text='', texthl='Red'})
-- Mappings
vim.api.nvim_command('n', '<leader>dn', ':lua require("dap").continue()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dd', ':lua require("dap").disconnect()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>db', ':lua require("dap").toggle_breakpoint()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dB', ':lua require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: "))<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dl', ':lua require("dap").list_breakpoints()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dc', ':lua require("dap").run_to_cursor()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dz', ':lua require("dap").run_last()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<F9>', ':lua require("dap").step_over()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dv', ':lua require("dap").step_over()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<F10>', ':lua require("dap").step_into()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>di', ':lua require("dap").step_into()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<F11>', ':lua require("dap").step_out()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>do', ':lua require("dap").step_out()<CR>', {noremap = true, silent = true})
vim.api.nvim_command('n', '<leader>dr', ':lua require("dap").repl.open()<CR>', {noremap = true, silent = true})
end
function M.dapui_conf()
local dap, dapui = require('dap'), require('dapui')
dap.listeners.after.event_initialized['dapui_config'] = function() dapui.open() end
dap.listeners.before.event_terminated['dapui_config'] = function() dapui.close() end
dap.listeners.before.event_exited['dapui_config'] = function() dapui.close() end
require('dapui').setup {
icons = {expanded = '', collapsed = ''},
mappings = {
expand = {'<CR>', '<2-LeftMouse>'},
open = 'o',
remove = 'd',
edit = 'e',
repl = 'r'
},
sidebar = {
elements = {
-- Provide as ID strings or tables with 'id' and 'size' keys
-- 'size' can be float or integer > 1
{id = 'scopes', size = 0.25},
{id = 'breakpoints', size = 0.25},
{id = 'stacks', size = 0.25},
{id = 'watches', size = 0.25},
},
size = 40,
position = 'left'
},
tray = {
elements = {'repl'},
size = 10,
position = 'bottom'
},
floating = {
max_height = nil, -- These can be integers or a float between 0 and 1.
max_width = nil, -- Floats will be treated as percentage of your screen.
mappings = {
close = {'q', '<Esc>'}
}
},
windows = {indent = 1}
}
-- Mappings
vim.api.nvim_set_keymap('n', '<leader>de', ':lua require("dapui").eval()<CR>', {noremap = true, silent = true})
vim.api.nvim_set_keymap('v', '<leader>de', ':lua require("dapui").eval()<CR>', {noremap = true, silent = true})
vim.api.nvim_set_keymap('n', '<leader>df', ':lua require("dapui").float_element()<CR>', {noremap = true, silent = true})
vim.api.nvim_set_keymap('n', '<leader>dt', ':lua require("dapui").toggle()<CR>', {noremap = true, silent = true})
end
return M