mirror of
https://github.com/neovim/neovim.git
synced 2026-07-09 19:09:39 +00:00
fix(cmdwin): handle split/tabpage
Problem: - If cmdwin window is split, ENTER in one does not close the others. - If cmdwin is put into a different tabpage via <c-w>T, it stops working (ENTER does not execute the cmd). Solution: - Close the buffer instead of the window. - In the WinClosed handler, skip `M._cleanup()` unless this is the last cmdwin window.
This commit is contained in:
@@ -1205,9 +1205,8 @@ There are two ways to open the command-line window:
|
||||
When the window opens it is filled with the command-line history. The editor
|
||||
opens in Normal mode. The last line contains the command as typed so far. The
|
||||
|cmdwin-char| is shown in 'statuscolumn', indicating the type of command-line.
|
||||
|
||||
The window height is decided by 'cmdwinheight' (if there is room). The window
|
||||
is full width and is positioned just above the command-line.
|
||||
The window is full width, positioned just above the command-line; its height
|
||||
is decided by 'cmdwinheight' (if there is room).
|
||||
|
||||
Window and tabpage commands work as usual while cmdwin is open: you can
|
||||
navigate, resize, close and open windows/tabpages. The mouse works as in any
|
||||
@@ -1236,8 +1235,9 @@ CLOSE
|
||||
|
||||
There are several ways to leave the command-line window:
|
||||
|
||||
<CR> Execute the command-line under the cursor. Works both in
|
||||
Insert and in Normal mode.
|
||||
<Enter> Execute the command-line under the cursor, then close the
|
||||
window(s) where cmdwin is visible. Works both in Insert and
|
||||
in Normal mode.
|
||||
CTRL-C Continue in Command-line mode. The command-line under the
|
||||
cursor is pre-filled in the command-line. Works both in
|
||||
Insert and in Normal mode.
|
||||
@@ -1249,8 +1249,8 @@ CTRL-C Continue in Command-line mode. The command-line under the
|
||||
|
||||
When the cmdwin closes, focus returns to the window where the command-line
|
||||
was started from (if possible). The cmdwin scratch buffer is destroyed
|
||||
(`bufhidden=wipe`). Any text edits other than the line executed by
|
||||
<CR> are lost.
|
||||
(`bufhidden=wipe`). Any text edits other than the line executed by <Enter>
|
||||
are lost.
|
||||
|
||||
If you would like to execute the command under the cursor and then have the
|
||||
command-line window open again, you may find this mapping useful: >
|
||||
|
||||
@@ -101,15 +101,22 @@ function M.open(type, init_line, init_col)
|
||||
caller_win = caller,
|
||||
}
|
||||
|
||||
-- Clean up if the window is closed by other means (`:q`, `:close`, etc.).
|
||||
-- Clean up when the (last-visible) cmdwin is closed by other means (`:q`, `:close`, etc.).
|
||||
vim.api.nvim_create_autocmd({ 'WinClosed' }, {
|
||||
buffer = buf,
|
||||
once = true,
|
||||
nested = true,
|
||||
callback = function()
|
||||
if state ~= nil then
|
||||
M._cleanup()
|
||||
callback = function(ev)
|
||||
if state == nil then
|
||||
return
|
||||
end
|
||||
local closing = tonumber(ev.match)
|
||||
for _, w in ipairs(vim.fn.win_findbuf(buf)) do
|
||||
if w ~= closing then
|
||||
return -- Still visible elsewhere; keep cmdwin (and this autocmd) active.
|
||||
end
|
||||
end
|
||||
M._cleanup()
|
||||
return true -- Last cmdwin window gone; delete this autocmd.
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -125,8 +132,8 @@ function M._cleanup()
|
||||
state = nil
|
||||
pcall(vim.api.nvim__cmdwin_set, '', 0) -- Clear the C-side globals.
|
||||
pcall(vim.api.nvim_exec_autocmds, 'CmdwinLeave', { pattern = s.type, modeline = false })
|
||||
if vim.api.nvim_win_is_valid(s.win) then
|
||||
pcall(vim.api.nvim_win_close, s.win, true)
|
||||
if vim.api.nvim_buf_is_valid(s.buf) then
|
||||
pcall(vim.api.nvim_buf_delete, s.buf, { force = true })
|
||||
end
|
||||
if vim.api.nvim_win_is_valid(s.caller_win) then
|
||||
pcall(vim.api.nvim_set_current_win, s.caller_win)
|
||||
|
||||
@@ -32,6 +32,35 @@ describe('cmdwin', function()
|
||||
eq('', fn.getcmdwintype())
|
||||
end)
|
||||
|
||||
it('<CR> closes all cmdwin (split) windows #40484', function()
|
||||
feed('q:')
|
||||
feed('ilet g:cmdwin_result = 7<Esc>')
|
||||
feed('<C-w>s') -- split: two windows now show the cmdwin buffer.
|
||||
local cmdwin_buf = api.nvim_get_current_buf()
|
||||
eq(2, #fn.win_findbuf(cmdwin_buf)) -- sanity: the split happened
|
||||
|
||||
feed('<CR>')
|
||||
eq(7, api.nvim_get_var('cmdwin_result')) -- the cmdline executed
|
||||
eq('', fn.getcmdwintype())
|
||||
eq(0, #fn.win_findbuf(cmdwin_buf)) -- All cmdwin windows are closed.
|
||||
eq(1, #api.nvim_list_wins()) -- Back to the single original window.
|
||||
end)
|
||||
|
||||
it('<CR> executes when cmdwin was moved to another tabpage #40484', function()
|
||||
feed('q:')
|
||||
feed('ilet g:cmdwin_result = 9<Esc>')
|
||||
feed('<C-w>T') -- Move the cmdwin to its own new tabpage.
|
||||
eq(2, fn.tabpagenr('$')) -- sanity: the new tabpage exists
|
||||
local cmdwin_buf = api.nvim_get_current_buf()
|
||||
|
||||
feed('<CR>')
|
||||
eq(9, api.nvim_get_var('cmdwin_result')) -- the cmdline executed.
|
||||
eq('', fn.getcmdwintype())
|
||||
eq(0, #fn.win_findbuf(cmdwin_buf)) -- cmdwin window closed.
|
||||
eq(1, fn.tabpagenr('$')) -- cmdwin's tabpage is gone.
|
||||
eq(1, #api.nvim_list_wins())
|
||||
end)
|
||||
|
||||
it('q/ opens cmdwin with search history', function()
|
||||
fn.histadd('/', 'foo')
|
||||
fn.histadd('/', 'bar')
|
||||
|
||||
Reference in New Issue
Block a user