@@ -53,10 +53,45 @@ local T = new_set({
5353 },
5454})
5555
56- -- Helper to enter insert mode and set cursor
57- local function set_cursor_insert (row , col )
58- child .cmd (" startinsert!" )
59- child .api .nvim_win_set_cursor (0 , { row , col })
56+ --- Helper to set buffer with cursor marker and enter insert mode
57+ --- Accepts string "text|" or table {"line1", "line|2"} where | marks cursor position
58+ --- @param text string | table
59+ local function set_buffer_text (text )
60+ if type (text ) == " string" then
61+ local cursor_pos = text :find (" |" , 1 , true )
62+ if not cursor_pos then
63+ error (" No cursor marker '|' found in text" )
64+ end
65+
66+ local line = text :sub (1 , cursor_pos - 1 ) .. text :sub (cursor_pos + 1 )
67+ child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { line })
68+ child .cmd (" startinsert!" )
69+ child .api .nvim_win_set_cursor (0 , { 1 , cursor_pos - 1 })
70+ elseif type (text ) == " table" then
71+ local cursor_row , cursor_col
72+ local lines = {}
73+
74+ for i , line in ipairs (text ) do
75+ local pos = line :find (" |" , 1 , true )
76+ if pos then
77+ cursor_row = i
78+ cursor_col = pos - 1
79+ table.insert (lines , line :sub (1 , pos - 1 ) .. line :sub (pos + 1 ))
80+ else
81+ table.insert (lines , line )
82+ end
83+ end
84+
85+ if not cursor_row then
86+ error (" No cursor marker '|' found in text" )
87+ end
88+
89+ child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , lines )
90+ child .cmd (" startinsert!" )
91+ child .api .nvim_win_set_cursor (0 , { cursor_row , cursor_col })
92+ else
93+ error (" Expected string or table" )
94+ end
6095end
6196
6297T [" accept_word()" ] = new_set ()
@@ -66,9 +101,7 @@ T["accept_word()"]["works with simple word completion"] = function()
66101 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
67102 end
68103
69- -- Set up: buffer has "-- Create a fib" and cursor is at end
70- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " -- Create a fib" })
71- set_cursor_insert (1 , 15 ) -- After "-- Create a fib"
104+ set_buffer_text (" -- Create a fib|" )
72105
73106 -- Set up the mock completion
74107 child .lua ([[
@@ -94,8 +127,7 @@ T["accept_word()"]["works with punctuation in completion"] = function()
94127 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
95128 end
96129
97- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " local x" })
98- set_cursor_insert (1 , 7 )
130+ set_buffer_text (" local x|" )
99131
100132 child .lua ([[
101133 _G.mock_completion_item = {
@@ -118,8 +150,7 @@ T["accept_word()"]["works with newline in word"] = function()
118150 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
119151 end
120152
121- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " function test()" })
122- set_cursor_insert (1 , 15 )
153+ set_buffer_text (" function test()|" )
123154
124155 child .lua ([[
125156 _G.mock_completion_item = {
@@ -143,9 +174,7 @@ T["accept_word()"]["ignores stale completion (cursor before range end)"] = funct
143174 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
144175 end
145176
146- -- Make a longer buffer so cursor doesn't get clamped
147- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " test some long text here" })
148- set_cursor_insert (1 , 10 ) -- Cursor at position 10
177+ set_buffer_text (" test some |long text here" )
149178
150179 child .lua ([[
151180 _G.mock_completion_item = {
@@ -168,8 +197,7 @@ T["accept_word()"]["handles empty buffer"] = function()
168197 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
169198 end
170199
171- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " " })
172- set_cursor_insert (1 , 0 )
200+ set_buffer_text (" |" )
173201
174202 child .lua ([[
175203 _G.mock_completion_item = {
@@ -187,13 +215,59 @@ T["accept_word()"]["handles empty buffer"] = function()
187215 h .eq (child .api .nvim_win_get_cursor (0 ), { 1 , 6 })
188216end
189217
218+ T [" accept_word()" ][" handles auto-pairs with cursor inside brackets" ] = function ()
219+ if vim .fn .has (" nvim-0.12" ) == 0 then
220+ MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
221+ end
222+
223+ set_buffer_text (" local function hello_world(|)" )
224+
225+ child .lua ([[
226+ _G.mock_completion_item = {
227+ insert_text = "local function hello_world(arg)",
228+ range = {
229+ start = { row = 0, col = 0 },
230+ end_ = { row = 0, col = 27 }
231+ }
232+ }
233+
234+ _G.completion.accept_word()
235+ ]] )
236+
237+ -- Should insert "arg" without being confused by the trailing ")"
238+ h .eq (child .api .nvim_buf_get_lines (0 , 0 , - 1 , true ), { " local function hello_world(arg)" })
239+ h .eq (child .api .nvim_win_get_cursor (0 ), { 1 , 30 })
240+ end
241+
242+ T [" accept_word()" ][" handles auto-pairs with cursor inside quotes" ] = function ()
243+ if vim .fn .has (" nvim-0.12" ) == 0 then
244+ MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
245+ end
246+
247+ set_buffer_text (' print("|")' ) -- print("|")
248+
249+ child .lua ([[
250+ _G.mock_completion_item = {
251+ insert_text = "print(\"hello world\")",
252+ range = {
253+ start = { row = 0, col = 0 },
254+ end_ = { row = 0, col = 7 }
255+ }
256+ }
257+
258+ _G.completion.accept_word()
259+ ]] )
260+
261+ h .eq (child .api .nvim_buf_get_lines (0 , 0 , - 1 , true ), { ' print("hello ")' })
262+ h .eq (child .api .nvim_win_get_cursor (0 ), { 1 , 13 })
263+ end
264+
190265T [" accept_word()" ][" handles completion that doesn't start with existing text" ] = function ()
191266 if vim .fn .has (" nvim-0.12" ) == 0 then
192267 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
193268 end
194269
195- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " foo bar" })
196- set_cursor_insert (1 , 7 )
270+ set_buffer_text (" foo bar|" )
197271
198272 child .lua ([[
199273 _G.mock_completion_item = {
@@ -218,8 +292,7 @@ T["accept_line()"]["works with single line completion"] = function()
218292 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
219293 end
220294
221- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " -- Comment" })
222- set_cursor_insert (1 , 10 )
295+ set_buffer_text (" -- Comment|" )
223296
224297 child .lua ([[
225298 _G.mock_completion_item = {
@@ -242,8 +315,7 @@ T["accept_line()"]["works with multi-line completion"] = function()
242315 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
243316 end
244317
245- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " function test()" })
246- set_cursor_insert (1 , 15 )
318+ set_buffer_text (" function test()|" )
247319
248320 child .lua ([[
249321 _G.mock_completion_item = {
@@ -257,7 +329,6 @@ T["accept_line()"]["works with multi-line completion"] = function()
257329 _G.completion.accept_line()
258330 ]] )
259331
260- -- Should insert newline + next line content + newline (avoiding the double-press issue)
261332 h .eq (child .api .nvim_buf_get_lines (0 , 0 , - 1 , true ), { " function test()" , " return 42" , " " })
262333 h .eq (child .api .nvim_win_get_cursor (0 ), { 3 , 0 })
263334end
@@ -267,9 +338,7 @@ T["accept_line()"]["ignores stale completion"] = function()
267338 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
268339 end
269340
270- -- Make a longer buffer so cursor doesn't get clamped
271- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " test some long text here" })
272- set_cursor_insert (1 , 10 )
341+ set_buffer_text (" test some |long text here" )
273342
274343 child .lua ([[
275344 _G.mock_completion_item = {
@@ -292,8 +361,7 @@ T["accept_line()"]["handles completion without newline"] = function()
292361 MiniTest .skip (" Requires Neovim 0.12+ for vim.lsp.inline_completion" )
293362 end
294363
295- child .api .nvim_buf_set_lines (0 , 0 , - 1 , true , { " hello" })
296- set_cursor_insert (1 , 5 )
364+ set_buffer_text (" hello|" )
297365
298366 child .lua ([[
299367 _G.mock_completion_item = {
0 commit comments