return { 'neovim/nvim-lspconfig', 'hrsh7th/nvim-cmp', -- Autocompletion plugin 'hrsh7th/cmp-nvim-lsp', -- LSP source for nvim-cmp 'L3MON4D3/LuaSnip', { 'jose-elias-alvarez/null-ls.nvim', dependencies = { 'nvim-lua/plenary.nvim' }, config = function() local null_ls = require("null-ls") local sources = { -- python null_ls.builtins.formatting.black.with({ extra_args = { "--line-length=79" } }), null_ls.builtins.formatting.isort, null_ls.builtins.diagnostics.flake8, -- java euh script null_ls.builtins.formatting.prettier, null_ls.builtins.code_actions.eslint, null_ls.builtins.diagnostics.eslint, -- convienence null_ls.builtins.code_actions.gitsigns, -- Docker null_ls.builtins.diagnostics.hadolint, -- TailwindCSS null_ls.builtins.formatting.rustywind.with({ filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "svelte", "html", "rust" }, }), } local lspconfig = require('lspconfig') -- Add additional capabilities supported by nvim-cmp local capabilities = require("cmp_nvim_lsp").default_capabilities() local on_attach = function(_, bufnr) local opts = { buffer = bufnr, remap = false } vim.keymap.set("n", "gd", function() vim.lsp.buf.definition() end, opts) vim.keymap.set("n", "k", function() vim.lsp.buf.hover() end, opts) vim.keymap.set("n", "vws", function() vim.lsp.buf.workspace_symbol() end, opts) vim.keymap.set("n", "vd", function() vim.diagnostic.open_float() end, opts) vim.keymap.set("n", "[d", function() vim.diagnostic.goto_next() end, opts) vim.keymap.set("n", "]d", function() vim.diagnostic.goto_prev() end, opts) vim.keymap.set("n", "ca", function() vim.lsp.buf.code_action() end, opts) vim.keymap.set("n", "gr", function() vim.lsp.buf.references() end, opts) vim.keymap.set("n", "rn", function() vim.lsp.buf.rename() end, opts) vim.keymap.set("i", "", function() vim.lsp.buf.signature_help() end, opts) vim.keymap.set("n", "fo", function() vim.lsp.buf.format() end, opts) vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts) vim.keymap.set('n', 'e', vim.diagnostic.open_float, opts) end lspconfig.rust_analyzer.setup { capabilities = capabilities, on_attach = on_attach, settings = { ['rust-analyzer'] = { checkOnSave = { allFeatures = true, overrideCommand = { 'cargo', 'clippy', '--workspace', '--message-format=json', '--all-targets', '--all-features' } } } } } lspconfig.lua_ls.setup { on_attach = on_attach, capabilities = capabilities, settings = { Lua = { runtime = { version = 'LuaJIT', }, diagnostics = { globals = { 'vim' }, }, workspace = { library = vim.api.nvim_get_runtime_file("", true), }, telemetry = { enable = false, }, }, }, } lspconfig.tsserver.setup { capabilities = capabilities, on_attach = on_attach, } lspconfig.vuels.setup { capabilities = capabilities, on_attach = on_attach, } lspconfig.pyright.setup { capabilities = capabilities, on_attach = on_attach, } lspconfig.bashls.setup { capabilities = capabilities, on_attach = on_attach, } lspconfig.clangd.setup { capabilities = capabilities, on_attach = on_attach, } -- lspconfig.volar.setup { -- filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue', 'json' }, -- capabilities = capabilities, -- on_attach = on_attach, -- } -- Keep null_ls last so that its diagnostics and code actions come last null_ls.setup({ sources = sources }) -- Global mappings. vim.keymap.set('n', 'e', vim.diagnostic.open_float) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) vim.keymap.set('n', ']d', vim.diagnostic.goto_next) vim.keymap.set('n', 'q', vim.diagnostic.setloclist) -- Use LspAttach autocommand to only map the following keys -- after the language server attaches to the current buffer vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('UserLspConfig', {}), callback = function(ev) -- Enable completion triggered by vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc' -- Buffer local mappings. local opts = { buffer = ev.buf } vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts) vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts) vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts) vim.keymap.set('n', '', vim.lsp.buf.signature_help, opts) vim.keymap.set('n', 'wa', vim.lsp.buf.add_workspace_folder, opts) vim.keymap.set('n', 'wr', vim.lsp.buf.remove_workspace_folder, opts) vim.keymap.set('n', 'wl', function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, opts) vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts) vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts) vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, opts) vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts) vim.keymap.set('n', 'f', function() vim.lsp.buf.format { async = true } end, opts) end, }) -- nvim-cmp setup local cmp = require 'cmp' cmp.setup { snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end, }, window = { completion = cmp.config.window.bordered(), documentation = cmp.config.window.bordered(), }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), -- Up [''] = cmp.mapping.scroll_docs(4), -- Down -- C-b (back) C-f (forward) for snippet placeholder navigation. [''] = cmp.mapping.complete(), [''] = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = true, }, [''] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() else fallback() end end, { 'i', 's' }), [''] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_prev_item() else fallback() end end, { 'i', 's' }), }), sources = cmp.config.sources({ { name = 'nvim_lsp' }, { name = 'luasnip' }, }, { { name = 'buffer' }, }) } -- Format on save vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]] end } }