diff --git a/docs/superpowers/plans/2026-06-27-neovim-vue-language-server.md b/docs/superpowers/plans/2026-06-27-neovim-vue-language-server.md new file mode 100644 index 0000000..596a41a --- /dev/null +++ b/docs/superpowers/plans/2026-06-27-neovim-vue-language-server.md @@ -0,0 +1,154 @@ +# Neovim Vue Language Server Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Enable current Vue 3 language-server support while preserving `ts_ls` behavior for JavaScript and TypeScript projects. + +**Architecture:** Neovim continues to run `ts_ls` for JavaScript and TypeScript. The nvim-lspconfig `vue_ls` configuration runs only for Vue single-file components and forwards TypeScript requests to the existing TypeScript client. + +**Tech Stack:** Neovim 0.12 native LSP API, nvim-lspconfig, mason.nvim, mason-lspconfig.nvim, Vue Language Server 3 + +--- + +### Task 1: Enable Vue Language Server + +**Files:** +- Modify: `nvim/lua/tracer/plugins/lspconfig.lua:57-63` + +- [x] **Step 1: Run the pre-change assertion** + +Run: + +```bash +nvim --headless \ + "+lua assert(not vim.lsp.is_enabled('vue_ls'), 'vue_ls was unexpectedly already enabled')" \ + +qa +``` + +Expected: exit status 0, proving the new server is not enabled before implementation. + +- [x] **Step 2: Enable the server** + +Add the following line after `vim.lsp.enable("ts_ls")`: + +```lua +vim.lsp.enable("vue_ls") +``` + +Do not extend `vue_ls.filetypes`; Vue Language Server 3 removed Take Over Mode. Leave the existing `ts_ls` line unchanged. + +- [x] **Step 3: Verify the LSP configuration** + +Run: + +```bash +nvim --headless \ + "+lua assert(vim.lsp.is_enabled('vue_ls'), 'vue_ls is not enabled')" \ + "+lua assert(vim.lsp.is_enabled('ts_ls'), 'ts_ls is not enabled')" \ + "+lua assert(vim.deep_equal(vim.lsp.config.vue_ls.filetypes, { 'vue' }), 'vue_ls filetypes changed')" \ + +qa +``` + +Expected: exit status 0 with no Lua errors. + +### Task 2: Extend Mason Health Reporting + +**Files:** +- Modify: `nvim/lua/mason/health.lua:21-42` + +- [x] **Step 1: Run the pre-change assertion** + +Run: + +```bash +nvim --headless \ + "+lua local source = table.concat(vim.fn.readfile('nvim/lua/mason/health.lua'), '\\n'); assert(not source:find('vue%-language%-server'), 'Vue executable check already exists')" \ + +qa +``` + +Expected: exit status 0, proving the executable check is absent. + +- [x] **Step 2: Add the Vue executable check** + +In `M.check()`, after the `node` check, add: + +```lua +check_executable( + "Vue Language Server", + "vue-language-server", + "Install the `vue-language-server` Mason package for Vue single-file component support." +) +``` + +Update the Node advice string to include Vue: + +```lua +"Required for your configured TypeScript, Vue, ESLint, HTML, CSS, Emmet, and Intelephense language servers." +``` + +- [x] **Step 3: Verify the health module loads** + +Run: + +```bash +nvim --headless \ + "+lua assert(type(require('mason.health').check) == 'function', 'Mason health check failed to load')" \ + "+lua local source = table.concat(vim.fn.readfile('nvim/lua/mason/health.lua'), '\\n'); assert(source:find('vue%-language%-server'), 'Vue executable check is missing')" \ + +qa +``` + +Expected: exit status 0 with no Lua errors. + +### Task 3: Install and Verify Vue Language Server + +**Files:** +- No repository file changes +- External package location: Neovim data directory under `mason/packages/vue-language-server` + +- [x] **Step 1: Install through Mason** + +Run: + +```bash +nvim --headless "+MasonInstall vue-language-server" +qa +``` + +Expected: Mason reports that `vue-language-server` was installed or is already installed. + +- [x] **Step 2: Verify the executable and package** + +Run: + +```bash +test -x "${XDG_DATA_HOME:-$HOME/.local/share}/nvim/mason/bin/vue-language-server" +"${XDG_DATA_HOME:-$HOME/.local/share}/nvim/mason/bin/vue-language-server" --version +``` + +Expected: both commands exit successfully and the second prints a version. + +- [x] **Step 3: Run the complete headless verification** + +Run: + +```bash +nvim --headless \ + "+lua assert(vim.lsp.is_enabled('vue_ls'), 'vue_ls is not enabled')" \ + "+lua assert(vim.lsp.is_enabled('ts_ls'), 'ts_ls is not enabled')" \ + "+lua assert(vim.fn.executable('vue-language-server') == 1, 'vue-language-server is unavailable')" \ + +qa +git diff --check +git status --short +``` + +Expected: Neovim exits successfully, `git diff --check` has no output, and status shows only the intended LSP/health changes plus pre-existing user changes and this plan. + +- [x] **Step 4: Commit the implementation** + +Run: + +```bash +git add nvim/lua/tracer/plugins/lspconfig.lua nvim/lua/mason/health.lua +git commit -m "Add Vue language server support" +``` + +Expected: the commit contains exactly the two Neovim configuration files.