nvim-treesitter/playground

TSHighlightCaptureUnderCursor improvements

folke opened this issue · 1 comments

folke commented

TSHighlightCaptureUnderCursor currently doesn't show all active treesitter highlights.

For example, a Lua file also has active queries for comment and possibly custom user queries.

I use the method below to get all active highlight groups from the highlighter:

local util = {}

local highlighter = require("vim.treesitter.highlighter")
local ts_utils = require "nvim-treesitter.ts_utils"

function util.getTreesitterHL()
  local buf = vim.api.nvim_get_current_buf()
  local row, col = unpack(vim.api.nvim_win_get_cursor(0))
  row = row - 1

  local self = highlighter.active[buf]
  if self == nil then return {} end

  local matches = {}

  self.tree:for_each_tree(function(tstree, tree)
    if not tstree then return end

    local root = tstree:root()
    local root_start_row, _, root_end_row, _ = root:range()

    -- Only worry about trees within the line range
    if root_start_row > row or root_end_row < row then return end

    local query = self:get_query(tree:lang())

    -- Some injected languages may not have highlight queries.
    if not query:query() then return end

    local iter = query:query():iter_captures(root, self.bufnr, row, row + 1)

    while true do
      local capture, node = iter()
      if capture == nil then break end

      local hl = query.hl_cache[capture]

      if hl and ts_utils.is_in_node_range(node, row, col) then
        local c = query._query.captures[capture] -- name of the capture in the query
        table.insert(matches,
                       "@" .. c .. " -> " .. hl .. " -> " .. query:_get_hl_from_capture(capture))
      end
    end

  end, true)
  return matches
end

image

Additionally, I've added the hl syntax groups when treesitter is not enabled for the current buffer:

function util.getSyntaxHL()
  local line = vim.fn.line(".")
  local col = vim.fn.col(".")
  local matches = {}
  for _, i1 in ipairs(vim.fn.synstack(line, col)) do
    local i2 = vim.fn.synIDtrans(i1)
    local n1 = vim.fn.synIDattr(i1, "name")
    local n2 = vim.fn.synIDattr(i2, "name")
    table.insert(matches, n1 .. " -> " .. n2)
  end
  return matches
end

function util.getHL()
  local buf = vim.api.nvim_get_current_buf()
  if highlighter.active[buf] == nil then
    return util.getSyntaxHL()
  else
    return util.getTreesitterHL()
  end
end

function util.showHL()
  local matches = util.getHL()
  if #matches == 0 then matches = { "No highlight groups found!" } end
  vim.lsp.util.open_floating_preview(matches, "show-hl")
end

image

Let me know if you'd like me to add a PR for the improved treesitter highlights and / or adding in the syntax groups.

Oh that looks really good indeed, we'd be very interesting in a pr for this!!