local nvim_lsp = require 'lspconfig' local protocol = require 'vim.lsp.protocol' local ts_utils = require 'nvim-lsp-ts-utils' local util = require 'lspconfig/util' local cmp = require 'cmp_nvim_lsp' -- https://github.com/neovim/nvim-lspconfig/wiki/User-contributed-tips function FormatRangeOperator() local old_func = vim.go.operatorfunc _G.op_func_formatting = function() local start = vim.api.nvim_buf_get_mark(0, '[') local finish = vim.api.nvim_buf_get_mark(0, ']') vim.lsp.buf.range_formatting({}, start, finish) vim.go.operatorfunc = old_func _G.op_func_formatting = nil end vim.go.operatorfunc = 'v:lua.op_func_formatting' vim.api.nvim_feedkeys('g@', 'n', false) end local function preview_location_callback(_, result) if result == nil or vim.tbl_isempty(result) then return nil end vim.lsp.util.preview_location(result[1]) end function PeekDefinition() local params = vim.lsp.util.make_position_params() return vim.lsp.buf_request(0, 'textDocument/definition', params, preview_location_callback) end local ts_utils_setup = function(client, bufnr, opts) if client.name == 'tsserver' then -- Disable tsserver formatting, we want formatting via prettier client.resolved_capabilities.document_formatting = false client.resolved_capabilities.document_range_formatting = false ts_utils.setup { debug = false, disable_commands = false, enable_import_on_completion = false, import_all_timeout = 5000, import_all_scan_buffers = 100, import_all_select_source = false, import_all_priorities = { buffers = 4, -- loaded buffer names buffer_content = 3, -- loaded buffer content local_files = 2, -- git files or files with relative path markers same_file = 1, -- add to existing import statement }, update_imports_on_move = false, require_confirmation_on_move = false, watch_dir = nil, filter_out_diagnostics_by_severity = {}, filter_out_diagnostics_by_code = {}, auto_inlay_hints = true, inlay_hints_highlight = "Hint", } ts_utils.setup_client(client) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'go', ':TSLspOrganize' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gf', ':TSLspFixCurrent', opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gI', ':TSLspImportAll' , opts) end end local on_attach = function(client, bufnr) vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') vim.lsp.set_log_level('warn') if client.config.flags then client.config.flags.allow_incremental_sync = true client.config.flags.debounce_text_changes = 500 end local opts = { noremap=true, silent=true } -- This needs to be here, so we disable formatting with tsserver before -- actually checking it below. ts_utils_setup(client, bufnr, opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd' , 'lua vim.lsp.buf.definition()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gD' , 'lua vim.lsp.buf.declaration()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gr' , 'lua vim.lsp.buf.references()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gi' , 'lua vim.lsp.buf.implementation()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', '' , 'lua vim.lsp.buf.type_definition()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', '1gd' , 'lua vim.lsp.buf.document_symbol()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', '1gD' , 'lua vim.lsp.buf.workspace_symbol()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gR' , 'lua vim.lsp.buf.rename()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'pd' , 'lua PeekDefinition()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'k', 'lua vim.lsp.buf.hover()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'S', 'lua vim.lsp.buf.signature_help()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'ga' , 'lua vim.lsp.buf.code_action()' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'v', 'ga' , 'lua vim.lsp.buf.range_code_action()', opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', 'r', 'lua vim.lsp.buf.code_action{ only = \'refactor\' }' , opts) vim.api.nvim_buf_set_keymap(bufnr, 'v', 'r', 'lua vim.lsp.buf.range_code_action{ only = \'refactor\' }', opts) if client.resolved_capabilities.document_range_formatting then vim.api.nvim_buf_set_keymap(bufnr, 'x', 'gq', 'lua FormatRangeOperator()', opts) end if client.resolved_capabilities.document_formatting then vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gq', 'lua vim.lsp.buf.formatting()', opts) end if client.resolved_capabilities.code_lens then vim.api.nvim_buf_set_keymap(bufnr, "n", "l", "lua vim.lsp.codelens.run()", opts) vim.api.nvim_command [[autocmd CursorHold,CursorHoldI,InsertLeave lua vim.lsp.codelens.refresh()]] end vim.api.nvim_command [[autocmd CursorHold lua vim.lsp.buf.document_highlight()]] vim.api.nvim_command [[autocmd CursorMoved,InsertEnter lua vim.lsp.buf.clear_references()]] protocol.CompletionItemKind = { ' '; -- text ' '; -- method ' '; -- function '全'; -- ctor ' '; -- field ' '; -- variable ' '; -- class ' '; -- interface ' '; -- module ' '; -- property ' '; -- unit ' '; -- value '螺'; -- enum ' '; -- keyword ' '; -- snippet ' '; -- color ' '; -- file ' '; -- reference ' '; -- folder ' '; -- enum member ' '; -- constant ' '; -- struct ' '; -- event '璉'; -- operator ' '; -- type parameter } vim.cmd [[autocmd CursorHold,CursorHoldI lua require'nvim-lightbulb'.update_lightbulb()]] end local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = cmp.update_capabilities(capabilities) local rust_tool_opts = { tools = { autoSetHints = true, hover_with_actions = false, runnables = { use_telescope = false }, debuggables = { use_telescope = false }, inlay_hints = { only_current_line = false, only_current_line_autocmd = "CursorHold", show_parameter_hints = true, parameter_hints_prefix = "<- ", other_hints_prefix = "=> ", highlight = "Hint", }, hover_actions = { auto_focus = true }, crate_graph = { backend = "svg", output = "crates_graph.svg", full = false, } }, server = { on_attach = on_attach, capabilities = capabilities, settings = { ["rust-analyzer"] = { checkOnSave = { command = "clippy" }, } } }, } nvim_lsp.clangd.setup { on_attach = on_attach, capabilities = capabilities, default_config = { cmd = { "clangd", "--background-index", "--pch-storage=memory", "--clang-tidy", "--suggest-missing-includes", "--header-insertion=never" }, filetypes = { 'c', 'cpp' }, root_dir = function(fname) -- We specify build/compile_commands.json as that is where the compile_commands.json -- gets generated automatically for meson projects. local root_pattern = util.root_pattern('build/compile_commands.json', 'compile_commands.json', 'compile_flags.txt', '.git') local filename = util.path.is_absolute(fname) and fname or util.path.join(vim.loop.cwd(), fname) return root_pattern(filename) or util.path.dirname(filename) end, } } nvim_lsp.hls.setup { on_attach = on_attach, capabilities = capabilities } nvim_lsp.pylsp.setup { on_attach = on_attach, capabilities = capabilities, settings = { pylsp = { plugins = { flake8 = { enabled = true, config = vim.fn.expand('~/.config/flake8') }, pylint = { enabled = true, } } } } } require('rust-tools').setup(rust_tool_opts) nvim_lsp.tsserver.setup { init_options = require("nvim-lsp-ts-utils").init_options, on_attach = on_attach, capabilities = capabilities, }