mirror of
https://github.com/neovim/neovim.git
synced 2026-06-30 19:57:54 +00:00
feat(cmdwin): drop CHECK_CMDWIN
Allow window navigation/creation even while cmdwin is alive! 😱
This commit is contained in:
@@ -1223,9 +1223,12 @@ but it's not possible to open another cmdwin from there. There is no
|
||||
nesting.
|
||||
|
||||
*E11*
|
||||
|CTRL-W| navigation/split commands and some operations (e.g. |:terminal|) emit
|
||||
E11. But mouse clicks may focus other windows. The cmdwin buffer is pinned by
|
||||
'winfixbuf', so the window cannot switch to a different buffer.
|
||||
|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.
|
||||
|
||||
|
||||
CLOSE
|
||||
|
||||
@@ -188,11 +188,11 @@ 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!
|
||||
• '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
|
||||
normally. Async plugins no longer need special |CmdwinLeave| workarounds.
|
||||
• Removed most cmdwin-specific |E11| guards, except for window navigation.
|
||||
• The |cmdwin-char| is shown via 'statuscolumn'.
|
||||
• |gf| and |<cfile>| support `file://…` URIs.
|
||||
• |:log| opens log files.
|
||||
|
||||
@@ -271,20 +271,11 @@ void do_window(int nchar, int Prenum, int xchar)
|
||||
|
||||
int Prenum1 = Prenum == 0 ? 1 : Prenum;
|
||||
|
||||
#define CHECK_CMDWIN \
|
||||
do { \
|
||||
if (cmdwin_buf != NULL) { \
|
||||
emsg(_(e_cmdwin)); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
switch (nchar) {
|
||||
// split current window in two parts, horizontally
|
||||
case 'S':
|
||||
case Ctrl_S:
|
||||
case 's':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
// When splitting the quickfix window open a new buffer in it,
|
||||
// don't replicate the quickfix buffer.
|
||||
@@ -297,7 +288,6 @@ void do_window(int nchar, int Prenum, int xchar)
|
||||
// split current window in two parts, vertically
|
||||
case Ctrl_V:
|
||||
case 'v':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
// When splitting the quickfix window open a new buffer in it,
|
||||
// don't replicate the quickfix buffer.
|
||||
@@ -310,7 +300,6 @@ void do_window(int nchar, int Prenum, int xchar)
|
||||
// split current window and edit alternate file
|
||||
case Ctrl_HAT:
|
||||
case '^':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
|
||||
if (buflist_findnr(Prenum == 0 ? curwin->w_alt_fnum : Prenum) == NULL) {
|
||||
@@ -331,7 +320,6 @@ void do_window(int nchar, int Prenum, int xchar)
|
||||
// open new window
|
||||
case Ctrl_N:
|
||||
case 'n':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
newwindow:
|
||||
if (Prenum) {
|
||||
@@ -366,7 +354,6 @@ newwindow:
|
||||
// close preview window
|
||||
case Ctrl_Z:
|
||||
case 'z':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
do_cmdline_cmd("pclose");
|
||||
break;
|
||||
@@ -391,7 +378,6 @@ newwindow:
|
||||
// close all but current window
|
||||
case Ctrl_O:
|
||||
case 'o':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
cmd_with_count("only", cbuf, sizeof(cbuf), Prenum);
|
||||
do_cmdline_cmd(cbuf);
|
||||
@@ -402,7 +388,6 @@ newwindow:
|
||||
case 'w':
|
||||
// cursor to previous window with wrap around
|
||||
case 'W':
|
||||
CHECK_CMDWIN;
|
||||
if (ONE_WINDOW && Prenum != 1) { // just one window
|
||||
beep_flush();
|
||||
} else {
|
||||
@@ -454,7 +439,6 @@ newwindow:
|
||||
case 'j':
|
||||
case K_DOWN:
|
||||
case Ctrl_J:
|
||||
CHECK_CMDWIN;
|
||||
win_goto_ver(false, Prenum1);
|
||||
break;
|
||||
|
||||
@@ -462,7 +446,6 @@ newwindow:
|
||||
case 'k':
|
||||
case K_UP:
|
||||
case Ctrl_K:
|
||||
CHECK_CMDWIN;
|
||||
win_goto_ver(true, Prenum1);
|
||||
break;
|
||||
|
||||
@@ -471,7 +454,6 @@ newwindow:
|
||||
case K_LEFT:
|
||||
case Ctrl_H:
|
||||
case K_BS:
|
||||
CHECK_CMDWIN;
|
||||
win_goto_hor(true, Prenum1);
|
||||
break;
|
||||
|
||||
@@ -479,13 +461,11 @@ newwindow:
|
||||
case 'l':
|
||||
case K_RIGHT:
|
||||
case Ctrl_L:
|
||||
CHECK_CMDWIN;
|
||||
win_goto_hor(false, Prenum1);
|
||||
break;
|
||||
|
||||
// move window to new tab page
|
||||
case 'T':
|
||||
CHECK_CMDWIN;
|
||||
if (one_window(curwin, NULL)) {
|
||||
msg(_(m_onlyone), 0);
|
||||
} else {
|
||||
@@ -533,21 +513,18 @@ newwindow:
|
||||
// exchange current and next window
|
||||
case 'x':
|
||||
case Ctrl_X:
|
||||
CHECK_CMDWIN;
|
||||
win_exchange(Prenum);
|
||||
break;
|
||||
|
||||
// rotate windows downwards
|
||||
case Ctrl_R:
|
||||
case 'r':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
win_rotate(false, Prenum1); // downwards
|
||||
break;
|
||||
|
||||
// rotate windows upwards
|
||||
case 'R':
|
||||
CHECK_CMDWIN;
|
||||
reset_VIsual_and_resel(); // stop Visual mode
|
||||
win_rotate(true, Prenum1); // upwards
|
||||
break;
|
||||
@@ -557,7 +534,6 @@ newwindow:
|
||||
case 'J':
|
||||
case 'H':
|
||||
case 'L':
|
||||
CHECK_CMDWIN;
|
||||
if (one_window(curwin, NULL)) {
|
||||
beep_flush();
|
||||
} else {
|
||||
@@ -608,7 +584,6 @@ newwindow:
|
||||
|
||||
// jump to tag and split window if tag exists (in preview window)
|
||||
case '}':
|
||||
CHECK_CMDWIN;
|
||||
if (Prenum) {
|
||||
g_do_tagpreview = Prenum;
|
||||
} else {
|
||||
@@ -617,7 +592,6 @@ newwindow:
|
||||
FALLTHROUGH;
|
||||
case ']':
|
||||
case Ctrl_RSB:
|
||||
CHECK_CMDWIN;
|
||||
// Keep visual mode, can select words to use as a tag.
|
||||
if (Prenum) {
|
||||
postponed_split = Prenum;
|
||||
@@ -640,7 +614,6 @@ newwindow:
|
||||
case 'F':
|
||||
case Ctrl_F: {
|
||||
wingotofile:
|
||||
CHECK_CMDWIN;
|
||||
if (check_text_or_curbuf_locked(NULL)) {
|
||||
break;
|
||||
}
|
||||
@@ -698,7 +671,6 @@ wingotofile:
|
||||
FALLTHROUGH;
|
||||
case 'd': // Go to definition, using 'define'
|
||||
case Ctrl_D: {
|
||||
CHECK_CMDWIN;
|
||||
size_t len;
|
||||
char *ptr;
|
||||
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT, NULL)) == 0) {
|
||||
@@ -726,7 +698,6 @@ wingotofile:
|
||||
// CTRL-W g extended commands
|
||||
case 'g':
|
||||
case Ctrl_G:
|
||||
CHECK_CMDWIN;
|
||||
no_mapping++;
|
||||
allow_keys++; // no mapping for xchar, but allow key codes
|
||||
if (xchar == NUL) {
|
||||
@@ -4936,10 +4907,6 @@ void goto_tabpage(int n)
|
||||
/// @param trigger_leave_autocmds when true trigger *Leave autocommands.
|
||||
void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_leave_autocmds)
|
||||
{
|
||||
if (trigger_enter_autocmds || trigger_leave_autocmds) {
|
||||
CHECK_CMDWIN;
|
||||
}
|
||||
|
||||
// Don't repeat a message in another tab page.
|
||||
set_keep_msg(NULL, 0);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ describe('eval-API', function()
|
||||
eq('Vim(call):E5555: API call: Invalid buffer id: 17', err)
|
||||
end)
|
||||
|
||||
it('cannot change text or window if textlocked', function()
|
||||
it('cannot change text or window if textlock', function()
|
||||
command('autocmd TextYankPost <buffer> ++once call nvim_buf_set_lines(0, 0, -1, v:false, [])')
|
||||
matches(
|
||||
'Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
|
||||
@@ -90,19 +90,16 @@ describe('eval-API', function()
|
||||
api.nvim_get_vvar('errmsg')
|
||||
)
|
||||
|
||||
-- cmdwin behavior (changed since #40312).
|
||||
-- cmdwin (#40312, #40484): E11 "Invalid in command-line window" restriction was removed.
|
||||
local old_win = api.nvim_get_current_win()
|
||||
feed('q:')
|
||||
local cmdwin_win = api.nvim_get_current_win()
|
||||
eq(
|
||||
'Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
|
||||
pcall_err(api.nvim_set_current_win, old_win)
|
||||
)
|
||||
neq(old_win, cmdwin_win)
|
||||
-- Switching to another window from the cmdwin now works (previously E11).
|
||||
api.nvim_set_current_win(old_win)
|
||||
eq(old_win, api.nvim_get_current_win())
|
||||
-- TODO(justinmk): awkward: E11 is raised but the focus switch happens anyway; inherited bug in
|
||||
-- goto_tabpage_win (calls win_enter unconditionally even when goto_tabpage_tp's CHECK_CMDWIN
|
||||
-- emsg'd). We should probably just remove CHECK_CMDWIN from goto_tabpage_tp. #40407
|
||||
pcall(api.nvim_set_current_win, cmdwin_win)
|
||||
-- ...and back into the cmdwin.
|
||||
api.nvim_set_current_win(cmdwin_win)
|
||||
eq(cmdwin_win, api.nvim_get_current_win())
|
||||
|
||||
-- nvim_buf_set_lines() in the cmdwin buffer is OK.
|
||||
|
||||
@@ -3242,11 +3242,8 @@ func Test_normal50_commandline()
|
||||
func! DoTimerWork(id)
|
||||
call assert_equal(1, getbufinfo('')[0].command)
|
||||
|
||||
" should fail, with E11, but does fail with E23?
|
||||
"call feedkeys("\<c-^>", 'tm')
|
||||
|
||||
" should fail with E11 - "Invalid in command-line window"
|
||||
call assert_fails(":wincmd p", 'E11')
|
||||
" Nvim removed the E11 "Invalid in command-line window" restriction (#40312, #40484).
|
||||
"call assert_fails(":wincmd p", 'E11')
|
||||
|
||||
" Return from commandline window.
|
||||
call feedkeys("\<CR>", 't')
|
||||
|
||||
Reference in New Issue
Block a user