summaryrefslogtreecommitdiff
path: root/lua/leap-ast.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/leap-ast.lua')
-rw-r--r--lua/leap-ast.lua51
1 files changed, 51 insertions, 0 deletions
diff --git a/lua/leap-ast.lua b/lua/leap-ast.lua
new file mode 100644
index 0000000..22a5876
--- /dev/null
+++ b/lua/leap-ast.lua
@@ -0,0 +1,51 @@
1local api = vim.api
2-- Note: The functions used here will be upstreamed eventually.
3local ts_utils = require('nvim-treesitter.ts_utils')
4
5local function get_ast_nodes()
6 local wininfo = vim.fn.getwininfo(api.nvim_get_current_win())[1]
7 -- Get current TS node.
8 local cur_node = ts_utils.get_node_at_cursor(0)
9 if not cur_node then return end
10 -- Get parent nodes recursively.
11 local nodes = { cur_node }
12 local parent = cur_node:parent()
13 while parent do
14 table.insert(nodes, parent)
15 parent = parent:parent()
16 end
17 -- Create Leap targets from TS nodes.
18 local targets = {}
19 local startline, startcol
20 for _, node in ipairs(nodes) do
21 startline, startcol, _, _ = node:range() -- (0,0)
22 if startline + 1 >= wininfo.topline then
23 local target = { node = node, pos = { startline + 1, startcol + 1 } }
24 table.insert(targets, target)
25 end
26 end
27 if #targets >= 1 then return targets end
28end
29
30local function select_range(target)
31 local mode = api.nvim_get_mode().mode
32 if not mode:match('n?o') then
33 -- Force going back to Normal (implies mode = v | V | ).
34 vim.cmd('normal! ' .. mode)
35 end
36 ts_utils.update_selection(0, target.node,
37 mode:match('V') and 'linewise' or
38 mode:match('') and 'blockwise' or
39 'charwise'
40 )
41end
42
43local function leap()
44 require('leap').leap {
45 targets = get_ast_nodes(),
46 action = api.nvim_get_mode().mode ~= 'n' and select_range, -- or jump
47 backward = true
48 }
49end
50
51return { leap = leap }