commit ed7ff848a02d37975dd56c2d67e0fe23e75f68dd
parent f7c939fa7af9744bcb6d79100a7e126f7e9c8f5c
Author: Shadman <shadmansaleh3@gmail.com>
Date: Mon, 30 Jun 2025 16:19:43 +0600
fix(prompt): prompt mark not placed after text edits correctly #34671
Diffstat:
4 files changed, 80 insertions(+), 3 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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<cr>')
+ feed('set_lines2<cr>')
+ screen:expect([[
+ % set_lines |
+ set_lines |
+ % set_lines2 |
+ set_lines2 |
+ % ^ |
+ {1:~ }|*4
+ {5:-- INSERT --} |
+ ]])
+
+ feed('set_lines3(multi-1)<s-cr>set_lines3(multi-2)<cr>')
+ 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<cr>')
+ feed('set_text2<cr>')
+ screen:expect([[
+ % set_text |
+ set_text |
+ % set_text2 |
+ set_text2 |
+ % ^ |
+ {1:~ }|*4
+ {5:-- INSERT --} |
+ ]])
+
+ feed('set_text3(multi-1)<s-cr>set_text3(multi-2)<cr>')
+ 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)