update
This commit is contained in:
parent
77ab9bf5e9
commit
770c9ae01f
|
|
@ -0,0 +1,168 @@
|
|||
# Neovim Config - AI Agent Instructions
|
||||
|
||||
## Project Overview
|
||||
Modern Lua-first Neovim configuration using lazy.nvim, currently in active migration from legacy Vimscript. Target: minimal, fast, tab-per-context workflow with Neo-tree, Telescope, LSP, and Copilot.
|
||||
|
||||
**Critical**: Read `AGENTS.md` first—it defines all coding rules, migration strategy, and what NOT to reintroduce.
|
||||
|
||||
## Architecture & Files
|
||||
|
||||
```
|
||||
~/.config/nvim/
|
||||
├── init.lua # Entry point: loads settings/keymaps/autocmds, bootstraps lazy.nvim
|
||||
├── lua/
|
||||
│ ├── settings.lua # Non-plugin vim options (exrc, secure, spelllang, listchars)
|
||||
│ ├── keymaps.lua # Non-plugin keymaps
|
||||
│ ├── autocmds.lua # Non-plugin autocommands
|
||||
│ └── plugins/ # One file per plugin/domain (lazy.nvim specs)
|
||||
│ ├── lsp.lua # LSP via vim.lsp.config + vim.lsp.enable (Neovim 0.11+)
|
||||
│ ├── cmp.lua # Completion: nvim-cmp + LuaSnip
|
||||
│ └── mason*.lua # LSP server installation
|
||||
├── AGENTS.md # PRIMARY: All rules, migration plan, do-not-reintroduce list
|
||||
├── MIGRATION_PLAN.md # Phase-by-phase checklist (source of truth for progress)
|
||||
├── README.md # Decision log and design rationale
|
||||
└── legacy/ # Archived Vimscript (do not edit; reference only)
|
||||
```
|
||||
|
||||
## Critical Patterns
|
||||
|
||||
### 1. LSP Configuration (Phase 3 Complete)
|
||||
**Modern API (Neovim 0.11+)**: Uses `vim.lsp.config()` + `vim.lsp.enable()`, NOT `require('lspconfig')[server].setup()`.
|
||||
|
||||
```lua
|
||||
-- lua/plugins/lsp.lua pattern:
|
||||
vim.lsp.config(server_name, {
|
||||
capabilities = capabilities,
|
||||
on_attach = on_attach,
|
||||
on_new_config = function(new_config, root_dir)
|
||||
-- Load project settings from root_dir/.nvim.lua
|
||||
end,
|
||||
})
|
||||
vim.lsp.enable({ "lua_ls", "intelephense", ... })
|
||||
```
|
||||
|
||||
**Key decisions**:
|
||||
- No neoconf (incompatible with Neovim 0.11+, issue #116)
|
||||
- Native `exrc` + `secure` for project config (see settings.lua)
|
||||
- `on_new_config` hook loads from actual `root_dir`, not cwd
|
||||
- `workspace/didChangeConfiguration` sent in `on_attach` for servers like intelephense
|
||||
|
||||
### 2. Project-Local Configuration
|
||||
**Format**: `.nvim.lua` at project root, returns:
|
||||
```lua
|
||||
return {
|
||||
lsp = {
|
||||
intelephense = {
|
||||
settings = {
|
||||
intelephense = {
|
||||
environment = {
|
||||
includePaths = { "/absolute/path/to/external/lib" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Security**: `vim.opt.secure = true` prompts user before loading (one-time per file hash). Trusted files stored in `~/.local/state/nvim/trust`.
|
||||
|
||||
### 3. Plugin Management
|
||||
- **lazy.nvim**: All plugins in `lua/plugins/` as individual files returning spec tables
|
||||
- **Mason**: Installs LSP servers only; custom lspconfig setup retained
|
||||
- **Plugin specs**: Use `opts = {}` for defaults, `config = function(_, opts)` for setup
|
||||
- **Approval policy**: Do not install unlisted plugins without explicit user confirmation
|
||||
|
||||
### 4. Tab-Per-Context Workflow (Future Phase 4)
|
||||
- Each tab maintains own Neo-tree root
|
||||
- Splits stay within tabs
|
||||
- Neo-tree: sidebar toggle + floating view + preview (no buffer pollution)
|
||||
- Heavy PHP/HTML/JS/Markdown usage (WordPress plugin dev)
|
||||
|
||||
## Conventions
|
||||
|
||||
### Code Style
|
||||
- **Lua APIs only**: `vim.opt`, `vim.keymap.set`, `vim.api.nvim_create_autocmd`
|
||||
- **No Vimscript**: Avoid `vim.cmd` blocks unless strictly necessary
|
||||
- **Keymaps**: `{ silent = true, noremap = true }` by default
|
||||
- **Autocommands**: Group via `vim.api.nvim_create_augroup`, narrow scope
|
||||
|
||||
### File Organization
|
||||
- One plugin = one file in `lua/plugins/`
|
||||
- Keep plugin config self-contained in its spec
|
||||
- Settings/keymaps/autocmds: only non-plugin logic in respective files
|
||||
- No global state; return tables from modules
|
||||
|
||||
### Migration Process
|
||||
1. Check `MIGRATION_PLAN.md` for current phase and priorities
|
||||
2. **Before large changes**: Update plan via CLI `update_plan` tool (if available)
|
||||
3. **After any change**: Immediately update `MIGRATION_PLAN.md` (check off items, add notes)
|
||||
4. **After decisions**: Update `README.md` decisions log
|
||||
5. Execute phases via subphases (N.x); one bullet = one implement-and-test step
|
||||
6. Archive legacy files to `legacy/` instead of deleting
|
||||
|
||||
## Do NOT Reintroduce (from AGENTS.md)
|
||||
- Custom Vimscript tabline/statusline/foldtext
|
||||
- Legacy autocommands (cursorline/column per window)
|
||||
- CoC or CoC-specific config
|
||||
- netrw settings (Neo-tree replaces it)
|
||||
- Providers for ruby/perl/node (disabled unless required)
|
||||
- Auto-reload vimrc-on-write templates
|
||||
- `cursorcolumn` and old folding logic (UFO will handle folding)
|
||||
- neoconf plugin (incompatible with Neovim 0.11+)
|
||||
|
||||
## Developer Workflows
|
||||
|
||||
### Testing Changes
|
||||
```bash
|
||||
# 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.lua` and `.git`
|
||||
- `EXTERNAL_TEST/`: External library referenced via includePaths
|
||||
- Test that `gd` resolves symbols in EXTERNAL_TEST from WORKSPACE_TEST
|
||||
|
||||
### Current Migration Status (as of 2025-12-07)
|
||||
- ✅ Phase 1-2: Archive legacy, bootstrap lazy.nvim
|
||||
- ✅ Phase 3: Core editing & LSP complete
|
||||
- Settings, completion, LSP servers, Mason installed
|
||||
- Native exrc + vim.lsp.config migration done
|
||||
- Project-local `.nvim.lua` working
|
||||
- ⏸️ Phase 4+: Navigation (Neo-tree, Telescope), Treesitter, UX plugins pending
|
||||
|
||||
## Integration Points
|
||||
|
||||
### External Dependencies
|
||||
- **Neovim 0.11+**: Required for `vim.lsp.config` API
|
||||
- **LSP Servers** (via Mason): lua_ls, ts_ls, html, cssls, jsonls, bashls, marksman, intelephense
|
||||
- **PHP**: intelephense with `single_file_support = false`, uses `environment.includePaths` for external libs
|
||||
|
||||
### Cross-Component Communication
|
||||
- LSP settings flow: `.nvim.lua` → `on_new_config` → `new_config.settings` → `workspace/didChangeConfiguration`
|
||||
- Completion: cmp-nvim-lsp provides capabilities → lspconfig → LSP servers
|
||||
|
||||
## 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 `on_new_config` with actual `root_dir`.
|
||||
|
||||
## When Stuck
|
||||
1. Check `MIGRATION_PLAN.md` for known issues and current phase
|
||||
2. Review `AGENTS.md` for rules about what to avoid
|
||||
3. Read `README.md` decisions log for context on past choices
|
||||
4. Validate with test workspaces before modifying production config
|
||||
|
|
@ -108,13 +108,32 @@ Source of truth for the step-by-step rebuild. Keep this concise and up to date.
|
|||
## Phase 4 — Navigation
|
||||
|
||||
## Phase 4.1 — Confirm scope and priorities
|
||||
- [ ] Confirm scope and priorities for this phase
|
||||
- [x] Confirm scope and priorities for this phase
|
||||
- [x] Decision: Skip Neo-tree in favor of netrw for navigation/visual context
|
||||
- [x] Decision: Use netrw for project structure visualization and file preview
|
||||
- [x] Decision: Telescope as primary "find file" tool
|
||||
- [x] Decision: Add Oil.nvim for file manipulation (handles buffer sync on rename/move/delete)
|
||||
- [x] Note: Oil.nvim is for evaluation; alternative is mini.files if too heavy
|
||||
|
||||
## Phase 4.2 — Neo-tree setup
|
||||
- [ ] Add `neo-tree.nvim` with per-tab roots, sidebar toggle, floating view, and preview keymap (no buffer pollution)
|
||||
## Phase 4.2 — Configure netrw
|
||||
- [ ] Configure netrw with tree view, preview split, and basic settings (no banner, sensible defaults)
|
||||
- [ ] Add simple keymaps for opening netrw (e.g., in split, tab, or current window)
|
||||
|
||||
## Phase 4.2.1 — PHP gf enhancement
|
||||
- [x] Add PHP `includeexpr` for intelligent `gf` behavior (handles `__DIR__`, `__FILE__`, `dirname(__FILE__)` patterns)
|
||||
- [x] Created `after/ftplugin/php.lua` with path resolution for WordPress/PHP patterns
|
||||
- [x] Tested and validated with test-gf.php
|
||||
|
||||
## Phase 4.3 — Telescope setup
|
||||
- [ ] Add `telescope.nvim` (+ optional `telescope-fzf-native.nvim`) and basic pickers
|
||||
- [ ] Add `telescope.nvim` + `telescope-fzf-native.nvim` for fuzzy finding
|
||||
- [ ] Configure basic pickers: `find_files`, `live_grep`, `buffers`, `help_tags`, `oldfiles`
|
||||
- [ ] Add sensible default keymaps
|
||||
|
||||
## Phase 4.4 — Oil.nvim for file manipulation
|
||||
- [ ] Add `stevearc/oil.nvim` for filesystem operations (rename, create, delete, copy, move)
|
||||
- [ ] Configure to handle buffer name sync on file operations
|
||||
- [ ] Keep minimal - use only when shell operations would cause buffer issues
|
||||
- [ ] Note: Evaluate practicality; can switch to `mini.files` if preferred
|
||||
|
||||
## Phase 5 — Treesitter
|
||||
|
||||
|
|
@ -231,3 +250,4 @@ Decisions & Changes:
|
|||
- **Project config format**: `.nvim.lua` files return `{ lsp = { [server_name] = { settings = {...} } } }`.
|
||||
- **Security model**: `secure` mode prompts user to trust `.nvim.lua` files before execution (one-time per file hash).
|
||||
- **Settings loading**: `on_new_config` hook loads project settings from actual `root_dir` (not cwd), ensuring correct behavior across different workspace structures.
|
||||
- **Phase 4 Navigation Strategy**: Skipped Neo-tree in favor of built-in netrw for visual context and project structure browsing. Telescope for fuzzy finding. Oil.nvim for file manipulation (evaluation phase; alternative is mini.files). Rationale: User needs visual context and preview, not per-tab roots or complex tree features. File manipulation primarily done in shell, but Oil.nvim handles buffer sync issues when renaming/moving files.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
-- PHP-specific settings and enhancements
|
||||
-- Loaded automatically for PHP files
|
||||
|
||||
-- Enable includeexpr for intelligent gf (goto file) behavior
|
||||
-- Handles common WordPress/PHP path patterns like:
|
||||
-- require_once __DIR__ . '/../path/to/file.php';
|
||||
-- include __FILE__ . '/relative/path.php';
|
||||
vim.opt_local.includeexpr = "v:lua.resolve_php_gf_path(v:fname)"
|
||||
|
||||
-- Global function to resolve PHP file paths for gf command
|
||||
function _G.resolve_php_gf_path(fname)
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local current_dir = vim.fn.expand('%:p:h')
|
||||
local current_file = vim.fn.expand('%:p')
|
||||
|
||||
-- Pattern 1: __DIR__ . '/path' or __DIR__ . '/../path'
|
||||
-- Most common in modern PHP/WordPress
|
||||
local path = line:match("__DIR__%s*%.%s*['\"]([^'\"]+)['\"]")
|
||||
if path then
|
||||
path = current_dir .. path
|
||||
return vim.fn.simplify(path)
|
||||
end
|
||||
|
||||
-- Pattern 2: __FILE__ . '/path'
|
||||
-- Less common but appears in legacy WordPress code
|
||||
-- __FILE__ resolves to the current file's full path, so we use its directory
|
||||
path = line:match("__FILE__%s*%.%s*['\"]([^'\"]+)['\"]")
|
||||
if path then
|
||||
-- __FILE__ is the file itself, but when concatenated with a path,
|
||||
-- it's typically used like __DIR__, so we use the directory
|
||||
path = current_dir .. path
|
||||
return vim.fn.simplify(path)
|
||||
end
|
||||
|
||||
-- Pattern 3: dirname(__FILE__) . '/path'
|
||||
-- Old-style equivalent to __DIR__
|
||||
path = line:match("dirname%s*%(%s*__FILE__%s*%)%s*%.%s*['\"]([^'\"]+)['\"]")
|
||||
if path then
|
||||
path = current_dir .. path
|
||||
return vim.fn.simplify(path)
|
||||
end
|
||||
|
||||
-- Pattern 4: Simple quoted path in require/include statements
|
||||
-- Fallback for basic relative paths
|
||||
path = line:match("require[_%w]*%s*['\"]([^'\"]+)['\"]")
|
||||
if path then
|
||||
-- Try relative to current file's directory
|
||||
path = current_dir .. '/' .. path
|
||||
return vim.fn.simplify(path)
|
||||
end
|
||||
|
||||
path = line:match("include[_%w]*%s*['\"]([^'\"]+)['\"]")
|
||||
if path then
|
||||
-- Try relative to current file's directory
|
||||
path = current_dir .. '/' .. path
|
||||
return vim.fn.simplify(path)
|
||||
end
|
||||
|
||||
-- Fallback: return as-is (normal gf behavior)
|
||||
-- This allows standard gf to work for simple filenames
|
||||
return fname
|
||||
end
|
||||
|
|
@ -27,3 +27,6 @@ vim.opt.listchars = {
|
|||
space = '·',
|
||||
}
|
||||
|
||||
-- Enable line numbers and relative line numbers
|
||||
vim.opt.number = true
|
||||
vim.opt.relativenumber = true
|
||||
Loading…
Reference in New Issue