return { { 'nvimtools/none-ls.nvim', dependencies = { 'mason.nvim' }, opts = function(_, opts) local nls = require 'null-ls' opts.root_dir = opts.root_dir or require('null-ls.utils').root_pattern('.null-ls-root', '.neoconf.json', 'Makefile', '.git') opts.sources = vim.list_extend(opts.sources or {}, { nls.builtins.formatting.fish_indent, nls.builtins.diagnostics.fish, nls.builtins.formatting.stylua, nls.builtins.formatting.shfmt, }) end, }, { 'tpope/vim-dadbod', }, { 'kristijanhusak/vim-dadbod-ui', dependencies = { { 'tpope/vim-dadbod', lazy = true }, { 'kristijanhusak/vim-dadbod-completion', ft = { 'sql', 'mysql', 'plsql' }, lazy = true }, }, cmd = { 'DBUI', 'DBUIToggle', 'DBUIAddConnection', 'DBUIFindBuffer', }, init = function() -- Your DBUI configuration vim.g.db_ui_use_nerd_fonts = 1 end, }, { 'nvim-neotest/neotest', dependencies = { 'nvim-neotest/nvim-nio', 'marilari88/neotest-vitest', 'mrcjkb/rustaceanvim' }, opts = { -- Can be a list of adapters like what neotest expects, -- or a list of adapter names, -- or a table of adapter names, mapped to adapter configs. -- The adapter will then be automatically loaded with the config. adapters = { ['neotest-vitest'] = {}, ['rustaceanvim.neotest'] = {}, }, -- Example for loading neotest-golang with a custom config -- adapters = { -- ["neotest-golang"] = { -- go_test_args = { "-v", "-race", "-count=1", "-timeout=60s" }, -- dap_go_enabled = true, -- }, -- }, status = { virtual_text = true }, output = { open_on_run = true }, quickfix = { open = function() require('trouble').open { mode = 'quickfix', focus = false } end, }, }, config = function(_, opts) local neotest_ns = vim.api.nvim_create_namespace 'neotest' vim.diagnostic.config({ virtual_text = { format = function(diagnostic) -- Replace newline and tab characters with space for more compact diagnostics local message = diagnostic.message:gsub('\n', ' '):gsub('\t', ' '):gsub('%s+', ' '):gsub('^%s+', '') return message end, }, }, neotest_ns) opts.consumers = opts.consumers or {} -- Refresh and auto close trouble after running tests ---@type neotest.Consumer opts.consumers.trouble = function(client) client.listeners.results = function(adapter_id, results, partial) if partial then return end local tree = assert(client:get_position(nil, { adapter = adapter_id })) local failed = 0 for pos_id, result in pairs(results) do if result.status == 'failed' and tree:get_key(pos_id) then failed = failed + 1 end end vim.schedule(function() local trouble = require 'trouble' if trouble.is_open() then trouble.refresh() if failed == 0 then trouble.close() end end end) return {} end end if opts.adapters then local adapters = {} for name, config in pairs(opts.adapters or {}) do if type(name) == 'number' then if type(config) == 'string' then config = require(config) end adapters[#adapters + 1] = config elseif config ~= false then local adapter = require(name) if type(config) == 'table' and not vim.tbl_isempty(config) then local meta = getmetatable(adapter) if adapter.setup then adapter.setup(config) elseif adapter.adapter then adapter.adapter(config) adapter = adapter.adapter elseif meta and meta.__call then adapter = adapter(config) else error('Adapter ' .. name .. ' does not support setup') end end adapters[#adapters + 1] = adapter end end opts.adapters = adapters end require('neotest').setup(opts) end, keys = { { 't', '', desc = '+test' }, { 'ta', function() require('neotest').run.attach() end, desc = 'Attach to Test (Neotest)' }, { 'tt', function() require('neotest').run.run(vim.fn.expand '%') end, desc = 'Run File (Neotest)' }, { 'tT', function() require('neotest').run.run(vim.uv.cwd()) end, desc = 'Run All Test Files (Neotest)' }, { 'tr', function() require('neotest').run.run() end, desc = 'Run Nearest (Neotest)' }, { 'tl', function() require('neotest').run.run_last() end, desc = 'Run Last (Neotest)' }, { 'ts', function() require('neotest').summary.toggle() end, desc = 'Toggle Summary (Neotest)' }, { 'to', function() require('neotest').output.open { enter = true, auto_close = true } end, desc = 'Show Output (Neotest)' }, { 'tO', function() require('neotest').output_panel.toggle() end, desc = 'Toggle Output Panel (Neotest)' }, { 'tS', function() require('neotest').run.stop() end, desc = 'Stop (Neotest)' }, { 'tw', function() require('neotest').watch.toggle(vim.fn.expand '%') end, desc = 'Toggle Watch (Neotest)' }, }, }, { 'mrcjkb/rustaceanvim', ft = { 'rust' }, opts = { server = { on_attach = function(_, bufnr) vim.keymap.set('n', 'cR', function() vim.cmd.RustLsp 'codeAction' end, { desc = 'Code Action', buffer = bufnr }) vim.keymap.set('n', 'dr', function() vim.cmd.RustLsp 'debuggables' end, { desc = 'Rust Debuggables', buffer = bufnr }) end, default_settings = { -- rust-analyzer language server configuration ['rust-analyzer'] = { cargo = { allFeatures = true, loadOutDirsFromCheck = true, buildScripts = { enable = true, }, }, -- Add clippy lints for Rust if using rust-analyzer checkOnSave = diagnostics == 'rust-analyzer', -- Enable diagnostics if using rust-analyzer diagnostics = { enable = diagnostics == 'rust-analyzer', }, procMacro = { enable = true, }, files = { exclude = { '.direnv', '.git', '.jj', '.github', '.gitlab', 'bin', 'node_modules', 'target', 'venv', '.venv', }, -- Avoid Roots Scanned hanging, see https://github.com/rust-lang/rust-analyzer/issues/12613#issuecomment-2096386344 watcher = 'client', }, }, }, }, }, config = function(_, opts) local codelldb = vim.fn.exepath 'codelldb' local codelldb_lib_ext = io.popen('uname'):read '*l' == 'Linux' and '.so' or '.dylib' local library_path = vim.fn.expand('$MASON/opt/lldb/lib/liblldb' .. codelldb_lib_ext) opts.dap = { adapter = require('rustaceanvim.config').get_codelldb_adapter(codelldb, library_path), } vim.g.rustaceanvim = vim.tbl_deep_extend('keep', vim.g.rustaceanvim or {}, opts or {}) end, }, }