From bee42bc87a249bddcd7d13a7a7c257f0c7f78072 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Tue, 1 Jul 2025 23:06:56 -0500 Subject: fix conversion of last byte selections If a language server sends a selection including the last byte, the line number will be one greater than the actual number of lines. Those selections are not converted by our algorithm iterating all lines. Add a special case to still convert them. Fixes: f5c2043 --- util.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/util.lua b/util.lua index 2b090b2..e36c23f 100644 --- a/util.lua +++ b/util.lua @@ -242,6 +242,14 @@ function util.vis_sorted_selections_to_pos(file, sorted_selections) pos = pos + #line + 1 end + + -- Some language servers (pylsp) sends a range including the first character after the last line. + -- e.g. [{"line":1, "col":1}, {"line":#lines+1, "col":1}] + -- But this selection can not be handled by iterating all lines. + -- Add a special case for the selection of the first char after the last line. + if sel.line == line_count + 1 and sel.col == 1 then + table.insert(positions, pos) + end return positions end -- cgit v1.2.3 From 05f2d8e253c3523e63ea08018f8bb9d23f6659b5 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Wed, 2 Jul 2025 23:06:50 -0400 Subject: add special case for the gopls empty file range --- util.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/util.lua b/util.lua index e36c23f..3d10e95 100644 --- a/util.lua +++ b/util.lua @@ -243,12 +243,16 @@ function util.vis_sorted_selections_to_pos(file, sorted_selections) pos = pos + #line + 1 end - -- Some language servers (pylsp) sends a range including the first character after the last line. + -- Some language servers (pylsp) send ranges including the first character after the last line. -- e.g. [{"line":1, "col":1}, {"line":#lines+1, "col":1}] -- But this selection can not be handled by iterating all lines. - -- Add a special case for the selection of the first char after the last line. - if sel.line == line_count + 1 and sel.col == 1 then + -- Special case ranges ensing after the last line. + -- Additionaly the start and end can overlap. + -- Gopls sends the range [{"line":1, "col":1}, {"line":1, "col":1}] when editing an empty file. + while sel and sel.line == line_count + 1 and sel.col == 1 do table.insert(positions, pos) + sel_i = sel_i + 1 + sel = sorted_selections[sel_i] end return positions end -- cgit v1.2.3 From 6a4755ec3ee4c8214d76bf8b0461534490df47dd Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sat, 12 Jul 2025 21:00:14 -0400 Subject: add autoconfirm_edits configuration option Some language servers replace the whole file content on an edit, thus producing potentially really big diffs not suitable for review and user confirmation. So some users may just accept the changes proposed from the language server. --- README.md | 1 + init.lua | 34 ++++++++++++++++++---------------- lspc.lua | 2 ++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 6825aef..8475982 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Available options are: * `autostart = true` - try to start a language server in WIN_OPEN * `menu_cmd = 'fzf' or 'vis-menu'` - program to prompt for user choices * `confirm_cmd = 'vis-menu'` - program to prompt for user confirmation +* `autoconfirm_edits = false` - apply workspaceEdits without user confirmation * `ls_map` - a table mapping `vis` syntax names to language server configurations * `highlight_diagnostics = 'line'` - highlight the `range` or `line`number of available diagnostics * `diagnostic_style_id = nil` - vis style id used to highlight diagnostics, win.STYLE_LEXER_MAX is used by default diff --git a/init.lua b/init.lua index 469736b..29a4ed2 100644 --- a/init.lua +++ b/init.lua @@ -487,27 +487,29 @@ local function vis_apply_workspaceEdit(_, _, workspaceEdit) end end - -- generate change summary - local summary = '--- workspace edit summary ---\n' - for uri, edits in pairs(file_edits) do - local path = uri_to_path(uri) - summary = summary .. path .. ':\n' - for i, edit in ipairs(edits) do - summary = summary .. '\t' .. i .. '.: ' .. lspc.json.encode(edit) .. '\n' + if not lspc.autoconfirm_edits then + -- generate change summary + local summary = '--- workspace edit summary ---\n' + for uri, edits in pairs(file_edits) do + local path = uri_to_path(uri) + summary = summary .. path .. ':\n' + for i, edit in ipairs(edits) do + summary = summary .. '\t' .. i .. '.: ' .. lspc.json.encode(edit) .. '\n' + end end - end - lspc_show_message(summary) - vis:redraw() + lspc_show_message(summary) + vis:redraw() - -- get user confirmation - local confirmation = lspc_confirm('apply changes:') + -- get user confirmation + local confirmation = lspc_confirm('apply changes:') - -- close summary window - lspc_close_message_win() + -- close summary window + lspc_close_message_win() - if not confirmation then - return + if not confirmation then + return + end end -- apply changes to open files diff --git a/lspc.lua b/lspc.lua index d8348a4..f34ba4d 100644 --- a/lspc.lua +++ b/lspc.lua @@ -23,6 +23,8 @@ local lspc = { menu_cmd = 'vis-menu -l 10', -- program used to ask the user for confirmation confirm_cmd = 'vis-menu', + -- apply workspaceEdits without confirmation + autoconfirm_edits = false, -- should diagnostics be highlighted if available highlight_diagnostics = 'line', -- cgit v1.2.3