From ed7ff848a02d37975dd56c2d67e0fe23e75f68dd Mon Sep 17 00:00:00 2001 From: Shadman Date: Mon, 30 Jun 2025 16:19:43 +0600 Subject: [PATCH] fix(prompt): prompt mark not placed after text edits correctly #34671 --- src/nvim/api/buffer.c | 2 +- src/nvim/edit.c | 1 + src/nvim/eval.c | 4 +- test/functional/legacy/prompt_buffer_spec.lua | 76 +++++++++++++++++++ 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 6f6076c29b..f6431fec33 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -663,7 +663,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // changed range, and move any in the remainder of the buffer. // Do not adjust any cursors. need to use column-aware logic (below) linenr_T adjust = end_row >= start_row ? MAXLNUM : 0; - mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, adjust, (linenr_T)extra, + mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row - 1, adjust, (linenr_T)extra, true, true, kExtmarkNOOP); extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col, diff --git a/src/nvim/edit.c b/src/nvim/edit.c index d27c175ecd..b1d32156c9 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1545,6 +1545,7 @@ static void init_prompt(int cmdchar_todo) ml_replace(curbuf->b_ml.ml_line_count, prompt, true); } else { ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false); + curbuf->b_prompt_start.mark.lnum += 1; } curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; coladvance(curwin, MAXCOL); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 981a1319fc..59421c24f7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8702,6 +8702,7 @@ void prompt_invoke_callback(void) appended_lines_mark(lnum, 1); curwin->w_cursor.lnum = lnum + 1; curwin->w_cursor.col = 0; + curbuf->b_prompt_start.mark.lnum = lnum + 1; if (curbuf->b_prompt_callback.type == kCallbackNone) { xfree(user_input); @@ -8720,8 +8721,7 @@ theend: // clear undo history on submit u_clearallandblockfree(curbuf); - pos_T next_prompt = { .lnum = curbuf->b_ml.ml_line_count, .col = 1, .coladd = 0 }; - RESET_FMARK(&curbuf->b_prompt_start, next_prompt, 0, ((fmarkv_T)INIT_FMARKV)); + curbuf->b_prompt_start.mark.lnum = curbuf->b_ml.ml_line_count; } /// @return true when the interrupt callback was invoked. diff --git a/test/functional/legacy/prompt_buffer_spec.lua b/test/functional/legacy/prompt_buffer_spec.lua index d88aa6858f..176470f248 100644 --- a/test/functional/legacy/prompt_buffer_spec.lua +++ b/test/functional/legacy/prompt_buffer_spec.lua @@ -12,6 +12,7 @@ local poke_eventloop = n.poke_eventloop local api = n.api local eq = t.eq local neq = t.neq +local exec_lua = n.exec_lua describe('prompt buffer', function() local screen @@ -596,4 +597,79 @@ describe('prompt buffer', function() eq('', fn('prompt_getinput', bufnr)) end) end) + + it('programmatic (non-user) edits', function() + api.nvim_set_option_value('buftype', 'prompt', { buf = 0 }) + + -- with nvim_buf_set_lines + exec_lua([[ + local buf = vim.api.nvim_get_current_buf() + vim.fn.prompt_setcallback(buf, function(text) + vim.api.nvim_buf_set_lines(buf, -2, -2, true, vim.split(text, '\n')) + end) + ]]) + feed('iset_lines') + feed('set_lines2') + screen:expect([[ + % set_lines | + set_lines | + % set_lines2 | + set_lines2 | + % ^ | + {1:~ }|*4 + {5:-- INSERT --} | + ]]) + + feed('set_lines3(multi-1)set_lines3(multi-2)') + screen:expect([[ + % set_lines | + set_lines | + % set_lines2 | + set_lines2 | + % set_lines3(multi-1) | + set_lines3(multi-2) | + set_lines3(multi-1) | + set_lines3(multi-2) | + % ^ | + {5:-- INSERT --} | + ]]) + -- with nvim_buf_set_text + source('bwipeout!') + api.nvim_set_option_value('buftype', 'prompt', { buf = 0 }) + exec_lua([[ + local buf = vim.api.nvim_get_current_buf() + vim.fn.prompt_setcallback(buf, function(text) + local lines = vim.split(text, '\n') + if lines[#lines] ~= '' then + table.insert(lines, '') + end + vim.api.nvim_buf_set_text(buf, -1, 0, -1, 0, lines) + end) + ]]) + feed('set_text') + feed('set_text2') + screen:expect([[ + % set_text | + set_text | + % set_text2 | + set_text2 | + % ^ | + {1:~ }|*4 + {5:-- INSERT --} | + ]]) + + feed('set_text3(multi-1)set_text3(multi-2)') + screen:expect([[ + % set_text | + set_text | + % set_text2 | + set_text2 | + % set_text3(multi-1) | + set_text3(multi-2) | + set_text3(multi-1) | + set_text3(multi-2) | + % ^ | + {5:-- INSERT --} | + ]]) + end) end)