From a5e8bbeb9d79d905a193e95a39acd29bc37e6c66 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Wed, 16 Sep 2026 08:47:13 +0200 Subject: Updated dotfiles --- neovim/.config/nvim/lua/plugins/claude-code.lua | 1 + neovim/.config/nvim/lua/plugins/colorscheme.lua | 8 + neovim/.config/nvim/lua/plugins/dap-python.lua | 71 +++++++++ neovim/.config/nvim/lua/plugins/dap.lua | 181 ++++++++++++++++++++++ neovim/.config/nvim/lua/plugins/editing.lua | 10 -- neovim/.config/nvim/lua/plugins/fuzzyfinder.lua | 36 ++++- neovim/.config/nvim/lua/plugins/git.lua | 5 +- neovim/.config/nvim/lua/plugins/indent-detect.lua | 8 + neovim/.config/nvim/lua/plugins/langs.lua | 14 -- neovim/.config/nvim/lua/plugins/overseer.lua | 57 +++++++ neovim/.config/nvim/lua/plugins/statusline.lua | 24 +-- neovim/.config/nvim/lua/plugins/toggleterm.lua | 18 +++ neovim/.config/nvim/lua/plugins/which-key.lua | 17 ++ 13 files changed, 397 insertions(+), 53 deletions(-) create mode 100644 neovim/.config/nvim/lua/plugins/dap-python.lua create mode 100644 neovim/.config/nvim/lua/plugins/dap.lua create mode 100644 neovim/.config/nvim/lua/plugins/indent-detect.lua delete mode 100644 neovim/.config/nvim/lua/plugins/langs.lua create mode 100644 neovim/.config/nvim/lua/plugins/overseer.lua create mode 100644 neovim/.config/nvim/lua/plugins/toggleterm.lua create mode 100644 neovim/.config/nvim/lua/plugins/which-key.lua (limited to 'neovim/.config/nvim/lua/plugins') diff --git a/neovim/.config/nvim/lua/plugins/claude-code.lua b/neovim/.config/nvim/lua/plugins/claude-code.lua index 0390852..b2e881f 100644 --- a/neovim/.config/nvim/lua/plugins/claude-code.lua +++ b/neovim/.config/nvim/lua/plugins/claude-code.lua @@ -1,5 +1,6 @@ return { "greggh/claude-code.nvim", + lazy = false, dependencies = { "nvim-lua/plenary.nvim" }, cmd = { "ClaudeCode", "ClaudeCodeContinue", "ClaudeCodeResume", "ClaudeCodeVerbose" }, config = function() diff --git a/neovim/.config/nvim/lua/plugins/colorscheme.lua b/neovim/.config/nvim/lua/plugins/colorscheme.lua index 457dc71..0349cf9 100644 --- a/neovim/.config/nvim/lua/plugins/colorscheme.lua +++ b/neovim/.config/nvim/lua/plugins/colorscheme.lua @@ -6,6 +6,14 @@ return { local ok = pcall(vim.cmd.colorscheme, "janah") if not ok then vim.cmd.colorscheme("desert") + return end + + -- vim-janah predates floating windows and never defines NormalFloat/ + -- FloatBorder, so they fall back to Neovim's near-black default and any + -- floating UI (:Mason, :Lazy, which-key's popup, ...) renders as a + -- mismatched black box. Match them to janah's own Normal/Comment colors. + vim.api.nvim_set_hl(0, "NormalFloat", { bg = "#262626", fg = "#dadada" }) + vim.api.nvim_set_hl(0, "FloatBorder", { bg = "#262626", fg = "#585858" }) end, } diff --git a/neovim/.config/nvim/lua/plugins/dap-python.lua b/neovim/.config/nvim/lua/plugins/dap-python.lua new file mode 100644 index 0000000..b61e0f4 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/dap-python.lua @@ -0,0 +1,71 @@ +-- Python launch configs (nvim-dap-python), wired to the debugpy adapter +-- that mason-nvim-dap.nvim installs (dap.lua). Kept in its own file since +-- this is the "per-language" half of debugging, parallel to how +-- ftplugin/python.lua holds Python-only settings. +return { + "mfussenegger/nvim-dap-python", + -- Not left to lazy-load off `ft = "python"`: dap.lua's dc picker + -- works from any window (not just a Python buffer) and needs + -- dap.adapters.python already registered by the time a config is picked, + -- even if no .py buffer has been opened yet this session. + lazy = false, + -- mason.nvim is listed directly (not just transitively via dap.lua) + -- because config() below needs require("mason-registry") to be loadable + -- from startup, same reasoning as lazy = false above. + dependencies = { "mfussenegger/nvim-dap", "mason-org/mason.nvim" }, + config = function() + local registry = require("mason-registry") + local pkg = registry.get_package("debugpy") + + -- debugpy_path is the interpreter that runs the debug *adapter* itself + -- (Mason's isolated venv) - it does not control which Python runs your + -- script. dap-python defaults that to the active venv/system python3; + -- project-specific venvs may need a manual `pythonPath` override in a + -- generated launch config later. + local debugpy_path = pkg:get_install_path() .. "/venv/bin/python" + + local function setup() + require("dap-python").setup(debugpy_path) + + -- nvim-dap-python doesn't expose adapter.options for tuning, and + -- nvim-dap's default terminate-request timeout (3s) is tight enough + -- that debugpy's real response can arrive just after nvim-dap already + -- gave up and moved on ("No callback found" in dap.log) - dt + -- still works, but dap.session() doesn't clear for a few extra + -- seconds, so dc right after can catch it still "active". + -- Wrap the adapter dap-python just registered to give it more room. + local dap = require("dap") + local base_adapter = dap.adapters.python + dap.adapters.python = function(cb, config) + base_adapter(function(adapter) + adapter.options = adapter.options or {} + adapter.options.disconnect_timeout_sec = 8 + cb(adapter) + end, config) + end + end + + if pkg:is_installed() then + setup() + else + -- dap.lua's mason-nvim-dap ensure_installed triggers debugpy's + -- install, but that's async - on a fresh machine (or before it + -- finishes) debugpy_path doesn't exist on disk yet, and dc + -- would fail with a raw ENOENT from debugpy itself instead of a clear + -- message. Wire up the adapter once the install actually completes + -- instead of pointing it at a path that isn't there yet. + vim.notify( + "debugpy not installed yet - dap.lua's ensure_installed should be" + .. " installing it now (check :Mason); run :MasonInstall debugpy" + .. " if it doesn't show up there. Debugging will work once it's" + .. " done.", + vim.log.levels.WARN + ) + registry:on("package:install:success", function(installed_pkg) + if installed_pkg.name == "debugpy" then + setup() + end + end) + end + end, +} diff --git a/neovim/.config/nvim/lua/plugins/dap.lua b/neovim/.config/nvim/lua/plugins/dap.lua new file mode 100644 index 0000000..975eaea --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/dap.lua @@ -0,0 +1,181 @@ +-- Debugging via nvim-dap. Adapter installs are bridged through Mason +-- (mason-nvim-dap.nvim), the same pattern lsp.lua uses for language servers, +-- so adding a debug adapter for another language later is just adding it to +-- ensure_installed here - Python specifics live in dap-python.lua, Node +-- specifics in lua/config/dap_node.lua. +return { + "mfussenegger/nvim-dap", + -- Not left to lazy-load off `keys`: a project's .nvim.lua (see + -- lua/config/project_run.lua) needs `require("dap")` to work immediately + -- when exrc sources it, which requires the plugin already being on + -- runtimepath rather than deferred until a d keymap fires. + lazy = false, + dependencies = { + { + "rcarriga/nvim-dap-ui", + dependencies = { "nvim-neotest/nvim-nio" }, + }, + "theHamsta/nvim-dap-virtual-text", + { + "jay-babu/mason-nvim-dap.nvim", + dependencies = { "mason-org/mason.nvim" }, + }, + }, + keys = { + { "db", function() require("dap").toggle_breakpoint() end, desc = "Toggle breakpoint" }, + { + "dB", + function() require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) end, + desc = "Conditional breakpoint", + }, + { + "dc", + function() + local dap = require("dap") + + if dap.session() then + -- Existing session: resume past a breakpoint, or nvim-dap's + -- terminate/pause/restart prompt if active but not stopped. + -- This branch doesn't consult buffer filetype, so it's fine to + -- call from any window. + dap.continue() + return + end + + -- No active session: pick a config to start. dap.continue()'s own + -- path for this (select_config_and_run) only offers + -- dap.configurations[], so calling it + -- from the task-output dock or some other non-source window finds + -- nothing. Flatten across every filetype instead - same as + -- rr does for run tasks - so this works from anywhere and + -- you just pick the config you want from the list. + local entries = {} + for filetype, configs in pairs(dap.configurations) do + for _, config in ipairs(configs) do + table.insert(entries, { config = config, filetype = filetype }) + end + end + + -- .vscode/launch.json (if present in cwd) is read on-demand by + -- nvim-dap's own "dap.launch.json" provider - dap.ext.vscode's + -- load_launchjs() is deprecated now that this exists. That provider + -- is normally consulted inside dap.continue()'s own + -- select_config_and_run, which we're bypassing above, so call it + -- directly here to fold its configs into the same picker - the + -- debug-side counterpart to overseer's tasks.json support (README's + -- Run configurations section). Pair a launch.json entry with a + -- same-named tasks.json entry for PyCharm-style "run or debug the + -- same thing". + local ok, launchjson_configs = pcall(dap.providers.configs["dap.launch.json"]) + if ok then + for _, config in ipairs(launchjson_configs) do + table.insert(entries, { config = config, filetype = config.type }) + end + end + + if vim.tbl_isempty(entries) then + vim.notify("No debug configurations registered (see project_run.lua)", vim.log.levels.WARN) + return + end + + vim.ui.select(entries, { + prompt = "Configuration: ", + format_item = function(e) return e.config.name end, + }, function(entry) + if entry then + -- Pass along the filetype the config was registered under (not + -- necessarily the invoking buffer's) so breakpoint-hit window + -- jumping still picks a sensible window. + dap.run(entry.config, { filetype = entry.filetype }) + end + end) + end, + desc = "Continue / start debugging", + }, + { "do", function() require("dap").step_over() end, desc = "Step over" }, + { "di", function() require("dap").step_into() end, desc = "Step into" }, + { "dO", function() require("dap").step_out() end, desc = "Step out" }, + { "dt", function() require("dap").terminate() end, desc = "Terminate session" }, + { "dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" }, + { "du", function() require("dapui").toggle() end, desc = "Toggle debug UI" }, + }, + config = function() + require("dapui").setup() + require("nvim-dap-virtual-text").setup() + + -- nvim-dap doesn't define these signs itself - it just places them + -- (breakpoints.lua, session.lua's DapStopped placement) and expects the + -- config to have already called sign_define, so without this nothing + -- renders: no breakpoint marker in the sign column, and no indication + -- of the current line when a session stops (the stop itself still + -- works, sign_place just errors silently into a pcall). + vim.fn.sign_define("DapBreakpoint", { text = "●", texthl = "DiagnosticError" }) + vim.fn.sign_define("DapBreakpointCondition", { text = "◆", texthl = "DiagnosticWarn" }) + vim.fn.sign_define("DapBreakpointRejected", { text = "✗", texthl = "DiagnosticError" }) + vim.fn.sign_define("DapLogPoint", { text = "📝", texthl = "DiagnosticInfo" }) + vim.fn.sign_define("DapStopped", { text = "▶", texthl = "DiagnosticWarn", linehl = "DapStoppedLine" }) + -- default = true so a colorscheme (or later config) can override this + -- without a load-order fight; Visual is just a visible fallback. + vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) + + -- handlers = {} opts out of mason-nvim-dap's automatic adapter + -- registration: nvim-dap-python (dap-python.lua) registers its own + -- "python" adapter/config, so we don't want a second one clobbering it. + -- Adding a language without its own dap-.lua later should drop + -- this override so its adapter gets auto-registered instead. + require("mason-nvim-dap").setup({ + -- ensure_installed wants nvim-dap *adapter/source* names, not Mason + -- *package* names - mason-nvim-dap looks each entry up in its own + -- name -> package mapping (source.lua: python -> debugpy) and just + -- silently skips anything it doesn't recognize, no error/log. Passing + -- "debugpy" here (the package name) matched nothing, so it never + -- triggered an install at all. + ensure_installed = { "python", "js" }, + automatic_installation = true, + handlers = {}, + }) + + -- Node/JS/TS adapter + default configs - not left to mason-nvim-dap's + -- own handler since "js" has no default adapter mapping there (only the + -- deprecated node2 does), see lua/config/dap_node.lua for why. + require("config.dap_node").setup() + + local dap, dapui = require("dap"), require("dapui") + + -- nvim-dap jumps to the stopped line using Neovim's 'switchbuf' option, + -- which defaults to "uselast": reuse the current window if it's already + -- a plain/source buffer, else fall back to the alternate window - and + -- if neither applies (e.g. dc was started from the task-output + -- dock or some other non-source window, which the picker now allows), + -- it silently does nothing. No error, no jump - the session *is* + -- stopped (stepping/continuing still works), it just never shows where. + -- Append "vsplit" so there's always a guaranteed-successful last resort + -- that opens the source file if nothing else matched. + dap.defaults.fallback.switchbuf = "usevisible,useopen,uselast,vsplit" + + -- Open/close dap-ui automatically around a debug session, so du + -- is only needed to bring it back after manually closing it mid-session. + dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() + end + dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close() + end + dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close() + end + + -- These events arrive asynchronously over debugpy's socket (a libuv + -- callback, not a keypress), and nvim-dap updates its state - cursor + -- position, signs, dapui panels - without that alone forcing Neovim to + -- repaint. So hitting a breakpoint, continuing past one, or a session + -- ending can all silently not *look* like anything happened until the + -- next keystroke forces a redraw that reveals the already-current + -- state (e.g. dc appearing to need pressing twice to resume). + for _, event in ipairs({ "event_stopped", "event_continued", "event_terminated", "event_exited" }) do + dap.listeners.after[event]["dap_redraw"] = function() + vim.cmd("redraw") + end + end + end, +} diff --git a/neovim/.config/nvim/lua/plugins/editing.lua b/neovim/.config/nvim/lua/plugins/editing.lua index c1d5567..62b1dbf 100644 --- a/neovim/.config/nvim/lua/plugins/editing.lua +++ b/neovim/.config/nvim/lua/plugins/editing.lua @@ -1,13 +1,3 @@ return { - { - "preservim/nerdcommenter", - init = function() - vim.g.NERDSpaceDelims = 1 - vim.g.NERDCompactSexyComs = 1 - vim.g.NERDDefaultAlign = "left" - vim.g.NERDCommentEmptyLines = 1 - vim.g.NERDTrimTrailingWhitespace = 1 - end, - }, "unblevable/quick-scope", } diff --git a/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua b/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua index 444d9ff..2ed9970 100644 --- a/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua +++ b/neovim/.config/nvim/lua/plugins/fuzzyfinder.lua @@ -1,10 +1,32 @@ return { - "ctrlpvim/ctrlp.vim", - init = function() - -- Use ripgrep for listing files (fast, respects .gitignore) - if vim.fn.executable("rg") == 1 then - vim.g.ctrlp_user_command = 'rg %s --files --color=never --glob ""' - vim.g.ctrlp_use_caching = 0 - end + "nvim-telescope/telescope.nvim", + -- Not left to lazy-load off `keys`: telescope-ui-select's vim.ui.select() + -- override (below) needs to be installed from startup, otherwise + -- overseer's rr / nvim-dap-python's dc pickers fall back + -- to Neovim's default list until something (e.g. ) happens to + -- trigger telescope's own lazy-load first. + lazy = false, + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope-ui-select.nvim", + }, + keys = { + { "", "Telescope find_files" }, + { "fg", "Telescope live_grep" }, + { "fb", "Telescope buffers" }, + }, + config = function() + -- telescope-ui-select makes vim.ui.select() - overseer's rr + -- template picker, nvim-dap-python's launch-config picker, LSP code + -- actions, etc. - a scrollable/fuzzy-searchable Telescope window + -- instead of Neovim's default numbered-list-in-the-cmdline prompt. + require("telescope").setup({ + extensions = { + ["ui-select"] = { + require("telescope.themes").get_dropdown({}), + }, + }, + }) + require("telescope").load_extension("ui-select") end, } diff --git a/neovim/.config/nvim/lua/plugins/git.lua b/neovim/.config/nvim/lua/plugins/git.lua index 8402905..ef07442 100644 --- a/neovim/.config/nvim/lua/plugins/git.lua +++ b/neovim/.config/nvim/lua/plugins/git.lua @@ -1,4 +1,7 @@ return { "tpope/vim-fugitive", - "mhinz/vim-signify", + { + "lewis6991/gitsigns.nvim", + opts = {}, + }, } diff --git a/neovim/.config/nvim/lua/plugins/indent-detect.lua b/neovim/.config/nvim/lua/plugins/indent-detect.lua new file mode 100644 index 0000000..945769c --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/indent-detect.lua @@ -0,0 +1,8 @@ +-- Detects each buffer's actual indentation/spacing on open and sets +-- shiftwidth/tabstop/expandtab to match, rather than relying solely on +-- ftplugin defaults (e.g. ftplugin/python.lua) or global options.opt. +return { + "nmac427/guess-indent.nvim", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, +} diff --git a/neovim/.config/nvim/lua/plugins/langs.lua b/neovim/.config/nvim/lua/plugins/langs.lua deleted file mode 100644 index 7bf22d4..0000000 --- a/neovim/.config/nvim/lua/plugins/langs.lua +++ /dev/null @@ -1,14 +0,0 @@ -return { - { - "chase/vim-ansible-yaml", - cond = function() - return vim.fn.executable("ansible") == 1 - end, - }, - { - "hashivim/vim-terraform", - cond = function() - return vim.fn.executable("terraform") == 1 - end, - }, -} diff --git a/neovim/.config/nvim/lua/plugins/overseer.lua b/neovim/.config/nvim/lua/plugins/overseer.lua new file mode 100644 index 0000000..99d0f5f --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/overseer.lua @@ -0,0 +1,57 @@ +-- Run configurations (PyCharm-style "run this again"), language-agnostic: +-- works for npm scripts, make, cargo, arbitrary shell commands, python +-- scripts, etc, unlike DAP which is Python-only for now. +return { + "stevearc/overseer.nvim", + -- Not left to lazy-load off `cmd`/`keys`: a project's .nvim.lua (see + -- lua/config/project_run.lua) needs `require("overseer")` to work + -- immediately when exrc sources it, which requires the plugin already + -- being on runtimepath rather than deferred until first use. + lazy = false, + keys = { + { "rr", "OverseerRun", desc = "Run task" }, + { + "rl", + function() + -- :OverseerRestartLast exists in current overseer.nvim versions; the + -- run_action fallback covers older/newer versions that lack it + -- rather than hard-failing the keymap. + if vim.fn.exists(":OverseerRestartLast") == 2 then + vim.cmd("OverseerRestartLast") + return + end + local overseer = require("overseer") + local tasks = overseer.list_tasks({ recent_first = true }) + if vim.tbl_isempty(tasks) then + vim.notify("No previous task to rerun", vim.log.levels.WARN) + else + overseer.run_action(tasks[1], "restart") + end + end, + desc = "Rerun last task", + }, + { "ro", "OverseerToggle", desc = "Toggle task list/output" }, + { "rq", "OverseerQuickAction", desc = "Quick action on task" }, + }, + opts = { + -- Patches nvim-dap so a debug config can set preLaunchTask/postDebugTask + -- to an overseer task name (or "${defaultBuildTask}" for whatever task + -- is tagged BUILD) - lets a dap.configurations entry build before it + -- launches the debugger. See README's Debugging section. + dap = true, + -- overseer's actual default components (on_exit_set_status, + -- on_complete_notify, on_complete_dispose) don't open the output panel + -- on their own - without open_output added here, starting any task + -- (whether from a template, .nvim.lua/project_run.lua, or auto-detected + -- npm/make scripts) runs silently until you manually ro to look. + -- Adding it here applies to every task, not just custom ones. + component_aliases = { + default = { + "on_exit_set_status", + "on_complete_notify", + { "on_complete_dispose", require_view = { "SUCCESS", "FAILURE" } }, + { "open_output", direction = "dock", focus = false, on_start = "always" }, + }, + }, + }, +} diff --git a/neovim/.config/nvim/lua/plugins/statusline.lua b/neovim/.config/nvim/lua/plugins/statusline.lua index b93b34c..17741a6 100644 --- a/neovim/.config/nvim/lua/plugins/statusline.lua +++ b/neovim/.config/nvim/lua/plugins/statusline.lua @@ -1,23 +1,5 @@ return { - "bling/vim-airline", - lazy = false, - dependencies = { - "vim-airline/vim-airline-themes", - "edkolev/tmuxline.vim", - }, - init = function() - -- On arch linux install the following: - -- otf-powerline-symbols-git - -- powerline-fonts-git - vim.g.airline_powerline_fonts = 1 - vim.g["airline#extensions#tabline#enabled"] = 1 - - -- vim.g dict reads return a copy, not a live reference, so the nested - -- field has to be set via a local table and reassigned. - local symbols = vim.g.airline_symbols or {} - symbols.space = "\u{a0}" - vim.g.airline_symbols = symbols - - vim.opt.laststatus = 2 - end, + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + opts = {}, } diff --git a/neovim/.config/nvim/lua/plugins/toggleterm.lua b/neovim/.config/nvim/lua/plugins/toggleterm.lua new file mode 100644 index 0000000..b8067a3 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/toggleterm.lua @@ -0,0 +1,18 @@ +-- Scratch terminal for running arbitrary shell commands, toggled like +-- claude-code.nvim's own - open/close (not kill) a persistent split. +return { + "akinsho/toggleterm.nvim", + lazy = false, -- global toggle must work from any window, not just after some trigger event + opts = { + open_mapping = [[]], -- registers n, t (terminal_mappings) and i (insert_mappings) mode maps automatically + direction = "vertical", + -- toggleterm's vertical direction always opens via "botright vsplit" internally, + -- so this already matches claude-code.nvim's right-side placement without + -- touching 'splitright'. + size = function(term) + if term.direction == "vertical" then + return math.floor(vim.o.columns * 0.3) -- matches claude-code.nvim's window.position ratio + end + end, + }, +} diff --git a/neovim/.config/nvim/lua/plugins/which-key.lua b/neovim/.config/nvim/lua/plugins/which-key.lua new file mode 100644 index 0000000..190d651 --- /dev/null +++ b/neovim/.config/nvim/lua/plugins/which-key.lua @@ -0,0 +1,17 @@ +-- Popup showing available keymaps/groups as you type a prefix like +-- d or r, so the debug/run namespaces stay discoverable +-- without memorizing every letter. Auto-discovers each keymap's own `desc` +-- field from dap.lua/overseer.lua/etc - only the group headers need +-- registering here. +return { + "folke/which-key.nvim", + event = "VeryLazy", + opts = { + spec = { + { "d", group = "Debug", icon = "🐞" }, + { "r", group = "Run", icon = "▶" }, + { "f", group = "Find" }, + { "e", group = "Explorer" }, + }, + }, +} -- cgit v1.3