fix(prompt): handle multi-element lists in prompt_appendbuf #39550

Problem:
When using prompt_appendbuf with multi-element list,
the first item is concated and rest replace the prompt instead of
inserting the lines before the prompt.

Solution:
Concat first element with replace_buf and insert the rest of the list
with set_buffer_lines.

Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
(cherry picked from commit a977e1077b)
This commit is contained in:
Tomas Slusny
2026-05-12 18:00:04 +02:00
committed by github-actions[bot]
parent ce26c51c8d
commit 42f6c1c443
2 changed files with 69 additions and 1 deletions

View File

@@ -291,6 +291,8 @@ void f_prompt_appendbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
linenr_T lnum = MAX(0, buf->b_prompt_start.mark.lnum - 1);
typval_T *lines = &argvars[1];
bool did_concat = false;
if (!buf->b_prompt_append_new_line) {
// Since we are not creating a new line we need to append input to current line
const char *text = (lnum > 0) ? (const char *)ml_get_buf(buf, lnum) : "";
@@ -303,6 +305,7 @@ void f_prompt_appendbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_clear(&li->li_tv);
li->li_tv.v_type = VAR_STRING;
li->li_tv.vval.v_string = new_str;
did_concat = true;
}
} else if (lines->v_type == VAR_STRING) {
const char *str = tv_get_string(lines);
@@ -314,7 +317,20 @@ void f_prompt_appendbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (did_emsg == did_emsg_before) {
set_buffer_lines(buf, lnum, buf->b_prompt_append_new_line, lines, rettv);
if (did_concat && tv_list_len(lines->vval.v_list) > 1) {
// Multi-element list with concat: first element (already concatenated)
// replaces the line at lnum, remaining elements are inserted after.
list_T *l = lines->vval.v_list;
listitem_T *li = tv_list_first(l);
set_buffer_lines(buf, lnum, false, &li->li_tv, rettv);
if (rettv->vval.v_number == 0) {
tv_list_item_remove(l, li);
set_buffer_lines(buf, lnum, true, lines, rettv);
}
} else {
set_buffer_lines(buf, lnum, buf->b_prompt_append_new_line, lines, rettv);
}
}
if (rettv->vval.v_number == 0) {

View File

@@ -1073,4 +1073,56 @@ describe('prompt buffer', function()
fn('prompt_setprompt', unloaded_buf, 'hello unloaded! > ')
eq('hello unloaded! > ', fn('prompt_getprompt', unloaded_buf))
end)
it('prompt_appendbuf with multi-element list and singleline prompt', function()
command('new')
local buf = api.nvim_get_current_buf()
api.nvim_set_option_value('buftype', 'prompt', { buf = buf })
fn('prompt_setprompt', buf, 'cmd: ')
-- Single element list: appends before prompt
fn('prompt_appendbuf', buf, { 'line1' })
eq({ 'line1', 'cmd: ' }, api.nvim_buf_get_lines(buf, 0, -1, false))
-- Multi-element list: first element appended, rest inserted as new lines before prompt
fn('prompt_appendbuf', buf, { '-append', 'line2' })
eq({ 'line1-append', 'line2', 'cmd: ' }, api.nvim_buf_get_lines(buf, 0, -1, false))
-- Multi-element list after multi-element list
fn('prompt_appendbuf', buf, { '', 'line3', 'line4', 'line5', 'line6' })
eq(
{ 'line1-append', 'line2', 'line3', 'line4', 'line5', 'line6', 'cmd: ' },
api.nvim_buf_get_lines(buf, 0, -1, false)
)
end)
it('prompt_appendbuf with multi-element list and multiline prompt', function()
command('new')
local buf = api.nvim_get_current_buf()
api.nvim_set_option_value('buftype', 'prompt', { buf = buf })
fn('prompt_setprompt', buf, 'cmd: ')
source('startinsert')
-- User types multiline input in the prompt
feed('input1<s-cr>input2')
eq({ 'cmd: input1', 'input2' }, api.nvim_buf_get_lines(buf, 0, -1, false))
-- Single element list: appends before prompt
fn('prompt_appendbuf', buf, { 'line1' })
eq({ 'line1', 'cmd: input1', 'input2' }, api.nvim_buf_get_lines(buf, 0, -1, false))
-- Multi-element list: first element appended, rest inserted as new lines before prompt
fn('prompt_appendbuf', buf, { '-append', 'line2' })
eq(
{ 'line1-append', 'line2', 'cmd: input1', 'input2' },
api.nvim_buf_get_lines(buf, 0, -1, false)
)
-- Multi-element list after multi-element list
fn('prompt_appendbuf', buf, { '', 'line3', 'line4', 'line5', 'line6' })
eq(
{ 'line1-append', 'line2', 'line3', 'line4', 'line5', 'line6', 'cmd: input1', 'input2' },
api.nvim_buf_get_lines(buf, 0, -1, false)
)
end)
end)