From f5c20434eaeb3e22cc50864d08878adef39fd233 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Wed, 5 Feb 2025 06:59:25 +0100 Subject: calculate the positions for multiple selections at once --- init.lua | 12 ++++++++---- util.lua | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/init.lua b/init.lua index 99cb3cb..49e0253 100644 --- a/init.lua +++ b/init.lua @@ -177,13 +177,17 @@ local function vis_get_doc_pos(win) } end --- convert a lsp_range to a vis_range +--- Convert a lsp_range to a vis_range +-- @param file the file in which the range lies +-- @param lsp_range the LSP range that should be converted +-- @return the according vis range local function lsp_range_to_vis_range(file, lsp_range) local start = lsp_pos_to_vis_sel(lsp_range.start) - local start_pos = util.vis_sel_to_pos(file, start) - local finish = lsp_pos_to_vis_sel(lsp_range['end']) - local finish_pos = util.vis_sel_to_pos(file, finish) + + local positions = util.vis_sorted_selections_to_pos(file, {start, finish}) + local start_pos = positions[1] + local finish_pos = positions[2] return {start = start_pos, finish = finish_pos} end diff --git a/util.lua b/util.lua index 93c7b50..076882d 100644 --- a/util.lua +++ b/util.lua @@ -211,24 +211,51 @@ local function get_selection(win) return {line = win.selection.line, col = win.selection.col} end ---- Get the 0-based byte offset from a selection. --- @param sel the vis_selection to convert to a position --- @return the 0-based position of the selection -function util.vis_sel_to_pos(file, sel) +--- Calculate the 0-based byte offsets from multiple sorted selections +-- @param file the file to calculate the positions in +-- @param sorted_selections a table of sorted vis_selections +-- @return a table of positions +function util.vis_sorted_selections_to_pos(file, sorted_selections) + local positions = {} if file.pos_by_linecol then - return file:pos_by_linecol(sel.line, sel.col) + for _, sel in ipairs(sorted_selections) do + table.insert(positions, file:pos_by_linecol(sel.line, sel.col)) + end + return positions end local line_count = 0 local pos = 0 + local sel_i = 1 + local sel = sorted_selections[sel_i] for line in file:lines_iterator() do line_count = line_count + 1 - if line_count == sel.line then - return pos + (sel.col - 1) + while line_count == sel.line do + table.insert(positions, pos + (sel.col - 1)) + sel_i = sel_i + 1 + -- no more selections to convert + if sel_i > #sorted_selections then + break + end + sel = sorted_selections[sel_i] end + pos = pos + #line + 1 end - return 0 + return positions +end + +local function vis_pos_before(p1, p2) + return p1.line < p2.line or (p1.line == p2.line and p1.col < p2.col) +end + +--- Calculate the 0-based byte offsets from multiple selections +-- @param file the file to calculate the positions in +-- @param selections a table of selections +-- @return a table of positions +function util.vis_selections_to_pos(file, selections) + table.sort(selections, vis_pos_before) + return util.vis_sorted_selections_to_pos(file, selections) end --- Get the line and column from a 0-based byte offset -- cgit v1.2.3