diff options
Diffstat (limited to 'neovim/.config/nvim/README.md')
| -rw-r--r-- | neovim/.config/nvim/README.md | 135 |
1 files changed, 130 insertions, 5 deletions
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 |
