return { -- vista-like outline view for code { "stevearc/aerial.nvim", config = true, -- Optional dependencies dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons", }, cmd = { "AerialToggle", "AerialOpen", "AerialOpenAll", "AerialClose", "AerialCloseAll", "AerialNext", "AerialPrev", "AerialGo", "AerialInfo", "AerialNavToggle", "AerialNavOpen", "AerialNavClose", }, opts = { backends = { "treesitter", "lsp", "markdown", "man" }, }, }, -- lsp setup { "junnplus/lsp-setup.nvim", dependencies = { { "neovim/nvim-lspconfig", -- will sometimes not keep up with lsp changes if set to stable version = false, }, { "williamboman/mason.nvim", cmd = { "Mason", "MasonInstall", "MasonUninstall", "MasonUninstallAll", "MasonLog", "MasonUpdate", }, build = ":MasonUpdate", keys = { { "vm", ":Mason", desc = "Mason" }, }, }, { "williamboman/mason-lspconfig.nvim", cmd = { "LspInstall", "LspUninstall" }, }, { "WhoIsSethDaniel/mason-tool-installer.nvim", }, }, event = "BufReadPost", config = function() require("plugins.config.lsp") end, keys = { { "vs", ":LspInfo", desc = "LspInfo", } }, }, -- linting setup { "mfussenegger/nvim-lint", config = function() local linters = { astro = {}, bash = {}, javascript = {}, javascriptreact = {}, markdown = {}, quarto = {}, sh = {}, svelte = {}, text = {}, typescript = {}, typescriptreact = {}, } local per_cmd = function(cmd, ft_table) if vim.fn.executable(cmd) == 1 then for _, v in pairs(ft_table) do table.insert(v, cmd) end end end per_cmd("markdownlint", { linters.markdown, linters.quarto }) per_cmd("vale", { linters.markdown, linters.text, linters.quarto }) per_cmd("shellcheck", { linters.sh, linters.bash }) per_cmd("eslint_d", { linters.astro, linters.javascript, linters.javascriptreact, linters.svelte, linters.typescript, linters.typescriptreact, }) require("lint").linters_by_ft = linters vim.api.nvim_create_autocmd({ "BufWritePost", "InsertLeave" }, { callback = function() require("lint").try_lint() end, }) end, event = { "BufReadPost", "BufNewFile" }, }, -- formatting setup { "stevearc/conform.nvim", config = function() require("conform").setup({ lsp_fallback = true, format_after_save = function(bufnr) if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end return { lsp_fallback = true } end, formatters_by_ft = { angular = { { "prettierd", "prettier" } }, astro = { { "prettierd", "prettier" } }, bash = { "shfmt" }, bib = { "bibtex-tidy" }, css = { { "prettierd", "prettier" } }, graphql = { { "prettierd", "prettier" } }, html = { { "prettierd", "prettier" } }, javascript = { { "prettierd", "prettier" } }, javascriptreact = { { "prettierd", "prettier" } }, json = { "jq" }, lua = { "stylua" }, python = { "ruff_fix", "ruff_format" }, sh = { "shfmt" }, svelte = { { "prettierd", "prettier" } }, typescript = { { "prettierd", "prettier" } }, typescriptreact = { { "prettierd", "prettier" } }, vue = { { "prettierd", "prettier" } }, yaml = { { "prettierd", "prettier" } }, zsh = { "shfmt" }, }, formatters = { -- enable python isort functionality ruff_fix = { prepend_args = { "--select", "I" }, }, }, }) vim.api.nvim_create_user_command("FormatDisable", function(args) if args.bang then -- FormatDisable! will disable formatting just for this buffer vim.b.disable_autoformat = true else vim.g.disable_autoformat = true end end, { desc = "Disable formatting on save", bang = true, }) vim.api.nvim_create_user_command("FormatEnable", function() vim.b.disable_autoformat = false vim.g.disable_autoformat = false end, { desc = "Enable formatting on save", }) end, cmd = { "ConformInfo" }, event = { "BufReadPre" }, keys = { { "ll", function() require("conform").format({ async = true, lsp_fallback = true }) end, desc = "Format buffer", }, { "lL", function() vim.g.disable_autoformat = not vim.g.disable_autoformat end, desc = "Toggle AutoFormat", }, { "vf", ":ConformInfo", desc = "ConformInfo", }, }, init = function() -- If you want the formatexpr, here is the place to set it vim.o.formatexpr = "v:lua.require'conform'.formatexpr()" end, }, -- completion setup { "hrsh7th/nvim-cmp", branch = "main", dependencies = { "andersevenrud/cmp-tmux", "cbarrete/completion-vcard", "f3fora/cmp-spell", "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-path", "hrsh7th/cmp-buffer", "hrsh7th/cmp-calc", "hrsh7th/cmp-cmdline", "hrsh7th/cmp-nvim-lua", "hrsh7th/cmp-nvim-lsp-signature-help", "dmitmel/cmp-digraphs", "jc-doyle/cmp-pandoc-references", "kdheepak/cmp-latex-symbols", "lukas-reineke/cmp-rg", "crispgm/cmp-beancount", "ray-x/cmp-treesitter", "saadparwaiz1/cmp_luasnip", { "L3MON4D3/LuaSnip", dependencies = { "rafamadriz/friendly-snippets" }, }, }, config = function() require("plugins.config.cmp") end, event = { "InsertEnter", "CmdlineEnter", "VeryLazy" }, }, -- loading animations for some LSP { "j-hui/fidget.nvim", config = true, tag = "legacy", event = "VeryLazy" }, -- useful quickfix-like buffer { "folke/trouble.nvim", dependencies = { "nvim-tree/nvim-web-devicons" }, opts = {}, cmd = { "Trouble", "TroubleRefresh", "TroubleToggle", "TroubleClose", }, }, -- testing setup { "nvim-neotest/neotest", dependencies = { "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", "antoinemadec/FixCursorHold.nvim", "nvim-neotest/neotest-python", }, config = function() require("neotest").setup({ adapters = { require("neotest-python")({ -- with coverage requires coverage.py and pytest-cov installed args = { "--cov" }, }), }, }) local status, wk = pcall(require, "which-key") if status then wk.register({ ["t"] = { name = "+test" } }) end end, ft = { "python" }, keys = { { "st", [[lua require('neotest').summary.toggle()]], desc = "toggle test list", silent = true, }, { "sT", [[lua require('neotest').output_panel.toggle()]], desc = "toggle test output", silent = true, }, { "to", [[lua require('neotest').output.open()]], desc = "toggle test output", silent = true, }, { "tt", [[lua require('neotest').run.run()]], desc = "run nearest test", silent = true, }, { "td", [[lua require('neotest').run.run({strategy = "dap"})]], desc = "debug nearest test", silent = true, }, -- REQUIRES DAP { "tT", [[lua require('neotest').run.run(vim.fn.expand("%"))]], desc = "test current file", silent = true, }, { "tr", [[lua require('neotest').run.run_last()]], desc = "re-run last test", silent = true, }, { "tw", [[lua require('neotest').watch.toggle()]], desc = "watch current test", silent = true, }, { "tW", [[lua require('neotest').watch.toggle(vim.fn.expand("%"))]], desc = "watch current file", silent = true, }, }, }, -- TODO needs to pick up poetry env for python, -- currently just hard-codes running through poetry { "andythigpen/nvim-coverage", dependencies = { "nvim-lua/plenary.nvim", }, config = function() require("coverage").setup({ lang = { python = { coverage_command = "poetry run coverage json -q -o -" } }, }) end, ft = { "python" }, cmd = { "Coverage", "CoverageLoad", "CoverageLoadLcov", "CoverageShow", "CoverageHide", "CoverageToggle", "CoverageClear", "CoverageSummary", }, keys = { { "tp", [[Coverage]], desc = "show coverage report", silent = true, }, { "tP", [[CoverageToggle]], desc = "toggle coverage gutter", silent = true, }, { "ts", [[CoverageSummary]], desc = "show coverage summary", silent = true, }, }, }, }