diff options
| author | 2026-09-16 08:47:13 +0200 | |
|---|---|---|
| committer | 2026-09-16 08:47:13 +0200 | |
| commit | a5e8bbeb9d79d905a193e95a39acd29bc37e6c66 (patch) | |
| tree | 5b42d54e6b91d454bcbac89f7aac42b0863a869d | |
| parent | 6906a9d55928c6250ff106d041b73fdd1ac8aae6 (diff) | |
| download | dotfiles-a5e8bbeb9d79d905a193e95a39acd29bc37e6c66.tar.gz dotfiles-a5e8bbeb9d79d905a193e95a39acd29bc37e6c66.tar.bz2 dotfiles-a5e8bbeb9d79d905a193e95a39acd29bc37e6c66.zip | |
Updated dotfiles
24 files changed, 862 insertions, 68 deletions
diff --git a/bash/.bashrc b/bash/.bashrc index 9ccd0e3..c923972 100755 --- a/bash/.bashrc +++ b/bash/.bashrc | |||
| @@ -104,10 +104,12 @@ fi | |||
| 104 | # Set the default editor | 104 | # Set the default editor |
| 105 | if exists nvim; then | 105 | if exists nvim; then |
| 106 | export EDITOR="nvim" | 106 | export EDITOR="nvim" |
| 107 | alias vim=nvim | ||
| 107 | elif exists vim; then | 108 | elif exists vim; then |
| 108 | export EDITOR="vim" | 109 | export EDITOR="vim" |
| 109 | elif exists vi; then | 110 | elif exists vi; then |
| 110 | export EDITOR="vi" | 111 | export EDITOR="vi" |
| 112 | alias vim=nvim | ||
| 111 | fi | 113 | fi |
| 112 | 114 | ||
| 113 | # vim() { | 115 | # vim() { |
diff --git a/iterm2/.iterm2/com.googlecode.iterm2.plist b/iterm2/.iterm2/com.googlecode.iterm2.plist index f7b56cd..848452e 100644 --- a/iterm2/.iterm2/com.googlecode.iterm2.plist +++ b/iterm2/.iterm2/com.googlecode.iterm2.plist | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | <string>https://api.openai.com/v1/responses</string> | 26 | <string>https://api.openai.com/v1/responses</string> |
| 27 | <key>CheckTestRelease</key> | 27 | <key>CheckTestRelease</key> |
| 28 | <true/> | 28 | <true/> |
| 29 | <key>ClaudeCodeWorkgroupUpsellSuppressed</key> | ||
| 30 | <true/> | ||
| 29 | <key>Default Bookmark Guid</key> | 31 | <key>Default Bookmark Guid</key> |
| 30 | <string>F73BDC14-4F5E-4A25-AE4A-2C6DB0A9BFEF</string> | 32 | <string>F73BDC14-4F5E-4A25-AE4A-2C6DB0A9BFEF</string> |
| 31 | <key>DisableFullscreenTransparency</key> | 33 | <key>DisableFullscreenTransparency</key> |
| @@ -53,6 +55,8 @@ | |||
| 53 | <false/> | 55 | <false/> |
| 54 | <key>Ambiguous Double Width</key> | 56 | <key>Ambiguous Double Width</key> |
| 55 | <false/> | 57 | <false/> |
| 58 | <key>Animate Movement</key> | ||
| 59 | <false/> | ||
| 56 | <key>Ansi 0 Color</key> | 60 | <key>Ansi 0 Color</key> |
| 57 | <dict> | 61 | <dict> |
| 58 | <key>Blue Component</key> | 62 | <key>Blue Component</key> |
| @@ -343,7 +347,7 @@ | |||
| 343 | <key>Non-ASCII Anti Aliased</key> | 347 | <key>Non-ASCII Anti Aliased</key> |
| 344 | <true/> | 348 | <true/> |
| 345 | <key>Normal Font</key> | 349 | <key>Normal Font</key> |
| 346 | <string>Menlo-Regular 11</string> | 350 | <string>JetBrainsMonoNLNFM-Regular 11</string> |
| 347 | <key>Option Key Sends</key> | 351 | <key>Option Key Sends</key> |
| 348 | <integer>0</integer> | 352 | <integer>0</integer> |
| 349 | <key>Prevent Opening in a Tab</key> | 353 | <key>Prevent Opening in a Tab</key> |
| @@ -621,6 +625,8 @@ | |||
| 621 | <string>xterm-256color</string> | 625 | <string>xterm-256color</string> |
| 622 | <key>Transparency</key> | 626 | <key>Transparency</key> |
| 623 | <real>0.0</real> | 627 | <real>0.0</real> |
| 628 | <key>Unicode Normalization</key> | ||
| 629 | <integer>0</integer> | ||
| 624 | <key>Unicode Version</key> | 630 | <key>Unicode Version</key> |
| 625 | <integer>9</integer> | 631 | <integer>9</integer> |
| 626 | <key>Unlimited Scrollback</key> | 632 | <key>Unlimited Scrollback</key> |
diff --git a/neovim/.config/nvim/README.md b/neovim/.config/nvim/README.md index 5092af0..0e50788 100644 --- a/neovim/.config/nvim/README.md +++ b/neovim/.config/nvim/README.md | |||
| @@ -15,6 +15,8 @@ lua/config/ Everything that isn't a plugin declaration | |||
| 15 | options.lua vim.opt settings (search, undo, whitespace display, ...) | 15 | options.lua vim.opt settings (search, undo, whitespace display, ...) |
| 16 | keymaps.lua Global keymaps not owned by a specific plugin | 16 | keymaps.lua Global keymaps not owned by a specific plugin |
| 17 | autocmds.lua Global autocmds not owned by a specific plugin | 17 | autocmds.lua Global autocmds not owned by a specific plugin |
| 18 | project_run.lua Helper for project-local run/debug configs (see below) | ||
| 19 | dap_node.lua Node/js-debug-adapter wiring for nvim-dap (see below) | ||
| 18 | lazy.lua Bootstraps lazy.nvim and points it at lua/plugins/ | 20 | lazy.lua Bootstraps lazy.nvim and points it at lua/plugins/ |
| 19 | lua/plugins/ One file per plugin (or small plugin group), each | 21 | lua/plugins/ One file per plugin (or small plugin group), each |
| 20 | returning a lazy.nvim plugin spec (or list of specs) | 22 | returning a lazy.nvim plugin spec (or list of specs) |
| @@ -34,18 +36,23 @@ such tables) and it's included on next launch. | |||
| 34 | | File | Plugin(s) | Purpose | | 36 | | File | Plugin(s) | Purpose | |
| 35 | |---|---|---| | 37 | |---|---|---| |
| 36 | | `colorscheme.lua` | vim-janah | Color scheme, falls back to `desert` if it fails to load | | 38 | | `colorscheme.lua` | vim-janah | Color scheme, falls back to `desert` if it fails to load | |
| 37 | | `statusline.lua` | vim-airline, vim-airline-themes, tmuxline.vim | Status/tab line | | 39 | | `statusline.lua` | lualine.nvim | Status line | |
| 38 | | `filetree.lua` | neo-tree.nvim | File explorer sidebar with git-status colors (`<leader>e` to toggle) | | 40 | | `filetree.lua` | neo-tree.nvim | File explorer sidebar with git-status colors (`<leader>e` to toggle) | |
| 39 | | `fuzzyfinder.lua` | ctrlp.vim | Fuzzy file finder (ripgrep-backed if `rg` is on PATH) | | 41 | | `fuzzyfinder.lua` | telescope.nvim, telescope-ui-select.nvim | Fuzzy file finder (`<C-p>`), live grep (`<leader>fg`), buffers (`<leader>fb`); also overrides `vim.ui.select` globally so overseer's/dap's pickers are Telescope windows | |
| 40 | | `editing.lua` | nerdcommenter, quick-scope | Comment toggling, `f`/`F`/`t`/`T` target highlighting | | 42 | | `editing.lua` | quick-scope | `f`/`F`/`t`/`T` target highlighting (comment toggling is Neovim's built-in `gc`/`gcc`) | |
| 41 | | `git.lua` | vim-fugitive, vim-signify | `:Git` commands, git-diff gutter signs | | 43 | | `git.lua` | vim-fugitive, gitsigns.nvim | `:Git` commands, git-diff gutter signs | |
| 42 | | `ale.lua` | ALE | Linters/fixers only — `g:ale_disable_lsp = 1` so it doesn't fight the LSP client's diagnostics/hover/go-to-def | | 44 | | `ale.lua` | ALE | Linters/fixers only — `g:ale_disable_lsp = 1` so it doesn't fight the LSP client's diagnostics/hover/go-to-def | |
| 43 | | `langs.lua` | vim-ansible-yaml, vim-terraform | Only loaded if `ansible`/`terraform` is on PATH (lazy.nvim `cond`) | | ||
| 44 | | `claude-code.lua` | claude-code.nvim (+ plenary.nvim) | `:ClaudeCode` and friends | | 45 | | `claude-code.lua` | claude-code.nvim (+ plenary.nvim) | `:ClaudeCode` and friends | |
| 46 | | `toggleterm.lua` | toggleterm.nvim | Scratch terminal toggle — `<C-.>`, vertical split on the right matching claude-code.nvim's placement/ratio | | ||
| 45 | | `treesitter.lua` | nvim-treesitter (`main` branch) | Parser installs + syntax highlighting | | 47 | | `treesitter.lua` | nvim-treesitter (`main` branch) | Parser installs + syntax highlighting | |
| 46 | | `autopairs.lua` | nvim-autopairs, nvim-ts-autotag | Auto-close brackets/quotes/HTML+JSX tags | | 48 | | `autopairs.lua` | nvim-autopairs, nvim-ts-autotag | Auto-close brackets/quotes/HTML+JSX tags | |
| 47 | | `completion.lua` | blink.cmp (+ friendly-snippets) | Completion popup, Tab-to-accept (`super-tab` preset) | | 49 | | `completion.lua` | blink.cmp (+ friendly-snippets) | Completion popup, Tab-to-accept (`super-tab` preset) | |
| 48 | | `lsp.lua` | nvim-lspconfig, mason.nvim, mason-lspconfig.nvim | Installs & enables language servers, wires blink.cmp's capabilities into them | | 50 | | `lsp.lua` | nvim-lspconfig, mason.nvim, mason-lspconfig.nvim | Installs & enables language servers, wires blink.cmp's capabilities into them | |
| 51 | | `dap.lua` | nvim-dap, nvim-dap-ui, nvim-dap-virtual-text, mason-nvim-dap.nvim | Debugger core + UI, installs debug adapters via Mason (`<leader>d*`) | | ||
| 52 | | `dap-python.lua` | nvim-dap-python | Python launch configs, wired to Mason's debugpy install | | ||
| 53 | | `overseer.lua` | overseer.nvim | Save/run/rerun arbitrary run configurations for any language (`<leader>r*`) | | ||
| 54 | | `which-key.lua` | which-key.nvim | Keymap discoverability popup; labels the `<leader>d`/`<leader>r`/etc. groups | | ||
| 55 | | `indent-detect.lua` | guess-indent.nvim | Detects each buffer's real indentation and matches shiftwidth/tabstop to it | | ||
| 49 | 56 | ||
| 50 | ## Language servers | 57 | ## Language servers |
| 51 | 58 | ||
| @@ -59,6 +66,112 @@ hover) come from Neovim's built-in default LSP keymaps (`:help lsp-defaults`) | |||
| 59 | once a server attaches — `grn`, `gra`, `grr`, `gri`, `gO`, `K`, `<C-]>`. No | 66 | once a server attaches — `grn`, `gra`, `grr`, `gri`, `gO`, `K`, `<C-]>`. No |
| 60 | extra plugin or keymap needed for these. | 67 | extra plugin or keymap needed for these. |
| 61 | 68 | ||
| 69 | ## Debugging | ||
| 70 | |||
| 71 | Python and Node.js (JavaScript/TypeScript), via `nvim-dap` + `nvim-dap-ui`. | ||
| 72 | The `debugpy` and `js-debug-adapter` adapters are installed and kept up to | ||
| 73 | date by Mason (via `mason-nvim-dap.nvim`, the DAP equivalent of | ||
| 74 | `mason-lspconfig.nvim`), so `:Mason` shows them alongside the language | ||
| 75 | servers. Keymaps live under `<leader>d` — `<leader>db` to set a breakpoint, | ||
| 76 | `<leader>dc` to start/continue (picks a registered config from any window, | ||
| 77 | not just the source buffer; resumes in place if a session is already stopped | ||
| 78 | at a breakpoint), `<leader>do`/`di`/`dO` to step over/into/out, `<leader>dt` | ||
| 79 | to terminate, `<leader>du` to reopen the UI if you close it manually (it | ||
| 80 | opens/closes itself automatically around a session). Press `<leader>d` and | ||
| 81 | wait to see the full list via which-key. | ||
| 82 | |||
| 83 | Python's adapter/config setup lives in `lua/plugins/dap-python.lua`, wrapping | ||
| 84 | the `nvim-dap-python` plugin. Node's lives in `lua/config/dap_node.lua` | ||
| 85 | instead — there's no maintained `nvim-dap-python`-style plugin for it (the | ||
| 86 | community option, `nvim-dap-vscode-js`, expects an older, manually-built | ||
| 87 | vscode-js-debug layout that doesn't match what Mason's `js-debug-adapter` | ||
| 88 | package installs), so that file resolves the Mason install path directly and | ||
| 89 | registers the `pwa-node` adapter + default `javascript`/`typescript`/ | ||
| 90 | `javascriptreact`/`typescriptreact` configs itself. It's called eagerly from | ||
| 91 | `dap.lua`'s own `config()` rather than being its own `lua/plugins/*` entry, | ||
| 92 | since it isn't an installable plugin — same reasoning as | ||
| 93 | `lua/config/project_run.lua`. | ||
| 94 | |||
| 95 | Adding another language later (e.g. C/C++ via `codelldb`) means adding its | ||
| 96 | adapter to `dap.lua`'s `ensure_installed`, and either writing its own | ||
| 97 | `dap-<language>.lua` plugin file (if a wrapper plugin exists, following the | ||
| 98 | `dap-python.lua` pattern) or a `lua/config/dap_<language>.lua` module called | ||
| 99 | from `dap.lua`'s `config()` (if not, following the `dap_node.lua` pattern) — | ||
| 100 | including `lazy = false` on `dap.lua` itself either way, so the adapter is | ||
| 101 | registered from startup rather than only after a buffer of that filetype is | ||
| 102 | opened (the `<leader>dc` picker works from any window, so it can't rely on | ||
| 103 | that to lazy-trigger the adapter). | ||
| 104 | |||
| 105 | `overseer.lua` sets `dap = true`, which patches `nvim-dap` so a debug | ||
| 106 | configuration can set `preLaunchTask`/`postDebugTask` to the name of an | ||
| 107 | overseer task (or `"${defaultBuildTask}"` for whichever task is tagged | ||
| 108 | `BUILD`) — useful for "build, then debug" workflows once a compiled | ||
| 109 | language is added; not needed for plain Python/Node scripts. | ||
| 110 | |||
| 111 | ## Run configurations | ||
| 112 | |||
| 113 | `overseer.nvim` provides PyCharm-style saved/rerunnable run configurations | ||
| 114 | for any language or toolchain (shell commands, npm scripts, make, cargo, | ||
| 115 | python scripts, ...) — it isn't tied to LSP/DAP language support. Keymaps | ||
| 116 | live under `<leader>r` — `<leader>rr` to run a task (prompts for a template | ||
| 117 | or a raw command), `<leader>rl` to rerun the last task, `<leader>ro` to | ||
| 118 | toggle the task list/output window, `<leader>rq` for quick actions | ||
| 119 | (restart/stop/dispose) on a selected task. Press `<leader>r` and wait to see | ||
| 120 | the full list via which-key. | ||
| 121 | |||
| 122 | `overseer.lua`'s `component_aliases.default` adds the `open_output` | ||
| 123 | component (`on_start = "always"`, `focus = false`) on top of overseer's own | ||
| 124 | defaults, so starting *any* task — custom, `.nvim.lua`-declared, or | ||
| 125 | auto-detected (npm/make/etc.) — docks its output automatically instead of | ||
| 126 | running silently until you manually `<leader>ro`. | ||
| 127 | |||
| 128 | ## Project-local run/debug configs | ||
| 129 | |||
| 130 | A project can drop a `.nvim.lua` anywhere in its directory tree and have it | ||
| 131 | auto-sourced (after a one-time `:help :trust` prompt — it runs arbitrary | ||
| 132 | Lua, so trust it deliberately, not reflexively). This is the PyCharm-style | ||
| 133 | "named configuration" mechanism, without adopting any other editor's file | ||
| 134 | format. | ||
| 135 | |||
| 136 | This is **not** core Vim/Neovim `'exrc'` (deliberately left off in | ||
| 137 | options.lua) — `exrc` only checks the literal cwd once at startup, so it | ||
| 138 | misses a project's `.nvim.lua` whenever Neovim didn't happen to start with | ||
| 139 | cwd exactly there. Instead, an autocmd in `lua/config/autocmds.lua` searches | ||
| 140 | *upward* from cwd on `VimEnter`/`DirChanged` (stopping at `$HOME`, same | ||
| 141 | nearest-ancestor pattern LSP root-dir detection uses) and reads the file via | ||
| 142 | `vim.secure.read` — the same trust mechanism `exrc` itself uses, so `:trust` | ||
| 143 | still manages the allowlist unchanged, it's just found reliably regardless | ||
| 144 | of how you opened Neovim. | ||
| 145 | |||
| 146 | `lua/config/project_run.lua` gives that file one call per config that | ||
| 147 | registers both a `<leader>rr` run task and a matching `<leader>dc` debug | ||
| 148 | config from the *same* declaration, instead of repeating the command across | ||
| 149 | two separate files: | ||
| 150 | |||
| 151 | ```lua | ||
| 152 | -- <project root>/.nvim.lua | ||
| 153 | require("config.project_run").python({ | ||
| 154 | name = "Run app", | ||
| 155 | program = vim.fn.getcwd() .. "/main.py", | ||
| 156 | args = { "--flag" }, -- optional, shared by both run and debug | ||
| 157 | }) | ||
| 158 | |||
| 159 | require("config.project_run").node({ | ||
| 160 | name = "Run app", | ||
| 161 | program = vim.fn.getcwd() .. "/index.js", -- or npmScript = "dev" for `npm run dev` | ||
| 162 | args = { "--flag" }, -- optional, shared by both run and debug | ||
| 163 | }) | ||
| 164 | ``` | ||
| 165 | |||
| 166 | `dap.lua` and `overseer.lua` are both `lazy = false` specifically so this | ||
| 167 | works immediately when the autocmd sources the file, rather than needing | ||
| 168 | the plugins already triggered by a keymap first. | ||
| 169 | |||
| 170 | (`nvim-dap` and `overseer.nvim` also natively read `.vscode/launch.json` and | ||
| 171 | `.vscode/tasks.json` respectively, if you'd rather use that ecosystem's | ||
| 172 | format for some reason — but `project_run.lua` is the recommended path here | ||
| 173 | since it states each command once.) | ||
| 174 | |||
| 62 | ## Adding a new plugin | 175 | ## Adding a new plugin |
| 63 | 176 | ||
| 64 | Drop a new file in `lua/plugins/` (or add to an existing group file if it | 177 | Drop a new file in `lua/plugins/` (or add to an existing group file if it |
| @@ -74,6 +187,18 @@ return { | |||
| 74 | Restart Neovim (or `:Lazy sync`) to install it, then commit the updated | 187 | Restart Neovim (or `:Lazy sync`) to install it, then commit the updated |
| 75 | `lazy-lock.json` alongside your change. | 188 | `lazy-lock.json` alongside your change. |
| 76 | 189 | ||
| 190 | If a plugin backs a keymap or command meant to work from any window — not | ||
| 191 | scoped to a particular filetype/buffer, like the run/debug pickers, the | ||
| 192 | fuzzy finder, or the file explorer — set `lazy = false` rather than gating | ||
| 193 | it behind `ft`/`event`, even though lazy.nvim would otherwise recommend one. | ||
| 194 | A trigger tied to "some buffer of type X was opened" silently breaks the | ||
| 195 | moment the keymap fires before that's happened (this bit `dap-python.lua`: | ||
| 196 | it lazy-loaded on `ft = "python"`, so debugging broke whenever `<leader>dc` | ||
| 197 | was pressed before any `.py` buffer had been opened this session). Plain | ||
| 198 | per-buffer editing conveniences (`autopairs.lua`'s `InsertEnter`, | ||
| 199 | `ale.lua`'s `BufReadPre`, `which-key.lua`'s `VeryLazy`) don't have this | ||
| 200 | problem and can stay lazy. | ||
| 201 | |||
| 77 | ## Relationship to Vim | 202 | ## Relationship to Vim |
| 78 | 203 | ||
| 79 | Vim and Neovim used to share one `vimrc` (`has('nvim')` branches handled the | 204 | Vim and Neovim used to share one `vimrc` (`has('nvim')` branches handled the |
diff --git a/neovim/.config/nvim/lazy-lock.json b/neovim/.config/nvim/lazy-lock.json index 6ac90ec..fd32868 100644 --- a/neovim/.config/nvim/lazy-lock.json +++ b/neovim/.config/nvim/lazy-lock.json | |||
| @@ -2,26 +2,33 @@ | |||
| 2 | "ale": { "branch": "master", "commit": "e1789bc54483d76ac9ddb40b633d1645c8281914" }, | 2 | "ale": { "branch": "master", "commit": "e1789bc54483d76ac9ddb40b633d1645c8281914" }, |
| 3 | "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, | 3 | "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, |
| 4 | "claude-code.nvim": { "branch": "main", "commit": "55c0cb59828fbc3bec744288286a46f5d5750b83" }, | 4 | "claude-code.nvim": { "branch": "main", "commit": "55c0cb59828fbc3bec744288286a46f5d5750b83" }, |
| 5 | "ctrlp.vim": { "branch": "master", "commit": "0065942ef13ce28293e2b26cb622d035da050b44" }, | ||
| 6 | "friendly-snippets": { "branch": "main", "commit": "b4d01b0fdf3c9a549961c2f9ffe8dc09be166219" }, | 5 | "friendly-snippets": { "branch": "main", "commit": "b4d01b0fdf3c9a549961c2f9ffe8dc09be166219" }, |
| 6 | "gitsigns.nvim": { "branch": "main", "commit": "f2421c550618d257048afa650413d9e542ddbe67" }, | ||
| 7 | "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, | ||
| 7 | "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, | 8 | "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, |
| 8 | "mason-lspconfig.nvim": { "branch": "main", "commit": "b5576cd62899a1a478d0e67ef3d378ee55dba82d" }, | 9 | "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, |
| 10 | "mason-lspconfig.nvim": { "branch": "main", "commit": "77e06f7d2fc127e6ef0a720b59acbc50757cff19" }, | ||
| 11 | "mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" }, | ||
| 9 | "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, | 12 | "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, |
| 10 | "neo-tree.nvim": { "branch": "v3.x", "commit": "1a14083046d96e88e361d1da00761c40d45012f3" }, | 13 | "neo-tree.nvim": { "branch": "v3.x", "commit": "1a14083046d96e88e361d1da00761c40d45012f3" }, |
| 11 | "nerdcommenter": { "branch": "master", "commit": "a462bbda1e26f44fb3d3eb9d9d1c6a07aa98e665" }, | ||
| 12 | "nui.nvim": { "branch": "main", "commit": "10fc361835c856ba4233ef5ea135b919bf3dce97" }, | 14 | "nui.nvim": { "branch": "main", "commit": "10fc361835c856ba4233ef5ea135b919bf3dce97" }, |
| 13 | "nvim-autopairs": { "branch": "master", "commit": "430522f95fe4fb7c511ec64f8c1a90cc6a66c05c" }, | 15 | "nvim-autopairs": { "branch": "master", "commit": "430522f95fe4fb7c511ec64f8c1a90cc6a66c05c" }, |
| 16 | "nvim-dap": { "branch": "master", "commit": "cfa2d58f4537aca6ca83e2de1a0d9f1491121264" }, | ||
| 17 | "nvim-dap-python": { "branch": "master", "commit": "1808458eba2b18f178f990e01376941a42c7f93b" }, | ||
| 18 | "nvim-dap-ui": { "branch": "master", "commit": "cc9dd33aade7f20bae414d0cba163bc60d4d4b43" }, | ||
| 19 | "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, | ||
| 14 | "nvim-lspconfig": { "branch": "master", "commit": "ac9d2f7c4757db6320cab6697fe73e5e8adb2457" }, | 20 | "nvim-lspconfig": { "branch": "master", "commit": "ac9d2f7c4757db6320cab6697fe73e5e8adb2457" }, |
| 15 | "nvim-treesitter": { "branch": "main", "commit": "d4d59cb369da46b95699bd2200efbcffc6dadb3b" }, | 21 | "nvim-nio": { "branch": "master", "commit": "edcc181a875301dd21840189aa2f2f9ad69fc172" }, |
| 22 | "nvim-treesitter": { "branch": "main", "commit": "9a168f6357ed21c3a636e1727bc7d382abc451b8" }, | ||
| 16 | "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, | 23 | "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, |
| 17 | "nvim-web-devicons": { "branch": "master", "commit": "5f032a85be210cd1c6ac98861eb3b187ff3bd5eb" }, | 24 | "nvim-web-devicons": { "branch": "master", "commit": "5f032a85be210cd1c6ac98861eb3b187ff3bd5eb" }, |
| 25 | "overseer.nvim": { "branch": "master", "commit": "a93d9f6d6defdac4bcd6d2c8ba988650e42e0a0e" }, | ||
| 18 | "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, | 26 | "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, |
| 19 | "quick-scope": { "branch": "master", "commit": "6cee1d9e0b9ac0fbffeb538d4a5ba9f5628fabbc" }, | 27 | "quick-scope": { "branch": "master", "commit": "6cee1d9e0b9ac0fbffeb538d4a5ba9f5628fabbc" }, |
| 20 | "tmuxline.vim": { "branch": "master", "commit": "4119c553923212cc67f4e135e6f946dc3ec0a4d6" }, | 28 | "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, |
| 21 | "vim-airline": { "branch": "master", "commit": "ae24f4aca06731d5d7224df1fc5415975331b214" }, | 29 | "telescope.nvim": { "branch": "master", "commit": "40aedd8a68c78a656a10a8d62d80c54af59420fb" }, |
| 22 | "vim-airline-themes": { "branch": "master", "commit": "77aab8c6cf7179ddb8a05741da7e358a86b2c3ab" }, | 30 | "toggleterm.nvim": { "branch": "main", "commit": "9a88eae817ef395952e08650b3283726786fb5fb" }, |
| 23 | "vim-ansible-yaml": { "branch": "master", "commit": "a6f92d17ff01b2e63d6c9fdbb7f7e13c7fd41d14" }, | ||
| 24 | "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, | 31 | "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, |
| 25 | "vim-janah": { "branch": "master", "commit": "3b8ae976987b6ade2abeac25f0208e8bc90d7138" }, | 32 | "vim-janah": { "branch": "master", "commit": "3b8ae976987b6ade2abeac25f0208e8bc90d7138" }, |
| 26 | "vim-signify": { "branch": "master", "commit": "3b5ae37eb2b77c3ae58d60dfdc3fc30258078663" } | 33 | "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } |
| 27 | } | 34 | } |
diff --git a/neovim/.config/nvim/lua/config/autocmds.lua b/neovim/.config/nvim/lua/config/autocmds.lua index 7bc4f6b..e9ebe04 100644 --- a/neovim/.config/nvim/lua/config/autocmds.lua +++ b/neovim/.config/nvim/lua/config/autocmds.lua | |||
| @@ -13,6 +13,49 @@ vim.api.nvim_create_autocmd("BufWritePre", { | |||
| 13 | callback = strip_trailing_whitespace, | 13 | callback = strip_trailing_whitespace, |
| 14 | }) | 14 | }) |
| 15 | 15 | ||
| 16 | -- Project-local config: search upward from cwd for a .nvim.lua, the same | ||
| 17 | -- nearest-ancestor pattern LSP root-dir detection uses, so it's found | ||
| 18 | -- regardless of exactly which subdirectory Neovim's cwd is or how you got | ||
| 19 | -- there (:cd, opening a file, session restore, ...) - unlike core 'exrc' | ||
| 20 | -- (deliberately left off in options.lua), which only ever checks the | ||
| 21 | -- literal cwd once at startup. | ||
| 22 | local sourced_project_configs = {} | ||
| 23 | |||
| 24 | local function source_project_config() | ||
| 25 | local found = vim.fs.find(".nvim.lua", { | ||
| 26 | upward = true, | ||
| 27 | path = vim.fn.getcwd(), | ||
| 28 | stop = vim.env.HOME, | ||
| 29 | })[1] | ||
| 30 | if not found or sourced_project_configs[found] then | ||
| 31 | return | ||
| 32 | end | ||
| 33 | |||
| 34 | -- vim.secure.read is the same trust mechanism 'exrc' itself uses: prompts | ||
| 35 | -- on first encounter, honors ~/.local/state/nvim/trust, :trust still | ||
| 36 | -- manages the allowlist unchanged. Returns nil (no prompt shown again) | ||
| 37 | -- for a file previously denied. | ||
| 38 | local content = vim.secure.read(found) | ||
| 39 | if not content then | ||
| 40 | return | ||
| 41 | end | ||
| 42 | sourced_project_configs[found] = true | ||
| 43 | |||
| 44 | local chunk, load_err = load(content, "@" .. found) | ||
| 45 | if not chunk then | ||
| 46 | vim.notify("Error loading " .. found .. ":\n" .. load_err, vim.log.levels.ERROR) | ||
| 47 | return | ||
| 48 | end | ||
| 49 | local ok, run_err = pcall(chunk) | ||
| 50 | if not ok then | ||
| 51 | vim.notify("Error running " .. found .. ":\n" .. run_err, vim.log.levels.ERROR) | ||
| 52 | end | ||
| 53 | end | ||
| 54 | |||
| 55 | vim.api.nvim_create_autocmd({ "VimEnter", "DirChanged" }, { | ||
| 56 | callback = source_project_config, | ||
| 57 | }) | ||
| 58 | |||
| 16 | -- Note: the colorscheme (with its "desert" fallback) is applied from | 59 | -- Note: the colorscheme (with its "desert" fallback) is applied from |
| 17 | -- lua/plugins/colorscheme.lua's own `config` function, not here — under | 60 | -- lua/plugins/colorscheme.lua's own `config` function, not here — under |
| 18 | -- lazy.nvim that's the natural place to react to "the plugin is now loaded". | 61 | -- lazy.nvim that's the natural place to react to "the plugin is now loaded". |
diff --git a/neovim/.config/nvim/lua/config/dap_node.lua b/neovim/.config/nvim/lua/config/dap_node.lua new file mode 100644 index 0000000..0fb6890 --- /dev/null +++ b/neovim/.config/nvim/lua/config/dap_node.lua | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | -- JavaScript/TypeScript launch configs, wired to the js-debug-adapter | ||
| 2 | -- (Microsoft's vscode-js-debug, bundled by Mason as a standalone | ||
| 3 | -- multi-session DAP server) that dap.lua's mason-nvim-dap ensure_installed | ||
| 4 | -- installs. | ||
| 5 | -- | ||
| 6 | -- There's no nvim-dap-python equivalent for this: the one community plugin | ||
| 7 | -- for it (mxsdev/nvim-dap-vscode-js) hardcodes the older | ||
| 8 | -- `out/src/vsDebugServer.js` vscode-js-debug build layout, which doesn't | ||
| 9 | -- match what Mason's js-debug-adapter package actually installs | ||
| 10 | -- (`js-debug/src/dapDebugServer.js`) - so this resolves the Mason path | ||
| 11 | -- directly instead, same approach as dap-python.lua's debugpy_path. | ||
| 12 | -- | ||
| 13 | -- Lives under lua/config/ rather than lua/plugins/ (and is required | ||
| 14 | -- eagerly from dap.lua's config()) because it isn't an installable plugin | ||
| 15 | -- itself, just adapter/config wiring - same reason project_run.lua lives | ||
| 16 | -- here instead of there. | ||
| 17 | -- | ||
| 18 | -- js-debug-adapter is a multi-session server: debugging a script that | ||
| 19 | -- spawns a worker thread arrives as a `startDebugging` reverse request | ||
| 20 | -- rather than a second top-level session. nvim-dap's core (dap/session.lua) | ||
| 21 | -- already handles that natively, so no extra plugin is needed for it either. | ||
| 22 | local M = {} | ||
| 23 | |||
| 24 | local function configurations() | ||
| 25 | return { | ||
| 26 | { | ||
| 27 | type = "pwa-node", | ||
| 28 | request = "launch", | ||
| 29 | name = "Launch file", | ||
| 30 | program = "${file}", | ||
| 31 | cwd = "${workspaceFolder}", | ||
| 32 | }, | ||
| 33 | { | ||
| 34 | type = "pwa-node", | ||
| 35 | request = "attach", | ||
| 36 | name = "Attach to process", | ||
| 37 | processId = require("dap.utils").pick_process, | ||
| 38 | cwd = "${workspaceFolder}", | ||
| 39 | }, | ||
| 40 | } | ||
| 41 | end | ||
| 42 | |||
| 43 | function M.setup() | ||
| 44 | local registry = require("mason-registry") | ||
| 45 | local pkg = registry.get_package("js-debug-adapter") | ||
| 46 | |||
| 47 | local function register() | ||
| 48 | local entrypoint = pkg:get_install_path() .. "/js-debug/src/dapDebugServer.js" | ||
| 49 | |||
| 50 | require("dap").adapters["pwa-node"] = { | ||
| 51 | type = "server", | ||
| 52 | host = "localhost", | ||
| 53 | port = "${port}", | ||
| 54 | executable = { | ||
| 55 | command = "node", | ||
| 56 | args = { entrypoint, "${port}" }, | ||
| 57 | }, | ||
| 58 | } | ||
| 59 | |||
| 60 | local dap = require("dap") | ||
| 61 | for _, filetype in ipairs({ "javascript", "typescript", "javascriptreact", "typescriptreact" }) do | ||
| 62 | dap.configurations[filetype] = configurations() | ||
| 63 | end | ||
| 64 | end | ||
| 65 | |||
| 66 | if pkg:is_installed() then | ||
| 67 | register() | ||
| 68 | else | ||
| 69 | -- Same reasoning as dap-python.lua: dap.lua's mason-nvim-dap | ||
| 70 | -- ensure_installed triggers the install, but that's async - on a fresh | ||
| 71 | -- machine (or before it finishes) the entrypoint doesn't exist on disk | ||
| 72 | -- yet, so wire up the adapter once the install actually completes | ||
| 73 | -- instead of pointing it at a path that isn't there yet. | ||
| 74 | vim.notify( | ||
| 75 | "js-debug-adapter not installed yet - dap.lua's ensure_installed should be" | ||
| 76 | .. " installing it now (check :Mason); run :MasonInstall js-debug-adapter" | ||
| 77 | .. " if it doesn't show up there. Debugging will work once it's done.", | ||
| 78 | vim.log.levels.WARN | ||
| 79 | ) | ||
| 80 | registry:on("package:install:success", function(installed_pkg) | ||
| 81 | if installed_pkg.name == "js-debug-adapter" then | ||
| 82 | register() | ||
| 83 | end | ||
| 84 | end) | ||
| 85 | end | ||
| 86 | end | ||
| 87 | |||
| 88 | return M | ||
diff --git a/neovim/.config/nvim/lua/config/keymaps.lua b/neovim/.config/nvim/lua/config/keymaps.lua index 66e97a0..65e3236 100644 --- a/neovim/.config/nvim/lua/config/keymaps.lua +++ b/neovim/.config/nvim/lua/config/keymaps.lua | |||
| @@ -14,6 +14,18 @@ map("t", "<C-k>", [[<C-\><C-n><C-w>k]]) | |||
| 14 | map("t", "<C-h>", [[<C-\><C-n><C-w>h]]) | 14 | map("t", "<C-h>", [[<C-\><C-n><C-w>h]]) |
| 15 | map("t", "<C-l>", [[<C-\><C-n><C-w>l]]) | 15 | map("t", "<C-l>", [[<C-\><C-n><C-w>l]]) |
| 16 | 16 | ||
| 17 | -- Copy to clipboard | ||
| 18 | map("v", "<leader>y", '"+y') | ||
| 19 | map("n", "<leader>Y", '"+yg_') | ||
| 20 | map("n", "<leader>y", '"+y') | ||
| 21 | map("n", "<leader>yy", '"+yy') | ||
| 22 | |||
| 23 | -- Paste from clipboard | ||
| 24 | map("n", "<leader>p", '"+p') | ||
| 25 | map("n", "<leader>P", '"+P') | ||
| 26 | map("v", "<leader>p", '"+p') | ||
| 27 | map("v", "<leader>P", '"+P') | ||
| 28 | |||
| 17 | -- Never use the arrow keys | 29 | -- Never use the arrow keys |
| 18 | for _, key in ipairs({ "<Up>", "<Down>", "<Left>", "<Right>" }) do | 30 | for _, key in ipairs({ "<Up>", "<Down>", "<Left>", "<Right>" }) do |
| 19 | map({ "n", "i" }, key, "<Nop>") | 31 | map({ "n", "i" }, key, "<Nop>") |
diff --git a/neovim/.config/nvim/lua/config/options.lua b/neovim/.config/nvim/lua/config/options.lua index be614e1..1282850 100644 --- a/neovim/.config/nvim/lua/config/options.lua +++ b/neovim/.config/nvim/lua/config/options.lua | |||
| @@ -34,3 +34,9 @@ opt.hlsearch = true | |||
| 34 | opt.incsearch = true | 34 | opt.incsearch = true |
| 35 | opt.ignorecase = true | 35 | opt.ignorecase = true |
| 36 | opt.smartcase = true | 36 | opt.smartcase = true |
| 37 | |||
| 38 | -- Project-local config (.nvim.lua) is handled by a custom autocmd in | ||
| 39 | -- autocmds.lua instead of the core 'exrc' option: 'exrc' only checks the | ||
| 40 | -- literal cwd at startup, once, so it misses a project's .nvim.lua whenever | ||
| 41 | -- Neovim didn't start with cwd exactly there. Leave 'exrc' off to avoid | ||
| 42 | -- double-sourcing the same file via both mechanisms. | ||
diff --git a/neovim/.config/nvim/lua/config/project_run.lua b/neovim/.config/nvim/lua/config/project_run.lua new file mode 100644 index 0000000..40c1795 --- /dev/null +++ b/neovim/.config/nvim/lua/config/project_run.lua | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | -- Single-source-of-truth helper for project-local run/debug configs, meant | ||
| 2 | -- to be called once per config from a project's `.nvim.lua` (requires | ||
| 3 | -- `opt.exrc` - see options.lua - and trusting the file once via | ||
| 4 | -- `:help :trust`). One call registers both an overseer run task and a | ||
| 5 | -- matching nvim-dap debug config, so a project states its command once | ||
| 6 | -- instead of repeating it across a separate run-file and debug-file. | ||
| 7 | -- | ||
| 8 | -- Example .nvim.lua (script invocation): | ||
| 9 | -- require("config.project_run").python({ | ||
| 10 | -- name = "Run app", | ||
| 11 | -- program = vim.fn.getcwd() .. "/main.py", | ||
| 12 | -- args = { "--flag" }, -- optional, shared by both run and debug | ||
| 13 | -- }) | ||
| 14 | -- | ||
| 15 | -- Example .nvim.lua (module invocation, `python -m <module>`): | ||
| 16 | -- require("config.project_run").python({ | ||
| 17 | -- name = "Run app", | ||
| 18 | -- module = "fastapi", | ||
| 19 | -- args = { "dev", "app" }, | ||
| 20 | -- }) | ||
| 21 | -- | ||
| 22 | -- This shows "Run app" in the <leader>rr picker (plain execution) and in | ||
| 23 | -- the <leader>dc picker (same script/module, under debugpy, breakpoints | ||
| 24 | -- included). If <cwd>/.venv exists, both get VIRTUAL_ENV/PATH pointed at | ||
| 25 | -- it, same as `uv run` (or `source .venv/bin/activate`) would - and the | ||
| 26 | -- debug config additionally gets pythonPath set to that venv's interpreter, | ||
| 27 | -- since debugpy runs the script with the literal interpreter it's told | ||
| 28 | -- rather than resolving `python3` via PATH. | ||
| 29 | -- | ||
| 30 | -- Example .nvim.lua (Node, script invocation): | ||
| 31 | -- require("config.project_run").node({ | ||
| 32 | -- name = "Run app", | ||
| 33 | -- program = vim.fn.getcwd() .. "/index.js", | ||
| 34 | -- args = { "--flag" }, -- optional, shared by both run and debug | ||
| 35 | -- }) | ||
| 36 | -- | ||
| 37 | -- Example .nvim.lua (Node, `npm run <script>` invocation): | ||
| 38 | -- require("config.project_run").node({ | ||
| 39 | -- name = "Run app", | ||
| 40 | -- npmScript = "dev", | ||
| 41 | -- }) | ||
| 42 | |||
| 43 | local M = {} | ||
| 44 | |||
| 45 | local function venv_dir() | ||
| 46 | local venv = vim.fn.getcwd() .. "/.venv" | ||
| 47 | if vim.fn.isdirectory(venv) == 0 then | ||
| 48 | return nil | ||
| 49 | end | ||
| 50 | return venv | ||
| 51 | end | ||
| 52 | |||
| 53 | local function venv_env(venv) | ||
| 54 | return { | ||
| 55 | VIRTUAL_ENV = venv, | ||
| 56 | PATH = venv .. "/bin:" .. vim.env.PATH, | ||
| 57 | } | ||
| 58 | end | ||
| 59 | |||
| 60 | function M.python(opts) | ||
| 61 | assert(opts.name, "project_run.python: opts.name is required") | ||
| 62 | assert(opts.program or opts.module, "project_run.python: opts.program or opts.module is required") | ||
| 63 | |||
| 64 | local venv = venv_dir() | ||
| 65 | local env = venv and venv_env(venv) or nil | ||
| 66 | local cmd = opts.module and { "python3", "-m", opts.module } or { "python3", opts.program } | ||
| 67 | |||
| 68 | require("overseer").register_template({ | ||
| 69 | name = opts.name, | ||
| 70 | builder = function() | ||
| 71 | return { | ||
| 72 | cmd = cmd, | ||
| 73 | args = opts.args, | ||
| 74 | name = opts.name, | ||
| 75 | env = env, | ||
| 76 | } | ||
| 77 | end, | ||
| 78 | }) | ||
| 79 | |||
| 80 | local dap = require("dap") | ||
| 81 | dap.configurations.python = dap.configurations.python or {} | ||
| 82 | table.insert(dap.configurations.python, { | ||
| 83 | type = "python", | ||
| 84 | request = "launch", | ||
| 85 | name = opts.name, | ||
| 86 | program = opts.program, | ||
| 87 | module = opts.module, | ||
| 88 | args = opts.args, | ||
| 89 | env = env, | ||
| 90 | -- nvim-dap-python only auto-detects an interpreter (VIRTUAL_ENV env var, | ||
| 91 | -- then a venv/.venv/env/.env folder search) when pythonPath/python isn't | ||
| 92 | -- already set - and debugpy needs the literal interpreter path here | ||
| 93 | -- regardless (it spawns it directly, not through a shell that'd resolve | ||
| 94 | -- `python3` via PATH the way env.PATH above does for the overseer task). | ||
| 95 | -- Set it explicitly from the same .venv we already found, so debugging | ||
| 96 | -- doesn't depend on that separate heuristic agreeing with us - without | ||
| 97 | -- this, a missed/wrong guess falls back to debugpy's own adapter venv, | ||
| 98 | -- which can't see the project's installed packages. | ||
| 99 | pythonPath = venv and (venv .. "/bin/python") or nil, | ||
| 100 | }) | ||
| 101 | end | ||
| 102 | |||
| 103 | -- Node has no venv-style interpreter juggling to do - node_modules | ||
| 104 | -- resolution is automatic - so this is a straight translation of opts into | ||
| 105 | -- an overseer task plus a pwa-node dap config, into all four JS/TS | ||
| 106 | -- filetypes (dap_node.lua registers the same four for its own defaults). | ||
| 107 | function M.node(opts) | ||
| 108 | assert(opts.name, "project_run.node: opts.name is required") | ||
| 109 | assert(opts.program or opts.npmScript, "project_run.node: opts.program or opts.npmScript is required") | ||
| 110 | |||
| 111 | local cmd = opts.npmScript and { "npm", "run", opts.npmScript } or { "node", opts.program } | ||
| 112 | |||
| 113 | require("overseer").register_template({ | ||
| 114 | name = opts.name, | ||
| 115 | builder = function() | ||
| 116 | return { | ||
| 117 | cmd = cmd, | ||
| 118 | args = opts.args, | ||
| 119 | name = opts.name, | ||
| 120 | } | ||
| 121 | end, | ||
| 122 | }) | ||
| 123 | |||
| 124 | -- A fresh table per filetype - nvim-dap's session setup can stash | ||
| 125 | -- bookkeeping fields onto a running config, so the four filetypes | ||
| 126 | -- shouldn't share one table instance. | ||
| 127 | local function config() | ||
| 128 | local c = { | ||
| 129 | type = "pwa-node", | ||
| 130 | request = "launch", | ||
| 131 | name = opts.name, | ||
| 132 | args = opts.args, | ||
| 133 | cwd = vim.fn.getcwd(), | ||
| 134 | } | ||
| 135 | if opts.npmScript then | ||
| 136 | c.runtimeExecutable = "npm" | ||
| 137 | c.runtimeArgs = { "run", opts.npmScript } | ||
| 138 | else | ||
| 139 | c.program = opts.program | ||
| 140 | end | ||
| 141 | return c | ||
| 142 | end | ||
| 143 | |||
| 144 | local dap = require("dap") | ||
| 145 | for _, filetype in ipairs({ "javascript", "typescript", "javascriptreact", "typescriptreact" }) do | ||
| 146 | dap.configurations[filetype] = dap.configurations[filetype] or {} | ||
| 147 | table.insert(dap.configurations[filetype], config()) | ||
| 148 | end | ||
| 149 | end | ||
| 150 | |||
| 151 | return M | ||
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 @@ | |||
| 1 | return { | 1 | return { |
| 2 | "greggh/claude-code.nvim", | 2 | "greggh/claude-code.nvim", |
| 3 | lazy = false, | ||
| 3 | dependencies = { "nvim-lua/plenary.nvim" }, | 4 | dependencies = { "nvim-lua/plenary.nvim" }, |
| 4 | cmd = { "ClaudeCode", "ClaudeCodeContinue", "ClaudeCodeResume", "ClaudeCodeVerbose" }, | 5 | cmd = { "ClaudeCode", "ClaudeCodeContinue", "ClaudeCodeResume", "ClaudeCodeVerbose" }, |
| 5 | config = function() | 6 | 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 { | |||
| 6 | local ok = pcall(vim.cmd.colorscheme, "janah") | 6 | local ok = pcall(vim.cmd.colorscheme, "janah") |
| 7 | if not ok then | 7 | if not ok then |
| 8 | vim.cmd.colorscheme("desert") | 8 | vim.cmd.colorscheme("desert") |
| 9 | return | ||
| 9 | end | 10 | end |
| 11 | |||
| 12 | -- vim-janah predates floating windows and never defines NormalFloat/ | ||
| 13 | -- FloatBorder, so they fall back to Neovim's near-black default and any | ||
| 14 | -- floating UI (:Mason, :Lazy, which-key's popup, ...) renders as a | ||
| 15 | -- mismatched black box. Match them to janah's own Normal/Comment colors. | ||
| 16 | vim.api.nvim_set_hl(0, "NormalFloat", { bg = "#262626", fg = "#dadada" }) | ||
| 17 | vim.api.nvim_set_hl(0, "FloatBorder", { bg = "#262626", fg = "#585858" }) | ||
| 10 | end, | 18 | end, |
| 11 | } | 19 | } |
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 @@ | |||
| 1 | -- Python launch configs (nvim-dap-python), wired to the debugpy adapter | ||
| 2 | -- that mason-nvim-dap.nvim installs (dap.lua). Kept in its own file since | ||
| 3 | -- this is the "per-language" half of debugging, parallel to how | ||
| 4 | -- ftplugin/python.lua holds Python-only settings. | ||
| 5 | return { | ||
| 6 | "mfussenegger/nvim-dap-python", | ||
| 7 | -- Not left to lazy-load off `ft = "python"`: dap.lua's <leader>dc picker | ||
| 8 | -- works from any window (not just a Python buffer) and needs | ||
| 9 | -- dap.adapters.python already registered by the time a config is picked, | ||
| 10 | -- even if no .py buffer has been opened yet this session. | ||
| 11 | lazy = false, | ||
| 12 | -- mason.nvim is listed directly (not just transitively via dap.lua) | ||
| 13 | -- because config() below needs require("mason-registry") to be loadable | ||
| 14 | -- from startup, same reasoning as lazy = false above. | ||
| 15 | dependencies = { "mfussenegger/nvim-dap", "mason-org/mason.nvim" }, | ||
| 16 | config = function() | ||
| 17 | local registry = require("mason-registry") | ||
| 18 | local pkg = registry.get_package("debugpy") | ||
| 19 | |||
| 20 | -- debugpy_path is the interpreter that runs the debug *adapter* itself | ||
| 21 | -- (Mason's isolated venv) - it does not control which Python runs your | ||
| 22 | -- script. dap-python defaults that to the active venv/system python3; | ||
| 23 | -- project-specific venvs may need a manual `pythonPath` override in a | ||
| 24 | -- generated launch config later. | ||
| 25 | local debugpy_path = pkg:get_install_path() .. "/venv/bin/python" | ||
| 26 | |||
| 27 | local function setup() | ||
| 28 | require("dap-python").setup(debugpy_path) | ||
| 29 | |||
| 30 | -- nvim-dap-python doesn't expose adapter.options for tuning, and | ||
| 31 | -- nvim-dap's default terminate-request timeout (3s) is tight enough | ||
| 32 | -- that debugpy's real response can arrive just after nvim-dap already | ||
| 33 | -- gave up and moved on ("No callback found" in dap.log) - <leader>dt | ||
| 34 | -- still works, but dap.session() doesn't clear for a few extra | ||
| 35 | -- seconds, so <leader>dc right after can catch it still "active". | ||
| 36 | -- Wrap the adapter dap-python just registered to give it more room. | ||
| 37 | local dap = require("dap") | ||
| 38 | local base_adapter = dap.adapters.python | ||
| 39 | dap.adapters.python = function(cb, config) | ||
| 40 | base_adapter(function(adapter) | ||
| 41 | adapter.options = adapter.options or {} | ||
| 42 | adapter.options.disconnect_timeout_sec = 8 | ||
| 43 | cb(adapter) | ||
| 44 | end, config) | ||
| 45 | end | ||
| 46 | end | ||
| 47 | |||
| 48 | if pkg:is_installed() then | ||
| 49 | setup() | ||
| 50 | else | ||
| 51 | -- dap.lua's mason-nvim-dap ensure_installed triggers debugpy's | ||
| 52 | -- install, but that's async - on a fresh machine (or before it | ||
| 53 | -- finishes) debugpy_path doesn't exist on disk yet, and <leader>dc | ||
| 54 | -- would fail with a raw ENOENT from debugpy itself instead of a clear | ||
| 55 | -- message. Wire up the adapter once the install actually completes | ||
| 56 | -- instead of pointing it at a path that isn't there yet. | ||
| 57 | vim.notify( | ||
| 58 | "debugpy not installed yet - dap.lua's ensure_installed should be" | ||
| 59 | .. " installing it now (check :Mason); run :MasonInstall debugpy" | ||
| 60 | .. " if it doesn't show up there. Debugging will work once it's" | ||
| 61 | .. " done.", | ||
| 62 | vim.log.levels.WARN | ||
| 63 | ) | ||
| 64 | registry:on("package:install:success", function(installed_pkg) | ||
| 65 | if installed_pkg.name == "debugpy" then | ||
| 66 | setup() | ||
| 67 | end | ||
| 68 | end) | ||
| 69 | end | ||
| 70 | end, | ||
| 71 | } | ||
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 @@ | |||
| 1 | -- Debugging via nvim-dap. Adapter installs are bridged through Mason | ||
| 2 | -- (mason-nvim-dap.nvim), the same pattern lsp.lua uses for language servers, | ||
| 3 | -- so adding a debug adapter for another language later is just adding it to | ||
| 4 | -- ensure_installed here - Python specifics live in dap-python.lua, Node | ||
| 5 | -- specifics in lua/config/dap_node.lua. | ||
| 6 | return { | ||
| 7 | "mfussenegger/nvim-dap", | ||
| 8 | -- Not left to lazy-load off `keys`: a project's .nvim.lua (see | ||
| 9 | -- lua/config/project_run.lua) needs `require("dap")` to work immediately | ||
| 10 | -- when exrc sources it, which requires the plugin already being on | ||
| 11 | -- runtimepath rather than deferred until a <leader>d keymap fires. | ||
| 12 | lazy = false, | ||
| 13 | dependencies = { | ||
| 14 | { | ||
| 15 | "rcarriga/nvim-dap-ui", | ||
| 16 | dependencies = { "nvim-neotest/nvim-nio" }, | ||
| 17 | }, | ||
| 18 | "theHamsta/nvim-dap-virtual-text", | ||
| 19 | { | ||
| 20 | "jay-babu/mason-nvim-dap.nvim", | ||
| 21 | dependencies = { "mason-org/mason.nvim" }, | ||
| 22 | }, | ||
| 23 | }, | ||
| 24 | keys = { | ||
| 25 | { "<leader>db", function() require("dap").toggle_breakpoint() end, desc = "Toggle breakpoint" }, | ||
| 26 | { | ||
| 27 | "<leader>dB", | ||
| 28 | function() require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) end, | ||
| 29 | desc = "Conditional breakpoint", | ||
| 30 | }, | ||
| 31 | { | ||
| 32 | "<leader>dc", | ||
| 33 | function() | ||
| 34 | local dap = require("dap") | ||
| 35 | |||
| 36 | if dap.session() then | ||
| 37 | -- Existing session: resume past a breakpoint, or nvim-dap's | ||
| 38 | -- terminate/pause/restart prompt if active but not stopped. | ||
| 39 | -- This branch doesn't consult buffer filetype, so it's fine to | ||
| 40 | -- call from any window. | ||
| 41 | dap.continue() | ||
| 42 | return | ||
| 43 | end | ||
| 44 | |||
| 45 | -- No active session: pick a config to start. dap.continue()'s own | ||
| 46 | -- path for this (select_config_and_run) only offers | ||
| 47 | -- dap.configurations[<current buffer's filetype>], so calling it | ||
| 48 | -- from the task-output dock or some other non-source window finds | ||
| 49 | -- nothing. Flatten across every filetype instead - same as | ||
| 50 | -- <leader>rr does for run tasks - so this works from anywhere and | ||
| 51 | -- you just pick the config you want from the list. | ||
| 52 | local entries = {} | ||
| 53 | for filetype, configs in pairs(dap.configurations) do | ||
| 54 | for _, config in ipairs(configs) do | ||
| 55 | table.insert(entries, { config = config, filetype = filetype }) | ||
| 56 | end | ||
| 57 | end | ||
| 58 | |||
| 59 | -- .vscode/launch.json (if present in cwd) is read on-demand by | ||
| 60 | -- nvim-dap's own "dap.launch.json" provider - dap.ext.vscode's | ||
| 61 | -- load_launchjs() is deprecated now that this exists. That provider | ||
| 62 | -- is normally consulted inside dap.continue()'s own | ||
| 63 | -- select_config_and_run, which we're bypassing above, so call it | ||
| 64 | -- directly here to fold its configs into the same picker - the | ||
| 65 | -- debug-side counterpart to overseer's tasks.json support (README's | ||
| 66 | -- Run configurations section). Pair a launch.json entry with a | ||
| 67 | -- same-named tasks.json entry for PyCharm-style "run or debug the | ||
| 68 | -- same thing". | ||
| 69 | local ok, launchjson_configs = pcall(dap.providers.configs["dap.launch.json"]) | ||
| 70 | if ok then | ||
| 71 | for _, config in ipairs(launchjson_configs) do | ||
| 72 | table.insert(entries, { config = config, filetype = config.type }) | ||
| 73 | end | ||
| 74 | end | ||
| 75 | |||
| 76 | if vim.tbl_isempty(entries) then | ||
| 77 | vim.notify("No debug configurations registered (see project_run.lua)", vim.log.levels.WARN) | ||
| 78 | return | ||
| 79 | end | ||
| 80 | |||
| 81 | vim.ui.select(entries, { | ||
| 82 | prompt = "Configuration: ", | ||
| 83 | format_item = function(e) return e.config.name end, | ||
| 84 | }, function(entry) | ||
| 85 | if entry then | ||
| 86 | -- Pass along the filetype the config was registered under (not | ||
| 87 | -- necessarily the invoking buffer's) so breakpoint-hit window | ||
| 88 | -- jumping still picks a sensible window. | ||
| 89 | dap.run(entry.config, { filetype = entry.filetype }) | ||
| 90 | end | ||
| 91 | end) | ||
| 92 | end, | ||
| 93 | desc = "Continue / start debugging", | ||
| 94 | }, | ||
| 95 | { "<leader>do", function() require("dap").step_over() end, desc = "Step over" }, | ||
| 96 | { "<leader>di", function() require("dap").step_into() end, desc = "Step into" }, | ||
| 97 | { "<leader>dO", function() require("dap").step_out() end, desc = "Step out" }, | ||
| 98 | { "<leader>dt", function() require("dap").terminate() end, desc = "Terminate session" }, | ||
| 99 | { "<leader>dr", function() require("dap").repl.toggle() end, desc = "Toggle REPL" }, | ||
| 100 | { "<leader>du", function() require("dapui").toggle() end, desc = "Toggle debug UI" }, | ||
| 101 | }, | ||
| 102 | config = function() | ||
| 103 | require("dapui").setup() | ||
| 104 | require("nvim-dap-virtual-text").setup() | ||
| 105 | |||
| 106 | -- nvim-dap doesn't define these signs itself - it just places them | ||
| 107 | -- (breakpoints.lua, session.lua's DapStopped placement) and expects the | ||
| 108 | -- config to have already called sign_define, so without this nothing | ||
| 109 | -- renders: no breakpoint marker in the sign column, and no indication | ||
| 110 | -- of the current line when a session stops (the stop itself still | ||
| 111 | -- works, sign_place just errors silently into a pcall). | ||
| 112 | vim.fn.sign_define("DapBreakpoint", { text = "●", texthl = "DiagnosticError" }) | ||
| 113 | vim.fn.sign_define("DapBreakpointCondition", { text = "◆", texthl = "DiagnosticWarn" }) | ||
| 114 | vim.fn.sign_define("DapBreakpointRejected", { text = "✗", texthl = "DiagnosticError" }) | ||
| 115 | vim.fn.sign_define("DapLogPoint", { text = "📝", texthl = "DiagnosticInfo" }) | ||
| 116 | vim.fn.sign_define("DapStopped", { text = "▶", texthl = "DiagnosticWarn", linehl = "DapStoppedLine" }) | ||
| 117 | -- default = true so a colorscheme (or later config) can override this | ||
| 118 | -- without a load-order fight; Visual is just a visible fallback. | ||
| 119 | vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) | ||
| 120 | |||
| 121 | -- handlers = {} opts out of mason-nvim-dap's automatic adapter | ||
| 122 | -- registration: nvim-dap-python (dap-python.lua) registers its own | ||
| 123 | -- "python" adapter/config, so we don't want a second one clobbering it. | ||
| 124 | -- Adding a language without its own dap-<lang>.lua later should drop | ||
| 125 | -- this override so its adapter gets auto-registered instead. | ||
| 126 | require("mason-nvim-dap").setup({ | ||
| 127 | -- ensure_installed wants nvim-dap *adapter/source* names, not Mason | ||
| 128 | -- *package* names - mason-nvim-dap looks each entry up in its own | ||
| 129 | -- name -> package mapping (source.lua: python -> debugpy) and just | ||
| 130 | -- silently skips anything it doesn't recognize, no error/log. Passing | ||
| 131 | -- "debugpy" here (the package name) matched nothing, so it never | ||
| 132 | -- triggered an install at all. | ||
| 133 | ensure_installed = { "python", "js" }, | ||
| 134 | automatic_installation = true, | ||
| 135 | handlers = {}, | ||
| 136 | }) | ||
| 137 | |||
| 138 | -- Node/JS/TS adapter + default configs - not left to mason-nvim-dap's | ||
| 139 | -- own handler since "js" has no default adapter mapping there (only the | ||
| 140 | -- deprecated node2 does), see lua/config/dap_node.lua for why. | ||
| 141 | require("config.dap_node").setup() | ||
| 142 | |||
| 143 | local dap, dapui = require("dap"), require("dapui") | ||
| 144 | |||
| 145 | -- nvim-dap jumps to the stopped line using Neovim's 'switchbuf' option, | ||
| 146 | -- which defaults to "uselast": reuse the current window if it's already | ||
| 147 | -- a plain/source buffer, else fall back to the alternate window - and | ||
| 148 | -- if neither applies (e.g. <leader>dc was started from the task-output | ||
| 149 | -- dock or some other non-source window, which the picker now allows), | ||
| 150 | -- it silently does nothing. No error, no jump - the session *is* | ||
| 151 | -- stopped (stepping/continuing still works), it just never shows where. | ||
| 152 | -- Append "vsplit" so there's always a guaranteed-successful last resort | ||
| 153 | -- that opens the source file if nothing else matched. | ||
| 154 | dap.defaults.fallback.switchbuf = "usevisible,useopen,uselast,vsplit" | ||
| 155 | |||
| 156 | -- Open/close dap-ui automatically around a debug session, so <leader>du | ||
| 157 | -- is only needed to bring it back after manually closing it mid-session. | ||
| 158 | dap.listeners.after.event_initialized["dapui_config"] = function() | ||
| 159 | dapui.open() | ||
| 160 | end | ||
| 161 | dap.listeners.before.event_terminated["dapui_config"] = function() | ||
| 162 | dapui.close() | ||
| 163 | end | ||
| 164 | dap.listeners.before.event_exited["dapui_config"] = function() | ||
| 165 | dapui.close() | ||
| 166 | end | ||
| 167 | |||
| 168 | -- These events arrive asynchronously over debugpy's socket (a libuv | ||
| 169 | -- callback, not a keypress), and nvim-dap updates its state - cursor | ||
| 170 | -- position, signs, dapui panels - without that alone forcing Neovim to | ||
| 171 | -- repaint. So hitting a breakpoint, continuing past one, or a session | ||
| 172 | -- ending can all silently not *look* like anything happened until the | ||
| 173 | -- next keystroke forces a redraw that reveals the already-current | ||
| 174 | -- state (e.g. <leader>dc appearing to need pressing twice to resume). | ||
| 175 | for _, event in ipairs({ "event_stopped", "event_continued", "event_terminated", "event_exited" }) do | ||
| 176 | dap.listeners.after[event]["dap_redraw"] = function() | ||
| 177 | vim.cmd("redraw") | ||
| 178 | end | ||
| 179 | end | ||
| 180 | end, | ||
| 181 | } | ||
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 @@ | |||
| 1 | return { | 1 | return { |
| 2 | { | ||
| 3 | "preservim/nerdcommenter", | ||
| 4 | init = function() | ||
| 5 | vim.g.NERDSpaceDelims = 1 | ||
| 6 | vim.g.NERDCompactSexyComs = 1 | ||
| 7 | vim.g.NERDDefaultAlign = "left" | ||
| 8 | vim.g.NERDCommentEmptyLines = 1 | ||
| 9 | vim.g.NERDTrimTrailingWhitespace = 1 | ||
| 10 | end, | ||
| 11 | }, | ||
| 12 | "unblevable/quick-scope", | 2 | "unblevable/quick-scope", |
| 13 | } | 3 | } |
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 @@ | |||
| 1 | return { | 1 | return { |
| 2 | "ctrlpvim/ctrlp.vim", | 2 | "nvim-telescope/telescope.nvim", |
| 3 | init = function() | 3 | -- Not left to lazy-load off `keys`: telescope-ui-select's vim.ui.select() |
| 4 | -- Use ripgrep for listing files (fast, respects .gitignore) | 4 | -- override (below) needs to be installed from startup, otherwise |
| 5 | if vim.fn.executable("rg") == 1 then | 5 | -- overseer's <leader>rr / nvim-dap-python's <leader>dc pickers fall back |
| 6 | vim.g.ctrlp_user_command = 'rg %s --files --color=never --glob ""' | 6 | -- to Neovim's default list until something (e.g. <C-p>) happens to |
| 7 | vim.g.ctrlp_use_caching = 0 | 7 | -- trigger telescope's own lazy-load first. |
| 8 | end | 8 | lazy = false, |
| 9 | dependencies = { | ||
| 10 | "nvim-lua/plenary.nvim", | ||
| 11 | "nvim-telescope/telescope-ui-select.nvim", | ||
| 12 | }, | ||
| 13 | keys = { | ||
| 14 | { "<C-p>", "<cmd>Telescope find_files<cr>" }, | ||
| 15 | { "<leader>fg", "<cmd>Telescope live_grep<cr>" }, | ||
| 16 | { "<leader>fb", "<cmd>Telescope buffers<cr>" }, | ||
| 17 | }, | ||
| 18 | config = function() | ||
| 19 | -- telescope-ui-select makes vim.ui.select() - overseer's <leader>rr | ||
| 20 | -- template picker, nvim-dap-python's launch-config picker, LSP code | ||
| 21 | -- actions, etc. - a scrollable/fuzzy-searchable Telescope window | ||
| 22 | -- instead of Neovim's default numbered-list-in-the-cmdline prompt. | ||
| 23 | require("telescope").setup({ | ||
| 24 | extensions = { | ||
| 25 | ["ui-select"] = { | ||
| 26 | require("telescope.themes").get_dropdown({}), | ||
| 27 | }, | ||
| 28 | }, | ||
| 29 | }) | ||
| 30 | require("telescope").load_extension("ui-select") | ||
| 9 | end, | 31 | end, |
| 10 | } | 32 | } |
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 @@ | |||
| 1 | return { | 1 | return { |
| 2 | "tpope/vim-fugitive", | 2 | "tpope/vim-fugitive", |
| 3 | "mhinz/vim-signify", | 3 | { |
| 4 | "lewis6991/gitsigns.nvim", | ||
| 5 | opts = {}, | ||
| 6 | }, | ||
| 4 | } | 7 | } |
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 @@ | |||
| 1 | -- Detects each buffer's actual indentation/spacing on open and sets | ||
| 2 | -- shiftwidth/tabstop/expandtab to match, rather than relying solely on | ||
| 3 | -- ftplugin defaults (e.g. ftplugin/python.lua) or global options.opt. | ||
| 4 | return { | ||
| 5 | "nmac427/guess-indent.nvim", | ||
| 6 | event = { "BufReadPost", "BufNewFile" }, | ||
| 7 | opts = {}, | ||
| 8 | } | ||
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 @@ | |||
| 1 | return { | ||
| 2 | { | ||
| 3 | "chase/vim-ansible-yaml", | ||
| 4 | cond = function() | ||
| 5 | return vim.fn.executable("ansible") == 1 | ||
| 6 | end, | ||
| 7 | }, | ||
| 8 | { | ||
| 9 | "hashivim/vim-terraform", | ||
| 10 | cond = function() | ||
| 11 | return vim.fn.executable("terraform") == 1 | ||
| 12 | end, | ||
| 13 | }, | ||
| 14 | } | ||
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 @@ | |||
| 1 | -- Run configurations (PyCharm-style "run this again"), language-agnostic: | ||
| 2 | -- works for npm scripts, make, cargo, arbitrary shell commands, python | ||
| 3 | -- scripts, etc, unlike DAP which is Python-only for now. | ||
| 4 | return { | ||
| 5 | "stevearc/overseer.nvim", | ||
| 6 | -- Not left to lazy-load off `cmd`/`keys`: a project's .nvim.lua (see | ||
| 7 | -- lua/config/project_run.lua) needs `require("overseer")` to work | ||
| 8 | -- immediately when exrc sources it, which requires the plugin already | ||
| 9 | -- being on runtimepath rather than deferred until first use. | ||
| 10 | lazy = false, | ||
| 11 | keys = { | ||
| 12 | { "<leader>rr", "<cmd>OverseerRun<cr>", desc = "Run task" }, | ||
| 13 | { | ||
| 14 | "<leader>rl", | ||
| 15 | function() | ||
| 16 | -- :OverseerRestartLast exists in current overseer.nvim versions; the | ||
| 17 | -- run_action fallback covers older/newer versions that lack it | ||
| 18 | -- rather than hard-failing the keymap. | ||
| 19 | if vim.fn.exists(":OverseerRestartLast") == 2 then | ||
| 20 | vim.cmd("OverseerRestartLast") | ||
| 21 | return | ||
| 22 | end | ||
| 23 | local overseer = require("overseer") | ||
| 24 | local tasks = overseer.list_tasks({ recent_first = true }) | ||
| 25 | if vim.tbl_isempty(tasks) then | ||
| 26 | vim.notify("No previous task to rerun", vim.log.levels.WARN) | ||
| 27 | else | ||
| 28 | overseer.run_action(tasks[1], "restart") | ||
| 29 | end | ||
| 30 | end, | ||
| 31 | desc = "Rerun last task", | ||
| 32 | }, | ||
| 33 | { "<leader>ro", "<cmd>OverseerToggle<cr>", desc = "Toggle task list/output" }, | ||
| 34 | { "<leader>rq", "<cmd>OverseerQuickAction<cr>", desc = "Quick action on task" }, | ||
| 35 | }, | ||
| 36 | opts = { | ||
| 37 | -- Patches nvim-dap so a debug config can set preLaunchTask/postDebugTask | ||
| 38 | -- to an overseer task name (or "${defaultBuildTask}" for whatever task | ||
| 39 | -- is tagged BUILD) - lets a dap.configurations entry build before it | ||
| 40 | -- launches the debugger. See README's Debugging section. | ||
| 41 | dap = true, | ||
| 42 | -- overseer's actual default components (on_exit_set_status, | ||
| 43 | -- on_complete_notify, on_complete_dispose) don't open the output panel | ||
| 44 | -- on their own - without open_output added here, starting any task | ||
| 45 | -- (whether from a template, .nvim.lua/project_run.lua, or auto-detected | ||
| 46 | -- npm/make scripts) runs silently until you manually <leader>ro to look. | ||
| 47 | -- Adding it here applies to every task, not just custom ones. | ||
| 48 | component_aliases = { | ||
| 49 | default = { | ||
| 50 | "on_exit_set_status", | ||
| 51 | "on_complete_notify", | ||
| 52 | { "on_complete_dispose", require_view = { "SUCCESS", "FAILURE" } }, | ||
| 53 | { "open_output", direction = "dock", focus = false, on_start = "always" }, | ||
| 54 | }, | ||
| 55 | }, | ||
| 56 | }, | ||
| 57 | } | ||
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 @@ | |||
| 1 | return { | 1 | return { |
| 2 | "bling/vim-airline", | 2 | "nvim-lualine/lualine.nvim", |
| 3 | lazy = false, | 3 | dependencies = { "nvim-tree/nvim-web-devicons" }, |
| 4 | dependencies = { | 4 | opts = {}, |
| 5 | "vim-airline/vim-airline-themes", | ||
| 6 | "edkolev/tmuxline.vim", | ||
| 7 | }, | ||
| 8 | init = function() | ||
| 9 | -- On arch linux install the following: | ||
| 10 | -- otf-powerline-symbols-git | ||
| 11 | -- powerline-fonts-git | ||
| 12 | vim.g.airline_powerline_fonts = 1 | ||
| 13 | vim.g["airline#extensions#tabline#enabled"] = 1 | ||
| 14 | |||
| 15 | -- vim.g dict reads return a copy, not a live reference, so the nested | ||
| 16 | -- field has to be set via a local table and reassigned. | ||
| 17 | local symbols = vim.g.airline_symbols or {} | ||
| 18 | symbols.space = "\u{a0}" | ||
| 19 | vim.g.airline_symbols = symbols | ||
| 20 | |||
| 21 | vim.opt.laststatus = 2 | ||
| 22 | end, | ||
| 23 | } | 5 | } |
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 @@ | |||
| 1 | -- Scratch terminal for running arbitrary shell commands, toggled like | ||
| 2 | -- claude-code.nvim's own <C-,> - open/close (not kill) a persistent split. | ||
| 3 | return { | ||
| 4 | "akinsho/toggleterm.nvim", | ||
| 5 | lazy = false, -- global <C-.> toggle must work from any window, not just after some trigger event | ||
| 6 | opts = { | ||
| 7 | open_mapping = [[<C-.>]], -- registers n, t (terminal_mappings) and i (insert_mappings) mode maps automatically | ||
| 8 | direction = "vertical", | ||
| 9 | -- toggleterm's vertical direction always opens via "botright vsplit" internally, | ||
| 10 | -- so this already matches claude-code.nvim's right-side placement without | ||
| 11 | -- touching 'splitright'. | ||
| 12 | size = function(term) | ||
| 13 | if term.direction == "vertical" then | ||
| 14 | return math.floor(vim.o.columns * 0.3) -- matches claude-code.nvim's window.position ratio | ||
| 15 | end | ||
| 16 | end, | ||
| 17 | }, | ||
| 18 | } | ||
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 @@ | |||
| 1 | -- Popup showing available keymaps/groups as you type a prefix like | ||
| 2 | -- <leader>d or <leader>r, so the debug/run namespaces stay discoverable | ||
| 3 | -- without memorizing every letter. Auto-discovers each keymap's own `desc` | ||
| 4 | -- field from dap.lua/overseer.lua/etc - only the group headers need | ||
| 5 | -- registering here. | ||
| 6 | return { | ||
| 7 | "folke/which-key.nvim", | ||
| 8 | event = "VeryLazy", | ||
| 9 | opts = { | ||
| 10 | spec = { | ||
| 11 | { "<leader>d", group = "Debug", icon = "🐞" }, | ||
| 12 | { "<leader>r", group = "Run", icon = "▶" }, | ||
| 13 | { "<leader>f", group = "Find" }, | ||
| 14 | { "<leader>e", group = "Explorer" }, | ||
| 15 | }, | ||
| 16 | }, | ||
| 17 | } | ||
diff --git a/neovim/.config/nvim/nvim.log b/neovim/.config/nvim/nvim.log new file mode 100644 index 0000000..7158332 --- /dev/null +++ b/neovim/.config/nvim/nvim.log | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | WRN 2026-09-14T16:30:21.846 ?.4836 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/StQYRj/nvim.4836.0 | ||
| 2 | WRN 2026-09-14T16:30:26.261 ?.4845 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/K4I50n/nvim.4845.0 | ||
| 3 | WRN 2026-09-14T16:31:13.471 ?.4921 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/OkXebD/nvim.4921.0 | ||
| 4 | WRN 2026-09-14T16:33:09.911 ?.5030 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/e73IV2/nvim.5030.0 | ||
| 5 | WRN 2026-09-15T10:45:56.983 ?.34498 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/R2azoM/nvim.34498.0 | ||
| 6 | WRN 2026-09-15T11:05:45.401 c/nvim.35169.0 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/8xMtRC/nvim.38701.0 | ||
diff --git a/nvim.log b/nvim.log new file mode 100644 index 0000000..54cac1c --- /dev/null +++ b/nvim.log | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | WRN 2026-09-15T10:52:53.198 c/nvim.35169.0 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/70FEV5/nvim.35600.0 | ||
| 2 | ERR 2026-09-15T10:52:53.200 c/nvim.35169.0 pty_proc_spawn:190: forkpty failed: Operation not permitted | ||
| 3 | WRN 2026-09-15T10:53:00.647 c/nvim.35169.0 server_start:197: Failed to start server: operation not permitted: /tmp/claude-501/nvim.tom/NuetHc/nvim.35627.0 | ||
| 4 | ERR 2026-09-15T10:53:00.650 c/nvim.35169.0 pty_proc_spawn:190: forkpty failed: Operation not permitted | ||
