Skip to content

Commit cfbf58b

Browse files
committed
fix(pairs): make close and closeopen work with inline virtual text
Details: - Setting `virtualedit=all` allows cursor to navigate inside inline virtual text. This can break "close" and "closeopen" actions when there is a closing character to the right in "real" text, but there is some "ghost" text in between (like from completion engine). Resolve #2166
1 parent 314befe commit cfbf58b

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

lua/mini/pairs.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,11 @@ H.get_open_char = function(x) return vim.fn.strcharpart(x, 0, 1) end
614614
H.get_close_char = function(x) return vim.fn.strcharpart(x, 1, 1) end
615615

616616
H.get_arrow_key = function(key, ensure_no_wildmenu)
617-
if vim.fn.mode() == 'i' then return key == 'right' and H.keys.right_undo or H.keys.left_undo end
617+
if vim.fn.mode() == 'i' then
618+
-- Take into account that `virtualedit=all` can go into inline virtual text
619+
H.with_temp_option('virtualedit', 'none')
620+
return key == 'right' and H.keys.right_undo or H.keys.left_undo
621+
end
618622
local prefix = ''
619623
-- In Command-line mode <Left> / <Right> act like <C-p> / <C-n> if wildmenu
620624
-- is shown. Make sure that arrow key moves cursor.

tests/test_pairs.lua

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,31 @@ T['Close action']['works with visible wildmenu'] = function()
794794
validate_cmdline('lua print(1 + AAA)', 19)
795795
end
796796

797+
T['Close action']['works with inline virtual text'] = function()
798+
if child.fn.has('nvim-0.10') == 0 then MiniTest.skip('Inline virtual text is present in Neovim>=0.10') end
799+
800+
set_lines({ '()' })
801+
local ns_id = child.api.nvim_create_namespace('Test')
802+
child.api.nvim_buf_set_extmark(0, ns_id, 0, 1, { virt_text = { { 'Virt', 'String' } }, virt_text_pos = 'inline' })
803+
804+
local validate = function(virtualedit)
805+
child.o.virtualedit = virtualedit
806+
set_cursor(1, 0)
807+
808+
type_keys('a', ')')
809+
eq(child.fn.getcurpos(), { 0, 1, 3, 0, 7 })
810+
-- Should have no side effects
811+
eq(child.o.virtualedit, virtualedit)
812+
813+
type_keys('<Esc>')
814+
end
815+
816+
validate('all')
817+
validate('none')
818+
validate('block')
819+
validate('onemore')
820+
end
821+
797822
local validate_slash_close = function(key, pair)
798823
set_lines({ pair })
799824
set_cursor(1, 1)
@@ -908,6 +933,31 @@ T['Closeopen action']['works with visible wildmenu'] = function()
908933
validate_cmdline('lua print`1 + AAA`', 19)
909934
end
910935

936+
T['Closeopen action']['works with inline virtual text'] = function()
937+
if child.fn.has('nvim-0.10') == 0 then MiniTest.skip('Inline virtual text is present in Neovim>=0.10') end
938+
939+
set_lines({ '""' })
940+
local ns_id = child.api.nvim_create_namespace('Test')
941+
child.api.nvim_buf_set_extmark(0, ns_id, 0, 1, { virt_text = { { 'Virt', 'String' } }, virt_text_pos = 'inline' })
942+
943+
local validate = function(virtualedit)
944+
child.o.virtualedit = virtualedit
945+
set_cursor(1, 0)
946+
947+
type_keys('a', '"')
948+
eq(child.fn.getcurpos(), { 0, 1, 3, 0, 7 })
949+
-- Should have no side effects
950+
eq(child.o.virtualedit, virtualedit)
951+
952+
type_keys('<Esc>')
953+
end
954+
955+
validate('all')
956+
validate('none')
957+
validate('block')
958+
validate('onemore')
959+
end
960+
911961
T['Closeopen action']['respects neighbor pattern'] = function()
912962
validate_slash('"')
913963
validate_slash("'")

0 commit comments

Comments
 (0)