11 KiB
11 KiB
AGENTS: Neovim Config Migration
Scope: applies to the entire ~/.config/nvim directory tree.
This repository is being migrated to a modern, minimal Neovim setup driven by Lua and lazy.nvim. Follow these rules when making changes.
Goals
- Modern Lua-first config; avoid Vimscript unless explicitly requested.
- Keep it minimal, fast, and maintainable.
- Base plugin management on
lazy.nvimwith modular plugin specs. - Support Telescope navigation, netrw for file browsing/preview, Oil.nvim for file operations, LSP, Treesitter, Copilot, and sane UX defaults.
- Native project-local configuration via
exrc+secure(no external config plugins).
Do Not Reintroduce
- Custom Vimscript tabline/statusline, foldtext, UI hacks.
- Legacy autocommands toggling cursorline/column per window.
- CoC or CoC-specific config.
- Neo-tree (skipped in favor of netrw for navigation).
- Providers for ruby/perl/node (disable unless required by a plugin).
- Auto-reload vimrc-on-write templates.
cursorcolumnand old folding logic not related to UFO.- neoconf plugin (incompatible with Neovim 0.11+, use native exrc instead).
- Motion plugins like leap.nvim or flash.nvim (not needed).
- Markdown rendering plugins (skipped entirely).
Repository Structure (target)
~/.config/nvim/
├── init.lua -- entrypoint; bootstraps lazy.nvim and loads Lua modules
└── lua/
├── settings.lua -- non-plugin options
├── keymaps.lua -- non-plugin keymaps
├── autocmds.lua -- non-plugin autocommands
├── abbreviations.lua -- insert-mode abbreviations
├── netrw-config.lua -- netrw configuration
├── utils.lua -- helpers (only if needed)
└── plugins/ -- one file per plugin or domain
├── telescope.lua
├── treesitter.lua
├── cmp.lua
├── lsp.lua
├── copilot.lua
├── oil.lua
├── ufo.lua
├── gitsigns.lua
├── none-ls.lua
├── nvim-lint.lua
├── mason.lua
├── mason-lspconfig.lua
├── mason-tool-installer.lua
├── comment.lua
├── surround.lua
├── autopairs.lua
└── indent-blankline.lua
├── after/
│ ├── ftplugin/
│ │ └── php.lua -- PHP-specific settings (includeexpr for gf)
│ └── queries/ -- Custom Treesitter queries
│ ├── css/
│ │ └── highlights.scm
│ └── html/
│ └── highlights.scm
├── templates/
│ └── template.sh -- Shell script template
└── legacy/ -- Archived Vimscript config (reference only)
Coding Conventions
- Use Lua APIs:
vim.opt,vim.api.nvim_create_autocmd,vim.keymap.set. - No inline Vimscript or
vim.cmdblocks unless strictly necessary. - Keep plugin configuration self-contained in its plugin spec file.
- Prefer small, readable modules and minimal configuration over heavy customization.
- Keymaps: use
vim.keymap.setwith{ silent = true, noremap = true }defaults unless otherwise required. - Autocommands: group via
vim.api.nvim_create_augroupand create specific, narrowly scoped autocmds. - Avoid global state; return tables from modules and plugin specs.
Plugin Management (lazy.nvim)
- Each plugin lives in
lua/plugins/<name>.luaand returns a spec table. - Use
opts = {}for default options andconfig = function(_, opts) ... endfor setup. - Do not install any plugin not listed without explicit user confirmation (proposal and rationale are welcome).
- Rejected:
folke/neoconf.nvim(incompatible with Neovim 0.11+ vim.lsp.config API).
Required Plugin Categories
- Core:
nvim-lspconfig,nvim-cmp,cmp-nvim-lsp,cmp-buffer,cmp-path,LuaSnip. - Navigation:
telescope.nvim+telescope-fzf-native.nvim,oil.nvim. - Treesitter:
nvim-treesitter,nvim-treesitter-textobjects,nvim-ts-autotag. - UX/Editing:
Comment.nvim,nvim-surround,nvim-autopairs,indent-blankline.nvim,nvim-ufo,undotree. - Git:
gitsigns.nvim. - Copilot:
copilot.lua,copilot-cmp. - Formatting/Linting:
none-ls.nvim,nvim-lint. - LSP Management:
mason.nvim,mason-lspconfig.nvim,mason-tool-installer.nvim.
Workflow Requirements to Preserve
- Netrw for visual context and project structure browsing (tree view, preview splits).
- Telescope for fuzzy finding (files, grep, buffers, LSP symbols).
- Oil.nvim for file manipulation (handles buffer sync on rename/move/delete).
- LSP for navigation (gd, gr, K, etc.).
- Heavy HTML/PHP/JS/Markdown usage (WordPress plugin dev) — prioritize these languages in LSP/Treesitter.
- Format-on-save with toggle capability.
- Project-local configuration via
.nvim.luafiles.
Behaviours to Keep (modernized)
- Abbreviations:
adn→and,waht→what,tehn→then,functin→function,positin→position. - Templates: auto-populate
.shfrom template. - Whitespace highlighting (use modern alternatives, e.g.,
listchars, plugins if needed). - Persistent folds (prefer
nvim-ufo). - Spell & text:
spelllang=en_gb, customlistchars,showbreak. - Keyword characters:
iskeyword+=$(for PHP/shell variables),iskeyword+=-(for CSS/HTML/config files).
Current Status (Phase 10 Complete)
- ✅ Phase 1-2: Archive legacy, bootstrap lazy.nvim
- ✅ Phase 3: Core editing & LSP (native exrc + vim.lsp.config migration complete)
- ✅ Phase 4: Navigation (Telescope, netrw, Oil.nvim)
- ✅ Phase 5: Treesitter (parsers, textobjects, autotag)
- ✅ Phase 6: UX/Editing (Comment, surround, autopairs, indent guides, UFO, undotree)
- ✅ Phase 7: Git integration (Gitsigns)
- ✅ Phase 8: Copilot integration (copilot.lua + copilot-cmp)
- ✅ Phase 9: Formatting & Linting (none-ls, nvim-lint, Mason tool installer)
- ✅ Phase 10: Migrate kept behaviors (abbreviations, templates, custom Treesitter queries)
- ⏸️ Phase 11: Cleanup & validation (pending)
Migration Notes
- Do not edit legacy Vimscript files except to extract settings to Lua. Keep them intact until migration completes.
- Introduce
init.luaand bootstraplazy.nvimbefore adding plugins. - Disable unnecessary providers early:
vim.g.loaded_ruby_provider = 0, etc. - Keep startup fast; avoid unnecessary autoloading or heavy defaults.
- When cleaning, archive existing files into a
legacy/folder within this config instead of deleting. Maintain a brief index if helpful.
Validation
- Ensure Neovim starts without errors and with minimal startup time.
- Verify Telescope navigation, netrw browsing, Oil.nvim file operations, LSP basics, and completion.
- Keep plugin count tight; remove anything unused.
Key Decisions & Architecture
LSP Configuration
- Modern API (Neovim 0.11+): Uses
vim.lsp.config()+vim.lsp.enable(), NOTrequire('lspconfig')[server].setup() - Project-local config: Native
exrc+secure(no neoconf - incompatible with 0.11+) - Config format:
.nvim.luafiles return{ lsp = { [server_name] = { settings = {...} } } } - Security:
securemode prompts user to trust.nvim.luafiles (one-time per file hash) - Settings loading:
on_new_confighook loads from actualroot_dir(not cwd) - PHP: intelephense with
single_file_support = false, usesenvironment.includePathsfor external libs
Navigation Strategy
- netrw: Visual context, tree view, preview splits (horizontal 50/50 below)
- Telescope: Fuzzy finding (files, grep, buffers, LSP symbols)
- Oil.nvim: File manipulation (handles buffer sync on rename/move/delete)
- PHP gf enhancement: Custom
includeexprinafter/ftplugin/php.luafor WordPress/PHP patterns
Formatting & Linting
- Formatters: prettier, phpcbf, stylua, black (project-local → Mason → global)
- Linters: eslint_d, phpcs, markdownlint, ruff (via nvim-lint)
- Format-on-save: Enabled by default, toggle with
<leader>lt - Philosophy: Formatters are source of truth; Neovim settings match formatter rules per filetype
Treesitter
- Parsers: lua, vim, vimdoc, php, html, javascript, typescript, tsx, css, scss, json, markdown, bash, regex
- Features: Incremental selection (CR/BS), textobjects (functions, classes, parameters), autotag
- Custom queries:
after/queries/css/highlights.scm,after/queries/html/highlights.scm
Session Management
- Auto-load: On
VimEnter, loadsSession.vimif it exists (unless files specified on command line) - Auto-save: On
VimLeavePre, saves toSession.vimif it already exists - Manual control: Create with
:mksessionto enable; delete to disable - Per-directory: Sessions are opt-in and workspace-specific
Developer Workflows
Testing Changes
# Quick syntax check
nvim --headless -c 'lua print("Config loads")' -c 'quitall'
# Check LSP status in test workspace
cd ~/.config/nvim/WORKSPACE_TEST
nvim site/external.php # Then :LspInfo
# Validate goto-definition for external libs
# In external.php, cursor on Util::greetExternal, press gd
Validation Workspaces
WORKSPACE_TEST/: PHP project with.nvim.luaand.gitEXTERNAL_TEST/: External library referenced via includePaths- Test that
gdresolves symbols in EXTERNAL_TEST from WORKSPACE_TEST
Common Issues
lua_ls Won't Start
Mason-installed lua_ls may fail with missing libbfd-2.38-system.so. Install via system package manager instead.
LSP Root Detection
If parent repo picked as root, create empty .git or .nvimroot marker in intended workspace root.
Duplicate gd Results (Fixed)
Was caused by settings loading at wrong time; fixed by using LspAttach autocmd with actual root_dir.
Process
- Before large changes, update the task plan via the CLI
update_plantool. - Keep the live checklist in
MIGRATION_PLAN.md:1up to date and in sync with changes. - After any config or plugin change, immediately update
MIGRATION_PLAN.md(check off items, add notes, or adjust next steps). - After any change or decision, also update
LOG.md:1(decisions log and design docs). - After adding/removing/editing any keymaps, immediately update
README.mdwith the change (add new entries, remove deleted mappings, or update descriptions). - After changing formatter/linter configuration, standards, or tool resolution, immediately update the "Configuration" section in
README.md(update tool lists, override instructions, or behavior descriptions). - At the start of each phase, confirm scope and priorities for that phase.
- Execute phases via subphases (
N.x), where each bullet under a phase is its own implement-and-test step (e.g., Phase 3.1, 3.2, 3.3, 3.4). - Record decisions and rationale in
LOG.md:1as they're made. - Keep PR-sized patches; avoid broad unrelated edits.
- Document non-obvious choices in commit messages or short comments near the code that needs it.