Skip to content

Instantly share code, notes, and snippets.

@coffebar
Created August 30, 2025 23:01
Show Gist options
  • Select an option

  • Save coffebar/59d7496c9735547bacb28059708ff0fd to your computer and use it in GitHub Desktop.

Select an option

Save coffebar/59d7496c9735547bacb28059708ff0fd to your computer and use it in GitHub Desktop.
compare ts_ls and volar capabilities at runtime
-- Script to compare ts_ls and volar capabilities at runtime
-- This will definitively show what capabilities conflict
local function get_client_caps(client_name)
-- Get list of all active LSP clients
local clients = vim.lsp.get_clients and vim.lsp.get_clients() or vim.lsp.get_active_clients()
for _, client in ipairs(clients) do
if client.name == client_name then
local caps = {}
for capability, value in pairs(client.server_capabilities) do
if value ~= false and value ~= nil then
caps[capability] = true
end
end
return caps
end
end
return {}
end
local function compare_capabilities()
-- Get capabilities from both servers
local ts_caps = get_client_caps("ts_ls")
local volar_caps = get_client_caps("volar")
if next(ts_caps) == nil then
print("Error: ts_ls not found. Make sure a .vue or .ts file is open")
return
end
if next(volar_caps) == nil then
print("Error: volar not found. Make sure a .vue file is open")
return
end
-- Find overlapping capabilities
local conflicts = {}
local volar_only = {}
local ts_only = {}
for cap, _ in pairs(volar_caps) do
if ts_caps[cap] then
table.insert(conflicts, cap)
else
table.insert(volar_only, cap)
end
end
for cap, _ in pairs(ts_caps) do
if not volar_caps[cap] then
table.insert(ts_only, cap)
end
end
-- Sort for consistent output
table.sort(conflicts)
table.sort(volar_only)
table.sort(ts_only)
-- Generate output
local output = {}
table.insert(output, "=== LSP Capability Comparison ===")
table.insert(output, "Date: " .. os.date())
table.insert(output, "")
table.insert(output, "CONFLICTING CAPABILITIES (both servers provide):")
table.insert(output, "-" .. string.rep("-", 50))
for _, cap in ipairs(conflicts) do
table.insert(output, " " .. cap)
end
table.insert(output, "")
table.insert(output, "VOLAR-ONLY CAPABILITIES (Vue-specific):")
table.insert(output, "-" .. string.rep("-", 50))
for _, cap in ipairs(volar_only) do
table.insert(output, " " .. cap)
end
table.insert(output, "")
table.insert(output, "TS_LS-ONLY CAPABILITIES:")
table.insert(output, "-" .. string.rep("-", 50))
for _, cap in ipairs(ts_only) do
table.insert(output, " " .. cap)
end
-- Generate Neovim config
table.insert(output, "")
table.insert(output, "=== RECOMMENDED CONFIG ===")
table.insert(output, "-" .. string.rep("-", 50))
table.insert(output, "-- Option 1: Disable conflicts in Volar")
table.insert(output, "on_attach = function(client, _)")
table.insert(output, " if client.name == 'volar' then")
table.insert(output, " local disable = {")
for _, cap in ipairs(conflicts) do
table.insert(output, " '" .. cap .. "',")
end
table.insert(output, " }")
table.insert(output, " for _, cap in ipairs(disable) do")
table.insert(output, " client.server_capabilities[cap] = false")
table.insert(output, " end")
table.insert(output, " end")
table.insert(output, "end")
table.insert(output, "")
table.insert(output, "-- Option 2: Keep only Vue-specific features")
table.insert(output, "on_attach = function(client, _)")
table.insert(output, " if client.name == 'volar' then")
table.insert(output, " local vue_only = {")
for _, cap in ipairs(volar_only) do
table.insert(output, " " .. cap .. " = true,")
end
-- Add essential capabilities
table.insert(output, " textDocumentSync = true,")
table.insert(output, " workspace = true,")
table.insert(output, " }")
table.insert(output, " for capability, _ in pairs(client.server_capabilities) do")
table.insert(output, " if not vue_only[capability] then")
table.insert(output, " client.server_capabilities[capability] = false")
table.insert(output, " end")
table.insert(output, " end")
table.insert(output, " end")
table.insert(output, "end")
-- Write to file
local file = io.open("/tmp/lsp_comparison_results.txt", "w")
if file then
file:write(table.concat(output, "\n"))
file:close()
print("Comparison results written to: /tmp/lsp_comparison_results.txt")
-- Also print summary
print("\n=== SUMMARY ===")
print("Conflicting capabilities: " .. #conflicts)
print("Volar-only capabilities: " .. #volar_only)
print("ts_ls-only capabilities: " .. #ts_only)
print("\nRun :e /tmp/lsp_comparison_results.txt to see full results")
else
-- Print to console if can't write file
print(table.concat(output, "\n"))
end
end
-- Usage:
-- 1. Comment out the on_attach function in your Volar config (lspconfig.lua)
-- 2. Restart Neovim completely (:qa and reopen)
-- 3. Open a .vue file (both ts_ls and volar will start)
-- 4. Run :luafile /tmp/compare_lsp_runtime.lua
-- The comparison will run automatically and save results to /tmp/lsp_comparison_results.txt
-- Run the comparison automatically when this file is sourced
compare_capabilities()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment