From 2a4bb3eb378a30093e6ce897a7398cb8bf3df013 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 29 Jun 2026 22:10:53 +0200 Subject: [PATCH] feat(cmdwin): allow tabpage actions --- runtime/doc/cmdline.txt | 16 ++++++------- runtime/doc/news.txt | 2 +- src/nvim/window.c | 4 ---- .../functional/autocmd/tabnewentered_spec.lua | 24 +++++++------------ 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index dd8db14a1c..182f03c006 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1209,6 +1209,11 @@ opens in Normal mode. The last line contains the command as typed so far. The The window height is decided by 'cmdwinheight' (if there is room). The window is full width and is positioned just above the command-line. +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 +window: clicks focus other windows, and statuslines and vertical separators +can be dragged to resize. + *E1292* Only one command-line window can be open at a time. @@ -1223,12 +1228,8 @@ but it's not possible to open another cmdwin from there. There is no nesting. *E11* -|CTRL-W| commands work as usual: you can navigate between, split, resize, and -close windows while the command-line window is open. E11 is still emitted by -operations that would leave or repurpose the cmdwin: opening a new tab page -(CTRL-W_T, |:tabnew|) or turning its buffer into a terminal (|:terminal|). -The cmdwin buffer is pinned by 'winfixbuf', so its window cannot switch to a -different buffer. +The cmdwin buffer cannot be used as a |:terminal|. Its window cannot switch to +a different buffer ('winfixbuf'). CLOSE @@ -1284,9 +1285,6 @@ If you don't want these mappings, disable them with: > au CmdwinEnter [:>] nunmap You could put these lines in your vimrc file. -The mouse works as in any window: clicks focus other windows, and statuslines -and vertical separators can be dragged to resize. - The |getcmdwintype()| function returns the type of the command-line being edited as described in |cmdwin-char|. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index bb9f81a700..d369034de2 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -188,7 +188,7 @@ EDITOR kind/menu/info/abbr for the popup menu. • |cmdwin| (|q:|, |q/|, |q?|, |c_CTRL-F|) is implemented as a "normal" buffer+window instead of a nested-state modal loop: - • You can create (and navigate) windows while cmdwin is active. Chaos! + • You can create/navigate windows/tabpages while cmdwin is active. Chaos! • 'inccommand' works in cmdwin! • API calls (e.g. |nvim_buf_delete()|) that previously failed with "E11: Invalid in command-line window" while cmdwin was open, now work diff --git a/src/nvim/window.c b/src/nvim/window.c index 77ebda0a39..3e5d437177 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4469,10 +4469,6 @@ tabpage_T *win_new_tabpage(int after, char *filename, bool enter, win_T **first) { tabpage_T *old_curtab = curtab; - if (enter && cmdwin_buf != NULL) { - emsg(_(e_cmdwin)); - return NULL; - } if (window_layout_locked(CMD_tabnew)) { return NULL; } diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index 93031a6b1c..5ed585a32d 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -618,7 +618,7 @@ describe('tabpage/previous', function() -- it('does not switch to previous via :tabn # after entering operator pending', -- does_not_switch_to_previous_after_entering_operator_pending(':tabn #')) - local function cmdwin_prevents_tab_switch(characters, completion_visible) + local function cmdwin_allows_tab_switch(characters) return function() -- Add three tabs for a total of four command('tabnew') @@ -633,25 +633,19 @@ describe('tabpage/previous', function() local cmdline_win_id = eval('win_getid()') - -- At this point switching to the previous tab should have no effect. + -- Switching to the previous tab now works. feed(characters) - -- Attempting to switch tabs maintains the current window. - eq(cmdline_win_id, eval('win_getid()')) - eq(completion_visible, eval('complete_info().pum_visible')) - - -- The current tab is still the fourth. - eq(4, eval('tabpagenr()')) - - -- The previous tab is still the third. - eq(3, eval("tabpagenr('#')")) + -- Focus moved out of the cmdwin to the previous (third) tab. + t.neq(cmdline_win_id, eval('win_getid()')) + eq(3, eval('tabpagenr()')) end end - it('cmdwin prevents tab switch via g', cmdwin_prevents_tab_switch('g', 0)) - it('cmdwin prevents tab switch via g', cmdwin_prevents_tab_switch('g', 0)) - it('cmdwin prevents tab switch via ', cmdwin_prevents_tab_switch('', 0)) - it('cmdwin prevents tab switch via :tabn #', cmdwin_prevents_tab_switch(':tabn #', 0)) + it('cmdwin allows tab switch via g', cmdwin_allows_tab_switch('g')) + it('cmdwin allows tab switch via g', cmdwin_allows_tab_switch('g')) + it('cmdwin allows tab switch via ', cmdwin_allows_tab_switch('')) + it('cmdwin allows tab switch via :tabn #', cmdwin_allows_tab_switch(':tabn #')) it(':tabs indicates correct prevtab curwin', function() -- Add three tabs for a total of four