Files
nvim-config/README.md

317 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Neovim Configuration (LazyVim)
A LazyVim-based setup focused on Go and Zig development, with LSP, debugging,
test running, task running, AI chat, database tooling, and a which-key cheat
sheet. Everything is lazy-loaded so plugins only activate for the filetype or
command that needs them.
## Prerequisites
- **Neovim >= 0.11** (developed on 0.12.x; 0.11+ is required for the modern
`vim.lsp` / `root_markers` API used by some servers)
- **Git**
- **A Nerd Font** (icons in the explorer, statusline, dadbod UI, etc.)
- **Node.js** — TypeScript/JSON/YAML/web LSPs and `prettier`
- **Go** — `gopls`, `delve`, `gofumpt`, `goimports`
- **Zig** — the `zig` toolchain on `$PATH` (for LSP, build/run, tests, debug)
- **Python** _(optional)_`pyright` + `ruff` are configured if you use it
Most language servers, linters, formatters, and DAP adapters install
automatically through Mason on first launch.
## Installation
1. **Back up any existing config:**
```bash
mv ~/.config/nvim ~/.config/nvim.bak
mv ~/.local/share/nvim ~/.local/share/nvim.bak
mv ~/.local/state/nvim ~/.local/state/nvim.bak
mv ~/.cache/nvim ~/.cache/nvim.bak
```
2. **Clone:**
```bash
git clone https://git.samoneal.io/sam_oneal/nvim-config.git ~/.config/nvim
```
3. **Launch Neovim.** lazy.nvim bootstraps itself and installs all plugins.
4. **Install tooling** with `:Mason` (or `:MasonInstall <tool>`). Check health
with `:checkhealth` and LSP attachment with `:checkhealth lsp`.
## What's included
**Base:** [LazyVim](https://www.lazyvim.org/) with leader = `<Space>`,
localleader = `\`, colorscheme `catppuccin-mocha`.
**LazyVim extras enabled** (in `lua/config/lazy.lua`): `lang.go`, `lang.json`,
`lang.yaml`, `lang.markdown`, `lang.typescript`, `lang.tailwind`,
`dap.core`.
**Languages (LSP + Treesitter):** Go, Zig, Lua, TypeScript/JavaScript, HTML,
CSS, JSON, YAML, Markdown, SQL, Dockerfile, Python.
| Concern | Plugin / tool |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| LSP | nvim-lspconfig + Mason (`gopls`, `zls`, `lua_ls`, `ts_ls`, `html`, `cssls`, `jsonls`, `yamlls`, `marksman`, `sqlls`, `dockerls`, `pyright`/`ruff`) |
| Completion | blink.cmp (LazyVim default; SQL routed to dadbod) |
| Formatting | conform.nvim via LazyVim's format pipeline |
| Debugging | nvim-dap + delve (Go), codelldb (Zig/C/C++) |
| Testing | neotest (Go, Python, Zig) with in-buffer pass/fail signs |
| Coverage | nvim-coverage (Go) |
| Task running | overseer.nvim (+ user templates) |
| AI chat | [opencode.nvim](https://github.com/nickjvandyke/opencode.nvim) (provider-agnostic) |
| Database | vim-dadbod + dadbod-ui + dadbod-completion |
| Git | Neogit + diffview, plus LazyVim's lazygit |
| Explorer/picker | snacks.nvim |
| Symbols | aerial.nvim |
| Diagnostics | trouble.nvim |
| Cheat sheet | which-key.nvim (hold `<leader>`) |
### AI (opencode.nvim)
AI is intentionally **environment-agnostic**: opencode.nvim drives the external
[`opencode`](https://opencode.ai) CLI, so the model/provider (Anthropic,
OpenAI, local models, etc.) is chosen in opencode's own config rather than here.
Install the `opencode` CLI separately and configure your provider there.
### Database (vim-dadbod)
Open the UI with `<leader>Du`. Add a connection with `<leader>Da`. Examples:
```
postgresql://user:pass@localhost:5432/dbname
mysql://user:pass@localhost:3306/dbname
sqlite:path/to/db.sqlite
```
SQL completion is provided via dadbod inside SQL buffers, and SQL
autoformat-on-save is intentionally disabled (format manually with
`<leader>cf`).
## Key bindings
Hold `<leader>` (Space) to pop up the **which-key** menu — it lists every group
below as a live cheat sheet. Mouse is enabled (`mouse=a`), and the explorer,
dadbod UI, Neogit, DAP UI, trouble, aerial, and Overseer pickers are all
clickable.
> Note the deliberate capitalization: **`<leader>T*`** is Terminal (lowercase
> `<leader>t*` is the Test group), and **`<leader>D*`** is Database (lowercase
> `<leader>d*` is Debug).
### AI (`<leader>a`)
| Key | Action |
| --------------------- | ---------------------------------- |
| `<leader>aa` | Ask AI about current context (n/v) |
| `<leader>ax` | Ask AI about selection |
| `<leader>at` | Toggle AI panel |
| `go` | Operator: add range to AI chat |
| `goo` | Add current line to AI chat |
| `<S-C-u>` / `<S-C-d>` | Scroll AI chat up/down |
### Code Go (`<leader>cg`)
| Key | Action |
| -------------- | ------------------------------------- |
| `<leader>cgb` | Run benchmarks (`-bench=. -benchmem`) |
| `<leader>cgpc` | CPU profile |
| `<leader>cgpm` | Memory profile |
| `<leader>cgpt` | Trace profile |
### Code Zig (`<leader>cz`)
| Key | Action |
| ------------- | ---------------- |
| `<leader>czb` | `zig build` |
| `<leader>czr` | `zig build run` |
| `<leader>czt` | `zig build test` |
### Tests (neotest, `<leader>t`)
Works in Go, Python, and Zig buffers; results show as signs in the gutter.
| Key | Action |
|-----|--------|
| `<leader>tt` | Run nearest test |
| `<leader>tf` | Run test file |
| `<leader>ts` | Toggle test summary |
| `<leader>to` | Open test output |
| `<leader>tc` | Show coverage (Go) |
### Debugging (DAP, `<leader>d`)
Go uses delve; Zig/C/C++ use codelldb. Zig launch configs build with debug
symbols first, then run (`Launch (zig build)` prompts for the exe under
`zig-out/bin`; `Launch (current file)` compiles the open file).
| Key | Action |
|-----|--------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Conditional breakpoint |
| `<leader>dc` | Continue / start |
| `<leader>dC` | Run to cursor |
| `<leader>di` | Step into |
| `<leader>dO` | Step over |
| `<leader>do` | Step out |
| `<leader>dj` / `<leader>dk` | Stack down / up |
| `<leader>dr` | Toggle REPL |
| `<leader>ds` | Session |
| `<leader>dt` | Terminate |
| `<leader>dw` | Inspect widget (hover) |
| `<leader>du` | Toggle DAP UI |
| `<leader>de` | Eval (n/v) |
| `<leader>dT` | Debug Go test |
| `<leader>dL` | Debug last Go test |
### Tasks (Overseer, `<leader>o`)
| Key | Action |
| ------------ | --------------------------------------------------------- |
| `<leader>or` | Run a task (picker — includes `go:` and `zig:` templates) |
| `<leader>ot` | Toggle task list |
### Database (`<leader>D`)
| Key | Action |
| ------------ | -------------- |
| `<leader>Du` | Toggle DB UI |
| `<leader>Da` | Add connection |
| `<leader>Df` | Find DB buffer |
### Git (`<leader>g`)
| Key | Action |
| ------------ | ------------------------- |
| `<leader>gg` | Lazygit (LazyVim default) |
| `<leader>gn` | Neogit |
| `<leader>gl` | Lazygit log |
| `<leader>gf` | Lazygit file history |
### Search / Symbols (`<leader>s`)
| Key | Action |
| ------------ | ------------------------ |
| `<leader>so` | Symbols outline (aerial) |
| `<leader>sh` | Incoming calls |
| `<leader>sc` | Outgoing calls |
### Diagnostics (Trouble, `<leader>x`)
| Key | Action |
| ------------ | --------------------- |
| `<leader>xx` | Diagnostics |
| `<leader>xw` | Workspace diagnostics |
| `<leader>xt` | TODOs |
### Terminal (`<leader>T`)
| Key | Action |
| ------------ | --------------------------- |
| `<leader>Th` | Terminal (horizontal split) |
| `<leader>Tv` | Terminal (vertical split) |
| `<Esc><Esc>` | Exit terminal mode |
### Explorer & windows
| Key | Action |
| ------------------------ | ----------------------------- |
| `<C-e>` | Toggle explorer (snacks) |
| `<C-S-v>` / `<C-v>` | Open file in vertical split |
| `<C-S-h>` / `<C-x>` | Open file in horizontal split |
| `<C-h/j/k/l>` | Navigate windows |
| `<C-Up/Down/Left/Right>` | Resize window |
### Formatting (LazyVim pipeline)
| Key / Command | Action |
| ------------- | -------------------------- |
| `<leader>cf` | Format buffer |
| `<leader>uf` | Toggle autoformat (buffer) |
| `<leader>uF` | Toggle autoformat (global) |
| `:LazyFormat` | Format now |
### General editing
| Key | Action |
| ------------------ | --------------------------- |
| `<C-s>` | Save file |
| `<S-h>` / `<S-l>` | Prev / next buffer |
| `<Esc>` | Clear search highlight |
| `<A-j>` / `<A-k>` | Move line/selection down/up |
| `<` / `>` (visual) | Indent, keep selection |
## Formatters by file type
| File type | Formatter |
| --------------- | ---------------------------------------- |
| Go | gofumpt, goimports (`-local github.com`) |
| Lua | stylua (2-space) |
| JS/TS/JSX/TSX | prettier (2-space, single quotes) |
| HTML/CSS/SCSS | prettier |
| JSON/JSONC/YAML | prettier |
| Markdown | prettier |
| SQL | sql-formatter (postgresql; manual only) |
## File structure
```
~/.config/nvim/
├── init.lua # Entry point → require("config.lazy")
├── lua/
│ ├── config/
│ │ ├── lazy.lua # lazy.nvim bootstrap, LazyVim + extras
│ │ ├── options.lua # Neovim options
│ │ ├── keymaps.lua # Custom keymaps
│ │ └── autocmds.lua # Autocommands (yank hl, ft tweaks, SQL no-autoformat…)
│ ├── plugins/
│ │ ├── mason.lua # Tooling installs (LSP/linters/formatters/DAP)
│ │ ├── lspconfig.lua # Per-server LSP config (gopls, zls, …)
│ │ ├── treesitter.lua # Parsers
│ │ ├── formatting.lua # conform.nvim
│ │ ├── dap.lua # Debugging (Go via delve, Zig via codelldb)
│ │ ├── neotest.lua # Test runner (go/python/zig)
│ │ ├── go-coverage.lua # Go coverage signs
│ │ ├── overseer.lua # Task runner
│ │ ├── ai.lua # opencode.nvim
│ │ ├── dadbod.lua # Database
│ │ ├── git.lua # Neogit + diffview
│ │ ├── editor.lua # snacks tweaks + which-key groups
│ │ ├── symbols.lua # aerial
│ │ ├── dashboard.lua # trouble opts
│ │ ├── devcontainer.lua # nvim-remote-containers
│ │ ├── performance.lua # treesitter large-file guard
│ │ ├── theme.lua # catppuccin
│ │ └── zig.lua # Zig ft plugin (toolchain wired across files)
│ └── overseer/template/user/ # go_*, zig_{build,run,test} task templates
```
## Zig notes
- LSP is `zls` (`lua/plugins/lspconfig.lua`), root markers `build.zig` /
`build.zig.zon`, with build-on-save and inlay hints.
- `zig build test` and project-wide neotest runs require a standard `test` step
in your `build.zig`; individual `.zig` files also work.
- Debugging needs `codelldb` (`:MasonInstall codelldb` if it doesn't
auto-install). Builds use `-O Debug` so symbols are present.
## Troubleshooting
- **LSP not attaching:** `:checkhealth lsp` — confirm the server appears and is
attached (not just installed in Mason). If `root_dir`/`root_markers` look off,
the server may not find your project root.
- **Formatting:** `:ConformInfo`.
- **Tests not detected:** ensure the Treesitter parser for the language is
installed (`:TSInstall <lang>`); Zig needs a `test` step in `build.zig`.
- **Ctrl+Shift keys not firing:** some terminals don't transmit them; use the
plain-Ctrl fallbacks (`<C-v>` / `<C-x>` in the explorer).
- **Nerd Font icons missing:** install a Nerd Font and set it in your terminal.
## Known issues (in current repo)
Two unrelated typos exist in `lua/config/keymaps.lua`'s opencode block (present
before these docs): the scroll-up command string reads `sesion.half.page.up`
(should be `session.…`), and `<leader>at` is mapped in `t` (terminal) mode where
`n`/`x` is likely intended. Documented here for accuracy; fix when convenient.