tidy up and update documentation
This commit is contained in:
parent
530a65a81a
commit
6aeb4ae913
|
|
@ -43,7 +43,7 @@ This repository is being migrated to a modern, minimal Neovim setup driven by Lu
|
|||
├── oil.lua
|
||||
├── ufo.lua
|
||||
├── gitsigns.lua
|
||||
├── none-ls.lua
|
||||
├── conform.lua
|
||||
├── nvim-lint.lua
|
||||
├── mason.lua
|
||||
├── mason-lspconfig.lua
|
||||
|
|
@ -87,7 +87,7 @@ This repository is being migrated to a modern, minimal Neovim setup driven by Lu
|
|||
- 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`.
|
||||
- Formatting/Linting: `conform.nvim`, `nvim-lint`.
|
||||
- LSP Management: `mason.nvim`, `mason-lspconfig.nvim`, `mason-tool-installer.nvim`.
|
||||
|
||||
## Workflow Requirements to Preserve
|
||||
|
|
@ -115,7 +115,7 @@ This repository is being migrated to a modern, minimal Neovim setup driven by Lu
|
|||
- ✅ 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 9: Formatting & Linting (conform.nvim, nvim-lint, Mason tool installer)
|
||||
- ✅ Phase 10: Migrate kept behaviors (abbreviations, templates, custom Treesitter queries)
|
||||
- ⏸️ Phase 11: Cleanup & validation (pending)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
# Migration Plan: none-ls → conform.nvim
|
||||
|
||||
**Date:** 2026-01-12
|
||||
**Status:** ✅ **COMPLETED**
|
||||
**Reason:** none-ls's phpcbf formatter is buggy (adds blank lines). conform.nvim is more modern, doesn't use LSP overhead, better maintained.
|
||||
|
||||
## Current State
|
||||
|
||||
**Formatting (none-ls):**
|
||||
**Formatting (conform.nvim):**
|
||||
- ✅ prettier (JS/TS/CSS/JSON/HTML/Markdown)
|
||||
- ✅ stylua (Lua)
|
||||
- ❌ phpcbf (PHP) - broken, using custom autocmd workaround
|
||||
- ✅ phpcbf (PHP) with WordPress standard
|
||||
|
||||
**Linting (nvim-lint):**
|
||||
- phpcs, eslint_d, markdownlint
|
||||
|
|
@ -19,34 +20,34 @@
|
|||
## Migration Checklist
|
||||
|
||||
### Phase 1: Setup conform.nvim
|
||||
- [ ] Create `lua/plugins/conform.lua`
|
||||
- [ ] Configure formatters:
|
||||
- [ ] prettier (JS/TS/CSS/JSON/HTML/Markdown)
|
||||
- [ ] stylua (Lua)
|
||||
- [ ] phpcbf (PHP) with WordPress standard support
|
||||
- [ ] Configure format-on-save behavior
|
||||
- [ ] Set up project-local executable resolution (vendor/bin, node_modules/.bin, Mason, global)
|
||||
- [ ] Add keymaps for manual formatting (`<leader>lf`, `<leader>lt`)
|
||||
- [x] Create `lua/plugins/conform.lua`
|
||||
- [x] Configure formatters:
|
||||
- [x] prettier (JS/TS/CSS/JSON/HTML/Markdown)
|
||||
- [x] stylua (Lua)
|
||||
- [x] phpcbf (PHP) with WordPress standard support
|
||||
- [x] Configure format-on-save behavior
|
||||
- [x] Set up project-local executable resolution (vendor/bin, node_modules/.bin, Mason, global)
|
||||
- [x] Add keymaps for manual formatting (`<leader>lf`, `<leader>lt`)
|
||||
|
||||
### Phase 2: Remove none-ls
|
||||
- [ ] Delete `lua/plugins/none-ls.lua`
|
||||
- [ ] Remove none-ls from lazy-lock.json (happens automatically on `:Lazy sync`)
|
||||
- [ ] Remove the custom phpcbf autocmd workaround (no longer needed)
|
||||
- [x] Delete `lua/plugins/none-ls.lua`
|
||||
- [x] Remove none-ls from lazy-lock.json (happens automatically on `:Lazy sync`)
|
||||
- [x] Remove the custom phpcbf autocmd workaround (no longer needed)
|
||||
|
||||
### Phase 3: Testing
|
||||
- [ ] Test prettier formatting (JS/TS/CSS files)
|
||||
- [ ] Test stylua formatting (Lua files)
|
||||
- [ ] Test phpcbf formatting (PHP files) - **verify NO blank lines added**
|
||||
- [ ] Test format-on-save toggle (`<leader>lt`)
|
||||
- [ ] Test manual format (`<leader>lf`)
|
||||
- [ ] Test project-local formatter detection
|
||||
- [ ] Verify phpcs.xml is respected when present
|
||||
- [x] Test prettier formatting (JS/TS/CSS files)
|
||||
- [x] Test stylua formatting (Lua files)
|
||||
- [x] Test phpcbf formatting (PHP files) - **verified NO blank lines added**
|
||||
- [x] Test format-on-save toggle (`<leader>lt`)
|
||||
- [x] Test manual format (`<leader>lf`)
|
||||
- [x] Test project-local formatter detection
|
||||
- [x] Verify phpcs.xml is respected when present
|
||||
|
||||
### Phase 4: Documentation
|
||||
- [ ] Update README.md Configuration section
|
||||
- [ ] Update AGENTS.md Process section (if needed)
|
||||
- [ ] Update MIGRATION_PLAN.md status
|
||||
- [ ] Update LOG.md with decision and rationale
|
||||
- [x] Update README.md Configuration section
|
||||
- [x] Update AGENTS.md Process section (plugin list, formatting tools)
|
||||
- [x] Update MIGRATION_PLAN.md status (Phase 9.2)
|
||||
- [x] Update LOG.md with decision and rationale
|
||||
|
||||
## Expected Benefits
|
||||
|
||||
|
|
|
|||
10
LOG.md
10
LOG.md
|
|
@ -69,7 +69,7 @@ Record every decision here with a short rationale. Append new entries; do not re
|
|||
- **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)
|
||||
- **Linting split**: conform.nvim for formatting, nvim-lint for diagnostics (replaced none-ls after discovering phpcbf preprocessing bug)
|
||||
- **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)
|
||||
|
|
@ -78,6 +78,14 @@ Record every decision here with a short rationale. Append new entries; do not re
|
|||
- 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
|
||||
|
|
|
|||
|
|
@ -275,14 +275,13 @@ Source of truth for the step-by-step rebuild. Keep this concise and up to date.
|
|||
- [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 — none-ls setup with project-aware executables
|
||||
- [x] Add `nvimtools/none-ls.nvim`
|
||||
- [x] Create helper function to detect project-local executables (node_modules/.bin/, vendor/bin/, Mason bin)
|
||||
- [x] Configure formatters:
|
||||
- [x] prettier (project-local first, then Mason, then global)
|
||||
- [x] phpcbf (project-local first, then global system install - already available)
|
||||
- [x] stylua (Mason installed)
|
||||
- [x] Add `mfussenegger/nvim-lint` for linting (none-ls removed most linters from builtins)
|
||||
## 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)
|
||||
|
|
@ -290,8 +289,9 @@ Source of truth for the step-by-step rebuild. Keep this concise and up to date.
|
|||
- [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: project node_modules/.bin/ → project vendor/bin/ → Mason bin → system PATH
|
||||
- [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
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -131,7 +131,7 @@ Buffer-local keymaps available when an LSP client attaches:
|
|||
| n | `gI` | LSP: implementation |
|
||||
| n | `K` | LSP hover |
|
||||
|
||||
### None-ls (Formatting) `lua/plugins/none-ls.lua`
|
||||
### Conform (Formatting) `lua/plugins/conform.lua`
|
||||
|
||||
#### Keymaps
|
||||
|
||||
|
|
@ -367,7 +367,7 @@ Buffer-local keymaps available when inside a git repository:
|
|||
|
||||
### Formatting & Linting
|
||||
|
||||
This config uses **none-ls** for formatting and **nvim-lint** for diagnostics. Both prefer project-local tools over global installations.
|
||||
This config uses **conform.nvim** for formatting and **nvim-lint** for diagnostics. Both prefer project-local tools over global installations.
|
||||
|
||||
#### Executable Resolution Order
|
||||
|
||||
|
|
@ -377,15 +377,15 @@ When looking for formatters/linters, the config searches in this priority:
|
|||
2. **Mason-managed** (`~/.local/share/nvim/mason/bin/`)
|
||||
3. **System PATH** (globally installed tools)
|
||||
|
||||
See `find_executable()` helper in `lua/plugins/none-ls.lua` and `lua/plugins/nvim-lint.lua`.
|
||||
Conform.nvim handles this resolution automatically via its built-in `util.find_executable()`. nvim-lint uses a custom `find_executable()` helper in `lua/plugins/nvim-lint.lua`.
|
||||
|
||||
#### Configured Tools
|
||||
|
||||
**Formatters** (`lua/plugins/none-ls.lua`):
|
||||
**Formatters** (`lua/plugins/conform.lua`):
|
||||
- **JavaScript/TypeScript/CSS/JSON/HTML/Markdown**: `prettier`
|
||||
- **PHP**: `phpcbf` (WordPress standard by default)
|
||||
- **Lua**: `stylua`
|
||||
- **Python**: handled by `ruff` LSP (not none-ls)
|
||||
- **Python**: handled by `ruff` LSP (not conform)
|
||||
|
||||
**Linters** (`lua/plugins/nvim-lint.lua`):
|
||||
- **JavaScript/TypeScript**: `eslint_d`
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
-- none-ls.nvim: Formatting only (linting moved to nvim-lint)
|
||||
-- Philosophy: Formatters are authoritative. Project-local executables preferred.
|
||||
-- Note: none-ls removed most linters from builtins, so we use nvim-lint for diagnostics
|
||||
|
||||
return {
|
||||
"nvimtools/none-ls.nvim",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
event = { "BufReadPre", "BufNewFile" },
|
||||
config = function()
|
||||
local null_ls = require("null-ls")
|
||||
local augroup = vim.api.nvim_create_augroup("LspFormatting", {})
|
||||
|
||||
-- Helper: Find project-local executable, fallback to global
|
||||
-- Searches node_modules/.bin/, vendor/bin/, and Mason bin first
|
||||
local function find_executable(names)
|
||||
local cwd = vim.fn.getcwd()
|
||||
local mason_bin = vim.fn.stdpath("data") .. "/mason/bin/"
|
||||
|
||||
-- Try project-local paths first, then Mason, then global
|
||||
local search_paths = {
|
||||
cwd .. "/node_modules/.bin/",
|
||||
cwd .. "/vendor/bin/",
|
||||
mason_bin,
|
||||
}
|
||||
|
||||
for _, name in ipairs(names) do
|
||||
for _, path in ipairs(search_paths) do
|
||||
local full_path = path .. name
|
||||
if vim.fn.executable(full_path) == 1 then
|
||||
return full_path
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to system PATH
|
||||
if vim.fn.executable(name) == 1 then
|
||||
return name
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Formatters
|
||||
local formatting = null_ls.builtins.formatting
|
||||
|
||||
-- Note: Diagnostics (linters) moved to nvim-lint plugin
|
||||
-- Note: Python formatting handled by ruff LSP
|
||||
|
||||
null_ls.setup({
|
||||
sources = {
|
||||
-- Prettier (JS, TS, CSS, SCSS, JSON, Markdown, HTML)
|
||||
formatting.prettier.with({
|
||||
command = find_executable({ "prettier" }),
|
||||
prefer_local = "node_modules/.bin",
|
||||
}),
|
||||
|
||||
-- PHP: phpcbf DISABLED - using direct autocmd approach instead (see bottom of file)
|
||||
-- formatting.phpcbf causes blank line bug even with custom formatters
|
||||
|
||||
-- stylua (Lua)
|
||||
formatting.stylua.with({
|
||||
command = find_executable({ "stylua" }),
|
||||
}),
|
||||
},
|
||||
|
||||
-- Format on save
|
||||
on_attach = function(client, bufnr)
|
||||
if client.supports_method("textDocument/formatting") then
|
||||
vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
|
||||
vim.api.nvim_create_autocmd("BufWritePre", {
|
||||
group = augroup,
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
-- Only format if format-on-save is enabled (global flag)
|
||||
if vim.g.format_on_save ~= false then
|
||||
-- Save view (cursor position, folds, etc.) before formatting
|
||||
local view = vim.fn.winsaveview()
|
||||
vim.lsp.buf.format({ bufnr = bufnr })
|
||||
-- Restore view after formatting to preserve folds
|
||||
vim.fn.winrestview(view)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Format-on-save is enabled by default
|
||||
vim.g.format_on_save = true
|
||||
|
||||
-- Keymaps
|
||||
-- Toggle format-on-save
|
||||
vim.keymap.set("n", "<leader>lt", function()
|
||||
vim.g.format_on_save = not vim.g.format_on_save
|
||||
local status = vim.g.format_on_save and "enabled" or "disabled"
|
||||
vim.notify("Format on save " .. status, vim.log.levels.INFO)
|
||||
end, { desc = "Formatting: Toggle format on save", silent = true, noremap = true })
|
||||
|
||||
-- Manual format (buffer)
|
||||
vim.keymap.set("n", "<leader>lf", function()
|
||||
vim.lsp.buf.format({ async = false })
|
||||
end, { desc = "Formatting: Format buffer", silent = true, noremap = true })
|
||||
|
||||
-- Manual format (visual range)
|
||||
vim.keymap.set("v", "<leader>lf", function()
|
||||
vim.lsp.buf.format({ async = false })
|
||||
end, { desc = "Formatting: Format selection", silent = true, noremap = true })
|
||||
|
||||
-- PHP: Direct phpcbf formatting (bypasses none-ls entirely)
|
||||
vim.api.nvim_create_autocmd("BufWritePre", {
|
||||
pattern = "*.php",
|
||||
callback = function()
|
||||
if vim.g.format_on_save == false then
|
||||
return
|
||||
end
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local filepath = vim.api.nvim_buf_get_name(bufnr)
|
||||
|
||||
-- Find phpcbf
|
||||
local phpcbf = find_executable({ "phpcbf" })
|
||||
if not phpcbf then
|
||||
return
|
||||
end
|
||||
|
||||
-- Determine standard
|
||||
local root = vim.fn.getcwd()
|
||||
local has_project_ruleset =
|
||||
vim.loop.fs_stat(root .. "/phpcs.xml")
|
||||
or vim.loop.fs_stat(root .. "/phpcs.xml.dist")
|
||||
|
||||
local cmd = { phpcbf, "-q", "--stdin-path=" .. filepath }
|
||||
if not has_project_ruleset then
|
||||
table.insert(cmd, "--standard=WordPress")
|
||||
end
|
||||
table.insert(cmd, "-")
|
||||
|
||||
-- Get buffer content
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
local input = table.concat(lines, "\n")
|
||||
|
||||
-- Run phpcbf
|
||||
local result = vim.fn.system(cmd, input)
|
||||
local exit_code = vim.v.shell_error
|
||||
|
||||
-- Apply result if successful (exit code 0 or 1)
|
||||
if exit_code == 0 or exit_code == 1 then
|
||||
local output_lines = vim.split(result, "\n", { plain = true })
|
||||
-- Remove trailing empty line if present
|
||||
if output_lines[#output_lines] == "" then
|
||||
table.remove(output_lines)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, output_lines)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
}
|
||||
Loading…
Reference in New Issue