nvim/README.md

183 lines
10 KiB
Markdown
Raw 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 Rebuild — Decisions & Reference
Authoritative notes for the Neovim migration. Use this alongside `MIGRATION_PLAN.md` and `neovim-migration-guide.md`.
- Migration plan: MIGRATION_PLAN.md
- Guide and requirements: neovim-migration-guide.md
## Decisions Log
Record every decision here with a short rationale. Append new entries; do not rewrite history.
- 2025-12-06: PHP LSP = `intelephense` (good PHP ecosystem support; integrates includePaths).
- 2025-12-06: Enable Markdown LSP = `marksman` (lightweight, good MD features).
- 2025-12-06: Use legacy `listchars` and `showbreak` values (preserve muscle memory).
- 2025-12-06: No direnv fallback for local config (keep setup simple and repo-driven).
- 2025-12-06: Project-local config = layered JSON `.nvim.json` + `.nvim.local.json` with `.nvimroot` as workspace boundary marker (multi-repo friendly).
- 2025-12-06: Switch to `folke/neoconf.nvim` for project-local configuration (supersedes custom layered JSON loader); use `.neoconf.json` at workspace root.
- 2025-12-06: Use `mason.nvim` + `mason-lspconfig.nvim` to install/manage LSP servers; keep custom lspconfig setup; include `.neoconf.json` in root detection.
- For PHP validation inside this repo: we require `.neoconf.json` to attach `intelephense` to avoid the repos `.git` being chosen as the LSP root.
- 2025-12-06: Plugin approval policy — other plugins are allowed, but do not install any plugin not listed without explicit confirmation.
- 2025-12-07: **CRITICAL REGRESSION FIX**: Neovim 0.11+ does NOT support `on_new_config` callback in `vim.lsp.config()`. Project-local settings (`.nvim.lua`) must be loaded via `LspAttach` autocmd instead. The `on_new_config` hook was silently ignored, causing empty settings and breaking goto-definition for external includes. Solution: Use `LspAttach` to load project settings, merge into `client.settings`, and send `workspace/didChangeConfiguration` notification.
- 2025-12-07: Native `exrc` + `.nvim.lua` finalized as project-local config approach (replaces neoconf, which is incompatible with Neovim 0.11+ native LSP API). Security via `vim.opt.secure = true`.
- 2025-12-07: Navigation Phase 4 decisions:
- Skip Neo-tree in favor of netrw for project visualization
- Use Telescope as primary "find file" tool with fuzzy finding
- Add Oil.nvim for file manipulation (rename/move/delete with buffer sync)
- netrw for tree view and preview splits; Oil for operations that would break buffer names
- PHP `gf` enhancement via `includeexpr` for WordPress/PHP path resolution
- 2025-12-07: Treesitter Phase 5 decisions:
- Focus on core languages: PHP, HTML, JavaScript, TypeScript, CSS, Markdown, Lua, Bash, JSON
- Enable syntax highlighting with performance safeguard (disable for files >100KB)
- Incremental selection: CR to expand, BS to shrink, S-CR for scope expansion
- Textobjects for functions (`af`/`if`), classes (`ac`/`ic`), parameters (`aa`/`ia`), conditionals, loops, comments
- Movement keymaps: `]f`/`[f` for next/prev function, `]c`/`[c` for classes, `]a`/`[a` for parameters
- Parameter swapping: `<leader>a`/`<leader>A` to swap with next/prev parameter
- Auto-tag for HTML/PHP/JS/React/TS/Vue files (auto-close, auto-rename, close-on-slash)
- Indent disabled initially (experimental); can enable per-filetype if stable
- 2025-12-07: UX/Editing Phase 6 decisions:
- Enable signcolumn=yes (always show for LSP diagnostics, git signs)
- Enable cursorline (highlight current line)
- Enable colorcolumn=80,120 (visual guides at 80 and 120 chars)
- NO cursorcolumn (as per AGENTS.md)
- NO auto-window toggling behavior (keep settings static, no per-window autocmds)
- NO motion plugin (skip leap/flash for simplicity)
- Undotree moved to separate phase (6.8)
- Comment.nvim for commenting (gcc/gc/gbc/gb keymaps)
- nvim-surround for text objects (ys/ds/cs operators)
- nvim-autopairs for auto-closing brackets/quotes with Treesitter and cmp integration
- indent-blankline for visual indent guides with scope highlighting
- nvim-ufo for enhanced folding with Treesitter/LSP providers (zR/zM/K for peek)
- undotree for visual undo history (<leader>u to toggle)
- 2025-12-07: Git integration Phase 7:
- Gitsigns with minimal config for signs in gutter (add, change, delete markers)
- Hunk navigation: `]h`/`[h` for next/prev hunk
- Hunk actions: stage, reset, preview
- NO inline blame or advanced features (keep minimal)
- 2025-12-07: Copilot Phase 8:
- Integrated via copilot.lua + copilot-cmp (completion source)
- Auto-trigger suggestions as you type
- Copilot suggestions appear before LSP in completion menu (higher priority)
- Enabled for all filetypes
- No specific Copilot keymaps (use existing cmp keymaps)
- Node.js v22.21.1 confirmed working
- 2025-12-07: Formatting & Linting Phase 9:
- **Philosophy**: Formatters are authoritative; Neovim settings match formatter output
- **Formatters**: prettier (JS/TS/CSS/JSON/MD/HTML), phpcbf (PHP/WordPress), stylua (Lua), black (Python)
- **Linters**: eslint_d (JS/TS), phpcs (PHP/WordPress), markdownlint (Markdown), ruff (Python)
- **Strategy**: Project-local executables first (node_modules/.bin/, vendor/bin/), then Mason, then system PATH
- **WordPress**: phpcs/phpcbf already installed globally; use phpcs.xml or --standard=WordPress
- **Format-on-save**: Enabled by default, toggle with `<leader>lt`
- **Manual format**: `<leader>lf` (buffer), `<leader>lf` (visual range)
- **Linting split**: none-ls for formatting only, nvim-lint for diagnostics (none-ls removed linters)
- **Python support**: pyright LSP, black formatter, ruff linter, treesitter parser
- **Per-filetype indentation**: Explicit settings per filetype to match formatters
- PHP: tabs, 2-space display (WordPress standards)
- JS/TS/CSS/JSON/HTML: 2 spaces (Prettier)
- Lua: 2 spaces (common convention)
- Markdown: 2 spaces (Prettier)
- Python: 4 spaces (Black/PEP 8)
- **Global defaults**: 4 spaces (reasonable baseline for other filetypes)
- 2025-12-07: Kept Behaviors Phase 10:
- **Abbreviations**: Common typo corrections (`adn→and`, `waht→what`, `tehn→then`, `functin→function`, `positin→position`) in dedicated `lua/abbreviations.lua` file for modularity
- **Templates**: Shell script template (template.sh) auto-loaded via BufNewFile autocmd for `*.sh` files
- **Whitespace highlighting**: Already handled via `listchars` in Phase 3.2 (settings.lua)
- **Persistent folds**: Not needed; UFO handles folding without explicit persistence mechanism
## Project-Local Configuration (design)
Context: Projects can contain multiple git repositories (e.g., WordPress site with theme + multiple plugins). We need a way to set per-project `intelephense.includePaths` and similar without globalizing settings.
Options considered
- Layered JSON files (recommended): `.nvim.json` (committed) + `.nvim.local.json` (gitignored)
- Walk upward from current file; collect and merge configs until reaching a boundary marker or filesystem root.
- Boundary marker: `.nvimroot` to define a workspace that can encompass multiple repos.
- Merge order: top → bottom; nearest wins on conflicts; arrays replace by default unless we later add a merge strategy.
- Pros: safe (data-only), portable, reviewable in PRs.
- Cons: less dynamic than Lua.
- Layered Lua files: `.nvim.lua` + `.nvim.local.lua`
- Pros: maximum flexibility (computed paths).
- Cons: executes code from the repo; security gates required.
- Env/direnv: rejected (decision 2025-12-06).
- Central registry file in `~/.config/nvim/`: possible later for private overrides, but not primary.
Chosen approach (confirmed)
- Use `folke/neoconf.nvim` with `.neoconf.json` at the workspace root (or project roots) to supply LSP/plugin settings. Multi-repo: keep a single `.neoconf.json` at the parent workspace folder and open Neovim from there (or use a rooter later if needed).
Example `.neoconf.json`
```
{
"lspconfig": {
"intelephense": {
"settings": {
"intelephense": {
"environment": {
"includePaths": [
"wp-content/themes/my-theme",
"wp-content/plugins/custom-plugin"
]
}
}
}
}
}
}
```
- Files recognized per directory level:
- `.nvim.json`: checked into VCS; shared per-project defaults.
- `.nvim.local.json`: gitignored; machine-specific overrides.
- Loader behavior:
1. Start at the buffers directory; ascend toward root.
2. Stop at directory containing `.nvimroot` (if found) or at filesystem root.
3. At each level, if `.nvim.json` or `.nvim.local.json` exists, parse and stage for merge.
4. Merge staged configs in ascending order; nearest directory applies last.
- Path resolution:
- Relative paths resolve against the topmost boundary (i.e., `.nvimroot` directory if present; otherwise the highest directory in which a config was found). This allows referencing sibling repos (e.g., theme and plugins) from a single top-level site folder.
Example `.nvim.json`
```
{
"lsp": {
"php": {
"intelephense": {
"includePaths": [
"wp-content/themes/my-theme",
"wp-content/plugins/custom-plugin",
"vendor/some-package/src"
]
}
}
}
}
```
Intended integration
- A helper module `lua/local_config.lua` will expose:
- `load(start_dir) -> table` collecting and merging configs
- `get(path, default)` for reads, e.g., `get({"lsp","php","intelephense","includePaths"}, {})`
- LSP wiring (in Phase 3.5):
- Read includePaths via the helper and pass to `settings.intelephense.environment.includePaths` in `lspconfig.intelephense.setup{}`.
Open items to confirm
- Confirm JSON as the format (vs Lua) for project-local config.
- Confirm `.nvimroot` as the workspace boundary marker name.
- Confirm array merge behavior (replace vs concatenate). Initial proposal: replace.
## LSP Scope (initial)
- Core servers: `lua_ls`, `tsserver`, `html`, `cssls`, `jsonls`, `bashls`
- PHP: `intelephense` (decision)
- Markdown: `marksman` (decision)
- Keep configuration minimal; defer language-specific tuning.
## Text & Editing Settings
- `spelllang = en_gb`
- `listchars` and `showbreak` will reuse legacy values.
- `completeopt = menu,menuone,noselect` for `nvim-cmp`.
## Process Reminders
- After any change or decision, update this README and MIGRATION_PLAN.md.
- Keep subphases small and verify each step in isolation.