mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
fix(prompt): prompt_setprompt does not adjust extmarks, no on_bytes
Problem: prompt_setprompt does not adjust extmarks or trigger on_bytes buffer-updates when fixing the prompt line. Solution: adjust them, trigger on_bytes. Notably, hides extmarks when replacing the entire line (and clearing user input). Otherwise, when just replacing the prompt text, hides extmarks there, but moves those after (in the user input area) to the correct spot.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "nvim/eval/typval_defs.h"
|
||||
#include "nvim/eval/window.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
#include "nvim/extmark.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/memline.h"
|
||||
@@ -790,6 +791,7 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
// If for some odd reason the old prompt is missing,
|
||||
// replace prompt line with new-prompt (discards user-input).
|
||||
ml_replace_buf(buf, prompt_lno, (char *)new_prompt, true, false);
|
||||
extmark_splice_cols(buf, prompt_lno - 1, 0, old_line_len, new_prompt_len, kExtmarkUndo);
|
||||
cursor_col = new_prompt_len;
|
||||
} else {
|
||||
// Replace prev-prompt + user-input with new-prompt + user-input
|
||||
@@ -797,6 +799,8 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
if (ml_replace_buf(buf, prompt_lno, new_line, false, false) != OK) {
|
||||
xfree(new_line);
|
||||
}
|
||||
extmark_splice_cols(buf, prompt_lno - 1, 0, buf->b_prompt_start.mark.col, new_prompt_len,
|
||||
kExtmarkUndo);
|
||||
cursor_col += new_prompt_len - old_prompt_len;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@ local feed = n.feed
|
||||
local clear = n.clear
|
||||
local command = n.command
|
||||
local exec = n.exec
|
||||
local exec_lua = n.exec_lua
|
||||
local api = n.api
|
||||
local fn = n.fn
|
||||
local assert_alive = n.assert_alive
|
||||
|
||||
local function expect(contents)
|
||||
@@ -1562,10 +1564,45 @@ describe('API/extmarks', function()
|
||||
|
||||
it('in prompt buffer', function()
|
||||
feed('dd')
|
||||
local id = set_extmark(ns, marks[1], 0, 0, {})
|
||||
set_extmark(ns, marks[1], 0, 0, {})
|
||||
api.nvim_set_option_value('buftype', 'prompt', {})
|
||||
feed('i<esc>')
|
||||
eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
|
||||
eq({ { marks[1], 0, 2 } }, get_extmarks(ns, 0, -1))
|
||||
fn.prompt_setprompt('', 'foo > ')
|
||||
eq({ { marks[1], 0, 6 } }, get_extmarks(ns, 0, -1))
|
||||
feed('ihello')
|
||||
eq({ { marks[1], 0, 11 } }, get_extmarks(ns, 0, -1))
|
||||
|
||||
local function get_extmark_range(id)
|
||||
local rv = get_extmark_by_id(ns, id, { details = true })
|
||||
return rv[3].invalid and 'invalid' or { rv[1], rv[2], rv[3].end_row, rv[3].end_col }
|
||||
end
|
||||
|
||||
set_extmark(ns, marks[2], 0, 0, { invalidate = true, end_col = 6 })
|
||||
set_extmark(ns, marks[3], 0, 6, { invalidate = true, end_col = 11 })
|
||||
set_extmark(ns, marks[4], 0, 0, { invalidate = true, end_col = 11 })
|
||||
set_extmark(ns, marks[5], 0, 0, { invalidate = true, end_row = 1 })
|
||||
fn.prompt_setprompt('', 'floob > ')
|
||||
eq({ 0, 13 }, get_extmark_range(marks[1]))
|
||||
eq('invalid', get_extmark_range(marks[2])) -- extmark spanning old prompt invalidated
|
||||
eq({ 0, 8, 0, 13 }, get_extmark_range(marks[3]))
|
||||
eq({ 0, 8, 0, 13 }, get_extmark_range(marks[4]))
|
||||
eq({ 0, 8, 1, 0 }, get_extmark_range(marks[5]))
|
||||
|
||||
set_extmark(ns, marks[2], 0, 0, { invalidate = true, end_col = 8 })
|
||||
set_extmark(ns, marks[3], 0, 8, { invalidate = true, end_col = 13 })
|
||||
set_extmark(ns, marks[4], 0, 0, { invalidate = true, end_col = 13 })
|
||||
set_extmark(ns, marks[5], 0, 0, { invalidate = true, end_row = 1 })
|
||||
-- Do this in the same event.
|
||||
exec_lua(function()
|
||||
vim.fn.setpos("':", { 0, 1, 999, 0 })
|
||||
vim.fn.prompt_setprompt('', 'discard > ')
|
||||
end)
|
||||
eq({ 0, 10 }, get_extmark_range(marks[1]))
|
||||
eq('invalid', get_extmark_range(marks[2])) -- all spans on line invalidated
|
||||
eq('invalid', get_extmark_range(marks[3]))
|
||||
eq('invalid', get_extmark_range(marks[4]))
|
||||
eq({ 0, 10, 1, 0 }, get_extmark_range(marks[5]))
|
||||
end)
|
||||
|
||||
it('can get details', function()
|
||||
|
||||
@@ -1618,6 +1618,40 @@ describe('lua: nvim_buf_attach on_bytes', function()
|
||||
{ 'test1', 'bytes', 1, 6, 2, 0, 6, 0, 0, 0, 1, 0, 1 },
|
||||
{ 'test1', 'bytes', 1, 7, 2, 0, 6, 0, 0, 0, 0, 2, 2 },
|
||||
}
|
||||
fn.prompt_setprompt('', 'foo > ')
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 8, 2, 0, 6, 0, 2, 2, 0, 6, 6 },
|
||||
}
|
||||
feed('hello')
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 9, 2, 6, 12, 0, 0, 0, 0, 5, 5 },
|
||||
}
|
||||
fn.prompt_setprompt('', 'uber-foo > ')
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 10, 2, 0, 6, 0, 6, 6, 0, 11, 11 },
|
||||
}
|
||||
eq({ '% ', '% ', 'uber-foo > hello' }, api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
-- Do this in the same event.
|
||||
exec_lua(function()
|
||||
vim.fn.setpos("':", { 0, vim.fn.line('.'), 999, 0 })
|
||||
vim.fn.prompt_setprompt('', 'discard > ')
|
||||
end)
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 11, 2, 0, 6, 0, 16, 16, 0, 10, 10 },
|
||||
}
|
||||
eq({ '% ', '% ', 'discard > ' }, api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
feed('sup<S-CR>dood')
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 12, 2, 10, 16, 0, 0, 0, 0, 3, 3 },
|
||||
{ 'test1', 'bytes', 1, 13, 2, 13, 19, 0, 0, 0, 1, 0, 1 },
|
||||
{ 'test1', 'bytes', 1, 14, 3, 0, 20, 0, 0, 0, 0, 4, 4 },
|
||||
}
|
||||
eq({ '% ', '% ', 'discard > sup', 'dood' }, api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
fn.prompt_setprompt('', 'cool > ')
|
||||
check_events {
|
||||
{ 'test1', 'bytes', 1, 15, 2, 0, 6, 0, 10, 10, 0, 7, 7 },
|
||||
}
|
||||
eq({ '% ', '% ', 'cool > sup', 'dood' }, api.nvim_buf_get_lines(0, 0, -1, true))
|
||||
end)
|
||||
|
||||
local function test_lockmarks(mode)
|
||||
|
||||
Reference in New Issue
Block a user