183 lines
10 KiB
Markdown
183 lines
10 KiB
Markdown
# 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 repo’s `.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 buffer’s 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.
|