feat(workflow): add backend engineering plugin stack

This commit is contained in:
Paul B. Kim 2026-02-17 15:09:13 +09:00
parent e5a8662c91
commit 6fb17303bc
No known key found for this signature in database
12 changed files with 385 additions and 2 deletions

View File

@ -395,13 +395,18 @@ require('lazy').setup({
-- Document existing key chains
spec = {
{ '<leader>a', group = 'Harpoon [A]dd' },
{ '<leader>c', group = '[C]Make' },
{ '<leader>d', group = '[D]iagnostics' },
{ '<leader>e', group = '[E]xplorer' },
{ '<leader>g', group = '[G]it' },
{ '<leader>m', group = '[M]arkdown' },
{ '<leader>n', group = '[N]eotest' },
{ '<leader>o', group = '[O]pencode' },
{ '<leader>s', group = '[S]earch' },
{ '<leader>t', group = '[T]oggle' },
{ '<leader>w', group = '[W]indow' },
{ '<leader>x', group = 'Trouble' },
{ '<leader>j', group = '[J]ump' },
{ '<leader>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" },
--

View File

@ -0,0 +1,29 @@
return {
'Civitasv/cmake-tools.nvim',
dependencies = { 'nvim-lua/plenary.nvim' },
cmd = {
'CMakeGenerate',
'CMakeBuild',
'CMakeRun',
'CMakeTest',
'CMakeSelectBuildType',
'CMakeSelectBuildTarget',
},
ft = { 'cmake' },
keys = {
{ '<leader>cg', '<cmd>CMakeGenerate<CR>', desc = '[C]Make [G]enerate' },
{ '<leader>cb', '<cmd>CMakeBuild<CR>', desc = '[C]Make [B]uild' },
{ '<leader>cr', '<cmd>CMakeRun<CR>', desc = '[C]Make [R]un' },
{ '<leader>ct', '<cmd>CMakeTest<CR>', desc = '[C]Make [T]est' },
{ '<leader>cc', '<cmd>CMakeSelectBuildType<CR>', desc = '[C]Make [C]onfiguration' },
},
opts = {
cmake_generate_options = { '-DCMAKE_EXPORT_COMPILE_COMMANDS=1' },
cmake_executor = {
name = 'quickfix',
},
cmake_runner = {
name = 'terminal',
},
},
}

View File

@ -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,
}

View File

@ -95,6 +95,7 @@ return {
ensure_installed = {
-- Update this to ensure that you have the debuggers for the langs you want
'delve',
'codelldb',
},
}

View File

@ -0,0 +1,27 @@
return {
'MagicDuck/grug-far.nvim',
cmd = { 'GrugFar', 'GrugFarWithin' },
opts = {},
keys = {
{
'<leader>sR',
function()
require('grug-far').open {
prefills = {
search = vim.fn.expand '<cword>',
},
}
end,
mode = 'n',
desc = '[S]earch project [R]eplace',
},
{
'<leader>sR',
function()
require('grug-far').with_visual_selection()
end,
mode = 'x',
desc = '[S]earch project [R]eplace selection',
},
},
}

View File

@ -0,0 +1,3 @@
return {
'towolf/vim-helm',
}

View File

@ -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,
})

View File

@ -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 = {
{
'<leader>nr',
function()
require('neotest').run.run()
end,
desc = '[N]eotest run nea[r]est',
},
{
'<leader>nf',
function()
require('neotest').run.run(vim.fn.expand '%')
end,
desc = '[N]eotest run [F]ile',
},
{
'<leader>ns',
function()
require('neotest').run.run(vim.fn.getcwd())
end,
desc = '[N]eotest run [S]uite',
},
{
'<leader>nd',
function()
require('neotest').run.run { strategy = 'dap' }
end,
desc = '[N]eotest [D]ebug nearest',
},
{
'<leader>nn',
function()
require('neotest').summary.toggle()
end,
desc = '[N]eotest summary',
},
{
'<leader>no',
function()
require('neotest').output.open { enter = true, auto_close = true }
end,
desc = '[N]eotest [O]utput',
},
{
'<leader>nO',
function()
require('neotest').output_panel.toggle()
end,
desc = '[N]eotest [O]utput panel',
},
{
'<leader>na',
function()
require('neotest').run.attach()
end,
desc = '[N]eotest [A]ttach',
},
{
'<leader>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,
}

View File

@ -0,0 +1,14 @@
return {
'stevearc/oil.nvim',
cmd = { 'Oil' },
keys = {
{ '<leader>eo', '<cmd>Oil<CR>', desc = '[E]xplorer [O]il' },
},
opts = {
default_file_explorer = false,
columns = { 'icon' },
view_options = {
show_hidden = true,
},
},
}

View File

@ -0,0 +1,17 @@
return {
'nvim-treesitter/nvim-treesitter-context',
opts = {
max_lines = 4,
multiline_threshold = 20,
trim_scope = 'outer',
},
keys = {
{
'<leader>tc',
function()
require('treesitter-context').toggle()
end,
desc = '[T]oggle code [C]ontext',
},
},
}

View File

@ -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', '<leader>jm', function()
move.goto_next_start '@function.outer'
end, { desc = '[J]ump next [M]ethod start' })
vim.keymap.set('n', '<leader>jM', function()
move.goto_next_end '@function.outer'
end, { desc = '[J]ump next [M]ethod end' })
vim.keymap.set('n', '<leader>jk', function()
move.goto_previous_start '@function.outer'
end, { desc = '[J]ump previous method start' })
vim.keymap.set('n', '<leader>jK', function()
move.goto_previous_end '@function.outer'
end, { desc = '[J]ump previous method end' })
vim.keymap.set('n', '<leader>jc', function()
move.goto_next_start '@class.outer'
end, { desc = '[J]ump next [C]lass start' })
vim.keymap.set('n', '<leader>jC', function()
move.goto_previous_start '@class.outer'
end, { desc = '[J]ump previous class start' })
end,
}

View File

@ -0,0 +1,45 @@
return {
'folke/trouble.nvim',
cmd = { 'Trouble' },
opts = {},
keys = {
{
'<leader>xx',
function()
require('trouble').toggle 'diagnostics'
end,
desc = 'Trouble: all diagnostics',
},
{
'<leader>xw',
function()
require('trouble').toggle 'diagnostics'
end,
desc = 'Trouble: [W]orkspace diagnostics',
},
{
'<leader>xd',
function()
require('trouble').toggle {
mode = 'diagnostics',
filter = { buf = 0 },
}
end,
desc = 'Trouble: [D]ocument diagnostics',
},
{
'<leader>xq',
function()
require('trouble').toggle 'qflist'
end,
desc = 'Trouble: [Q]uickfix list',
},
{
'<leader>xl',
function()
require('trouble').toggle 'loclist'
end,
desc = 'Trouble: [L]ocation list',
},
},
}