You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
5.3 KiB
Lua

local utils = require "nvim-treesitter-playground.utils"
local highlighter = require "vim.treesitter.highlighter"
local ts_utils = require "nvim-treesitter.ts_utils"
local parsers = require "nvim-treesitter.parsers"
local M = {}
function M.get_treesitter_hl()
local bufnr = vim.api.nvim_get_current_buf()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
row = row - 1
local results = utils.get_hl_groups_at_position(bufnr, row, col)
local highlights = {}
for _, hl in pairs(results) do
local line = "* **@" .. hl.capture .. "**"
if hl.specific then
line = line .. " -> **" .. hl.specific .. "**"
end
if hl.general then
line = line .. " -> **" .. hl.general .. "**"
end
if hl.priority then
line = line .. "(" .. hl.priority .. ")"
end
table.insert(highlights, line)
end
return highlights
end
function M.get_syntax_hl()
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 M.show_hl_captures()
local buf = vim.api.nvim_get_current_buf()
local lines = {}
local function show_matches(matches)
if #matches == 0 then
table.insert(lines, "* No highlight groups found")
end
for _, line in ipairs(matches) do
table.insert(lines, line)
end
table.insert(lines, "")
end
if highlighter.active[buf] then
table.insert(lines, "# Treesitter")
local matches = M.get_treesitter_hl()
show_matches(matches)
end
if vim.b.current_syntax then
table.insert(lines, "# Syntax")
local matches = M.get_syntax_hl()
show_matches(matches)
end
vim.lsp.util.open_floating_preview(lines, "markdown", { border = "single", pad_left = 4, pad_right = 4 })
end
-- Show Node at Cursor
---@param opts? table with optional fields
--- - full_path: (boolean, default false) show full path to current node
--- - show_range: (boolean, default true) show range of current node
--- - include_anonymous: (boolean, default false) include anonymous node
--- - highlight_node: (boolean, default true) highlight the current node
--- - hl_group: (string, default "TSPlaygroundFocus") name of group
--- @return number|nil bufnr number
function M.show_ts_node(opts)
opts = vim.tbl_deep_extend("keep", opts or {}, {
full_path = false,
show_range = true,
include_anonymous = false,
highlight_node = true,
hl_group = "TSPlaygroundFocus",
})
if not parsers.has_parser() then
return
end
-- Get Full Path to node
-- @param node
-- @param array?
-- @return string
local function get_full_path(node, array)
local parent = node:parent()
if parent == nil then
if array == nil then
return node:type()
end
local reverse = vim.tbl_map(function(index)
return array[#array + 1 - index]:type()
end, vim.tbl_keys(array))
return table.concat(reverse, " -> ")
end
return get_full_path(parent, vim.list_extend(array or {}, { node }))
end
local cursor = vim.api.nvim_win_get_cursor(0)
local line = cursor[1] - 1
local col = cursor[2]
local bufnr = 0
local root_lang_tree = parsers.get_parser(bufnr)
local lang_tree = root_lang_tree:language_for_range { line, col, line, col }
local lines = { "# Treesitter" }
local node_under_cursor
for _, tree in ipairs(lang_tree:trees()) do
local root = tree:root()
if root and ts_utils.is_in_node_range(root, line, col) then
local node = root:named_descendant_for_range(line, col, line, col)
local path = opts.full_path and get_full_path(node) or node:type()
node_under_cursor = node
vim.list_extend(lines, {
"* Parser: " .. lang_tree:lang(),
string.format("* %s: ", opts.full_path and "Node path" or "Node") .. path,
})
if opts.include_anonymous then
local anonymous_node = root:descendant_for_range(line, col, line, col)
vim.list_extend(lines, {
" - Anonymous: " .. anonymous_node:type(),
})
end
if opts.show_range then
local srow, scol, erow, ecol = ts_utils.get_vim_range({ node:range() }, bufnr)
vim.list_extend(lines, {
"* Range: ",
" - Start row: " .. srow,
" - End row: " .. erow,
" - Start col: " .. scol,
" - End col: " .. ecol,
})
end
end
end
if not node_under_cursor then
lines[#lines + 1] = "* Node not found"
end
if opts.highlight_node and node_under_cursor then
local ns = vim.api.nvim_create_namespace "nvim-treesitter-current-node"
ts_utils.highlight_node(node_under_cursor, bufnr, ns, opts.hl_group)
vim.api.nvim_create_autocmd("CursorMoved", {
group = vim.api.nvim_create_augroup("TSNodeUnderCursor", {}),
buffer = bufnr,
callback = function()
require("nvim-treesitter-playground.internal").clear_highlights(bufnr, ns)
end,
desc = "TSPlayground: clear highlights",
})
end
return vim.lsp.util.open_floating_preview(lines, "markdown", { border = "single", pad_left = 4, pad_right = 4 })
end
return M