feat: add support for vim help files (#164)

This commit is contained in:
Steven Arcangeli 2022-10-19 08:09:06 -07:00
parent c2487319c0
commit 817be1d211
6 changed files with 124 additions and 4 deletions

View file

@ -119,6 +119,62 @@ M.markdown = {
end,
}
M.help = {
_get_level = function(node)
local level_str = node:type():match("^h(%d+)$")
if level_str then
return tonumber(level_str)
else
return 99
end
end,
get_parent = function(stack, match, node)
-- Fix the symbol nesting
local level = M.help._get_level(node)
for i = #stack, 1, -1 do
local last = stack[i]
if M.help._get_level(last.node) < level then
return last.item, last.node, i
else
table.remove(stack, i)
end
end
return nil, nil, 0
end,
postprocess = function(bufnr, item, match)
-- The name node of headers only captures the final node.
-- We need to get _all_ word nodes
local pieces = {}
local node = match.name.node
if vim.startswith(match.type.node:type(), "h") then
while node and node:type() == "word" do
local row, col = node:start()
table.insert(pieces, 1, get_node_text(node, bufnr))
node = node:prev_sibling()
item.lnum = row + 1
item.col = col
end
item.name = table.concat(pieces, " ")
end
end,
postprocess_symbols = function(bufnr, items)
-- Sometimes helpfiles have a bunch of tags at the top in the same line. Collapse them.
while #items > 1 and items[1].lnum == items[2].lnum do
table.remove(items, 2)
end
-- Remove the first tag under a header IF that tag appears on the same line
for _, item in ipairs(items) do
if item.children and item.children[1] then
local child = item.children[1]
if child.lnum == item.lnum then
table.remove(item.children, 1)
end
M.help.postprocess_symbols(bufnr, item.children)
end
end
end,
}
M.rust = {
postprocess = function(bufnr, item, match)
if item.kind == "Class" then

View file

@ -62,12 +62,12 @@ M.fetch_symbols_sync = function(bufnr)
local ext = extensions[lang]
local kind_map = language_kind_map[lang]
for match in query.iter_group_results(bufnr, "aerial", syntax_tree:root(), lang) do
local name_node = (utils.get_at_path(match, "name") or {}).node
local type_node = (utils.get_at_path(match, "type") or {}).node
local name_node = (match.name or {}).node
local type_node = (match.type or {}).node
-- The location capture groups are optional. We default to the
-- location of the @type capture
local start_node = (utils.get_at_path(match, "start") or {}).node or type_node
local end_node = (utils.get_at_path(match, "end") or {}).node or start_node
local start_node = (match.start or {}).node or type_node
local end_node = (match["end"] or {}).node or start_node
local parent_item, parent_node, level = ext.get_parent(stack, match, type_node)
-- Sometimes our queries will match the same node twice.
-- Detect that (type_node == parent_node), and skip dupes.

View file

@ -38,6 +38,11 @@ return {
method_declaration = "Method",
struct_type = "Struct",
},
help = {
h1 = "Interface",
h2 = "Interface",
tag = "Interface",
},
java = {
class_declaration = "Class",
enum_declaration = "Enum",

13
queries/help/aerial.scm Normal file
View file

@ -0,0 +1,13 @@
(h1
(word)+ @name @start
(tag)
) @type
(h2
(word)+ @name @start
(tag)
) @type
(tag
text: (word) @name
) @type

View file

@ -0,0 +1,37 @@
local util = require("tests.test_util")
describe("treesitter help", function()
it("parses all symbols correctly", function()
util.test_file_symbols("treesitter", "./tests/treesitter/help_test.txt", {
{
kind = "Interface",
name = "help_test.txt",
level = 0,
lnum = 1,
col = 0,
end_lnum = 1,
end_col = 15,
},
{
kind = "Interface",
name = "TEST INTRO",
level = 0,
lnum = 3,
col = 0,
end_lnum = 3,
end_col = 10,
children = {
{
kind = "Interface",
name = ":SomeCommand",
level = 1,
lnum = 5,
col = 68,
end_lnum = 5,
end_col = 82,
},
},
},
})
end)
end)

View file

@ -0,0 +1,9 @@
*help_test.txt* *help_test*
--------------------------------------------------------------------------------
TEST INTRO *test-intro*
SomeCommand *:SomeCommand*
Description of the command
================================================================================
vim:tw=80:ts=2:ft=help:norl:syntax=help: