mirror of
https://github.com/neovim/neovim.git
synced 2026-07-11 03:49:41 +00:00
fix(cmdwin): handle control characters properly #40488
- Replace newlines in the current cmdline with NULs when opening cmdwin, and do the reverse when putting a cmdwin line back into the cmdline. - Escape control characters with Ctrl-V when feeding cmdline.
This commit is contained in:
@@ -81,9 +81,10 @@ function M.open(type, init_line, init_col)
|
||||
vim.wo[win][0].statuscolumn = '%#NonText#' .. type
|
||||
|
||||
local filled = fill_history(buf, type)
|
||||
init_line = init_line and init_line:gsub('\n', '\0') or ''
|
||||
|
||||
-- Append the in-flight cmdline as the last line (or only line if history is empty).
|
||||
vim.api.nvim_buf_set_lines(buf, filled and -1 or 0, -1, false, { init_line or '' })
|
||||
vim.api.nvim_buf_set_lines(buf, filled and -1 or 0, -1, false, { init_line })
|
||||
local last = vim.api.nvim_buf_line_count(buf)
|
||||
vim.api.nvim_win_set_cursor(win, { last, math.max(0, (init_col or 1) - 1) })
|
||||
|
||||
@@ -92,6 +93,11 @@ function M.open(type, init_line, init_col)
|
||||
vim.bo[buf].filetype = 'vim'
|
||||
end
|
||||
|
||||
if vim.o.wildchar == ('\t'):byte() then
|
||||
vim.keymap.set('i', '<Tab>', '<C-X><C-V>', { buf = buf })
|
||||
vim.keymap.set('n', '<Tab>', 'a<C-X><C-V>', { buf = buf })
|
||||
end
|
||||
|
||||
vim.api.nvim__cmdwin_set(type, buf) -- Update the C-side globals.
|
||||
|
||||
state = {
|
||||
@@ -155,6 +161,7 @@ function M.confirm()
|
||||
return
|
||||
end
|
||||
local line, type = _close()
|
||||
line = line:gsub('%z', '\n'):gsub('(%c)', '\022%1') -- Escape control characters.
|
||||
vim.api.nvim_feedkeys(type .. line .. vim.keycode('<CR>'), 'nt', false)
|
||||
end
|
||||
|
||||
@@ -164,6 +171,7 @@ function M.cancel()
|
||||
return
|
||||
end
|
||||
local line, type = _close()
|
||||
line = line:gsub('%z', '\n'):gsub('(%c)', '\022%1') -- Escape control characters.
|
||||
vim.api.nvim_feedkeys(type .. line, 'nt', false)
|
||||
end
|
||||
|
||||
|
||||
@@ -81,13 +81,6 @@ describe('cmdwin', function()
|
||||
eq(2, fn.histnr('cmd')) -- History unchanged (the in-flight cmdline was not added).
|
||||
end)
|
||||
|
||||
it('history entry with literal newline char', function()
|
||||
fn.histadd(':', 'echo \n x')
|
||||
feed('q:')
|
||||
eq(':', fn.getcmdwintype())
|
||||
eq('echo \0 x', api.nvim_buf_get_lines(0, 0, 1, false)[1])
|
||||
end)
|
||||
|
||||
it('<C-C> in normal mode cancels without executing', function()
|
||||
feed('q:')
|
||||
feed('ilet g:executed = 1<Esc>')
|
||||
@@ -102,6 +95,28 @@ describe('cmdwin', function()
|
||||
eq(':', fn.getcmdtype())
|
||||
end)
|
||||
|
||||
it('history entry or current cmdline with control chars', function()
|
||||
local firstbuf = api.nvim_get_current_buf()
|
||||
local cmdline = 'normal! \023\022ifoo\nbar\027' -- Ctrl-W Ctrl-V ifoo\nbar Esc
|
||||
local bufline = cmdline:gsub('\n', '\0')
|
||||
fn.histadd(':', cmdline)
|
||||
feed('q:')
|
||||
eq(':', fn.getcmdwintype())
|
||||
eq({ bufline, '' }, api.nvim_buf_get_lines(0, 0, -1, false))
|
||||
api.nvim_win_set_cursor(0, { 1, 0 })
|
||||
feed('<C-C>')
|
||||
eq(cmdline, fn.getcmdline())
|
||||
eq(':', fn.getcmdtype())
|
||||
eq({ firstbuf }, fn.tabpagebuflist())
|
||||
feed('<C-F>')
|
||||
n.poke_eventloop()
|
||||
eq(':', fn.getcmdwintype())
|
||||
eq({ bufline, bufline }, api.nvim_buf_get_lines(0, 0, -1, false))
|
||||
feed('<CR>')
|
||||
eq({ firstbuf, firstbuf }, fn.tabpagebuflist())
|
||||
eq({ 'foo', 'bar' }, api.nvim_buf_get_lines(0, 0, -1, false))
|
||||
end)
|
||||
|
||||
it('async API calls work while cmdwin is open #40312', function()
|
||||
feed('q:')
|
||||
eq(':', fn.getcmdwintype())
|
||||
|
||||
Reference in New Issue
Block a user