diff --git a/MIGRATION_PLAN.md b/MIGRATION_PLAN.md index 9beba66..62e382b 100644 --- a/MIGRATION_PLAN.md +++ b/MIGRATION_PLAN.md @@ -157,16 +157,29 @@ Source of truth for the step-by-step rebuild. Keep this concise and up to date. ## Phase 5 — Treesitter ## Phase 5.1 — Confirm scope and priorities -- [ ] Confirm scope and priorities for this phase +- [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 -- [ ] Add `nvim-treesitter` with incremental selection, highlighting +- [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 -- [ ] Add `nvim-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: `a`/`A` (swap parameter with next/prev) ## Phase 5.4 — Treesitter autotag -- [ ] Add `nvim-ts-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 @@ -240,7 +253,7 @@ Source of truth for the step-by-step rebuild. Keep this concise and up to date. - [ ] Validate startup performance (no errors, fast launch) ## Phase 9.4 — Tab workflow validation -- [ ] Validate tab-per-context workflow with Neo-tree +- [ ] Validate tab-per-context workflow with Neo-tree (if used) ## Phase 9.5 — Navigation validation - [ ] Validate Telescope navigation + LSP jumps diff --git a/README.md b/README.md index e2885b9..a7e79f6 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,15 @@ Record every decision here with a short rationale. Append new entries; do not re - 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 +- 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: `a`/`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 ## Project-Local Configuration (design) diff --git a/lazy-lock.json b/lazy-lock.json index 2372b87..eb68f21 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -8,6 +8,9 @@ "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" }, "nvim-cmp": { "branch": "main", "commit": "d97d85e01339f01b842e6ec1502f639b080cb0fc" }, "nvim-lspconfig": { "branch": "master", "commit": "9c923997123ff9071198ea3b594d4c1931fab169" }, + "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "nvim-treesitter-textobjects": { "branch": "master", "commit": "5ca4aaa6efdcc59be46b95a3e876300cfead05ef" }, + "nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" }, "oil.nvim": { "branch": "master", "commit": "cbcb3f997f6f261c577b943ec94e4ef55108dd95" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..f757d68 --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,146 @@ +-- Treesitter: Syntax highlighting, incremental selection, textobjects, autotag +return { + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + event = { "BufReadPost", "BufNewFile" }, + dependencies = { + "nvim-treesitter/nvim-treesitter-textobjects", + "windwp/nvim-ts-autotag", + }, + config = function() + require("nvim-treesitter.configs").setup({ + -- Install parsers for primary languages + ensure_installed = { + "lua", + "vim", + "vimdoc", + "php", + "html", + "javascript", + "typescript", + "tsx", + "css", + "scss", + "json", + "markdown", + "markdown_inline", + "bash", + "regex", + }, + + -- Auto-install missing parsers + auto_install = true, + + -- Syntax highlighting + highlight = { + enable = true, + -- Disable for very large files + disable = function(lang, buf) + local max_filesize = 100 * 1024 -- 100 KB + local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) + if ok and stats and stats.size > max_filesize then + return true + end + end, + additional_vim_regex_highlighting = false, + }, + + -- Incremental selection + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = "", + node_decremental = "", + }, + }, + + -- Indentation (experimental, disable if issues) + indent = { + enable = false, -- Start disabled; can enable per-filetype if stable + }, + + -- Textobjects + textobjects = { + select = { + enable = true, + lookahead = true, -- Jump forward to next textobject + keymaps = { + -- Functions + ["af"] = "@function.outer", + ["if"] = "@function.inner", + -- Classes + ["ac"] = "@class.outer", + ["ic"] = "@class.inner", + -- Parameters/arguments + ["aa"] = "@parameter.outer", + ["ia"] = "@parameter.inner", + -- Conditionals + ["ai"] = "@conditional.outer", + ["ii"] = "@conditional.inner", + -- Loops + ["al"] = "@loop.outer", + ["il"] = "@loop.inner", + -- Comments + ["a/"] = "@comment.outer", + }, + }, + move = { + enable = true, + set_jumps = true, -- Add to jumplist + goto_next_start = { + ["]f"] = "@function.outer", + ["]c"] = "@class.outer", + ["]a"] = "@parameter.inner", + }, + goto_next_end = { + ["]F"] = "@function.outer", + ["]C"] = "@class.outer", + ["]A"] = "@parameter.inner", + }, + goto_previous_start = { + ["[f"] = "@function.outer", + ["[c"] = "@class.outer", + ["[a"] = "@parameter.inner", + }, + goto_previous_end = { + ["[F"] = "@function.outer", + ["[C"] = "@class.outer", + ["[A"] = "@parameter.inner", + }, + }, + swap = { + enable = true, + swap_next = { + ["a"] = "@parameter.inner", + }, + swap_previous = { + ["A"] = "@parameter.inner", + }, + }, + }, + }) + + -- Setup autotag + require("nvim-ts-autotag").setup({ + opts = { + enable_close = true, -- Auto close tags + enable_rename = true, -- Auto rename pairs of tags + enable_close_on_slash = true, -- Auto close on trailing