|
|
||
|---|---|---|
| .github | ||
| UltiSnips | ||
| after/ftplugin | ||
| legacy | ||
| lua | ||
| spell | ||
| templates | ||
| undodir | ||
| view | ||
| .gitignore | ||
| AGENTS.md | ||
| MIGRATION_PLAN.md | ||
| README.md | ||
| REGRESSION_FIX_2025-12-07.md | ||
| init.lua | ||
| lazy-lock.json | ||
| neovim-migration-guide.md | ||
README.md
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
listcharsandshowbreakvalues (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.jsonwith.nvimrootas workspace boundary marker (multi-repo friendly). - 2025-12-06: Switch to
folke/neoconf.nvimfor project-local configuration (supersedes custom layered JSON loader); use.neoconf.jsonat workspace root. - 2025-12-06: Use
mason.nvim+mason-lspconfig.nvimto install/manage LSP servers; keep custom lspconfig setup; include.neoconf.jsonin root detection.- For PHP validation inside this repo: we require
.neoconf.jsonto attachintelephenseto avoid the repo’s.gitbeing chosen as the LSP root.
- For PHP validation inside this repo: we require
- 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_configcallback invim.lsp.config(). Project-local settings (.nvim.lua) must be loaded viaLspAttachautocmd instead. Theon_new_confighook was silently ignored, causing empty settings and breaking goto-definition for external includes. Solution: UseLspAttachto load project settings, merge intoclient.settings, and sendworkspace/didChangeConfigurationnotification. - 2025-12-07: Native
exrc+.nvim.luafinalized as project-local config approach (replaces neoconf, which is incompatible with Neovim 0.11+ native LSP API). Security viavim.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
gfenhancement viaincludeexprfor 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/[ffor next/prev function,]c/[cfor classes,]a/[afor parameters - Parameter swapping:
<leader>a/<leader>Ato 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 (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/[hfor 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 dedicatedlua/abbreviations.luafile for modularity - Templates: Shell script template (template.sh) auto-loaded via BufNewFile autocmd for
*.shfiles - Whitespace highlighting: Already handled via
listcharsin Phase 3.2 (settings.lua) - Persistent folds: Not needed; UFO handles folding without explicit persistence mechanism
- Abbreviations: Common typo corrections (
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:
.nvimrootto 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.nvimwith.neoconf.jsonat the workspace root (or project roots) to supply LSP/plugin settings. Multi-repo: keep a single.neoconf.jsonat 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:
- Start at the buffer’s directory; ascend toward root.
- Stop at directory containing
.nvimroot(if found) or at filesystem root. - At each level, if
.nvim.jsonor.nvim.local.jsonexists, parse and stage for merge. - Merge staged configs in ascending order; nearest directory applies last.
- Path resolution:
- Relative paths resolve against the topmost boundary (i.e.,
.nvimrootdirectory 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.
- Relative paths resolve against the topmost boundary (i.e.,
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.luawill expose:load(start_dir) -> tablecollecting and merging configsget(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.includePathsinlspconfig.intelephense.setup{}.
- Read includePaths via the helper and pass to
Open items to confirm
- Confirm JSON as the format (vs Lua) for project-local config.
- Confirm
.nvimrootas 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_gblistcharsandshowbreakwill reuse legacy values.completeopt = menu,menuone,noselectfornvim-cmp.
Process Reminders
- After any change or decision, update this README and MIGRATION_PLAN.md.
- Keep subphases small and verify each step in isolation.