aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/dot_config/nvim/lua/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'dot_config/nvim/lua/plugins')
-rw-r--r--dot_config/nvim/lua/plugins/ai.lua34
-rw-r--r--dot_config/nvim/lua/plugins/completion.lua86
-rw-r--r--dot_config/nvim/lua/plugins/debug.lua75
-rw-r--r--dot_config/nvim/lua/plugins/editing.lua61
-rw-r--r--dot_config/nvim/lua/plugins/git.lua123
-rw-r--r--dot_config/nvim/lua/plugins/init.lua58
-rw-r--r--dot_config/nvim/lua/plugins/lsp.lua280
-rw-r--r--dot_config/nvim/lua/plugins/runner.lua77
-rw-r--r--dot_config/nvim/lua/plugins/search.lua60
-rw-r--r--dot_config/nvim/lua/plugins/session.lua77
-rw-r--r--dot_config/nvim/lua/plugins/treesitter.lua83
-rw-r--r--dot_config/nvim/lua/plugins/ui.lua58
12 files changed, 1072 insertions, 0 deletions
diff --git a/dot_config/nvim/lua/plugins/ai.lua b/dot_config/nvim/lua/plugins/ai.lua
new file mode 100644
index 0000000..8c213b5
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/ai.lua
@@ -0,0 +1,34 @@
+require("copilot").setup({
+ suggestion = { enabled = false },
+ panel = { enabled = false },
+ server_opts_overrides = {
+ settings = {
+ telemetry = {
+ telemetryLevel = "off",
+ },
+ },
+ },
+ nes = {
+ enabled = true,
+ keymap = {
+ accept_and_goto = "<leader>p",
+ accept = false,
+ dismiss = "<Esc>",
+ },
+ },
+})
+
+-- Accept NES in insert mode (copilot.lua only binds normal mode)
+vim.keymap.set("i", "<C-f>", function()
+ local ok, nes = pcall(require, "copilot-lsp.nes")
+ if ok and nes.apply_pending_nes() then
+ return
+ end
+ -- Fallback: native <C-f> (scroll window forward)
+ local key = vim.api.nvim_replace_termcodes("<C-f>", true, false, true)
+ vim.api.nvim_feedkeys(key, "n", false)
+end, { desc = "Accept Copilot NES / scroll forward" })
+
+vim.keymap.set("n", "<leader>tc", function()
+ require("copilot.command").toggle()
+end, { desc = "[T]oggle [C]opilot attachment" })
diff --git a/dot_config/nvim/lua/plugins/completion.lua b/dot_config/nvim/lua/plugins/completion.lua
new file mode 100644
index 0000000..df24a5d
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/completion.lua
@@ -0,0 +1,86 @@
+require("blink.compat").setup({})
+
+require("blink.cmp").setup({
+ keymap = {
+ preset = "cmdline",
+ ["<CR>"] = { "accept", "fallback" },
+ },
+ appearance = {
+ use_nvim_cmp_as_default = true,
+ },
+ completion = {
+ menu = {
+ draw = {
+ columns = { { "kind_icon" }, { "label", gap = 1 } },
+ components = {
+ label = {
+ text = function(ctx)
+ return require("colorful-menu").blink_components_text(ctx)
+ end,
+ highlight = function(ctx)
+ return require("colorful-menu").blink_components_highlight(ctx)
+ end,
+ },
+ },
+ },
+ },
+ list = {
+ selection = {
+ preselect = function()
+ return not require("blink.cmp").snippet_active({ direction = 1 })
+ end,
+ },
+ },
+ documentation = { auto_show = true },
+ },
+ signature = {
+ enabled = true,
+ trigger = {
+ enabled = true,
+ show_on_keyword = true,
+ show_on_insert = true,
+ },
+ },
+ sources = {
+ default = { "lazydev", "lsp", "copilot", "snippets", "path", "buffer" },
+ per_filetype = {
+ ["dap-repl"] = { "dap" },
+ },
+ providers = {
+ path = {
+ opts = {
+ get_cwd = vim.fn.getcwd,
+ },
+ },
+ copilot = {
+ name = "copilot",
+ module = "blink-copilot",
+ score_offset = 100,
+ async = true,
+ },
+ lazydev = {
+ name = "LazyDev",
+ module = "lazydev.integrations.blink",
+ score_offset = 100,
+ },
+ dap = { name = "dap", module = "blink.compat.source" },
+ },
+ },
+})
+
+require("blink.pairs").setup({
+ mappings = {
+ disabled_filetypes = {},
+ },
+ highlights = {
+ groups = {
+ "BlinkIndentOrange",
+ "BlinkIndentViolet",
+ "BlinkIndentBlue",
+ "BlinkIndentRed",
+ "BlinkIndentCyan",
+ "BlinkIndentYellow",
+ "BlinkIndentGreen",
+ },
+ },
+})
diff --git a/dot_config/nvim/lua/plugins/debug.lua b/dot_config/nvim/lua/plugins/debug.lua
new file mode 100644
index 0000000..bef0d1c
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/debug.lua
@@ -0,0 +1,75 @@
+vim.keymap.set("n", "<leader>td", function()
+ require("debugmaster").mode.toggle()
+end, { desc = "[T]oggle [D]ebug mode" })
+
+local dap = require("dap")
+
+local function get_env_vars()
+ local variables = vim.fn.environ()
+ table.insert(variables, { ASAN_OPTIONS = "detect_leaks=0" })
+ return variables
+end
+
+dap.adapters.lldb = {
+ type = "executable",
+ command = "lldb-dap",
+ name = "lldb",
+ env = get_env_vars,
+}
+dap.adapters.gdb = {
+ type = "executable",
+ command = "gdb",
+ args = { "--interpreter=dap" },
+ env = get_env_vars,
+}
+dap.adapters.codelldb = {
+ type = "executable",
+ command = "codelldb",
+ env = get_env_vars,
+}
+
+local function get_program()
+ local _program
+ vim.ui.input({
+ prompt = "Program: ",
+ complete = "file_in_path",
+ }, function(res)
+ _program = res
+ end)
+ return vim.fn.system("which " .. _program):gsub("\n$", "")
+end
+
+local function get_args()
+ local _args
+ vim.ui.input({
+ prompt = "Args: ",
+ default = vim.fn.getreg("+"),
+ complete = "file",
+ }, function(res)
+ _args = res
+ end)
+ return require("dap.utils").splitstr(_args)
+end
+
+dap.configurations.cpp = {
+ {
+ name = "codelldb Launch",
+ type = "codelldb",
+ request = "launch",
+ cwd = "${workspaceFolder}",
+ program = get_program,
+ args = get_args,
+ stopOnEntry = true,
+ console = "integratedTerminal",
+ },
+}
+
+dap.configurations.c = dap.configurations.cpp
+dap.configurations.rust = dap.configurations.cpp
+
+require("nvim-dap-virtual-text").setup({})
+require("mason-nvim-dap").setup({
+ automatic_installation = false,
+ handlers = {},
+ ensure_installed = {},
+})
diff --git a/dot_config/nvim/lua/plugins/editing.lua b/dot_config/nvim/lua/plugins/editing.lua
new file mode 100644
index 0000000..5175516
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/editing.lua
@@ -0,0 +1,61 @@
+require("guess-indent").setup({})
+
+require("various-textobjs").setup({
+ keymaps = {
+ useDefaults = true,
+ },
+})
+
+-- dial.nvim: enhanced increment/decrement on standard vim keys
+vim.keymap.set("n", "<C-a>", function()
+ return require("dial.map").inc_normal()
+end, { expr = true, desc = "Increment" })
+vim.keymap.set("n", "<C-x>", function()
+ return require("dial.map").dec_normal()
+end, { expr = true, desc = "Decrement" })
+vim.keymap.set("v", "<C-a>", function()
+ return require("dial.map").inc_visual()
+end, { expr = true, desc = "Increment" })
+vim.keymap.set("v", "<C-x>", function()
+ return require("dial.map").dec_visual()
+end, { expr = true, desc = "Decrement" })
+vim.keymap.set("v", "g<C-a>", function()
+ return require("dial.map").inc_gvisual()
+end, { expr = true, desc = "Increment (sequential)" })
+vim.keymap.set("v", "g<C-x>", function()
+ return require("dial.map").dec_gvisual()
+end, { expr = true, desc = "Decrement (sequential)" })
+
+-- refactoring.nvim
+require("refactoring").setup({})
+
+vim.keymap.set("x", "<leader>re", function()
+ require("refactoring").refactor("Extract Function")
+end, { desc = "[R]efactor [E]xtract function" })
+vim.keymap.set("x", "<leader>rf", function()
+ require("refactoring").refactor("Extract Function To File")
+end, { desc = "[R]efactor extract function to [F]ile" })
+vim.keymap.set("x", "<leader>rv", function()
+ require("refactoring").refactor("Extract Variable")
+end, { desc = "[R]efactor extract [V]ariable" })
+vim.keymap.set("n", "<leader>rI", function()
+ require("refactoring").refactor("Inline Function")
+end, { desc = "[R]efactor [I]nline function" })
+vim.keymap.set({ "x", "n" }, "<leader>ri", function()
+ require("refactoring").refactor("Inline Variable")
+end, { desc = "[R]efactor [I]nline variable" })
+vim.keymap.set("n", "<leader>rb", function()
+ require("refactoring").refactor("Extract Block")
+end, { desc = "[R]efactor extract [B]lock" })
+vim.keymap.set("n", "<leader>rB", function()
+ require("refactoring").refactor("Extract Block To File")
+end, { desc = "[R]efactor extract [B]lock to file" })
+vim.keymap.set("n", "<leader>rp", function()
+ require("refactoring").debug.printf({})
+end, { desc = "[R]efactor [P]rint" })
+vim.keymap.set({ "x", "n" }, "<leader>rV", function()
+ require("refactoring").debug.print_var({})
+end, { desc = "[R]efactor [P]rint [V]ariable" })
+vim.keymap.set("n", "<leader>rc", function()
+ require("refactoring").debug.cleanup({})
+end, { desc = "[R]efactor [C]leanup" })
diff --git a/dot_config/nvim/lua/plugins/git.lua b/dot_config/nvim/lua/plugins/git.lua
new file mode 100644
index 0000000..b052c33
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/git.lua
@@ -0,0 +1,123 @@
+require("git-conflict").setup({
+ disable_diagnostics = true,
+ default_mappings = {
+ next = "]x",
+ prev = "[x",
+ },
+})
+
+require("neogit").setup({
+ disable_commit_confirmation = true,
+ kind = "split",
+ console_timeout = 5000,
+ auto_show_console = false,
+})
+
+vim.keymap.set("n", "<leader>go", function()
+ require("neogit").open()
+end, { desc = "neo[G]it [O]pen" })
+
+require("gitlinker").setup({
+ callbacks = {
+ ["git.sommerfeld.dev"] = function(url_data)
+ local url = require("gitlinker.hosts").get_base_https_url(url_data)
+ url = url .. "/tree/" .. url_data.file .. "?id=" .. url_data.rev
+ if url_data.lstart then
+ url = url .. "#n" .. url_data.lstart
+ end
+ return url
+ end,
+ },
+})
+
+vim.keymap.set("n", "<leader>gy", function()
+ require("gitlinker").get_buf_range_url("n")
+end)
+vim.keymap.set("v", "<leader>gy", function()
+ require("gitlinker").get_buf_range_url("v")
+end)
+
+require("gitsigns").setup({
+ signs = {
+ change = { show_count = true },
+ delete = { show_count = true },
+ topdelete = { show_count = true },
+ changedelete = { show_count = true },
+ },
+ numhl = true,
+ on_attach = function(bufnr)
+ local gs = require("gitsigns")
+ local function map(mode, l, r, desc)
+ vim.keymap.set(mode, l, r, { buffer = bufnr, desc = desc })
+ end
+ local function nmap(l, r, desc)
+ map("n", l, r, desc)
+ end
+ local function vmap(l, r, desc)
+ map("v", l, r, desc)
+ end
+ -- Navigation
+ nmap("]c", function()
+ if vim.wo.diff then
+ vim.cmd.normal({ "]c", bang = true })
+ else
+ gs.nav_hunk("next")
+ end
+ end, "Jump to next git [c]hange")
+
+ nmap("[c", function()
+ if vim.wo.diff then
+ vim.cmd.normal({ "[c", bang = true })
+ else
+ gs.nav_hunk("prev")
+ end
+ end, "Jump to previous git [c]hange")
+
+ -- Actions
+ nmap("<leader>hs", gs.stage_hunk, "git [s]tage hunk")
+ nmap("<leader>hr", gs.reset_hunk, "git [r]eset hunk")
+ vmap("<leader>hs", function()
+ gs.stage_hunk({ vim.fn.line("."), vim.fn.line("v") })
+ end, "git [s]tage hunk")
+ vmap("<leader>hr", function()
+ gs.reset_hunk({ vim.fn.line("."), vim.fn.line("v") })
+ end, "git [r]eset hunk")
+ nmap("<leader>hS", gs.stage_buffer, "git [S]tage buffer")
+ nmap("<leader>hR", gs.reset_buffer, "git [R]eset buffer")
+ nmap("<leader>hp", gs.preview_hunk, "git [p]review hunk")
+ nmap("<leader>hb", function()
+ gs.blame_line({ full = true })
+ end, "git [b]lame line")
+ nmap(
+ "<leader>tb",
+ gs.toggle_current_line_blame,
+ "[T]oggle git show [b]lame line"
+ )
+ nmap("<leader>hd", gs.diffthis, "git [d]iff against index")
+ nmap("<leader>hD", function()
+ gs.diffthis("~")
+ end, "git [D]iff against last commit")
+ nmap("<leader>hc", gs.change_base, "git [C]hange base to index")
+ nmap("<leader>hC", function()
+ gs.change_base("~")
+ end, "git [C]hange base to HEAD")
+ nmap(
+ "<leader>tgd",
+ gs.preview_hunk_inline,
+ "[T]oggle [G]it show [D]eleted"
+ )
+ nmap("<leader>tgw", gs.toggle_word_diff, "[T]oggle [G]it [W]ord diff")
+ nmap(
+ "<leader>tgl",
+ gs.toggle_linehl,
+ "[T]oggle [G]it [L]ine highlighting"
+ )
+ -- Text object
+ map(
+ { "o", "x" },
+ "ih",
+ ":<C-U>Gitsigns select_hunk<CR>",
+ "git [H]unk text object"
+ )
+ end,
+})
diff --git a/dot_config/nvim/lua/plugins/init.lua b/dot_config/nvim/lua/plugins/init.lua
new file mode 100644
index 0000000..b106b6e
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/init.lua
@@ -0,0 +1,58 @@
+-- Seamless navigation between neovim splits and zellij panes
+require("smart-splits").setup({})
+vim.keymap.set("n", "<C-h>", require("smart-splits").move_cursor_left, { desc = "Move to left split/pane" })
+vim.keymap.set("n", "<C-j>", require("smart-splits").move_cursor_down, { desc = "Move to below split/pane" })
+vim.keymap.set("n", "<C-k>", require("smart-splits").move_cursor_up, { desc = "Move to above split/pane" })
+vim.keymap.set("n", "<C-l>", require("smart-splits").move_cursor_right, { desc = "Move to right split/pane" })
+
+require("which-key").setup({
+ spec = {
+ { "g", group = "[G]oto" },
+ { "yo", group = "Toggle options" },
+ { "]", group = "Navigate to next" },
+ { "[", group = "Navigate to previous" },
+ { "<leader>c", group = "[C]ode", mode = { "n", "x" } },
+ { "<leader>g", group = "[G]it" },
+ { "<leader>h", group = "Git [H]unk", mode = { "n", "v" } },
+ { "<leader>o", group = "[O]verseer" },
+ { "<leader>r", group = "[R]efactor" },
+ { "<leader>w", group = "[W]orkspace" },
+ { "<leader>t", group = "[T]oggle" },
+ },
+})
+
+vim.keymap.set("n", "<leader>?", function()
+ require("which-key").show({ global = false })
+end, { desc = "Buffer Local Keymaps (which-key)" })
+
+require("quicker").setup({
+ keys = {
+ {
+ ">",
+ function()
+ require("quicker").expand({
+ before = 2,
+ after = 2,
+ add_to_existing = true,
+ })
+ end,
+ desc = "Expand quickfix context",
+ },
+ {
+ "<",
+ function()
+ require("quicker").collapse()
+ end,
+ desc = "Collapse quickfix context",
+ },
+ },
+})
+
+vim.keymap.set("n", "<leader>tq", function()
+ require("quicker").toggle()
+end, { desc = "[T]oggle [Q]uickfix" })
+vim.keymap.set("n", "<leader>tl", function()
+ require("quicker").toggle({ loclist = true })
+end, { desc = "[T]oggle [L]oclist" })
+
+require("oil").setup({})
diff --git a/dot_config/nvim/lua/plugins/lsp.lua b/dot_config/nvim/lua/plugins/lsp.lua
new file mode 100644
index 0000000..ddd5bea
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/lsp.lua
@@ -0,0 +1,280 @@
+require("lazydev").setup({
+ library = {
+ { path = "${3rd}/luv/library", words = { "vim%.uv" } },
+ },
+})
+
+vim.lsp.enable("just")
+pcall(vim.lsp.enable, "tblgen_lsp_server")
+
+require("fidget").setup({})
+require("mason").setup({})
+require("mason-lspconfig").setup({
+ ensure_installed = {},
+ automatic_installation = false,
+ handlers = {
+ function(server_name)
+ vim.lsp.enable(server_name)
+ end,
+ },
+})
+require("mason-tool-installer").setup({
+ ensure_installed = {
+ "actionlint",
+ "autotools-language-server",
+ "basedpyright",
+ "bash-language-server",
+ "clangd",
+ "codelldb",
+ "codespell",
+ "css-lsp",
+ "dockerfile-language-server",
+ "gh",
+ "gh-actions-language-server",
+ "groovy-language-server",
+ "hadolint",
+ "html-lsp",
+ "jq",
+ "json-lsp",
+ "jsonlint",
+ "just-lsp",
+ "lua-language-server",
+ "markdownlint",
+ "mdformat",
+ "neocmakelsp",
+ "nginx-config-formatter",
+ "nginx-language-server",
+ "npm-groovy-lint",
+ "prettier",
+ "ruff",
+ "rust-analyzer",
+ "shellcheck",
+ "shellharden",
+ "shfmt",
+ "stylelint",
+ "stylua",
+ "systemd-lsp",
+ "systemdlint",
+ "typescript-language-server",
+ "typos",
+ "yaml-language-server",
+ "yamllint",
+ "yq",
+ },
+})
+
+vim.api.nvim_create_autocmd("LspAttach", {
+ group = vim.api.nvim_create_augroup("lsp-attach", { clear = true }),
+ callback = function(event)
+ local bufnr = event.buf
+
+ local function map(mode, l, r, desc)
+ vim.keymap.set(mode, l, r, { buffer = bufnr, desc = "LSP: " .. desc })
+ end
+ local function nmap(l, r, desc)
+ map("n", l, r, desc)
+ end
+ nmap("<c-]>", vim.lsp.buf.definition, "Goto definition")
+ nmap("gD", vim.lsp.buf.declaration, "[G]oto [D]eclaration")
+
+ local fzf = require("fzf-lua")
+ nmap("gd", fzf.lsp_definitions, "[G]oto [D]efinition")
+ nmap("gvd", function()
+ fzf.lsp_definitions({ jump1_action = fzf.actions.file_vsplit })
+ end, "[G]oto in a [V]ertical split to [D]efinition")
+ nmap("gxd", function()
+ fzf.lsp_definitions({ jump1_action = fzf.actions.file_split })
+ end, "[G]oto in a [X]horizontal split to [D]efinition")
+ nmap("gtd", function()
+ fzf.lsp_definitions({ jump1_action = fzf.actions.file_tabedit })
+ end, "[G]oto in a [T]ab to [D]efinition")
+ nmap("gvt", function()
+ fzf.lsp_typedefs({ jump1_action = fzf.actions.file_vsplit })
+ end, "[G]oto in a [V]ertical split to [T]ype definition")
+ nmap("gxt", function()
+ fzf.lsp_typedefs({ jump1_action = fzf.actions.file_split })
+ end, "[G]oto in a [X]horizontal split to [T]ype definition")
+ nmap("gtt", function()
+ fzf.lsp_typedefs({ jump1_action = fzf.actions.file_tabedit })
+ end, "[G]oto in a [T]ab to [T]ype definition")
+ nmap("gri", fzf.lsp_implementations, "[G]oto [I]mplementation")
+ nmap("grvi", function()
+ fzf.lsp_implementations({ jump1_action = fzf.actions.file_vsplit })
+ end, "[G]oto in a [V]ertical split to [I]mplementation")
+ nmap("grxi", function()
+ fzf.lsp_implementations({ jump1_action = fzf.actions.file_split })
+ end, "[G]oto in a [X]horizontal split to [I]mplementation")
+ nmap("grti", function()
+ fzf.lsp_implementations({ jump1_action = fzf.actions.file_tabedit })
+ end, "[G]oto in a [T]ab to [I]mplementation")
+ nmap("grr", fzf.lsp_references, "[G]oto [R]eferences")
+ nmap("gvr", function()
+ fzf.lsp_references({ jump1_action = fzf.actions.file_vsplit })
+ end, "[G]oto in a [V]ertical split to [R]eferences")
+ nmap("gxr", function()
+ fzf.lsp_references({ jump1_action = fzf.actions.file_split })
+ end, "[G]oto in a [X]horizontal split to [R]eferences")
+ nmap("gtr", function()
+ fzf.lsp_references({ jump1_action = fzf.actions.file_tabedit })
+ end, "[G]oto in a [T]ab to [R]eferences")
+ nmap("<leader>ci", fzf.lsp_incoming_calls, "[C]ode [I]ncoming calls")
+ nmap("<leader>co", fzf.lsp_outgoing_calls, "[C]ode [O]utgoing calls")
+ nmap("gO", fzf.lsp_document_symbols, "d[O]ocument symbols")
+ nmap(
+ "<leader>ws",
+ fzf.lsp_live_workspace_symbols,
+ "[W]orkspace [S]ymbols"
+ )
+ nmap(
+ "<leader>wd",
+ fzf.diagnostics_workspace,
+ "[W]orkspace [D]iagnostics"
+ )
+
+ local client = vim.lsp.get_client_by_id(event.data.client_id)
+ if
+ client
+ and client:supports_method(
+ vim.lsp.protocol.Methods.textDocument_documentHighlight,
+ event.buf
+ )
+ then
+ local highlight_augroup =
+ vim.api.nvim_create_augroup("lsp-highlight", { clear = false })
+ vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
+ buffer = event.buf,
+ group = highlight_augroup,
+ callback = vim.lsp.buf.document_highlight,
+ })
+
+ vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
+ buffer = event.buf,
+ group = highlight_augroup,
+ callback = vim.lsp.buf.clear_references,
+ })
+
+ vim.api.nvim_create_autocmd("LspDetach", {
+ group = vim.api.nvim_create_augroup(
+ "lsp-detach",
+ { clear = true }
+ ),
+ callback = function(event2)
+ vim.lsp.buf.clear_references()
+ vim.api.nvim_clear_autocmds({
+ group = "lsp-highlight",
+ buffer = event2.buf,
+ })
+ end,
+ })
+ end
+
+ if
+ client
+ and client:supports_method(
+ vim.lsp.protocol.Methods.textDocument_codeLens,
+ event.buf
+ )
+ then
+ vim.lsp.codelens.enable(true, { bufnr = bufnr })
+ end
+
+ if
+ client
+ and client:supports_method(
+ vim.lsp.protocol.Methods.textDocument_inlayHint,
+ event.buf
+ )
+ then
+ nmap("<leader>th", function()
+ vim.lsp.inlay_hint.enable(
+ not vim.lsp.inlay_hint.is_enabled(event.buf)
+ )
+ end, "[T]oggle Inlay [H]ints")
+ end
+ end,
+})
+
+require("conform").setup({
+ formatters_by_ft = {
+ awk = { "gawk" },
+ bash = { "shfmt" },
+ cmake = { "cmake_format" },
+ css = { "prettier", "stylelint" },
+ groovy = { "npm-groovy-lint" },
+ html = { "prettier" },
+ javascript = { "prettier" },
+ typescript = { "prettier" },
+ jenkins = { "npm-groovy-lint" },
+ json = { "jq", "jsonlint" },
+ jsonc = { "prettier" },
+ just = { "just" },
+ markdown = { "mdformat" },
+ nginx = { "nginxfmt" },
+ lua = { "stylua" },
+ python = { "ruff_format", "ruff_fix", "ruff_organize_imports" },
+ rust = { "rustfmt" },
+ sh = { "shfmt", "shellcheck", "shellharden" },
+ yaml = { "yamllint" },
+ zsh = { "shfmt", "shellcheck", "shellharden" },
+ },
+ default_format_opts = {
+ lsp_format = "fallback",
+ },
+ formatters = {
+ shfmt = {
+ prepend_args = { "-i", "2" },
+ },
+ },
+})
+vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
+
+vim.keymap.set("", "<leader>f", function()
+ require("conform").format({ async = true, lsp_fallback = true })
+end, { desc = "[F]ormat buffer" })
+
+local lint = require("lint")
+lint.linters_by_ft = {
+ css = { "stylelint" },
+ dockerfile = { "hadolint" },
+ groovy = { "npm-groovy-lint" },
+ jenkins = { "npm-groovy-lint" },
+ json = { "jsonlint" },
+ markdown = { "markdownlint" },
+ makefile = { "checkmake" },
+ systemd = { "systemdlint" },
+ yaml = { "yamllint", "yq" },
+ ghaction = { "actionlint" },
+ zsh = { "zsh" },
+ ["*"] = { "codespell", "typos" },
+}
+vim.api.nvim_create_autocmd({ "BufReadPost", "BufWritePost" }, {
+ group = vim.api.nvim_create_augroup("lint", { clear = true }),
+ callback = function()
+ if vim.opt_local.modifiable:get() then
+ lint.try_lint()
+ end
+ end,
+})
+
+require("tiny-inline-diagnostic").setup({
+ options = {
+ show_source = {
+ if_many = true,
+ },
+ set_arrow_to_diag_color = true,
+ multilines = {
+ enabled = true,
+ },
+ show_all_diags_on_cursorline = true,
+ enable_on_select = true,
+ break_line = {
+ enabled = true,
+ },
+ severity = {
+ vim.diagnostic.severity.ERROR,
+ vim.diagnostic.severity.WARN,
+ vim.diagnostic.severity.INFO,
+ vim.diagnostic.severity.HINT,
+ },
+ },
+})
diff --git a/dot_config/nvim/lua/plugins/runner.lua b/dot_config/nvim/lua/plugins/runner.lua
new file mode 100644
index 0000000..28e4e5f
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/runner.lua
@@ -0,0 +1,77 @@
+local overseer = require("overseer")
+overseer.setup({})
+overseer.add_template_hook({ name = ".*" }, function(task_defn, util)
+ util.add_component(task_defn, {
+ "open_output",
+ on_start = "never",
+ on_complete = "failure",
+ direction = "vertical",
+ })
+end)
+
+vim.keymap.set("n", "<leader>to", function()
+ overseer.toggle()
+end, { desc = "[T]oggle [O]verseer" })
+vim.keymap.set("n", "<leader>ob", function()
+ overseer.run_task({ name = "just build", disallow_prompt = true })
+end, { desc = "[O]verseer [B]uild" })
+vim.keymap.set("n", "<leader>oB", function()
+ overseer.run_task({ name = "just build" })
+end, { desc = "[O]verseer [B]uild" })
+vim.keymap.set("n", "<leader>ot", function()
+ overseer.run_task({ name = "just test", disallow_prompt = true })
+end, { desc = "[O]verseer [J]ust [T]est" })
+vim.keymap.set("n", "<leader>oT", function()
+ overseer.run_task({ name = "just test" })
+end, { desc = "[O]verseer [J]ust [T]est" })
+vim.keymap.set("n", "<leader>of", function()
+ overseer.run_task({
+ name = "just test",
+ disallow_prompt = true,
+ params = { target = vim.fn.expand("%") },
+ })
+end, { desc = "[O]verseer test [F]ile" })
+vim.keymap.set("n", "<leader>oF", function()
+ overseer.run_task({
+ name = "just test",
+ params = { target = vim.fn.expand("%") },
+ })
+end, { desc = "[O]verseer test [F]ile" })
+vim.keymap.set("n", "<leader>od", function()
+ overseer.run_task({
+ name = "just debug=true test",
+ disallow_prompt = true,
+ params = { target = vim.fn.expand("%") },
+ })
+end, { desc = "[O]verseer [d]ebug test file" })
+vim.keymap.set("n", "<leader>oD", function()
+ overseer.run_task({
+ name = "just debug=true test",
+ params = { target = vim.fn.expand("%") },
+ })
+end, { desc = "[O]verseer [D]ebug test file" })
+vim.keymap.set("n", "<leader>oa", function()
+ overseer.run_task({
+ name = "just test_autofix",
+ disallow_prompt = true,
+ params = { target = vim.fn.expand("%") },
+ })
+end, { desc = "[O]verseer [A]utofix" })
+vim.keymap.set("n", "<leader>or", function()
+ overseer.run_task()
+end, { desc = "[O]verseer [R]un" })
+vim.keymap.set("n", "<leader>os", function()
+ vim.cmd("OverseerShell")
+end, { desc = "[O]verseer [S]hell" })
+vim.keymap.set("n", "<leader>ol", function()
+ local tasks = overseer.list_tasks({
+ sort = function(a, b)
+ return a.id > b.id
+ end,
+ })
+ if vim.tbl_isempty(tasks) then
+ vim.notify("No tasks found", vim.log.levels.WARN)
+ else
+ overseer.run_action(tasks[1], "restart")
+ end
+end, { desc = "[O]verseer run [L]ast" })
diff --git a/dot_config/nvim/lua/plugins/search.lua b/dot_config/nvim/lua/plugins/search.lua
new file mode 100644
index 0000000..a36cddc
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/search.lua
@@ -0,0 +1,60 @@
+local fzflua = require("fzf-lua")
+fzflua.setup({
+ keymap = {
+ builtin = {
+ true,
+ ["<M-p>"] = "toggle-preview",
+ },
+ },
+ grep = {
+ hidden = true,
+ RIPGREP_CONFIG_PATH = "~/.config/ripgrep/ripgreprc",
+ },
+ lsp = {
+ includeDeclaration = false,
+ },
+ actions = {
+ files = {
+ true,
+ ["ctrl-x"] = fzflua.actions.file_split,
+ },
+ },
+})
+fzflua.register_ui_select()
+
+vim.keymap.set("n", "<localleader>b", function()
+ fzflua.buffers()
+end, { desc = "fzf-lua [B]uffers" })
+vim.keymap.set("n", "<localleader>/", function()
+ fzflua.live_grep()
+end, { desc = "fzf-lua live grep" })
+vim.keymap.set("n", "<localleader>f", function()
+ fzflua.files()
+end, { desc = "fzf-lua [F]iles" })
+vim.keymap.set("n", "<leader><leader>", function()
+ fzflua.global()
+end, { desc = "fzf-lua global picker" })
+vim.keymap.set("n", "<localleader>d", function()
+ fzflua.diagnostics()
+end, { desc = "fzf-lua [D]iagnostics" })
+vim.keymap.set("n", "<localleader>r", function()
+ fzflua.resume()
+end, { desc = "fzf-lua [R]esume" })
+vim.keymap.set("n", "<localleader>gc", function()
+ fzflua.git_bcommits()
+end, { desc = "[G]it buffer [C]commits" })
+vim.keymap.set("v", "<localleader>gc", function()
+ fzflua.git_bcommits_range()
+end, { desc = "[G]it [C]commits for selected range" })
+vim.keymap.set("n", "<localleader>gC", function()
+ fzflua.git_commits()
+end, { desc = "[G]it (all) [C]commits" })
+vim.keymap.set("n", "<localleader>gb", function()
+ fzflua.git_branches()
+end, { desc = "[G]it [B]ranches" })
+vim.keymap.set("n", "<localleader>gs", function()
+ fzflua.git_status()
+end, { desc = "[G]it [S]tatus" })
+vim.keymap.set("n", "<localleader>gS", function()
+ fzflua.git_stash()
+end, { desc = "[G]it [S]tash" })
diff --git a/dot_config/nvim/lua/plugins/session.lua b/dot_config/nvim/lua/plugins/session.lua
new file mode 100644
index 0000000..a094727
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/session.lua
@@ -0,0 +1,77 @@
+local function get_cwd_as_name()
+ local dir = vim.fn.getcwd(0)
+ return dir:gsub("[^A-Za-z0-9]", "_")
+end
+local overseer = require("overseer")
+
+require("auto-session").setup({
+ use_git_branch = true,
+ pre_save_cmds = {
+ function()
+ overseer.save_task_bundle(
+ get_cwd_as_name(),
+ nil,
+ { on_conflict = "overwrite" }
+ )
+ end,
+ },
+ pre_restore_cmds = {
+ function()
+ for _, task in ipairs(overseer.list_tasks({})) do
+ task:dispose(true)
+ end
+ end,
+ },
+ post_restore_cmds = {
+ function()
+ overseer.load_task_bundle(
+ get_cwd_as_name(),
+ { ignore_missing = true, autostart = false }
+ )
+ end,
+ },
+ save_extra_data = function(_)
+ local ok, breakpoints = pcall(require, "dap.breakpoints")
+ if not ok or not breakpoints then
+ return
+ end
+
+ local bps = {}
+ local breakpoints_by_buf = breakpoints.get()
+ for buf, buf_bps in pairs(breakpoints_by_buf) do
+ bps[vim.api.nvim_buf_get_name(buf)] = buf_bps
+ end
+ if vim.tbl_isempty(bps) then
+ return
+ end
+ local extra_data = {
+ breakpoints = bps,
+ }
+ return vim.fn.json_encode(extra_data)
+ end,
+
+ restore_extra_data = function(_, extra_data)
+ local json = vim.fn.json_decode(extra_data)
+
+ if json.breakpoints then
+ local ok, breakpoints = pcall(require, "dap.breakpoints")
+
+ if not ok or not breakpoints then
+ return
+ end
+ vim.notify("restoring breakpoints")
+ for buf_name, buf_bps in pairs(json.breakpoints) do
+ for _, bp in pairs(buf_bps) do
+ local line = bp.line
+ local opts = {
+ condition = bp.condition,
+ log_message = bp.logMessage,
+ hit_condition = bp.hitCondition,
+ }
+ breakpoints.set(opts, vim.fn.bufnr(buf_name), line)
+ end
+ end
+ end
+ end,
+ suppressed_dirs = { "~/", "/" },
+})
diff --git a/dot_config/nvim/lua/plugins/treesitter.lua b/dot_config/nvim/lua/plugins/treesitter.lua
new file mode 100644
index 0000000..a4a488c
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/treesitter.lua
@@ -0,0 +1,83 @@
+require("treewalker").setup({})
+
+vim.keymap.set({ "n", "v" }, "<a-k>", "<cmd>Treewalker Up<cr>", { silent = true, desc = "Moves up to the previous neighbor node" })
+vim.keymap.set({ "n", "v" }, "<a-j>", "<cmd>Treewalker Down<cr>", { silent = true, desc = "Moves up to the next neighbor node" })
+vim.keymap.set({ "n", "v" }, "<a-h>", "<cmd>Treewalker Left<cr>", { silent = true, desc = "Moves to the first ancestor node that's on a different line from the current node" })
+vim.keymap.set({ "n", "v" }, "<a-l>", "<cmd>Treewalker Right<cr>", { silent = true, desc = "Moves to the next node down that's indented further than the current node" })
+vim.keymap.set("n", "<s-a-k>", "<cmd>Treewalker SwapUp<cr>", { silent = true, desc = "Swaps the highest node on the line upwards in the document" })
+vim.keymap.set("n", "<s-a-j>", "<cmd>Treewalker SwapDown<cr>", { silent = true, desc = "Swaps the biggest node on the line downward in the document" })
+vim.keymap.set("n", "<s-a-h>", "<cmd>Treewalker SwapLeft<cr>", { silent = true, desc = "Swap the node under the cursor with its previous neighbor" })
+vim.keymap.set("n", "<s-a-l>", "<cmd>Treewalker SwapRight<cr>", { silent = true, desc = "Swap the node under the cursor with its next neighbor" })
+
+require("nvim-treesitter").install({
+ "awk",
+ "bash",
+ "c",
+ "cmake",
+ "comment",
+ "cpp",
+ "css",
+ "csv",
+ "diff",
+ "dockerfile",
+ "doxygen",
+ "editorconfig",
+ "fortran",
+ "git_config",
+ "git_rebase",
+ "gitattributes",
+ "gitcommit",
+ "gitignore",
+ "groovy",
+ "gpg",
+ "hlsplaylist",
+ "html",
+ "http",
+ "ini",
+ "javascript",
+ "jq",
+ "jsdoc",
+ "json",
+ "just",
+ "llvm",
+ "lua",
+ "luadoc",
+ "luap",
+ "make",
+ "markdown",
+ "markdown_inline",
+ "query",
+ "passwd",
+ "printf",
+ "python",
+ "regex",
+ "readline",
+ "requirements",
+ "rust",
+ "sql",
+ "ssh_config",
+ "strace",
+ "tablegen",
+ "todotxt",
+ "toml",
+ "typescript",
+ "vim",
+ "vimdoc",
+ "xcompose",
+ "xml",
+ "xresources",
+ "yaml",
+})
+
+require("nvim-dap-repl-highlights").setup({})
+require("treesitter-context").setup({})
+
+require("ts_context_commentstring").setup({
+ enable_autocmd = false,
+})
+local get_option = vim.filetype.get_option
+vim.filetype.get_option = function(filetype, option)
+ return option == "commentstring"
+ and require("ts_context_commentstring.internal").calculate_commentstring()
+ or get_option(filetype, option)
+end
diff --git a/dot_config/nvim/lua/plugins/ui.lua b/dot_config/nvim/lua/plugins/ui.lua
new file mode 100644
index 0000000..50a2114
--- /dev/null
+++ b/dot_config/nvim/lua/plugins/ui.lua
@@ -0,0 +1,58 @@
+-- blink.indent (gruvbox setup is in init.lua)
+require("blink.indent").setup({
+ scope = {
+ highlights = {
+ "BlinkIndentOrange",
+ "BlinkIndentViolet",
+ "BlinkIndentBlue",
+ "BlinkIndentRed",
+ "BlinkIndentCyan",
+ "BlinkIndentYellow",
+ "BlinkIndentGreen",
+ },
+ underline = {
+ enabled = true,
+ highlights = {
+ "BlinkIndentOrangeUnderline",
+ "BlinkIndentVioletUnderline",
+ "BlinkIndentBlueUnderline",
+ "BlinkIndentRedUnderline",
+ "BlinkIndentCyanUnderline",
+ "BlinkIndentYellowUnderline",
+ "BlinkIndentGreenUnderline",
+ },
+ },
+ },
+})
+
+require("lualine").setup({
+ options = {
+ icons_enabled = false,
+ theme = "gruvbox_dark",
+ component_separators = "",
+ section_separators = "|",
+ disabled_filetypes = {
+ winbar = {
+ "dap-view",
+ "dap-repl",
+ "dap-view-term",
+ },
+ },
+ },
+ sections = {
+ lualine_a = { "filetype", { "filename", path = 1 } },
+ lualine_b = { "%l/%L:%c:%o" },
+ lualine_c = { "diff" },
+ lualine_x = { "searchcount", "selectioncount" },
+ lualine_y = { "overseer", "copilot" },
+ lualine_z = { "diagnostics" },
+ },
+ inactive_sections = {
+ lualine_a = {},
+ lualine_b = {},
+ lualine_c = { "filename" },
+ lualine_x = {},
+ lualine_y = {},
+ lualine_z = {},
+ },
+})