return { 'neovim/nvim-lspconfig', dependencies = { -- Language server management plugins 'williamboman/mason.nvim', 'williamboman/mason-lspconfig.nvim', -- Completion plugins 'hrsh7th/cmp-nvim-lsp', -- Source for built-in language server client 'hrsh7th/cmp-buffer', -- Source for buffer words 'hrsh7th/cmp-path', -- Source for filesystem paths 'hrsh7th/cmp-cmdline', -- Source for command-line 'hrsh7th/nvim-cmp', -- Completion engine combines and use the above -- LSP UI plugins 'aznhe21/actions-preview.nvim', 'j-hui/fidget.nvim', 'folke/trouble.nvim', 'nvim-tree/nvim-web-devicons', -- Lue vim module support in lua language server 'folke/neodev.nvim', -- Snippet pluggins 'L3MON4D3/LuaSnip', 'saadparwaiz1/cmp_luasnip', -- TODO: https://github.com/nvimtools/none-ls.nvim -- TODO: https://github.com/mfussenegger/nvim-dap -- TODO: https://github.com/rcarriga/nvim-dap-ui }, config = function() require('mason').setup() require('mason-lspconfig').setup({ automatic_installation = false, ensure_installed = { 'ansiblels', -- Ansible 'bashls', -- Bash 'clangd', -- C/C++ 'cmake', -- Cmake 'docker_compose_language_service', -- Docker Compose 'dockerls', -- Dockerfile 'esbonio', -- Sphinx 'html', -- HTML 'jsonls', -- JSON 'lemminx', -- XML 'lua_ls', -- Lua 'opencl_ls', -- OpenCL 'powershell_es', -- Powershell 'pyright', -- Python 'ruff_lsp', -- Python 'vimls', -- VimScript 'yamlls', -- YAML }, handlers = { -- Default handler, sets up everything unless a custom language server -- setup handler is defined below function(server_name) require('lspconfig')[server_name].setup({}) end, ['lua_ls'] = function() require('neodev').setup() require('lspconfig').lua_ls.setup({ settings = { Lua = { diagnostics = { disable = { 'missing-fields', }, globals = { 'vim', }, } } } }) end, ['pyright'] = function() require('lspconfig').pyright.setup({ settings = { pyright = { -- Using Ruff's import organizer disableOrganizeImports = true, }, } }) end, }, }) local cmp = require('cmp') cmp.setup({ snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end }, mapping = cmp.mapping.preset.insert({ -- Open completion menu/confirm completion [''] = cmp.mapping.complete(), [''] = cmp.mapping.confirm({ select = true }), -- Select completion from menu [''] = cmp.mapping.select_next_item(), [''] = cmp.mapping.select_prev_item(), -- Scroll documentation of selected completion item [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.scroll_docs(-4), }), sources = { { name = 'nvim_lsp' }, { name = 'luasnip' }, -- { name = 'buffer' }, { name = 'path' }, -- { name = 'cmdline' }, }, }) -- Disable displaying diagnostics as virtual text vim.diagnostic.config({ virtual_text = false }) -- Diagnostic mappings -- TODO: trouble.nvim mappings instead? https://youtu.be/MuUrCcvE-Yw?t=631 vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { remap = false }) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { remap = false }) vim.keymap.set('n', 'sd', vim.diagnostic.open_float, { remap = false }) -- LSP mappings created when attached to a buffer local augroup = vim.api.nvim_create_augroup('lsp', { clear = true }) vim.api.nvim_create_autocmd('LspAttach', { pattern = '*', group = augroup, callback = function(ev) local opts = { noremap = true, buffer = ev.buf } -- Fixit mapping, or close enough, actually any code action vim.keymap.set('n', 'fi', require("actions-preview").code_actions, opts) -- Goto mappings vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts) vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts) vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts) -- Get references to symbol under cursor, store in quickfix window vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts) -- Refactoring mappings vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts) -- Format whole buffer mapping vim.keymap.set('n', 'gq', vim.lsp.buf.format, opts) -- Help mappings vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts) vim.keymap.set('i', '', vim.lsp.buf.signature_help, opts) end }) -- Snippet mappings local luasnip = require('luasnip') luasnip.setup({}) vim.keymap.set({ 'i', 's' }, '', function() if luasnip.expand_or_jumpable() then luasnip.expand_or_jump() end end, { silent = true }) vim.keymap.set({ 'i', 's' }, '', function() if luasnip.jumpable(-1) then luasnip.jump(-1) end end, { silent = true }) -- Load snippets local opts = { paths = vim.fn.stdpath('config') .. '/snippets' } require('luasnip.loaders.from_snipmate').lazy_load(opts) require('luasnip.loaders.from_lua').lazy_load(opts) -- LSP UI plugins require('fidget').setup({}) require('trouble').setup({}) vim.keymap.set('n', 't', function() require('trouble').toggle() end, { remap = false }) end }