700 lines
39 KiB
Markdown
700 lines
39 KiB
Markdown
# Neovim Migration Checklist
|
||
|
||
Source of truth for the step-by-step rebuild. Keep this concise and up to date. See details in `neovim-migration-guide.md`.
|
||
|
||
## Phase 0 — Ground Rules
|
||
- [x] Create AGENTS.md with rules
|
||
|
||
## Phase 1 — Clean & Archive Legacy Config
|
||
|
||
## Phase 1.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
|
||
## Phase 1.2 — Inventory legacy files
|
||
- [x] Inventory existing Vimscript, plugin files, and directories
|
||
|
||
## Phase 1.3 — Create archive location
|
||
- [x] Create `legacy/` archive folder within this config
|
||
|
||
## Phase 1.4 — Move legacy files into archive
|
||
- [x] Move legacy init files and plugin directories into `legacy/` (do not delete)
|
||
|
||
## Phase 1.5 — Document archived contents
|
||
- [x] Optionally add `legacy/README.md` noting what was archived
|
||
|
||
## Phase 1.6 — Preserve selected directories
|
||
- [x] Keep `undodir`, `spell`, `view`, `UltiSnips`, `templates` as-is for now (review later)
|
||
- [x] Re-enabled persistent undo in settings.lua (2025-01-06)
|
||
|
||
## Phase 2 — Bootstrap
|
||
|
||
## Phase 2.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
|
||
## Phase 2.2 — Scaffold Lua config skeleton
|
||
- [x] Scaffold Lua config skeleton (`init.lua`, `lua/settings.lua`, `lua/keymaps.lua`, `lua/autocmds.lua`, `lua/utils.lua`, `lua/plugins/`)
|
||
|
||
## Phase 2.3 — Bootstrap lazy.nvim
|
||
- [x] Bootstrap `lazy.nvim` plugin manager
|
||
|
||
## Phase 2.4 — Disable unused providers
|
||
- [x] Disable unused providers (ruby, perl, node)
|
||
|
||
## Phase 2.5 — Ensure lazy boots without specs
|
||
- [x] Ensure lazy boots without specs (add empty `lua/plugins/init.lua`)
|
||
|
||
## Phase 3 — Core Editing & LSP
|
||
|
||
## Phase 3.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: PHP LSP = `intelephense`
|
||
- [x] Decision: Enable Markdown LSP = `marksman`
|
||
- [x] Decision: Use legacy `listchars` and `showbreak` values
|
||
- [x] Decision: Support per‑project config for `intelephense.includePaths`
|
||
- [x] Decision: No direnv fallback for local config
|
||
|
||
## Phase 3.2 — Non-plugin settings to Lua
|
||
- [x] Port non-plugin settings to Lua (options, listchars, showbreak, spelllang=en_gb)
|
||
|
||
## Phase 3.3 — Core completion stack
|
||
- [x] Add core completion stack: `nvim-cmp`, `cmp-nvim-lsp`, `cmp-buffer`, `cmp-path`, `LuaSnip`
|
||
- [x] Disable auto-selection in nvim-cmp (require explicit confirm)
|
||
|
||
## Phase 3.4 — Project‑local configuration (native exrc)
|
||
- [x] Confirm scope and priorities for this subphase
|
||
- [x] Decision: Use native `exrc` + `secure` instead of neoconf (neoconf incompatible with Neovim 0.11+ vim.lsp.config API)
|
||
- [x] Enable `exrc` and `secure` in settings.lua
|
||
- [x] Implement `.nvim.lua` loader in an `LspAttach` callback using the client's actual root directory
|
||
- [x] Wire `intelephense.environment.includePaths` via `.nvim.lua`
|
||
- [x] Create validation workspaces: `WORKSPACE_TEST/` and `EXTERNAL_TEST/` with sample PHP files
|
||
- [x] Migrate to `vim.lsp.config()` and `vim.lsp.enable()` (Neovim 0.11+ native API)
|
||
- [x] Verify project settings load correctly from actual root_dir
|
||
- [x] Clean up debug notifications and temporary code
|
||
|
||
## Phase 3.7 — Clean LSP config
|
||
- [x] Remove debug/helper logic from LSP config
|
||
- [x] Migrate from deprecated `require('lspconfig')[server].setup()` to `vim.lsp.config()` + `vim.lsp.enable()`
|
||
- [x] Use `LspAttach` for project-local settings loading (loads from actual root_dir, not cwd)
|
||
|
||
## Phase 3.8 — Validate project-local LSP settings
|
||
- [x] Create test workspaces with `.nvim.lua` files
|
||
- [x] Validate settings load from the attached client's actual root_dir
|
||
- [x] Verify `gd` works for external library references via `intelephense.environment.includePaths`
|
||
- [x] Clean up debug code and notifications
|
||
|
||
## Phase 3.9 — Native exrc + vim.lsp.config migration (RESOLVED)
|
||
- [x] Discovered neoconf incompatible with Neovim 0.11+ (GitHub issue #116, unresolved since May 2024)
|
||
- [x] Migrated to native `exrc` + `secure` approach (zero dependencies, aligned with minimal philosophy)
|
||
- [x] Implemented secure `.nvim.lua` loading during `LspAttach` (loads from actual root_dir)
|
||
- [x] Migrated from deprecated `require('lspconfig')` framework to `vim.lsp.config()` + `vim.lsp.enable()`
|
||
- [x] Root detection handled by nvim-lspconfig's native configs (no custom root_dir needed)
|
||
- [x] Validated `gd` works for external library symbols via `intelephense.environment.includePaths`
|
||
- [x] Settings schema: `.nvim.lua` returns `{ lsp = { [server_name] = { settings = {...} } } }`
|
||
- [x] Security: `secure` mode prompts user to trust `.nvim.lua` files before execution
|
||
- [x] Kept `single_file_support = false` for `intelephense`
|
||
- [x] Fixed duplicate `gd` results issue
|
||
|
||
## Phase 3.5 — LSP minimal defaults
|
||
- [x] Add `nvim-lspconfig` with minimal defaults (no over-configuration)
|
||
- [x] Add minimal LSP on-attach keymaps (gd, gr, K, gD, gI)
|
||
- [x] Add global LSP keymaps with fallback in `lua/keymaps.lua`
|
||
- [x] Intelephense: set `single_file_support=false`, root detection via nvim-lspconfig defaults
|
||
- [x] Project settings securely loaded during `LspAttach` from `.nvim.lua` files
|
||
|
||
## Phase 3.6 — LSP server management (Mason)
|
||
- [x] Confirm scope and priorities for this subphase
|
||
- [x] Add `williamboman/mason.nvim` and `williamboman/mason-lspconfig.nvim`
|
||
- [x] Ensure servers installed: `lua_ls`, `tsserver`, `html`, `cssls`, `jsonls`, `bashls`, `marksman`, `intelephense`
|
||
- [x] Keep our custom per-server setup; use Mason only for installation
|
||
|
||
## Phase 4 — Navigation
|
||
|
||
## Phase 4.1 — Confirm scope and priorities
|
||
- [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: Evaluate Oil.nvim for file manipulation (later removed in Phase 4.5)
|
||
|
||
## Phase 4.2 — Configure netrw
|
||
- [x] Configure netrw with tree view, preview split, and basic settings (no banner, sensible defaults)
|
||
- [x] Created `lua/netrw-config.lua` with settings: tree view, horizontal preview split below, 50/50 split, human-readable sizes
|
||
- [x] Add netrw keymaps: `<leader>te` (new tab at current file's directory), `<leader>tE` (new tab at project root)
|
||
- [x] Decision: No `<leader>e` or `<leader>v` keymaps - use `:Ex`, `:Vex` directly when needed
|
||
- [x] Preview behavior: Enter opens file in netrw window, `p` opens 50/50 horizontal split below
|
||
|
||
## 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
|
||
- [x] Add `telescope.nvim` + `telescope-fzf-native.nvim` for fuzzy finding
|
||
- [x] Configure basic pickers: `find_files`, `live_grep`, `buffers`, `help_tags`, `oldfiles`, `current_buffer_fuzzy_find`
|
||
- [x] Add LSP pickers: `lsp_document_symbols`, `lsp_workspace_symbols`
|
||
- [x] Keymaps configured:
|
||
- `<leader>ff` - Find files
|
||
- `<leader>fg` - Live grep (search text)
|
||
- `<leader>fb` - Find buffers (with `<C-d>` to delete)
|
||
- `<leader>fh` - Find help
|
||
- `<leader>fr` - Recent files
|
||
- `<leader>/` - Search current buffer
|
||
- `<leader>fs` - Document symbols (LSP)
|
||
- `<leader>fS` - Workspace symbols (LSP)
|
||
- [x] Minimal UI: dropdown theme for files/buffers, no previewer for quick selection
|
||
|
||
## Phase 4.4 — Oil.nvim evaluation (retired)
|
||
- [x] Add `stevearc/oil.nvim` for filesystem operations (rename, create, delete, copy, move)
|
||
- [x] Configure to handle buffer name sync on file operations
|
||
- [x] Keep minimal - use only when shell operations would cause buffer issues
|
||
- [x] Keymaps configured:
|
||
- `<leader>fo` - Open Oil file browser (regular buffer)
|
||
- `<leader>fO` - Open Oil in floating window (with floating previews)
|
||
- `<C-p>` in Oil - Preview files (vertical split to right for regular, floating window for float mode)
|
||
- [x] Preview splits open to the right via `vertical = true` and `split = 'belowright'`
|
||
- [x] Floating window preview direction: `preview_split = "right"`
|
||
- [x] Note: Evaluate practicality; can switch to `mini.files` if preferred
|
||
|
||
## Phase 4.5 — Return to a netrw-only explorer workflow
|
||
- [x] Remove Oil.nvim after workflow evaluation
|
||
- [x] Use netrw as the sole tree browser and file explorer for consistency on remote systems
|
||
- [x] Keep Telescope as a fuzzy finder rather than a file explorer
|
||
|
||
## Phase 5 — Treesitter
|
||
|
||
## Phase 5.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Focus on languages: PHP, HTML, JavaScript, TypeScript, CSS, Markdown, Lua, Bash, JSON
|
||
- [x] Decision: Enable syntax highlighting and incremental selection (CR to expand, BS to shrink)
|
||
- [x] Decision: Enable textobjects for functions, classes, parameters, conditionals, loops
|
||
- [x] Decision: Enable autotag for HTML/PHP/JS/React files
|
||
- [x] Decision: Disable indent (experimental) to start; can enable per-filetype if stable
|
||
|
||
## Phase 5.2 — Base Treesitter
|
||
- [x] Add `nvim-treesitter` with incremental selection, highlighting
|
||
- [x] Configure parsers: lua, vim, vimdoc, php, html, javascript, typescript, tsx, css, scss, json, markdown, markdown_inline, bash, regex
|
||
- [x] Enable auto-install for missing parsers
|
||
- [x] Incremental selection keymaps: CR (init/expand), S-CR (scope expand), BS (shrink)
|
||
- [x] Disable for large files (>100KB) to maintain performance
|
||
|
||
## Phase 5.3 — Treesitter textobjects
|
||
- [x] Add `nvim-treesitter-textobjects`
|
||
- [x] Select keymaps: `af`/`if` (function), `ac`/`ic` (class), `aa`/`ia` (parameter), `ai`/`ii` (conditional), `al`/`il` (loop), `a/` (comment)
|
||
- [x] Move keymaps: `]f`/`[f` (next/prev function start), `]F`/`[F` (function end), similar for classes and parameters
|
||
- [x] Swap keymaps: `<leader>a`/`<leader>A` (swap parameter with next/prev)
|
||
|
||
## Phase 5.4 — Treesitter autotag
|
||
- [x] Add `nvim-ts-autotag`
|
||
- [x] Enable auto-close, auto-rename, and close-on-slash for HTML/PHP/JS/React/TS/Vue files
|
||
|
||
## Phase 6 — UX / Editing
|
||
|
||
## Phase 6.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: No cursorcolumn (as per AGENTS.md)
|
||
- [x] Decision: No auto-window toggling behavior (keep settings static)
|
||
- [x] Decision: No motion plugin (skip leap/flash)
|
||
- [x] Decision: Move undotree to separate Phase 6.8
|
||
- [x] UX settings to add: signcolumn, cursorline, colorcolumn
|
||
|
||
## Phase 6.2 — Core UX settings
|
||
- [x] Add signcolumn=yes (always show gutter for LSP/git)
|
||
- [x] Add cursorline (highlight current line)
|
||
- [x] Add colorcolumn=80,120 (visual guides)
|
||
- [x] No cursorcolumn (excluded as per AGENTS.md)
|
||
- [x] No per-window autocommands (keep simple)
|
||
|
||
## Phase 6.3 — Comment.nvim
|
||
- [x] Add `numToStr/Comment.nvim`
|
||
- [x] Configure for gcc/gc commenting
|
||
- [x] Add keymaps if needed
|
||
|
||
## Phase 6.4 — Surround
|
||
- [x] Add `kylechui/nvim-surround`
|
||
- [x] Minimal config with default keymaps (ys, ds, cs)
|
||
|
||
## Phase 6.5 — Autopairs
|
||
- [x] Add `windwp/nvim-autopairs`
|
||
- [x] Integrate with nvim-cmp
|
||
|
||
## Phase 6.6 — Indent guides
|
||
- [x] Add `lukas-reineke/indent-blankline.nvim`
|
||
- [x] Configure scope highlighting
|
||
|
||
## Phase 6.7 — Folding (UFO)
|
||
- [x] Add `kevinhwang91/nvim-ufo` for folding
|
||
- [x] Configure with Treesitter and LSP providers
|
||
- [x] Add fold keymaps (za, zR, zM, etc.)
|
||
|
||
## Phase 6.8 — Undotree
|
||
- [x] Add `mbbill/undotree`
|
||
- [x] Add keymap to toggle undotree
|
||
- [x] Configure minimal settings
|
||
|
||
## Phase 7 — Git Integration
|
||
|
||
## Phase 7.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Gitsigns with minimal config - signs in gutter, hunk navigation/actions only
|
||
- [x] Decision: Skip markdown rendering plugins entirely
|
||
|
||
## Phase 7.2 — Gitsigns
|
||
- [x] Add `lewis6991/gitsigns.nvim`
|
||
- [x] Configure signs in gutter (add, change, delete, topdelete, changedelete)
|
||
- [x] Add hunk navigation keymaps (]h/[h for next/prev hunk)
|
||
- [x] Add hunk action keymaps (stage, reset, preview)
|
||
- [x] Keep minimal - no inline blame, no advanced features
|
||
|
||
## Phase 8 — Copilot
|
||
|
||
## Phase 8.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Integrate Copilot into nvim-cmp as completion source
|
||
- [x] Decision: Auto-trigger suggestions as you type
|
||
- [x] Decision: No specific Copilot keymaps needed (use existing cmp keymaps)
|
||
- [x] Decision: Enable for all filetypes
|
||
- [x] Decision: Copilot suggestions appear before LSP suggestions in completion menu
|
||
- [x] Node.js v22.21.1 upgraded and confirmed working
|
||
|
||
## Phase 8.2 — Copilot setup
|
||
- [x] Add `zbirenbaum/copilot.lua` + `zbirenbaum/copilot-cmp`
|
||
- [x] Configure copilot.lua with auto-trigger and all filetypes
|
||
- [x] Add copilot-cmp as source to nvim-cmp
|
||
- [x] Set copilot-cmp priority higher than LSP in completion menu
|
||
- [x] Note: Copilot initializes on first InsertEnter; enter/exit insert mode once before using `:Copilot auth`
|
||
|
||
## Phase 9 — Formatting & Linting
|
||
|
||
## Phase 9.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Formatters - prettier (JS/TS/CSS/JSON/MD/HTML), phpcbf (PHP), stylua (Lua), ruff_format via conform (Python; supersedes the original black plan)
|
||
- [x] Decision: Linters - eslint (JS/TS), phpcs (PHP), markdownlint (Markdown), ruff (Python)
|
||
- [x] Decision: Project-local executables preferred, fallback to global (node_modules/.bin/, vendor/bin/)
|
||
- [x] Decision: phpcs/phpcbf already installed globally with WordPress coding standards - no installation needed
|
||
- [x] Decision: Format-on-save enabled by default with toggle capability
|
||
- [x] Decision: Manual format keymaps: `<leader>lf` (normal), `<leader>lf` (visual range)
|
||
- [x] Decision: Respect project config files (.prettierrc, phpcs.xml, .eslintrc, pyproject.toml, etc.)
|
||
- [x] Strategy: Helper function detects project-local executables first, then global
|
||
- [x] WordPress: phpcs.xml in project root or --standard=WordPress flag for WordPress projects
|
||
- [x] Philosophy: Formatters are authoritative source of truth; Neovim settings should match formatter rules per filetype
|
||
- [x] Note: Phase 9.4 will align Neovim editor settings (tabstop, shiftwidth, expandtab) with formatter configurations
|
||
|
||
## Phase 9.2 — conform.nvim setup with project-aware executables
|
||
- [x] Add `stevearc/conform.nvim` (replaced none-ls due to phpcbf preprocessing bug)
|
||
- [x] Configure formatters (conform has built-in support for all):
|
||
- [x] prettier (auto-detects project-local, Mason, global)
|
||
- [x] phpcbf (auto-detects project-local, global; customized for WordPress standard)
|
||
- [x] stylua (auto-detects project-local, Mason, global)
|
||
- [x] Add `mfussenegger/nvim-lint` for linting (separate from formatting)
|
||
- [x] Configure linters via nvim-lint:
|
||
- [x] eslint_d (project-local first, then Mason, then global - daemon version for speed)
|
||
- [x] phpcs (project-local first, then global system install - already available)
|
||
- [x] markdownlint (Mason installed)
|
||
- [x] Add format-on-save autocommand with toggle capability (`<leader>lt` to toggle)
|
||
- [x] Add manual format keymaps: `<leader>lf` (buffer), `<leader>lf` (visual range)
|
||
- [x] Ensure WordPress coding standards work via phpcs.xml or --standard flag
|
||
- [x] Search order handled by conform.nvim automatically: project → Mason → system PATH
|
||
- [x] Note: Linting runs on BufEnter, BufWritePost, InsertLeave events
|
||
- [x] Removed none-ls.lua (bug caused blank lines in PHP formatting)
|
||
|
||
## Phase 9.3 — Mason formatter/linter installation
|
||
- [x] Add `WhoIsSethDaniel/mason-tool-installer.nvim` for automated installation
|
||
- [x] Install via Mason: prettier, eslint_d, markdownlint, stylua, and ruff
|
||
- [x] Note: phpcs/phpcbf already installed globally, skip Mason installation
|
||
- [x] Verify all tools available: Tools installed to ~/.local/share/nvim/mason/bin/
|
||
|
||
## Phase 9.4 — Align Neovim settings with formatter rules
|
||
- [x] Configure per-filetype settings to match formatter defaults
|
||
- [x] PHP: tabs, 2-width display (WordPress standards)
|
||
- [x] JS/TS/CSS/JSON/HTML: spaces, 2-width (Prettier defaults)
|
||
- [x] Lua: spaces, 2-width (common Neovim convention)
|
||
- [x] Markdown: spaces, 2-width (Prettier defaults)
|
||
- [x] Python: spaces, 4-width (Black/PEP 8 defaults)
|
||
- [x] Use autocmds in lua/autocmds.lua for filetype-specific tabstop, shiftwidth, expandtab
|
||
- [x] Set global defaults: 4-width, spaces (reasonable baseline)
|
||
- [x] Goal: Manual editing feels natural and matches what formatter will produce on save
|
||
- [x] Note: All settings kept explicit per-filetype for clarity and maintainability
|
||
|
||
## Phase 10 — Migrate Kept Behaviours
|
||
|
||
## Phase 10.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Port abbreviations to Lua via vim.cmd.iabbrev
|
||
- [x] Decision: Port shell template auto-loading via autocmd + BufReadPost
|
||
- [x] Decision: Whitespace highlighting already handled via listchars (Phase 3.2)
|
||
- [x] Decision: Skip persistent folds (UFO handles folding, no explicit persistence needed)
|
||
|
||
## Phase 10.2 — Abbreviations
|
||
- [x] Abbreviations: `adn→and`, `waht→what`, `tehn→then`, `functin→function`, `positin→position`
|
||
- [x] Created dedicated `lua/abbreviations.lua` for modularity and easier maintenance
|
||
|
||
## Phase 10.3 — Templates
|
||
- [x] Templates: auto-populate new `.sh` from template
|
||
- [x] Added BufNewFile autocmd for *.sh in lua/autocmds.lua
|
||
|
||
## Phase 10.4 — Whitespace highlighting
|
||
- [x] Whitespace highlighting (modern approach)
|
||
- [x] Note: Already handled via listchars in Phase 3.2 (settings.lua)
|
||
|
||
## Phase 10.5 — Persistent folds
|
||
- [x] Persistent folds (via UFO) -- no need, this is no longer required.
|
||
- [x] Note: UFO handles folding; no explicit persistence mechanism needed
|
||
|
||
## Phase 10.6 — Custom tabline function
|
||
- [x] Implement custom tabline with configurable path shortening (`lua/utils.lua`)
|
||
- [x] Configure tabline in `lua/settings.lua` with `utils.tabline_full_parents`
|
||
- [x] Document tabline configuration in `README.md`
|
||
- [x] Show N parent directories in full, shorten earlier paths to first letter
|
||
|
||
## Phase 11 — Colorscheme: Modern Paper Tonic
|
||
|
||
## Phase 11.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Decision: Create modern Paper Tonic fork from scratch
|
||
- [x] Decision: Name = "paper-tonic-modern"
|
||
- [x] Decision: Location = inside nvim config initially, move to repo later
|
||
- [x] Decision: Structure = modular Lua colorscheme (colors.lua, groups/*.lua)
|
||
- [x] Phased approach:
|
||
- Phase 11.2-11.4: Extract palette and base groups
|
||
- Phase 11.5-11.6: General TreeSitter highlights (modern @* groups)
|
||
- Phase 11.7: Semantic highlighting (custom CSS/HTML captures)
|
||
- Phase 11.8: Plugin support (LSP, Telescope, Gitsigns, etc.)
|
||
|
||
## Phase 11.2 — Extract Paper Tonic color palette
|
||
- [x] Create `lua/paper-tonic-modern/colors.lua`
|
||
- [x] Extract all `c_*` color variables from Paper Tonic
|
||
- [x] Document what each color represents (foreground, background, accent colors)
|
||
- [x] Convert to modern format (keep hex, 256-color, ANSI mappings)
|
||
|
||
## Phase 11.3 — Create colorscheme structure
|
||
- [x] Create directory structure:
|
||
- `colors/paper-tonic-modern.lua` (entry point)
|
||
- `lua/paper-tonic-modern/init.lua` (main logic)
|
||
- `lua/paper-tonic-modern/colors.lua` (palette)
|
||
- `lua/paper-tonic-modern/groups/` (highlight group definitions)
|
||
- [x] Create helper function for setting highlights
|
||
- [x] Set up colorscheme loading mechanism
|
||
|
||
## Phase 11.4 — Base vim highlight groups
|
||
- [x] Create `lua/paper-tonic-modern/groups/editor.lua`
|
||
- [x] Map Paper Tonic colors to base groups: Normal, Comment, LineNr, CursorLine, etc.
|
||
- [x] Create `lua/paper-tonic-modern/groups/syntax.lua`
|
||
- [x] Map to syntax groups: Function, String, Keyword, Identifier, etc.
|
||
- [x] Test with simple Lua file to verify base colors work
|
||
|
||
## Phase 11.5 — Modern TreeSitter highlight groups
|
||
- [x] Create `lua/paper-tonic-modern/groups/treesitter.lua`
|
||
- [x] Map modern `@*` groups to Paper Tonic colors:
|
||
- Core: @variable, @function, @keyword, @string, @number, @boolean, @comment
|
||
- Types: @type, @property, @field, @parameter
|
||
- Operators: @operator, @punctuation.delimiter, @punctuation.bracket
|
||
- Language constructs: @keyword.function, @keyword.return, @keyword.conditional
|
||
- [x] Use `:help treesitter-highlight-groups` as reference
|
||
- [x] Test with multiple languages: Lua, PHP, JavaScript, HTML, CSS
|
||
|
||
## Phase 11.6 — Language-specific TreeSitter groups
|
||
- [x] Add language-specific overrides (e.g., @variable.php, @tag.html)
|
||
- [x] Ensure HTML tags, CSS selectors, PHP variables have appropriate colors
|
||
- [x] Test across primary languages (HTML, PHP, JS, CSS, Markdown)
|
||
- [x] Added comprehensive language-specific groups:
|
||
- CSS/SCSS: properties, variables, functions (green c2 tones)
|
||
- HTML: tags, attributes, delimiters (blue c3)
|
||
- PHP: variables, functions, methods, built-ins (primary brownish-red)
|
||
- JavaScript/TypeScript: variables, functions, properties, JSX tags (primary + blue for JSX)
|
||
- Lua: variables, functions, built-ins (primary)
|
||
- Markdown: headings, links, code blocks (primary for structure)
|
||
- JSON: properties, strings, numbers (neutral)
|
||
- Bash: variables, functions, built-ins (primary)
|
||
|
||
## Phase 11.7 — Semantic highlighting (custom captures)
|
||
- [x] Create `lua/paper-tonic-modern/groups/semantic.lua`
|
||
- [x] Define your custom semantic captures:
|
||
- @CssClassName (for CSS .class and HTML class="" - same color)
|
||
- @CssIdentifier (for CSS #id and HTML id="" - same color)
|
||
- @DataAttribute, @DataAttributeValue (HTML data-* attributes)
|
||
- @cssPseudoClass, @cssNestingSelector, @CssUniversalSelector (CSS-specific)
|
||
- [x] Verify cross-language consistency: class names in HTML match CSS
|
||
- [x] Implemented semantic highlights:
|
||
- CSS: @CssClassName (green c2), @CssIdentifier (strong green c2_strong), @cssPseudoClass (weak green c2_weak)
|
||
- CSS: @cssNestingSelector (strong green), @CssUniversalSelector (SpecialChar)
|
||
- CSS: @CssProp (primary_weak), @CssPropertyValue (bold), @CssUnit (Delimiter)
|
||
- HTML: @ClassNameAttribute, @IdAttribute, @DataAttribute (all fg_weak for attribute names)
|
||
- HTML: @DataAttributeValue (Function)
|
||
- Cross-language: class values and #id values in HTML use same colors as CSS selectors
|
||
- [x] Test with existing custom queries (after/queries/css/highlights.scm, after/queries/html/highlights.scm)
|
||
|
||
## Phase 11.8 — Plugin highlight groups
|
||
- [x] Create `lua/paper-tonic-modern/groups/lsp.lua`
|
||
- [x] Define LSP diagnostics: DiagnosticError, DiagnosticWarn, DiagnosticHint, DiagnosticInfo
|
||
- [x] Define LSP UI: LspReferenceText, LspReferenceRead, LspReferenceWrite
|
||
- [x] Create `lua/paper-tonic-modern/groups/plugins.lua`
|
||
- [x] Add Telescope highlights (TelescopeNormal, TelescopeBorder, TelescopeSelection)
|
||
- [x] Add Gitsigns highlights (GitSignsAdd, GitSignsChange, GitSignsDelete)
|
||
- [x] Add nvim-cmp highlights (CmpItemKind*, CmpItemMenu, etc.)
|
||
|
||
**Notes**:
|
||
- LSP diagnostics use red (error), orange (warn), blue (info), green (hint)
|
||
- LSP references use cyan backgrounds with varying intensity (text/read/write)
|
||
- LSP semantic tokens link to TreeSitter groups for consistency
|
||
- Telescope uses neutral colors with primary accent for matching and selection
|
||
- Gitsigns uses status colors: green (add), blue (change), red (delete)
|
||
- nvim-cmp uses primary tones for kinds, bold for matching text
|
||
- indent-blankline and ufo use subtle grays for non-intrusive UI
|
||
|
||
## Phase 11.9 — Update plugin configuration
|
||
- [x] Update `lua/plugins/colorscheme.lua` to use paper-tonic-modern
|
||
- [x] Remove old Paper Tonic reference
|
||
- [x] Remove colorscheme-overrides.lua (no longer needed)
|
||
- [x] Test full config reload
|
||
|
||
**Notes**:
|
||
- `lua/plugins/colorscheme.lua` already updated to load `paper-tonic-modern`
|
||
- Old `paper-tonic/` directory moved to `legacy/paper-tonic-original/` (archived)
|
||
- No `colorscheme-overrides.lua` existed (not needed with modern implementation)
|
||
- Full config reload tested: Normal ✓, DiagnosticError ✓, TelescopeNormal ✓, GitSignsAdd ✓
|
||
- Colorscheme loads correctly: `vim.g.colors_name = 'paper-tonic-modern'`
|
||
|
||
## Phase 11.10 — Validation and polish
|
||
- [x] Test all primary language parsers (Lua, PHP, HTML, CSS, JS, Markdown)
|
||
- [x] Verify semantic highlight captures for matching CSS/HTML classes and IDs load correctly
|
||
- [x] Check configured plugin UI highlight groups (Telescope, Gitsigns, nvim-cmp)
|
||
- [x] Verify LSP diagnostic highlight groups are defined and distinct
|
||
- [x] Document color scheme in README
|
||
|
||
## Phase 11.11 — Extract to separate repo (later)
|
||
- [ ] Move to `~/projects/paper-tonic-modern/`
|
||
- [ ] Update plugin config to point to new location
|
||
- [ ] Add proper README, LICENSE, screenshots
|
||
- [ ] Consider publishing to GitHub
|
||
|
||
## Phase 12 — Cleanup & Validation
|
||
|
||
## Phase 12.1 — Confirm scope and priorities
|
||
- [x] Confirm scope and priorities for this phase
|
||
|
||
## Phase 12.2 — Retire legacy files
|
||
- [x] Retire tracked `.vimtmp` backup artifacts and prevent them from being re-added
|
||
- [x] Retire the broken `legacy/paper-tonic-original` symlink
|
||
- [x] Keep the meaningful legacy Vimscript archive as historical reference
|
||
|
||
## Phase 12.3 — Startup performance
|
||
- [x] Validate startup performance (clean headless launch in approximately 45 ms on 2026-10-27)
|
||
|
||
## Phase 12.4 — Navigation validation
|
||
- [ ] Validate Telescope navigation + LSP jumps
|
||
- [ ] Validate netrw browsing and preview splits
|
||
- [x] Remove Oil.nvim and its keymaps, lockfile entry, highlights, and active documentation
|
||
- [x] Fix working directory behavior (disabled autochdir, locked Telescope to project root)
|
||
- [x] Make alternate-buffer jumps skip netrw explorer buffers when returning to the last real file
|
||
- [x] Guard alternate-buffer tracking against unset or invalid buffer numbers
|
||
|
||
## Phase 12.5 — Language tooling validation
|
||
- [ ] Validate HTML/PHP/JS/Markdown tooling
|
||
- [ ] Verify LSP (gd, gr, K, diagnostics)
|
||
- [ ] Verify formatting (prettier, phpcbf, stylua)
|
||
- [ ] Verify linting (eslint_d, phpcs, markdownlint)
|
||
- [x] Confirm primary Tree-sitter parsers and HTML/CSS custom queries load
|
||
- [x] Confirm Intelephense attaches with secure project-local includePaths
|
||
- [x] Confirm configured formatter and linter executables resolve
|
||
|
||
## Phase 12.6 — Final polish
|
||
- [x] Review all keymaps and ensure they're documented (README.md + :KeymapsGuide)
|
||
- [x] Update LOG.md with final architecture and usage
|
||
- [ ] Clean up any remaining debug code or temporary comments
|
||
|
||
## Phase 13 — Controlled Neovim 0.12 Upgrade
|
||
|
||
## Phase 13.1 — Confirm scope and upgrade policy
|
||
- [x] Confirm scope and priorities for this phase
|
||
- [x] Target the current stable release: Neovim 0.12.6
|
||
- [x] Continue using the official standalone Linux archive; do not hand Neovim management to pacman
|
||
- [x] Keep Neovim 0.11.5 available until the upgraded setup has passed normal-use validation
|
||
- [x] Separate the Neovim upgrade, plugin update, and Mason tool update into independently testable steps
|
||
|
||
## Phase 13.2 — Create a clean rollback checkpoint
|
||
- [x] Commit the completed Oil.nvim removal before beginning the upgrade
|
||
- [x] Record the current Neovim version, plugin lockfile, parser state, and startup result
|
||
- [x] Confirm the existing 0.11.5 configuration still passes its automated checks
|
||
- [x] Do not remove or overwrite the working 0.11.5 installation
|
||
|
||
## Phase 13.3 — Audit 0.12 compatibility before switching
|
||
- [x] Review the Neovim 0.12 breaking changes against the active configuration
|
||
- [x] Remove deprecated `vim.lsp.with()` handler wrappers; the shared floating-preview override already supplies the configured border
|
||
- [x] Disable mason-lspconfig's automatic server activation and remove its obsolete `automatic_installation` option; `lsp.lua` remains the sole activation authority
|
||
- [x] Replace deprecated `client.notify(...)` with the 0.12-compatible `client:notify(...)` method for project-local settings
|
||
- [x] Replace deprecated `vim.loop` usage with `vim.uv`
|
||
- [x] Replace deprecated diagnostic navigation APIs with the current diagnostic jump API
|
||
- [x] Revalidate native `exrc` behavior now that 0.12 searches parent directories
|
||
- [x] Verify `vim.secure.read()` behavior in the project-local LSP settings loader
|
||
- [x] Determine how Neovim 0.12's bundled optional netrw package behaves with the configured explorer workflow
|
||
- [x] Confirm no explicit `:packadd netrw` is needed: Neovim's default runtime wrapper loads netrw automatically
|
||
- [x] Keep the existing Undotree plugin: Neovim 0.12's built-in `:Undotree` is an inactive optional package, while the configured plugin's richer `:UndotreeToggle` workflow still opens cleanly
|
||
|
||
## Phase 13.4 — Install Neovim 0.12.6 alongside 0.11.5
|
||
- [x] Download the official `nvim-linux-x86_64.tar.gz` release archive
|
||
- [x] Verify the archive against the SHA-256 digest published with the release
|
||
- [x] Install into a versioned directory without replacing 0.11.5
|
||
- [x] Introduce an explicit user-level selector for the active version
|
||
- [x] Activate 0.12.6 through the existing `~/.local/bin` PATH entry after verifying both binaries
|
||
- [x] Document rollback by repointing `~/.local/bin/nvim` to the 0.11.5 binary
|
||
|
||
Installed layout:
|
||
|
||
```text
|
||
/opt/neovim/nvim-linux-x86_64/ # 0.11.5 rollback runtime
|
||
/opt/neovim/nvim-0.12.6/
|
||
~/.local/bin/nvim -> /opt/neovim/nvim-0.12.6/bin/nvim
|
||
```
|
||
|
||
## Phase 13.5 — Test 0.12 with the existing plugin lockfile
|
||
- [x] Use isolated `XDG_DATA_HOME`, `XDG_CACHE_HOME`, and `XDG_STATE_HOME` directories
|
||
- [ ] Install the currently locked plugin revisions into the isolated data directory
|
||
- [x] Keep the production plugin and Mason directories untouched during candidate testing
|
||
- [x] Validate headless startup and capture startup time
|
||
- [x] Run `:checkhealth` and review every relevant warning/error
|
||
- [x] Verify netrw can be loaded and `:Explore` opens the expected tree browser
|
||
- [x] Fix core/config compatibility issues before updating plugins
|
||
|
||
## Phase 13.6 — Update plugins in isolation
|
||
- [x] Use a temporary branch or worktree based on the rollback checkpoint
|
||
- [x] Run lazy.nvim updates only inside the isolated 0.12 test environment
|
||
- [x] Review every lockfile change before adopting it
|
||
- [x] Prioritize lazy.nvim, nvim-lspconfig, Treesitter, Telescope, Mason integration, completion, formatting, linting, UFO, and Copilot compatibility
|
||
- [x] Rebuild or update Treesitter parsers for the 0.12 runtime and verify custom queries
|
||
- [x] Keep Mason-managed language servers, formatters, and linters pinned during this step
|
||
- [x] Adopt the tested lockfile only after all plugin-level regressions are resolved
|
||
|
||
## Phase 13.7 — Validate the complete 0.12 candidate
|
||
- [x] Validate startup, lazy loading, commands, and configured keymaps automatically
|
||
- [x] Validate netrw tree browsing, previews, alternate-buffer behavior, and file operations
|
||
- [ ] Validate Telescope files, grep, buffers, and LSP symbol pickers
|
||
- [x] Validate LSP attachment, `gd`, `gr`, `K`, diagnostics, and project-local `.nvim.lua` settings
|
||
- [x] Validate the current completion stack before activation; native completion migration follows in Phase 13.9
|
||
- [x] Validate conform formatter availability and nvim-lint diagnostics; retain normal-use checks for save-time behavior
|
||
- [x] Validate Treesitter parsers and custom HTML/CSS queries; retain interactive checks for highlighting, text objects, autotag, and folding
|
||
- [ ] Validate the Paper Tonic colorscheme, plugin highlights, sessions, persistent undo, and shell templates
|
||
- [x] Perform a PTY-backed PHP smoke test for native completion selection, acceptance, snippets, LSP settings, and diagnostics
|
||
|
||
## Phase 13.8 — Activate with rollback available
|
||
- [x] Switch the active-version selector from 0.11.5 to 0.12.6
|
||
- [x] Repeat a short smoke test through the normal shell/PATH entrypoint
|
||
- [x] Keep 0.11.5 and its rollback instructions available during a settling period
|
||
- [x] Update AGENTS.md, README.md, and LOG.md with the final supported version and upgrade procedure
|
||
- [ ] Remove 0.11.5 only after an explicit later decision
|
||
|
||
## Phase 13.9 — Consolidate on Neovim 0.12 native features
|
||
- [x] Keep lazy.nvim as the plugin manager; do not combine the runtime upgrade with a migration to experimental `vim.pack`
|
||
- [x] Replace `mbbill/undotree` with the optional native `nvim.undotree` package while preserving `<leader>u`
|
||
- [x] Configure native automatic/LSP completion with explicit selection and built-in snippet expansion for its settling trial
|
||
- [x] Enable Copilot inline suggestions with a distinct accept key and hide them while the native completion menu is visible
|
||
- [x] Validate PHP, HTML, JavaScript/TypeScript, Markdown, Lua, paths, snippets, autopairs, and Copilot interactively
|
||
- [x] Remove nvim-cmp, cmp-nvim-lsp, cmp-buffer, cmp-path, LuaSnip, and copilot-cmp from the 0.12 candidate
|
||
- [x] Remove obsolete completion integrations, lockfile entries, highlights, and documentation
|
||
|
||
## Phase 13.10 — Update external tools separately
|
||
- [ ] Review Mason package updates only after Neovim and plugin revisions are stable
|
||
- [ ] Update language servers, formatters, and linters in small groups
|
||
- [ ] Revalidate PHP, JavaScript/TypeScript, HTML/CSS, Markdown, Lua, and Python after each group
|
||
|
||
## Phase 14 — Netrw Live Preview and Directory Summaries
|
||
|
||
## Phase 14.1 — Confirm the final interaction model
|
||
- [x] Confirm scope and priorities for this phase after the 0.12 upgrade
|
||
- [x] Keep netrw as the sole tree browser and file explorer
|
||
- [x] Keep `p` as the preview entry point so stock-netrw muscle memory remains useful on remote systems
|
||
- [x] Once a native preview window exists, update it automatically as the netrw cursor moves
|
||
- [x] Close the preview automatically when a file is opened for editing or netrw is left
|
||
- [x] Treat the existence of the preview window as state; avoid a separate global preview-mode flag
|
||
|
||
Target workflow:
|
||
|
||
```text
|
||
p on file/directory open preview and begin live updates
|
||
j / k replace preview with the selected entry
|
||
<CR>, o, v, t open the file and close the preview
|
||
:pclose / <C-w>z close the preview and stop live updates
|
||
```
|
||
|
||
## Phase 14.2 — Revalidate netrw integration on Neovim 0.12
|
||
- [x] Confirm bundled netrw v184 and its documented `netrw#Call()` bridge
|
||
- [x] Confirm `NetrwGetWord`, `NetrwBrowseChgDir`, `NetrwTreePath`, and `NetrwPreview` remain available
|
||
- [x] Confirm tree paths, symlinks, directory markers, local paths, and URI paths are classified correctly
|
||
- [x] Resolve any interaction with Neovim 0.12's directory startup behavior: a real UI opens the configured netrw tree normally
|
||
- [x] Keep a graceful stock-netrw fallback if enhanced preview setup cannot be installed
|
||
|
||
## Phase 14.3 — Implement live preview lifecycle
|
||
- [x] Extend netrw's buffer-local `p` behavior without changing its familiar purpose
|
||
- [x] Add a narrowly scoped, buffer-local `CursorMoved` autocmd
|
||
- [x] Debounce preview updates by approximately 75–100 ms
|
||
- [x] Update only when a preview window exists in the current tab
|
||
- [x] Continue using netrw's native preview machinery for regular files
|
||
- [x] Close the preview when leaving the netrw buffer to edit a file
|
||
- [x] Cancel and close pending timers when the netrw buffer is wiped out
|
||
- [x] Avoid focus changes: keep the cursor in the tree while previews update
|
||
|
||
## Phase 14.4 — Add read-only directory summaries
|
||
- [x] Show an informational scratch-buffer preview when the selected entry is a directory
|
||
- [x] List immediate children only; do not calculate recursive directory sizes
|
||
- [x] Sort directories first and files second, alphabetically within each group
|
||
- [x] Show entry type, human-readable file size, modification time, and name
|
||
- [x] Show a summary count and total size for immediate files
|
||
- [x] Cap output at approximately 200 entries and show a truncation notice
|
||
- [x] Handle empty, missing, unreadable, and rapidly changing directories without errors
|
||
- [x] Display symlinks distinctly without recursively following directory links
|
||
- [x] Mirror netrw's hidden-file visibility where practical
|
||
- [x] Support local filesystems when Neovim itself is running over SSH
|
||
- [x] Fall back to native behavior for remote netrw URI schemes if directory enumeration is unavailable
|
||
|
||
Example directory preview:
|
||
|
||
```text
|
||
lua/plugins/
|
||
|
||
Type Size Modified Name
|
||
dir — 2026-10-27 11:42 helpers/
|
||
file 4.8K 2026-10-27 13:10 lsp.lua
|
||
file 3.2K 2026-10-27 12:55 telescope.lua
|
||
|
||
1 directory, 2 files, 8.0K
|
||
```
|
||
|
||
## Phase 14.5 — Test preview behavior
|
||
- [x] Test file → file, file → directory, directory → file, and directory → directory movement
|
||
- [x] Test directory expand/collapse while a preview exists
|
||
- [x] Test manual preview closure and confirm cursor movement no longer previews
|
||
- [x] Test `<CR>`, horizontal split, vertical split, and tab selection cleanup
|
||
- [ ] Test separate preview windows across tabpages
|
||
- [x] Test spaces, Unicode, symlinks, unreadable entries, and large directories
|
||
- [x] Test rapid cursor movement for flicker, stale timers, and excess filesystem work
|
||
- [x] Prevent Tree-sitter parser races during rapid cross-language file preview replacement and restore highlighting on edit
|
||
- [x] Hide diagnostics in file previews and restore their prior per-buffer state on edit
|
||
- [x] Suppress remaining Vim syntax and indent-guide decoration in file previews, restoring prior state on edit
|
||
- [x] Add count-aware `<M-j>` / `<M-k>` preview scrolling without moving focus from netrw
|
||
- [x] Make preview scrolling silently clamp at file/window boundaries
|
||
- [ ] Test the workflow in an actual SSH session
|
||
- [ ] Confirm stock netrw remains understandable when this configuration is unavailable
|
||
|
||
## Phase 14.6 — Document and finalize
|
||
- [x] Update README.md and dynamic `:KeymapsGuide` mapping descriptions with the enhanced `p` lifecycle
|
||
- [x] Record implementation decisions and limitations in LOG.md
|
||
- [ ] Mark Phase 12.4 netrw preview validation complete after interactive use
|
||
|
||
---
|
||
|
||
Notes:
|
||
- Keep plugin specs minimal; configure in their own `lua/plugins/*.lua` files.
|
||
- Avoid adding plugins not listed in the guide unless explicitly requested.
|
||
- Prefer simple defaults; only add settings that clearly improve workflow.
|
||
- Plugin approval policy: unlisted plugins may be proposed, but must be explicitly confirmed before installation.
|
||
|
||
Known Issues / Follow-ups:
|
||
- lua-language-server (lua_ls) from Mason failed to start due to missing shared library `libbfd-2.38-system.so`. **RESOLVED**: Installed lua-language-server via system package manager (pacman) instead of Mason. Removed `lua_ls` from Mason's ensure_installed list in `lua/plugins/mason-lspconfig.lua`.
|
||
- LSP root detection: In some cases, the parent repository is picked as the root (e.g., when a workspace lives inside another repo). Workaround: create an empty `.git` directory (or a marker like `.nvimroot`) in the intended workspace root to pin the project root for LSPs.
|
||
|
||
Decisions & Changes:
|
||
- **Neoconf dropped**: folke/neoconf.nvim incompatible with Neovim 0.11+ vim.lsp.config API (GitHub issue #116, open since May 2024, no resolution). Migrated to native `exrc` + `secure` approach.
|
||
- **vim.lsp.config migration**: Migrated from deprecated `require('lspconfig')[server].setup()` to `vim.lsp.config()` + `vim.lsp.enable()` (Neovim 0.11+ native API).
|
||
- **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**: An `LspAttach` callback securely reads project settings from the client's actual `root_dir` (not cwd), ensuring correct behavior across different workspace structures.
|
||
- **Phase 4 Navigation Strategy**: Use built-in netrw as the sole tree browser and file explorer so the workflow transfers to remote systems. Telescope remains the fuzzy finder. Oil.nvim was evaluated and removed because maintaining a second explorer split muscle memory without providing the preferred tree view.
|