ast.lua (1648B)
1 local api = vim.api 2 local ts = vim.treesitter 3 4 local M = {} 5 6 local function get_ts_nodes() 7 if not pcall(ts.get_parser) then return end 8 local wininfo = vim.fn.getwininfo(api.nvim_get_current_win())[1] 9 -- Get current node, and then its parent nodes recursively. 10 local cur_node = ts.get_node() 11 if not cur_node then return end 12 local nodes = { cur_node } 13 local parent = cur_node:parent() 14 while parent do 15 table.insert(nodes, parent) 16 parent = parent:parent() 17 end 18 -- Create Leap targets from TS nodes. 19 local targets = {} 20 local startline, startcol 21 for _, node in ipairs(nodes) do 22 startline, startcol, endline, endcol = node:range() -- (0,0) 23 local startpos = { startline + 1, startcol + 1 } 24 local endpos = { endline + 1, endcol + 1 } 25 -- Add both ends of the node. 26 if startline + 1 >= wininfo.topline then 27 table.insert(targets, { pos = startpos, altpos = endpos }) 28 end 29 if endline + 1 <= wininfo.botline then 30 table.insert(targets, { pos = endpos, altpos = startpos }) 31 end 32 end 33 if #targets >= 1 then return targets end 34 end 35 36 local function select_node_range(target) 37 local mode = api.nvim_get_mode().mode 38 -- Force going back to Normal from Visual mode. 39 if not mode:match('no?') then vim.cmd('normal! ' .. mode) end 40 vim.fn.cursor(unpack(target.pos)) 41 local v = mode:match('V') and 'V' or mode:match('�') and '�' or 'v' 42 vim.cmd('normal! ' .. v) 43 vim.fn.cursor(unpack(target.altpos)) 44 end 45 46 function M.leap_ts() 47 require('leap').leap { 48 target_windows = { api.nvim_get_current_win() }, 49 targets = get_ts_nodes, 50 action = select_node_range, 51 } 52 end 53 54 return M