mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-18 11:20:07 -04:00
Incremental selection: fix skipping some nodes
The range from ts nodes are a little different than neovim's nodes. They start at 0 and the end is exclusive. For example, a nvim range (1, 3, 2, 4) is the equivalent to the ts range (0, 2, 1, 4). Since we may hit parent nodes that have the same range as its child, we skip those till we find one that actually changes the selection (since this is the relevant part for the user). Fixes https://github.com/nvim-treesitter/nvim-treesitter/issues/232
This commit is contained in:
parent
a5360d02e4
commit
9c456edb3a
1 changed files with 28 additions and 25 deletions
|
|
@ -16,25 +16,16 @@ function M.init_selection()
|
||||||
ts_utils.update_selection(buf, node)
|
ts_utils.update_selection(buf, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- moves 0-based node position by one character
|
--- Get a ts compatible range of the current visual selection.
|
||||||
local function inclusive_pos_to_exclusive(row, col)
|
--
|
||||||
local line = vim.fn.getline(row + 1)
|
-- The range of ts nodes start with 0 and the ending range is exclusive.
|
||||||
|
|
||||||
-- move by one character changes row?
|
|
||||||
if #line == col + 1 then
|
|
||||||
return row + 1, 0
|
|
||||||
else
|
|
||||||
return row, col + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function visual_selection_range()
|
local function visual_selection_range()
|
||||||
local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<"))
|
local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<"))
|
||||||
local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>"))
|
local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>"))
|
||||||
if csrow < cerow or (csrow == cerow and cscol <= cecol) then
|
if csrow < cerow or (csrow == cerow and cscol <= cecol) then
|
||||||
return csrow-1, cscol-1, inclusive_pos_to_exclusive(cerow-1, cecol-1)
|
return csrow - 1, cscol - 1, cerow - 1, cecol
|
||||||
else
|
else
|
||||||
return cerow-1, cecol-1, inclusive_pos_to_exclusive(csrow-1, cscol-1)
|
return cerow - 1, cecol - 1, csrow - 1, cscol
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -49,9 +40,9 @@ local function select_incremental(get_parent)
|
||||||
local buf = api.nvim_get_current_buf()
|
local buf = api.nvim_get_current_buf()
|
||||||
local nodes = selections[buf]
|
local nodes = selections[buf]
|
||||||
|
|
||||||
-- initialize incremental selection with current selection
|
local csrow, cscol, cerow, cecol = visual_selection_range()
|
||||||
|
-- Initialize incremental selection with current selection
|
||||||
if not nodes or #nodes == 0 or not range_matches(nodes[#nodes]) then
|
if not nodes or #nodes == 0 or not range_matches(nodes[#nodes]) then
|
||||||
local csrow, cscol, cerow, cecol = visual_selection_range()
|
|
||||||
local root = parsers.get_parser().tree:root()
|
local root = parsers.get_parser().tree:root()
|
||||||
local node = root:named_descendant_for_range(csrow, cscol, cerow, cecol)
|
local node = root:named_descendant_for_range(csrow, cscol, cerow, cecol)
|
||||||
ts_utils.update_selection(buf, node)
|
ts_utils.update_selection(buf, node)
|
||||||
|
|
@ -63,15 +54,27 @@ local function select_incremental(get_parent)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local node = get_parent(nodes[#nodes])
|
-- Find a node that changes the current selection.
|
||||||
if not node then return end
|
local node = nodes[#nodes]
|
||||||
|
while true do
|
||||||
table.insert(selections[buf], node)
|
node = get_parent(node)
|
||||||
if node ~= nodes[#nodes] then
|
if not node then return end
|
||||||
table.insert(nodes, node)
|
local srow, scol, erow, ecol = node:range()
|
||||||
|
local same_range = (
|
||||||
|
srow == csrow
|
||||||
|
and scol == cscol
|
||||||
|
and erow == cerow
|
||||||
|
and ecol == cecol
|
||||||
|
)
|
||||||
|
if not same_range then
|
||||||
|
table.insert(selections[buf], node)
|
||||||
|
if node ~= nodes[#nodes] then
|
||||||
|
table.insert(nodes, node)
|
||||||
|
end
|
||||||
|
ts_utils.update_selection(buf, node)
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ts_utils.update_selection(buf, node)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue