From 019b2050e13583f8a26dc5dc1c7e20ca07bb51e5 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Tue, 22 Apr 2025 21:35:10 +0200 Subject: [PATCH] fix(snippet): use call cursor() for visual range Problem: Change applied in d3e495ce uses a byte-offset where a virtual column is expected. Solution: Set the cursor directly through a mapping, while making sure the commands are ordered correctly by adding them to the type-ahead buffer. --- runtime/lua/vim/snippet.lua | 26 ++++++++++---------------- test/functional/lua/snippet_spec.lua | 6 ++++++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index e84a9e376a..0d7dd6a034 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -278,15 +278,6 @@ local function select_tabstop(tabstop) vim.api.nvim_feedkeys(keys, 'n', true) end - --- NOTE: We don't use `vim.api.nvim_win_set_cursor` here because it causes the cursor to end - --- at the end of the selection instead of the start. - --- - --- @param row integer - --- @param col integer - local function move_cursor_to(row, col) - feedkeys(string.format('%sG%s|', row, col)) - end - local range = tabstop:get_range() local mode = vim.fn.mode() @@ -311,13 +302,16 @@ local function select_tabstop(tabstop) end else -- Else, select the tabstop's text. - if mode ~= 'n' then - feedkeys('') - end - move_cursor_to(range[1] + 1, range[2] + 1) - feedkeys('v') - move_cursor_to(range[3] + 1, range[4]) - feedkeys('o_') + -- Need this exact order so cannot mix regular API calls with feedkeys, which + -- are not executed immediately. Use to set the cursor position. + local keys = { + mode ~= 'n' and '' or '', + ('call cursor(%s,%s)'):format(range[1] + 1, range[2] + 1), + 'v', + ('call cursor(%s,%s)'):format(range[3] + 1, range[4]), + 'o_', + } + feedkeys(table.concat(keys)) end end diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua index 724437f0b2..33f2ef6222 100644 --- a/test/functional/lua/snippet_spec.lua +++ b/test/functional/lua/snippet_spec.lua @@ -307,4 +307,10 @@ describe('vim.snippet', function() ]] ) end) + + it('correct visual selection with multi-byte text', function() + test_expand_success({ 'function(${1:var})' }, { '口口function(var)' }, nil, '口口') + feed('foo') + eq({ '口口function(foo)' }, buf_lines(0)) + end) end)