Skip to content

Commit 1564999

Browse files
Add option to get ts headline at specific cursor
1 parent 74317bc commit 1564999

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lua/orgmode/treesitter/init.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ local tree_utils = require('orgmode.utils.treesitter')
22
local Headline = require('orgmode.treesitter.headline')
33
local Listitem = require('orgmode.treesitter.listitem')
44

5+
---@param cursor? Table Cursor position tuple {row, col}
56
---@return Headline
6-
local function closest_headline()
7-
local ts_headline = tree_utils.closest_headline()
7+
local function closest_headline(cursor)
8+
local ts_headline = tree_utils.closest_headline(cursor)
89
if not ts_headline then
910
error('Unable to locate closest headline')
1011
end

lua/orgmode/utils/treesitter.lua

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,47 @@
11
local ts_utils = require('nvim-treesitter.ts_utils')
2+
local parsers = require('nvim-treesitter.parsers')
23
local M = {}
34

45
function M.current_node()
56
local window = vim.api.nvim_get_current_win()
67
return ts_utils.get_node_at_cursor(window)
78
end
89

10+
---This is a full copy of nvim_treesiter get_node_at_cursor with support for custom cursor position
11+
---@param cursor? Table Cursor position tuple {row, col}
12+
---@param winnr? number
13+
---@param ignore_injected_langs? boolean
14+
function M.get_node_at_cursor(cursor, winnr, ignore_injected_langs)
15+
winnr = winnr or 0
16+
cursor = cursor or vim.api.nvim_win_get_cursor(winnr)
17+
local cursor_range = { cursor[1] - 1, cursor[2] }
18+
19+
local buf = vim.api.nvim_win_get_buf(winnr)
20+
local root_lang_tree = parsers.get_parser(buf)
21+
if not root_lang_tree then
22+
return
23+
end
24+
25+
local root
26+
if ignore_injected_langs then
27+
for _, tree in ipairs(root_lang_tree:trees()) do
28+
local tree_root = tree:root()
29+
if tree_root and ts_utils.is_in_node_range(tree_root, cursor_range[1], cursor_range[2]) then
30+
root = tree_root
31+
break
32+
end
33+
end
34+
else
35+
root = ts_utils.get_root_for_position(cursor_range[1], cursor_range[2], root_lang_tree)
36+
end
37+
38+
if not root then
39+
return
40+
end
41+
42+
return root:named_descendant_for_range(cursor_range[1], cursor_range[2], cursor_range[1], cursor_range[2])
43+
end
44+
945
-- walks the tree to find a headline
1046
function M.find_headline(node)
1147
if node:type() == 'headline' then
@@ -21,9 +57,9 @@ function M.find_headline(node)
2157
end
2258

2359
-- returns the nearest headline
24-
function M.closest_headline()
60+
function M.closest_headline(cursor)
2561
vim.treesitter.get_parser(0, 'org', {}):parse()
26-
return M.find_headline(M.current_node())
62+
return M.find_headline(M.get_node_at_cursor(cursor))
2763
end
2864

2965
function M.find_parent_type(node, type)

0 commit comments

Comments
 (0)