diff --git a/init.lua b/init.lua index 0194b1ff..71c0867e 100644 --- a/init.lua +++ b/init.lua @@ -395,13 +395,18 @@ require('lazy').setup({ -- Document existing key chains spec = { { 'a', group = 'Harpoon [A]dd' }, + { 'c', group = '[C]Make' }, { 'd', group = '[D]iagnostics' }, + { 'e', group = '[E]xplorer' }, { 'g', group = '[G]it' }, { 'm', group = '[M]arkdown' }, + { 'n', group = '[N]eotest' }, { 'o', group = '[O]pencode' }, { 's', group = '[S]earch' }, { 't', group = '[T]oggle' }, { 'w', group = '[W]indow' }, + { 'x', group = 'Trouble' }, + { 'j', group = '[J]ump' }, { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, }, }, @@ -762,7 +767,23 @@ require('lazy').setup({ cssls = {}, html = {}, jsonls = {}, - yamlls = {}, + yamlls = { + settings = { + yaml = { + schemas = { + ['https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.32.1-standalone-strict/all.json'] = { + '*.k8s.yaml', + 'k8s/**/*.yaml', + 'manifests/**/*.yaml', + 'kubernetes/**/*.yaml', + }, + ['https://json.schemastore.org/chart'] = 'Chart.yaml', + ['https://json.schemastore.org/helmfile.json'] = 'helmfile.yaml', + ['https://json.schemastore.org/kustomization.json'] = 'kustomization.yaml', + }, + }, + }, + }, taplo = {}, elixirls = {}, gh_actions_ls = {}, @@ -785,6 +806,7 @@ require('lazy').setup({ eslint = {}, astro = {}, vue_ls = {}, + helm_ls = {}, ts_ls = { filetypes = { 'vue' }, init_options = { @@ -830,6 +852,13 @@ require('lazy').setup({ vim.list_extend(ensure_installed, { 'stylua', -- Used to format Lua code 'markdownlint', -- Used by nvim-lint for Markdown buffers + 'prettierd', + 'prettier', + 'clang-format', + 'hadolint', + 'yamllint', + 'js-debug-adapter', + 'codelldb', }) require('mason-tool-installer').setup { ensure_installed = ensure_installed } @@ -876,6 +905,15 @@ require('lazy').setup({ end, formatters_by_ft = { lua = { 'stylua' }, + javascript = { 'prettierd', 'prettier', stop_after_first = true }, + javascriptreact = { 'prettierd', 'prettier', stop_after_first = true }, + typescript = { 'prettierd', 'prettier', stop_after_first = true }, + typescriptreact = { 'prettierd', 'prettier', stop_after_first = true }, + json = { 'prettierd', 'prettier', stop_after_first = true }, + jsonc = { 'prettierd', 'prettier', stop_after_first = true }, + yaml = { 'prettierd', 'prettier', stop_after_first = true }, + c = { 'clang_format' }, + cpp = { 'clang_format' }, -- Conform can also run multiple formatters sequentially -- python = { "isort", "black" }, -- diff --git a/lua/custom/plugins/cmake_tools.lua b/lua/custom/plugins/cmake_tools.lua new file mode 100644 index 00000000..b532dc2d --- /dev/null +++ b/lua/custom/plugins/cmake_tools.lua @@ -0,0 +1,29 @@ +return { + 'Civitasv/cmake-tools.nvim', + dependencies = { 'nvim-lua/plenary.nvim' }, + cmd = { + 'CMakeGenerate', + 'CMakeBuild', + 'CMakeRun', + 'CMakeTest', + 'CMakeSelectBuildType', + 'CMakeSelectBuildTarget', + }, + ft = { 'cmake' }, + keys = { + { 'cg', 'CMakeGenerate', desc = '[C]Make [G]enerate' }, + { 'cb', 'CMakeBuild', desc = '[C]Make [B]uild' }, + { 'cr', 'CMakeRun', desc = '[C]Make [R]un' }, + { 'ct', 'CMakeTest', desc = '[C]Make [T]est' }, + { 'cc', 'CMakeSelectBuildType', desc = '[C]Make [C]onfiguration' }, + }, + opts = { + cmake_generate_options = { '-DCMAKE_EXPORT_COMPILE_COMMANDS=1' }, + cmake_executor = { + name = 'quickfix', + }, + cmake_runner = { + name = 'terminal', + }, + }, +} diff --git a/lua/custom/plugins/dap_js_ts.lua b/lua/custom/plugins/dap_js_ts.lua new file mode 100644 index 00000000..8dc13a72 --- /dev/null +++ b/lua/custom/plugins/dap_js_ts.lua @@ -0,0 +1,40 @@ +return { + 'mxsdev/nvim-dap-vscode-js', + dependencies = { 'mfussenegger/nvim-dap' }, + ft = { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'vue' }, + config = function() + require('dap-vscode-js').setup { + debugger_cmd = { 'js-debug-adapter' }, + adapters = { + 'pwa-node', + 'pwa-chrome', + 'pwa-msedge', + 'node-terminal', + 'pwa-extensionHost', + }, + } + + local dap = require 'dap' + local configs = { + { + type = 'pwa-node', + request = 'launch', + name = 'Launch current file (Node)', + program = '${file}', + cwd = '${workspaceFolder}', + sourceMaps = true, + }, + { + type = 'pwa-node', + request = 'attach', + name = 'Attach to process', + processId = require('dap.utils').pick_process, + cwd = '${workspaceFolder}', + }, + } + + for _, language in ipairs { 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'vue' } do + dap.configurations[language] = vim.list_extend(dap.configurations[language] or {}, configs) + end + end, +} diff --git a/lua/custom/plugins/debug.lua b/lua/custom/plugins/debug.lua index 753cb0ce..ab989236 100644 --- a/lua/custom/plugins/debug.lua +++ b/lua/custom/plugins/debug.lua @@ -95,6 +95,7 @@ return { ensure_installed = { -- Update this to ensure that you have the debuggers for the langs you want 'delve', + 'codelldb', }, } diff --git a/lua/custom/plugins/grug_far.lua b/lua/custom/plugins/grug_far.lua new file mode 100644 index 00000000..7023842f --- /dev/null +++ b/lua/custom/plugins/grug_far.lua @@ -0,0 +1,27 @@ +return { + 'MagicDuck/grug-far.nvim', + cmd = { 'GrugFar', 'GrugFarWithin' }, + opts = {}, + keys = { + { + 'sR', + function() + require('grug-far').open { + prefills = { + search = vim.fn.expand '', + }, + } + end, + mode = 'n', + desc = '[S]earch project [R]eplace', + }, + { + 'sR', + function() + require('grug-far').with_visual_selection() + end, + mode = 'x', + desc = '[S]earch project [R]eplace selection', + }, + }, +} diff --git a/lua/custom/plugins/helm.lua b/lua/custom/plugins/helm.lua new file mode 100644 index 00000000..d4b5e1b4 --- /dev/null +++ b/lua/custom/plugins/helm.lua @@ -0,0 +1,3 @@ +return { + 'towolf/vim-helm', +} diff --git a/lua/custom/plugins/lint.lua b/lua/custom/plugins/lint.lua index 61ec2d27..2c194f59 100644 --- a/lua/custom/plugins/lint.lua +++ b/lua/custom/plugins/lint.lua @@ -7,6 +7,9 @@ return { local lint = require 'lint' lint.linters_by_ft = { markdown = { 'markdownlint' }, + dockerfile = { 'hadolint' }, + yaml = { 'yamllint' }, + ['yaml.helm-values'] = { 'yamllint' }, } lint.linters.markdownlint = vim.tbl_deep_extend('force', lint.linters.markdownlint or {}, { args = { @@ -56,11 +59,41 @@ return { vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost', 'InsertLeave' }, { group = lint_augroup, callback = function() + local function executable_cmd(cmd) + if type(cmd) == 'function' then + local ok, value = pcall(cmd) + if not ok then + return nil + end + return value + end + return cmd + end + + local function available_linters_for(ft) + local configured = lint.linters_by_ft[ft] or {} + local available = {} + + for _, linter_name in ipairs(configured) do + local linter = lint.linters[linter_name] + local cmd = linter and executable_cmd(linter.cmd) + if cmd == nil or cmd == '' or vim.fn.executable(cmd) == 1 then + table.insert(available, linter_name) + end + end + + return available + end + -- Only run the linter in buffers that you can modify in order to -- avoid superfluous noise, notably within the handy LSP pop-ups that -- describe the hovered symbol using Markdown. if vim.bo.modifiable then - lint.try_lint() + local filetype = vim.bo.filetype + local linters = available_linters_for(filetype) + if #linters > 0 then + lint.try_lint(linters) + end end end, }) diff --git a/lua/custom/plugins/neotest.lua b/lua/custom/plugins/neotest.lua new file mode 100644 index 00000000..1b0d2937 --- /dev/null +++ b/lua/custom/plugins/neotest.lua @@ -0,0 +1,98 @@ +return { + 'nvim-neotest/neotest', + dependencies = { + 'nvim-neotest/nvim-nio', + 'nvim-lua/plenary.nvim', + 'nvim-treesitter/nvim-treesitter', + 'nvim-neotest/neotest-jest', + 'marilari88/neotest-vitest', + 'alfaix/neotest-gtest', + }, + keys = { + { + 'nr', + function() + require('neotest').run.run() + end, + desc = '[N]eotest run nea[r]est', + }, + { + 'nf', + function() + require('neotest').run.run(vim.fn.expand '%') + end, + desc = '[N]eotest run [F]ile', + }, + { + 'ns', + function() + require('neotest').run.run(vim.fn.getcwd()) + end, + desc = '[N]eotest run [S]uite', + }, + { + 'nd', + function() + require('neotest').run.run { strategy = 'dap' } + end, + desc = '[N]eotest [D]ebug nearest', + }, + { + 'nn', + function() + require('neotest').summary.toggle() + end, + desc = '[N]eotest summary', + }, + { + 'no', + function() + require('neotest').output.open { enter = true, auto_close = true } + end, + desc = '[N]eotest [O]utput', + }, + { + 'nO', + function() + require('neotest').output_panel.toggle() + end, + desc = '[N]eotest [O]utput panel', + }, + { + 'na', + function() + require('neotest').run.attach() + end, + desc = '[N]eotest [A]ttach', + }, + { + 'nS', + function() + require('neotest').run.stop() + end, + desc = '[N]eotest [S]top', + }, + }, + config = function() + local adapters = {} + + local ok_jest, jest = pcall(require, 'neotest-jest') + if ok_jest then + table.insert(adapters, jest {}) + end + + local ok_vitest, vitest = pcall(require, 'neotest-vitest') + if ok_vitest then + table.insert(adapters, vitest {}) + end + + local ok_gtest, gtest = pcall(require, 'neotest-gtest') + if ok_gtest then + table.insert(adapters, gtest.setup {}) + end + + require('neotest').setup { + adapters = adapters, + } + end, +} diff --git a/lua/custom/plugins/oil.lua b/lua/custom/plugins/oil.lua new file mode 100644 index 00000000..8a6d6767 --- /dev/null +++ b/lua/custom/plugins/oil.lua @@ -0,0 +1,14 @@ +return { + 'stevearc/oil.nvim', + cmd = { 'Oil' }, + keys = { + { 'eo', 'Oil', desc = '[E]xplorer [O]il' }, + }, + opts = { + default_file_explorer = false, + columns = { 'icon' }, + view_options = { + show_hidden = true, + }, + }, +} diff --git a/lua/custom/plugins/treesitter_context.lua b/lua/custom/plugins/treesitter_context.lua new file mode 100644 index 00000000..2904e807 --- /dev/null +++ b/lua/custom/plugins/treesitter_context.lua @@ -0,0 +1,17 @@ +return { + 'nvim-treesitter/nvim-treesitter-context', + opts = { + max_lines = 4, + multiline_threshold = 20, + trim_scope = 'outer', + }, + keys = { + { + 'tc', + function() + require('treesitter-context').toggle() + end, + desc = '[T]oggle code [C]ontext', + }, + }, +} diff --git a/lua/custom/plugins/treesitter_textobjects.lua b/lua/custom/plugins/treesitter_textobjects.lua new file mode 100644 index 00000000..417daad4 --- /dev/null +++ b/lua/custom/plugins/treesitter_textobjects.lua @@ -0,0 +1,38 @@ +return { + 'nvim-treesitter/nvim-treesitter-textobjects', + branch = 'main', + dependencies = { 'nvim-treesitter/nvim-treesitter' }, + config = function() + require('nvim-treesitter-textobjects').setup { + move = { + set_jumps = true, + }, + } + + local move = require 'nvim-treesitter-textobjects.move' + + vim.keymap.set('n', 'jm', function() + move.goto_next_start '@function.outer' + end, { desc = '[J]ump next [M]ethod start' }) + + vim.keymap.set('n', 'jM', function() + move.goto_next_end '@function.outer' + end, { desc = '[J]ump next [M]ethod end' }) + + vim.keymap.set('n', 'jk', function() + move.goto_previous_start '@function.outer' + end, { desc = '[J]ump previous method start' }) + + vim.keymap.set('n', 'jK', function() + move.goto_previous_end '@function.outer' + end, { desc = '[J]ump previous method end' }) + + vim.keymap.set('n', 'jc', function() + move.goto_next_start '@class.outer' + end, { desc = '[J]ump next [C]lass start' }) + + vim.keymap.set('n', 'jC', function() + move.goto_previous_start '@class.outer' + end, { desc = '[J]ump previous class start' }) + end, +} diff --git a/lua/custom/plugins/trouble.lua b/lua/custom/plugins/trouble.lua new file mode 100644 index 00000000..d47f80a7 --- /dev/null +++ b/lua/custom/plugins/trouble.lua @@ -0,0 +1,45 @@ +return { + 'folke/trouble.nvim', + cmd = { 'Trouble' }, + opts = {}, + keys = { + { + 'xx', + function() + require('trouble').toggle 'diagnostics' + end, + desc = 'Trouble: all diagnostics', + }, + { + 'xw', + function() + require('trouble').toggle 'diagnostics' + end, + desc = 'Trouble: [W]orkspace diagnostics', + }, + { + 'xd', + function() + require('trouble').toggle { + mode = 'diagnostics', + filter = { buf = 0 }, + } + end, + desc = 'Trouble: [D]ocument diagnostics', + }, + { + 'xq', + function() + require('trouble').toggle 'qflist' + end, + desc = 'Trouble: [Q]uickfix list', + }, + { + 'xl', + function() + require('trouble').toggle 'loclist' + end, + desc = 'Trouble: [L]ocation list', + }, + }, +}