From 6592873f773b4c358ea950bfcfa8cbc3fc3bc8cc Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 8 Jun 2024 10:49:15 +0200 Subject: feat(help): use treesitter for table of contents Problem: Creating the table of contents for `gO` is complicated. Solution: Use treesitter instead. --- runtime/lua/vim/vimhelp.lua | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'runtime/lua/vim/vimhelp.lua') diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua index 4af6866d48..33324602c9 100644 --- a/runtime/lua/vim/vimhelp.lua +++ b/runtime/lua/vim/vimhelp.lua @@ -30,4 +30,42 @@ function M.highlight_groups(patterns) vim.fn.setpos('.', save_cursor) end +--- Show a table of contents for the help buffer in a loclist +function M.show_toc() + local bufnr = vim.api.nvim_get_current_buf() + local parser = vim.treesitter.get_parser(bufnr, 'vimdoc') + local query = vim.treesitter.query.parse( + parser:lang(), + [[ + (h1 (heading) @h1) + (h2 (heading) @h2) + (h3 (heading) @h3) + (column_heading (heading) @h4) + ]] + ) + local root = parser:parse()[1]:root() + local headings = {} + for id, node, _, _ in query:iter_captures(root, bufnr) do + local text = vim.treesitter.get_node_text(node, bufnr) + local capture = query.captures[id] + local row, col = node:start() + -- only column_headings at col 1 are headings, otherwise it's code examples + local is_code = (capture == 'h4' and col > 0) + -- ignore tabular material + local is_table = (capture == 'h4' and (text:find('\t') or text:find(' '))) + -- ignore tag-only headings + local is_tag = node:child_count() == 1 and node:child(0):type() == 'tag' + if not (is_code or is_table or is_tag) then + table.insert(headings, { + bufnr = bufnr, + lnum = row + 1, + text = (capture == 'h3' or capture == 'h4') and '  ' .. text or text, + }) + end + end + vim.fn.setloclist(0, headings, ' ') + vim.fn.setloclist(0, {}, 'a', { title = 'Help TOC' }) + vim.cmd.lopen() +end + return M -- cgit From b9b408a56c7e607972beaa7214719ff1494e384c Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Fri, 13 Sep 2024 05:09:11 -0700 Subject: feat(treesitter): start moving get_parser to return nil #30313 **Problem:** `vim.treesitter.get_parser` will throw an error if no parser can be found. - This means the caller is responsible for wrapping it in a `pcall`, which is easy to forget - It also makes it slightly harder to potentially memoize `get_parser` in the future - It's a bit unintuitive since many other `get_*` style functions conventionally return `nil` if no object is found (e.g. `get_node`, `get_lang`, `query.get`, etc.) **Solution:** Return `nil` if no parser can be found or created - This requires a function signature change, and some new assertions in places where the parser will always (or should always) be found. - This commit starts by making this change internally, since it is breaking. Eventually it will be rolled out to the public API. --- runtime/lua/vim/vimhelp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/vimhelp.lua') diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua index 33324602c9..01af5425c3 100644 --- a/runtime/lua/vim/vimhelp.lua +++ b/runtime/lua/vim/vimhelp.lua @@ -33,7 +33,7 @@ end --- Show a table of contents for the help buffer in a loclist function M.show_toc() local bufnr = vim.api.nvim_get_current_buf() - local parser = vim.treesitter.get_parser(bufnr, 'vimdoc') + local parser = assert(vim.treesitter._get_parser(bufnr, 'vimdoc'), 'vimdoc parser not found.') local query = vim.treesitter.query.parse( parser:lang(), [[ -- cgit From 0f067cd34d09b38f9aaf2e1732d825e89b573077 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Sat, 14 Sep 2024 12:57:33 -0700 Subject: fix(treesitter): suppress get_parser warnings via opts.error --- runtime/lua/vim/vimhelp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/vimhelp.lua') diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua index 01af5425c3..5579cc0174 100644 --- a/runtime/lua/vim/vimhelp.lua +++ b/runtime/lua/vim/vimhelp.lua @@ -33,7 +33,7 @@ end --- Show a table of contents for the help buffer in a loclist function M.show_toc() local bufnr = vim.api.nvim_get_current_buf() - local parser = assert(vim.treesitter._get_parser(bufnr, 'vimdoc'), 'vimdoc parser not found.') + local parser = assert(vim.treesitter.get_parser(bufnr, 'vimdoc', { error = false })) local query = vim.treesitter.query.parse( parser:lang(), [[ -- cgit