nvim/LOG.md
2026-10-27 13:49:50 +00:00

21 KiB
Raw Blame History

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-01-13: Popup borders for visibility: Added rounded borders to all floating windows to prevent them from blending into the background. Changed NormalFloat and FloatBorder backgrounds from transparent (c.NONE) to c.bg_ui (slightly off-white) in colorscheme. Configured LSP handlers for hover and signature help to use border = "rounded". Diagnostics already had borders configured. This provides clear visual separation between popups and main editor content.
  • 2025-01-13: Git files to quickfix: Added <leader>gg keymap to send all modified, deleted, and untracked Git files to quickfix list with status indicators. Uses git status --porcelain to parse file status (Modified, Deleted, Added, Untracked, etc.) and displays it in the quickfix text column. Implementation in utils.git_changed_files(). Complements existing <leader>hq (Gitsigns hunks to quickfix) with file-level Git status workflow.
  • 2025-01-12: Custom Tabline Function: Implemented configurable custom tabline to replace Neovim's hardcoded path shortening (e.g., a/p/file.txt). Function in lua/utils.lua allows controlling: (1) number of full parent directories via utils.tabline_full_parents (default: 1), and (2) shortening length via utils.tabline_shorten_length (default: 3 characters). Example: with defaults, /path/to/my/project/src/file.txt becomes pat/to/my/project/src/file.txt. User preference for seeing enough context in shortened paths while keeping tab width manageable.
  • 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
    • Working directory locked to project root: Disabled autochdir, set netrw_keepdir = 1, captured initial cwd in vim.g.project_root, configured Telescope to always search from project root regardless of current buffer
  • 2026-07-06: Alternate-buffer netrw skip: Added a lightweight real-file buffer tracker and mapped <C-6>/<C-^> so alternate-buffer jumps skip netrw explorer buffers when # points at netrw. Netrw buffers are also marked unlisted on FileType to reduce their impact on buffer navigation while preserving netrw browsing behavior. Fallback uses explicit :buffer # instead of :normal! <C-^> so regular alternate-file switching still works from the Lua mapping.
  • 2026-07-07: Netrw alternate detection fix: Real netrw alternate buffers can lose filetype=netrw and remain as an unlisted NetrwTreeListing buffer. The alternate-buffer skip now detects that buffer name as netrw so <C-6> returns to the previous real file instead of reopening an empty explorer buffer.
  • 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 (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: conform.nvim for formatting, nvim-lint for diagnostics (replaced none-ls after discovering phpcbf preprocessing bug)
    • Python support: pyright LSP, ruff formatter/linter, treesitter parser (the original black plan was superseded)
    • 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)
  • 2026-01-12: conform.nvim migration:
    • Trigger: none-ls phpcbf builtin had preprocessing bug that added blank lines before formatting
    • Root cause: none-ls uses LSP protocol for formatters, adds preprocessing step that corrupted input
    • Investigation: Created debug wrappers, confirmed phpcbf CLI works correctly, traced issue to none-ls preprocessing
    • Solution: Migrated to conform.nvim (modern, actively maintained, no LSP overhead)
    • Configuration: Simplified config using conform's built-in formatters, only customized phpcbf for WordPress standard
    • Benefits: Simpler code, no custom executable resolution needed, proper stdin/tmpfile handling per formatter
    • Removed: none-ls.lua deleted (was renamed to .disabled during migration)
  • 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
    • Persistent undo: Re-enabled 2025-01-06 via undofile=true and undodir in settings.lua (preserves undo history across sessions)
  • 2025-12-11: Colorscheme Phase 11.2:
    • Color palette extraction: Extracted all 45 color definitions from original Paper Tonic colorscheme
    • Structure: Created lua/paper-tonic-modern/colors.lua with comprehensive documentation
    • Categories: Background colors (main, UI, highlights, status), foreground colors (text grays, exceptions), alerts/diagnostics, primary accents (brownish-red), and secondary accents (green/blue/cyan/magenta palettes)
    • Format: Each color defined as {hex, 256-color, ansi} tuple for broad terminal compatibility
    • Philosophy: Light, paper-like theme with subtle colors for long reading sessions
    • Next steps: Phase 11.3 will create colorscheme structure and entry point
  • 2025-12-11: Colorscheme Phase 11.3:
    • Colorscheme structure: Created complete modular colorscheme architecture
    • Entry point: colors/paper-tonic-modern.lua properly resets and loads colorscheme
    • Main module: lua/paper-tonic-modern/init.lua with helper functions for setting highlights
    • Helper functions: M.highlight() for single groups, M.highlight_all() for batch operations
    • Color conversion: Smart conversion between gui/cterm/ansi formats
    • Group modules: Created stub files for editor, syntax, treesitter, semantic, lsp, and plugins
    • Loading order: Structured to load groups in logical sequence (editor → syntax → treesitter → semantic → lsp → plugins)
    • Validation: Colorscheme loads successfully, highlights applied correctly
    • Language color consistency: All documentation updated to reflect that each language maintains its color identity everywhere (PHP=primary, HTML=blue, CSS=green, templates=magenta)
  • 2025-12-11: Colorscheme Phase 11.4:
    • Editor highlights: Comprehensive UI element highlighting (Normal, StatusLine, CursorLine, Visual, Search, Pmenu, Folds, Diffs, Spelling, Messages)
    • Syntax highlights: Traditional Vim syntax groups (Comment, String, Function, Keyword, Type, etc.) with language-specific overrides
    • Language support: Added specific highlighting for CSS (green/c2), HTML (blue/c3), Lua, Markdown, JSON, JavaScript/TypeScript, PHP
    • Color verification: All key groups tested and verified (Normal=#8c8c8c on #ffffff, htmlTag=#005faf, cssClassName=#008700)
    • CSS classes: Green tones (c2) for CSS syntax elements
    • HTML tags: Blue tones (c3) for HTML structure
    • PHP syntax: Primary brownish-red tones for PHP keywords/functions
    • Test file: Created test-colorscheme.lua for visual verification
  • 2025-12-11: Colorscheme Phase 11.5:
    • TreeSitter highlights: Comprehensive modern @* highlight groups implemented
    • Core groups: @variable, @function, @keyword, @string, @number, @boolean, @comment, @type, @property, @operator, @punctuation
    • Language constructs: @keyword.function, @keyword.return, @keyword.conditional, @keyword.repeat, @keyword.exception
    • Markup: @markup.strong, @markup.italic, @markup.heading (1-6), @markup.link, @markup.raw, @markup.list
    • Template languages: @punctuation.special.twig, @keyword.jinja (magenta c5 for template syntax)
    • Diagnostics: @diff.plus, @diff.minus, @diff.delta
    • Debug tool: Added <leader>hi keymap to show highlight group and resolved colors under cursor
    • Validation: All TreeSitter groups tested and verified with correct palette colors
  • 2025-12-11: Colorscheme Phase 11.6:
    • Language-specific TreeSitter groups: Enhanced with comprehensive per-language overrides
    • CSS/SCSS: Properties, variables ($var, --custom), functions, tag selectors (green c2 tones)
    • HTML: Tags, attributes, delimiters (blue c3 throughout)
    • PHP: Variables ($var), functions, methods, built-ins ($this, $GLOBALS), properties (primary brownish-red)
    • JavaScript/TypeScript: Variables, functions, properties, built-ins (this, arguments), JSX/TSX tags (primary + blue for JSX)
    • Lua: Variables, functions, built-ins (_G, _VERSION), properties (primary)
    • Markdown: Headings (1-6), links, code blocks, inline code (primary for structure)
    • JSON: Properties, strings, numbers, booleans (neutral colors)
    • Bash/Shell: Variables, functions, built-ins, strings (primary)
    • Color consistency verified: HTML=#005faf (blue), CSS properties=#7c6666 (primary_weak), PHP variables=#7c6666
    • Test files: Created test-html.html, test-css.css, test-colors.php for validation
  • 2025-12-11: Colorscheme Phase 11.7:
    • Semantic highlighting: Custom TreeSitter captures for cross-language consistency
    • CSS semantic captures: @CssClassName (green c2), @CssIdentifier (strong green c2_strong, bold), @cssPseudoClass (bold brownish-red primary_strong - distinguishes from green selectors), @cssPseudoElement (bold brownish-red), @cssNestingSelector (strong green), @CssUniversalSelector
    • CSS properties: @CssProp (primary_weak), @CssPropertyValue (bold fg), @CssUnit (delimiter)
    • CSS media queries: @cssMediaFeatureName, @cssMediaQuery, @cssMediaQueryValue
    • HTML attributes: @ClassNameAttribute, @IdAttribute, @DataAttribute (all fg_weak for attribute names)
    • HTML data attributes: @DataAttributeValue (Function color)
    • Cross-language consistency: Critical feature - class="my-class" in HTML uses same color (@CssClassName, green c2) as .my-class in CSS; id="my-id" in HTML uses same color (@CssIdentifier, green c2_strong) as #my-id in CSS
    • Visual benefits: Easy to visually match selectors between HTML and CSS files; consistent color coding across languages
    • Custom queries: Leverages existing after/queries/css/highlights.scm and after/queries/html/highlights.scm
    • Priority fix: Added (#set! priority 200) to all custom captures to override built-in captures (@string priority 99, @constant default priority)
    • Technical note: Custom queries require ;extends directive and higher priority than built-in captures to work correctly
    • Pseudo-class design: Uses bold brownish-red (primary_strong) instead of green to distinguish behavioral modifiers (:hover, :focus) from structural selectors (.class, #id)
  • 2025-12-11: Colorscheme Phase 11.8:
    • LSP highlights: Comprehensive diagnostic and UI highlights
    • LSP diagnostics: Error (red #d70000), Warn (orange #d75f00), Info (blue #8989af), Hint (green #89af89)
    • LSP diagnostic UI: Underlines (undercurl for errors/warnings), signs, floating windows, virtual text with tinted backgrounds
    • LSP references: Cyan background gradients - Text (#e0eaff subtle), Read (#d4f0ff medium), Write (#a3e0ff strong)
    • LSP semantic tokens: Fallback groups linking to TreeSitter equivalents for consistency
    • Telescope highlights: Neutral base with primary accent for matching, selection, and titles
    • Gitsigns highlights: Status colors - Add (green), Change (blue), Delete (red); inline diff backgrounds
    • nvim-cmp highlights: Primary tones for item kinds, bold for match highlighting, italic for menu
    • Oil.nvim highlights: Bold directories, status colors for permissions (read=green, write=orange, execute=blue), operation colors
    • indent-blankline: Subtle grays for guides and scope
    • nvim-ufo: Subtle backgrounds for folds with preview support
  • 2025-12-11: Colorscheme Phase 11.9:
    • Plugin configuration updated: lua/plugins/colorscheme.lua loads paper-tonic-modern
    • Cleanup: Moved old paper-tonic/ directory to legacy/paper-tonic-original/
    • Validation: Full config reload tested - all highlight groups load correctly
    • Colorscheme integration: Native Neovim colorscheme at colors/paper-tonic-modern.lua
    • No overrides needed: Modern implementation doesn't require separate override file
  • 2025-12-12: Added keymap reference documentation (now README.md) + :KeymapsGuide floating viewer to document every configured keymap (global + plugin-specific) grouped by source file.
  • 2025-12-12: nvim-cmp updated to disable auto-selection; confirm requires explicit item selection.
  • 2026-10-27: Phase 12 cleanup retired 607 tracked .vimtmp backup artifacts and a broken legacy Paper Tonic symlink while preserving the meaningful Vimscript archive. Added an ignore rule for the retired backup directory and corrected the legacy archive index.
  • 2026-10-27: Project .nvim.lua settings are now read with vim.secure.read() before evaluation. This closes the trust bypass caused by manually calling dofile() from the LSP attachment callback.
  • 2026-10-27: Validation confirmed a clean Neovim 0.11.5 headless launch in approximately 45 ms with 29 configured plugins. Formatter and language-server executables managed by Mason are present in Mason's bin directory; PHP tools and lua-language-server are available system-wide.
  • 2026-10-27: Repaired test-diagnostics.lua so its intentional unreachable-code example remains valid Lua and can be parsed by lua_ls.
  • 2026-10-27: Live validation confirmed Intelephense attaches in WORKSPACE_TEST and receives the trusted external includePaths. Conform reports prettier, phpcbf, and stylua available; nvim-lint resolves eslint_d, phpcs, and markdownlint.
  • 2026-10-27: Updated AGENTS.md status and LSP architecture notes to reflect completed colorscheme work and the current Phase 12 implementation.
  • 2026-10-27: Added Conform's built-in ruff_format for Python. Ruff was already Mason-managed for diagnostics; this closes a gap where documentation claimed Python formatting but format-on-save had no Python formatter and disabled LSP fallback.

Project-Local Configuration

The final implementation uses Neovim's native exrc support with secure enabled. A project's trusted .nvim.lua returns an lsp table keyed by server name. An LspAttach callback securely reads settings from the client's actual root directory and sends them with workspace/didChangeConfiguration, so settings do not depend on Neovim's current working directory.

Example .nvim.lua:

return {
  lsp = {
    intelephense = {
      settings = {
        intelephense = {
          environment = {
            includePaths = {
              "wp-content/themes/my-theme",
              "wp-content/plugins/custom-plugin",
            },
          },
        },
      },
    },
  },
}

Neoconf and the earlier layered JSON proposal were rejected. They remain in the chronological decision entries above only as superseded history.

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.