From b2bf7bcfb15125fe65f3e503af00174f31eb92d8 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 19 Jun 2026 12:56:38 +0200 Subject: [PATCH 1/2] feat(cmdwin): implement cmdwin as a normal buf+win MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: cmdwin (the `:q` cmdline buffer) has various limitations which require special-casing all over the codebase. Besides complicating the code, it also breaks async plugins if they try to create buffers/windows after some work is done, if the user happens to open cmdwin at the wrong the moment: Lua callback: …/guh.nvim/lua/guh/util.lua:531: E11: Invalid in command-line window; executes, CTRL-C quits stack traceback: [C]: in function 'nvim_buf_delete' …/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526> Solution: Just say no to "inception". Reimplement cmdwin as a normal buffer+window. All of the cmdwin contortions (in both core, and innocent plugins) exist literally only to support "inception": recursive cmdwin-in-cmdline-things, like `=`, `/`, search-during-substitute, `:input()`, etc. So we just won't support that (though I have a potential plan for that later, which I call "modal parking lot"). The benefit is that plugins, and core, no longer have to care about cmdwin. BONUS: - mouse-drag on vertical separators works (it only worked for horizontal/statusline before) - inccommand-in-cmdwin now works correctly, for free (thus don't need #40077). POTENTIAL FOLLOWUPS - Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos. - Unify `BUFLOCK_OK` / `LOCK_OK` ? DESIGN: - Eliminate lots of C globals, `EX_CMDWIN`, etc. - `text_locked()` no longer reports true for cmdwin. - cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe', 'buftype=nofile'. Invariants come from those options rather than special cases throughout the codebase. - `nv_record` for q:/q//q? calls Lua `nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN` / cmdline-reader detour. - `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls `vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so the in-flight cmdline cancels. Reader state is not serialized; instead the captured `(type, line, col)` is replayed via `nvim_feedkeys(type..line.."", "nt", …)` after user confirms. - On confirm/cancel: `` / `` calls into Lua which closes the window and re-feeds the cmdline. BREAKING CHANGES: - Expression-register cmdline (`=` from insert-mode) no longer supports cmdwin. Same applies to `input()` / `inputlist()` (already covered by `text_locked`). - Usage of cmdwin in macros/mappings will probably break (assuming they ever worked). --- runtime/doc/api.txt | 24 +- runtime/doc/cmdline.txt | 84 +-- runtime/doc/news.txt | 14 +- runtime/doc/vim_diff.txt | 4 + runtime/lua/vim/_core/cmdwin.lua | 168 +++++ runtime/lua/vim/_meta/api.gen.lua | 10 +- src/gen/c_grammar.lua | 2 - src/gen/cdoc_parser.lua | 1 - src/gen/gen_api_dispatch.lua | 12 - src/gen/gen_ex_cmds.lua | 6 + src/gen/gen_vimdoc.lua | 3 +- src/nvim/api/buffer.c | 4 +- src/nvim/api/tabpage.c | 6 +- src/nvim/api/vim.c | 38 +- src/nvim/api/win_config.c | 11 +- src/nvim/api/window.c | 16 +- src/nvim/arglist.c | 4 - src/nvim/buffer.c | 37 +- src/nvim/clipboard.c | 22 - src/nvim/drawline.c | 10 +- src/nvim/edit.c | 12 - src/nvim/eval/buffer.c | 2 +- src/nvim/eval/funcs.c | 5 + src/nvim/eval/window.c | 2 +- src/nvim/ex_cmds.c | 18 - src/nvim/ex_cmds.lua | 631 +++++++++--------- src/nvim/ex_cmds_defs.h | 8 +- src/nvim/ex_docmd.c | 45 +- src/nvim/ex_getln.c | 364 ++-------- src/nvim/func_attr.h | 2 - src/nvim/globals.h | 10 +- src/nvim/insexpand.c | 2 +- src/nvim/keycodes.h | 3 +- src/nvim/main.c | 2 +- src/nvim/mouse.c | 12 +- src/nvim/move.c | 1 - src/nvim/normal.c | 51 +- src/nvim/popupmenu.c | 2 +- src/nvim/textformat.c | 3 - src/nvim/window.c | 26 +- src/nvim/winfloat.c | 16 - src/uncrustify.cfg | 1 - test/functional/api/tabpage_spec.lua | 38 +- test/functional/api/window_spec.lua | 304 +-------- test/functional/autocmd/cmdline_spec.lua | 19 +- .../functional/autocmd/tabnewentered_spec.lua | 17 +- test/functional/core/main_spec.lua | 1 + test/functional/editor/cmdwin_spec.lua | 115 ++++ test/functional/editor/completion_spec.lua | 22 +- test/functional/ex_cmds/append_spec.lua | 20 +- test/functional/legacy/cmdwin_spec.lua | 97 --- test/functional/ui/cmdline_spec.lua | 50 +- test/functional/ui/fold_spec.lua | 149 ----- test/functional/ui/messages2_spec.lua | 53 +- test/functional/ui/popupmenu_spec.lua | 15 +- test/functional/ui/statuscolumn_spec.lua | 7 +- .../vimscript/api_functions_spec.lua | 15 +- test/old/testdir/test_arglist.vim | 1 + test/old/testdir/test_autocmd.vim | 7 + test/old/testdir/test_cmdline.vim | 9 + test/old/testdir/test_cmdwin.vim | 6 + test/old/testdir/test_menu.vim | 1 + test/old/testdir/test_normal.vim | 3 + test/old/testdir/test_popup.vim | 1 + test/old/testdir/test_tabpage.vim | 1 + test/old/testdir/test_usercommands.vim | 1 + test/old/testdir/test_window_cmd.vim | 4 + 67 files changed, 1005 insertions(+), 1645 deletions(-) create mode 100644 runtime/lua/vim/_core/cmdwin.lua create mode 100644 test/functional/editor/cmdwin_spec.lua delete mode 100644 test/functional/legacy/cmdwin_spec.lua diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 31fc1ab32a..cbfe46fbce 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -609,9 +609,6 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()* Return: ~ (`integer`) Buffer id, or 0 on error - See also: ~ - • buf_open_scratch - nvim_del_current_line() *nvim_del_current_line()* Deletes the current line. @@ -1489,7 +1486,7 @@ nvim_set_current_buf({buf}) *nvim_set_current_buf()* Sets the current window's buffer to `buf`. Attributes: ~ - not allowed when |textlock| is active or in the |cmdwin| + not allowed when |textlock| is active Since: 0.1.0 Parameters: ~ @@ -1518,7 +1515,7 @@ nvim_set_current_tabpage({tabpage}) *nvim_set_current_tabpage()* Sets the current tabpage. Attributes: ~ - not allowed when |textlock| is active or in the |cmdwin| + not allowed when |textlock| is active Since: 0.1.0 Parameters: ~ @@ -1528,7 +1525,7 @@ nvim_set_current_win({win}) *nvim_set_current_win()* Navigates to the given window (and tabpage, implicitly). Attributes: ~ - not allowed when |textlock| is active or in the |cmdwin| + not allowed when |textlock| is active Since: 0.1.0 Parameters: ~ @@ -1711,6 +1708,19 @@ nvim__chan_set_detach({detach}) *nvim__chan_set_detach()* Parameters: ~ • {detach} (`boolean`) New detach value for the channel. +nvim__cmdwin_set({type}, {buf}) *nvim__cmdwin_set()* + WARNING: This feature is experimental/unstable. + + Records the cmdwin scratchbuf and type, or clears both when type="" / + buf=0. Internal use only. + + Attributes: ~ + Since: 0.12.0 + + Parameters: ~ + • {type} (`string`) ':', '/', '?' (first char only); empty to clear. + • {buf} (`integer`) cmdwin buffer id, or 0 to clear. + nvim__complete_set({index}, {opts}) *nvim__complete_set()* WARNING: This feature is experimental/unstable. @@ -2493,7 +2503,7 @@ nvim_buf_delete({buf}, {opts}) *nvim_buf_delete()* < Attributes: ~ - not allowed when |textlock| is active or in the |cmdwin| + not allowed when |textlock| is active Since: 0.5.0 Parameters: ~ diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 2dc7ac0a0f..332786f391 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1188,72 +1188,65 @@ Also see |`=|. ============================================================================== 7. Command-line window *cmdline-window* *cmdwin* *command-line-window* -In the command-line window the command line can be edited just like editing -text in any window. It is a special kind of window, because you cannot leave -it in a normal way. +The command-line window ("cmdwin") is a buffer+window in which the command +line can be edited. OPEN *c_CTRL-F* *q:* *q/* *q?* There are two ways to open the command-line window: -1. From Command-line mode, use the key specified with the 'cedit' option. +1. From Command-line mode, use (or the 'cedit' key). + - Not supported from the expr-register cmdline (|c_CTRL-R_=| |i_CTRL-R_=|). 2. From Normal mode, use the "q:", "q/" or "q?" command. This starts editing an Ex command-line ("q:") or search string ("q/" or "q?"). Note that this is not possible while recording is in progress (the "q" stops recording then). -When the window opens it is filled with the command-line history. The last -line contains the command as typed so far. The left column will show a -character that indicates the type of command-line being edited, see -|cmdwin-char|. +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. -Vim will be in Normal mode when the editor is opened. *E1292* -Once a command-line window is open it is not possible to open another one. - -The height of the window is specified with 'cmdwinheight' (or smaller if there -is no room). The window is always full width and is positioned just above the -command-line. +Only one command-line window can be open at a time. EDIT -You can now use commands to move around and edit the text in the window. Both -in Normal mode and Insert mode. +You can use any commands to move around and edit the text in the window, both +in Normal and Insert mode. It is possible to use ":", "/" and other commands that use the command-line, -but it's not possible to open another command-line window then. There is no +but it's not possible to open another cmdwin from there. There is no nesting. - *E11* *E1188* -The command-line window is not a normal window. It is not possible to move to -another window or edit another buffer. All commands that would do this are -disabled in the command-line window. Of course it _is_ possible to execute -any command that you entered in the command-line window. Other text edits are -discarded when closing the window. + + *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. -CLOSE *E199* +CLOSE There are several ways to leave the command-line window: Execute the command-line under the cursor. Works both in Insert and in Normal mode. CTRL-C Continue in Command-line mode. The command-line under the - cursor is used as the command-line. Works both in Insert and - in Normal mode. There is no redraw, thus the window will - remain visible. + cursor is pre-filled in the command-line. Works both in + Insert and in Normal mode. :quit Discard the command line and go back to Normal mode. ":close", CTRL-W c, ":exit", ":xit" and CTRL-\ CTRL-N also work. -:qall Quit Vim, unless there are changes in some buffer. -:qall! Quit Vim, discarding changes to any buffer. +:qall Quit Nvim, unless there are changes in some buffer. +:qall! Quit Nvim, discarding changes to any buffer. -Once the command-line window is closed the old window sizes are restored. The -executed command applies to the window and buffer where the command-line was -started from. This works as if the command-line window was not there, except -that there will be an extra screen redraw. -The buffer used for the command-line window is deleted. Any changes to lines -other than the one that is executed with are lost. +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 + 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: > @@ -1263,16 +1256,15 @@ command-line window open again, you may find this mapping useful: > VARIOUS -The command-line window cannot be used when there already is a command-line -window (no nesting). - -Some options are set when the command-line window is opened: -'filetype' "vim", when editing an Ex command-line; this starts Vim syntax - highlighting if it was enabled -'rightleft' off -'modifiable' on +Buffer and window options set on cmdwin open: +'bufhidden' "wipe" +'buflisted' off 'buftype' "nofile" +'filetype' "vim" (only for ":" type) +'foldenable' off +'statuscolumn' shows the |cmdwin-char| 'swapfile' off +'winfixbuf' on It is allowed to write the buffer contents to a file. This is an easy way to save the command-line history and read it back later. @@ -1289,10 +1281,8 @@ If you don't want these mappings, disable them with: > au CmdwinEnter [:>] nunmap You could put these lines in your vimrc file. -While in the command-line window you cannot use the mouse to put the cursor in -another window, or drag statuslines of other windows. You can drag the -statusline of the command-line window itself and the statusline above it. -Thus you can resize the command-line window, but not others. +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 87b3ea9d1c..573bcbd7d1 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -81,8 +81,12 @@ DIAGNOSTICS EDITOR • On Windows, the |trust| db now stores paths with "/" slashes. This means the - trust store will be reset. + trust store will be reset (one time). • `stdpath("log")` moved to `stdpath("state")/logs`. +• |cmdwin| (|q:|, |q/|, |q?|, |c_CTRL-F|): + • Only supports one "cmdline level", not "infinite recursion". + • Expr-register (|i_CTRL-R_=|, |c_CTRL-R_=|) no longer supports opening + cmdwin via |c_CTRL-F|. EVENTS @@ -164,6 +168,14 @@ EDITOR • |:command-completion-customlist| can return a list of dictionaries with 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: + • '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 || support `file://…` URIs. • |:log| opens log files. • |ZR| restarts Nvim (|:restart|). diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 1e53dfd89e..c73529fdb5 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -304,6 +304,9 @@ Command-line: - (Experimental) *g:Nvim_color_cmdline* Command-line (|:|) is colored by callback defined in `g:Nvim_color_cmdline` (this callback is for testing only, and will be removed in the future). +- |cmdwin| (|q:|, |q/|, |q?|, |c_CTRL-F|) is a "normal" buffer+window, instead + of a nested modal loop. API and Lua callbacks can run without |E11| while it + is open. The |cmdwin-char| is shown via 'statuscolumn'. Commands: - |:checkhealth| @@ -761,6 +764,7 @@ Compile-time features: - X11 integration (see |x11-selection|) Editor: +- |c_CTRL-F| cannot enter |cmdwin| from the |expr-register| prompt. - *cscope* support was removed in favour of plugin-based solutions such as: https://github.com/dhananjaylatkar/cscope_maps.nvim - *popup-window* : Use |floating-windows| instead. diff --git a/runtime/lua/vim/_core/cmdwin.lua b/runtime/lua/vim/_core/cmdwin.lua new file mode 100644 index 0000000000..e223354599 --- /dev/null +++ b/runtime/lua/vim/_core/cmdwin.lua @@ -0,0 +1,168 @@ +--- @brief Command-line window (q:, q/, q?, c_CTRL-F). +--- +--- Implements cmdwin as a normal window+buffer, instead of the legacy nested `state_enter` loop. +--- - On confirm, curline is fed back through the cmdline via |nvim_feedkeys()|. +--- - On cancel, curline is pre-filled in the ":" cmdline. + +local M = {} + +--- @class vim._core.cmdwin.State +--- @field type string ':', '/', '?' +--- @field win integer cmdwin window id +--- @field buf integer cmdwin buffer id +--- @field caller_win integer Window to return-to on close + +--- @type vim._core.cmdwin.State? +local state = nil + +local cmdwin_types = { [':'] = true, ['/'] = true, ['?'] = true } + +--- Fills the cmdwin buffer with the cmdline history. +local function fill_history(buf, type) + local histname = type == ':' and 'cmd' or (type == '/' or type == '?') and 'search' or nil + assert(histname, 'cmdwin: unknown type: ' .. tostring(type)) + local n = vim.fn.histnr(histname) + if n <= 0 then -- May be -1 if history is empty. + return + end + local lines = {} --- @type string[] + for i = 1, n do + local h = vim.fn.histget(histname, i) + if h ~= '' then + -- One cmdwin line = one cmdline. Entry may have embedded newlines (e.g. via feedkeys or :execute). + lines[#lines + 1] = (h:gsub('\n', '\0')) + end + end + if #lines > 0 then + vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) + end +end + +--- Open the command-line window. +--- +--- @param type? string ':', '/', '?'. Default ':'. +--- @param init_line? string Pre-fill the last line (the "live" cmdline). +--- @param init_col? integer 1-based cursor column in the last line. +function M.open(type, init_line, init_col) + type = type or ':' + assert(cmdwin_types[type], 'cmdwin: unknown type: ' .. tostring(type)) + if state ~= nil then + vim.api.nvim_echo( + { { 'E1292: Command-line window is already open', 'ErrorMsg' } }, + true, + { err = true } + ) + return + end + + local caller = vim.api.nvim_get_current_win() + + -- Split a horizontal window at the bottom, sized by 'cmdwinheight'. + local ok, err = pcall(function() + vim.cmd(('botright %dnew'):format(vim.o.cmdwinheight)) + end) + if not ok then + vim.api.nvim_echo({ { tostring(err), 'ErrorMsg' } }, true, { err = true }) + return + end + local win = vim.api.nvim_get_current_win() + local buf = vim.api.nvim_get_current_buf() + + vim.bo[buf].buftype = 'nofile' + vim.bo[buf].bufhidden = 'wipe' + vim.bo[buf].swapfile = false + vim.bo[buf].buflisted = false + vim.wo[win][0].winfixbuf = true + vim.wo[win][0].foldenable = false + -- Show cmdwin-char via 'statuscolumn'. + vim.wo[win][0].statuscolumn = '%#NonText#' .. type .. ' ' + + fill_history(buf, type) + + -- Append the in-flight cmdline (or empty placeholder) as the last line. + vim.api.nvim_buf_set_lines(buf, -1, -1, false, { init_line or '' }) + 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) }) + + pcall(vim.api.nvim_buf_set_name, buf, '[Command Line]') + if type == ':' then + vim.bo[buf].filetype = 'vim' + end + + vim.api.nvim__cmdwin_set(type, buf) -- Update the C-side globals. + + state = { + type = type, + win = win, + buf = buf, + caller_win = caller, + } + + -- Buffer-local mappings. + vim.keymap.set( + { 'n', 'i' }, + '', + [[lua require'vim._core.cmdwin'.confirm()]], + { buffer = buf, silent = true, desc = 'cmdwin: execute' } + ) + vim.keymap.set( + { 'n', 'i', 'x' }, + '', + [[lua require'vim._core.cmdwin'.cancel()]], + { buffer = buf, silent = true, desc = 'cmdwin: cancel' } + ) + + -- Clean up if the window is closed by other means (`:q`, `:close`, etc.). + vim.api.nvim_create_autocmd({ 'WinClosed' }, { + buffer = buf, + once = true, + callback = function() + if state ~= nil then + M._cleanup() + end + end, + }) + + vim.api.nvim_exec_autocmds('CmdwinEnter', { pattern = type, modeline = false }) +end + +--- @private +function M._cleanup() + if state == nil then + return + end + local s = state + 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) + end + if vim.api.nvim_win_is_valid(s.caller_win) then + pcall(vim.api.nvim_set_current_win, s.caller_win) + end +end + +local function _confirm() + if state == nil then + return + end + local line = vim.api.nvim_get_current_line() + local type = state.type + M._cleanup() + return line, type +end + +--- Confirm and execute the current line as a cmdline. +function M.confirm() + local line, type = _confirm() + vim.api.nvim_feedkeys(type .. line .. vim.keycode(''), 'nt', false) +end + +--- Cancel: close the cmdwin and re-enter cmdline mode with the line pre-filled (no execute). +function M.cancel() + local line, type = _confirm() + vim.api.nvim_feedkeys(type .. line, 'nt', false) +end + +return M diff --git a/runtime/lua/vim/_meta/api.gen.lua b/runtime/lua/vim/_meta/api.gen.lua index e3a4fda5c6..c596bee759 100644 --- a/runtime/lua/vim/_meta/api.gen.lua +++ b/runtime/lua/vim/_meta/api.gen.lua @@ -24,6 +24,14 @@ function vim.api.nvim__buf_debug_extmarks(buf, keys, dot) end --- @return table function vim.api.nvim__buf_stats(buf) end +--- WARNING: This feature is experimental/unstable. +--- +--- Records the cmdwin scratchbuf and type, or clears both when type="" / buf=0. Internal use only. +--- +--- @param type string ':', '/', '?' (first char only); empty to clear. +--- @param buf integer cmdwin buffer id, or 0 to clear. +function vim.api.nvim__cmdwin_set(type, buf) end + --- WARNING: This feature is experimental/unstable. --- --- Sets info for the completion item at the given index. If the info text was shown in a window, @@ -967,12 +975,10 @@ function vim.api.nvim_create_autocmd(event, opts) end --- Creates a new, empty, unnamed buffer. --- ---- @see buf_open_scratch --- @param listed boolean Sets 'buflisted' --- @param scratch boolean Creates a "throwaway" `scratch-buffer` for temporary work --- (always 'nomodified'). Also sets 'nomodeline' on the buffer. --- @return integer # Buffer id, or 0 on error ---- function vim.api.nvim_create_buf(listed, scratch) end --- Creates a new namespace or gets an existing one. [namespace]() diff --git a/src/gen/c_grammar.lua b/src/gen/c_grammar.lua index 48d27d67af..cb0908497b 100644 --- a/src/gen/c_grammar.lua +++ b/src/gen/c_grammar.lua @@ -26,7 +26,6 @@ --- @field noexport true? --- @field remote_only true? --- @field lua_only true? ---- @field textlock_allow_cmdwin true? --- @field textlock true? --- @field remote_impl true? --- @field compositor_impl true? @@ -198,7 +197,6 @@ local fattr = ( + attr('FUNC_API_NOEXPORT', 'noexport') + attr('FUNC_API_REMOTE_ONLY', 'remote_only') + attr('FUNC_API_LUA_ONLY', 'lua_only') - + attr('FUNC_API_TEXTLOCK_ALLOW_CMDWIN', 'textlock_allow_cmdwin') + attr('FUNC_API_TEXTLOCK', 'textlock') + attr('FUNC_API_REMOTE_IMPL', 'remote_impl') + attr('FUNC_API_COMPOSITOR_IMPL', 'compositor_impl') diff --git a/src/gen/cdoc_parser.lua b/src/gen/cdoc_parser.lua index f754d06642..493fbbf928 100644 --- a/src/gen/cdoc_parser.lua +++ b/src/gen/cdoc_parser.lua @@ -175,7 +175,6 @@ local function process_proto(item, state) 'remote_only', 'lua_only', 'textlock', - 'textlock_allow_cmdwin', }) do if item[a] then cur_obj.attrs = cur_obj.attrs or {} diff --git a/src/gen/gen_api_dispatch.lua b/src/gen/gen_api_dispatch.lua index c78eb94176..e8bf7ea8f7 100644 --- a/src/gen/gen_api_dispatch.lua +++ b/src/gen/gen_api_dispatch.lua @@ -567,11 +567,6 @@ for i = 1, #functions do output:write('\n api_set_error(error, kErrorTypeException, "%s", get_text_locked_msg());') output:write('\n goto cleanup;') output:write('\n }\n') - elseif fn.textlock_allow_cmdwin then - output:write('\n if (textlock != 0 || expr_map_locked()) {') - output:write('\n api_set_error(error, kErrorTypeException, "%s", e_textlock);') - output:write('\n goto cleanup;') - output:write('\n }\n') end -- function call @@ -759,13 +754,6 @@ local function process_function(fn) goto exit_0; } ]]) - elseif fn.textlock_allow_cmdwin then - write_shifted_output([[ - if (textlock != 0 || expr_map_locked()) { - api_set_error(&err, kErrorTypeException, "%%s", e_textlock); - goto exit_0; - } - ]]) end local cparams = '' diff --git a/src/gen/gen_ex_cmds.lua b/src/gen/gen_ex_cmds.lua index 67b124bfec..d2c0a01e3a 100644 --- a/src/gen/gen_ex_cmds.lua +++ b/src/gen/gen_ex_cmds.lua @@ -116,6 +116,12 @@ for _, cmd in ipairs(defs) do string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command) ) end + if bit.band(cmd.flags, flags.BUFLOCK_OK) == flags.BUFLOCK_OK then + assert( + bit.band(cmd.flags, flags.LOCK_OK) == flags.LOCK_OK, + string.format('ex_cmds.lua:%s: BUFLOCK_OK implies LOCK_OK\n', cmd.command) + ) + end local enumname = cmd.enum or ('CMD_' .. cmd.command) local byte_cmd = cmd.command:sub(1, 1):byte() if byte_a <= byte_cmd and byte_cmd <= byte_z then diff --git a/src/gen/gen_vimdoc.lua b/src/gen/gen_vimdoc.lua index 22a94b049b..4d92c94be8 100755 --- a/src/gen/gen_vimdoc.lua +++ b/src/gen/gen_vimdoc.lua @@ -981,8 +981,7 @@ local function render_fun(fun, classes, cfg) table.insert(ret, '\n Attributes: ~\n') for _, attr in ipairs(fun.attrs) do local attr_str = ({ - textlock = 'not allowed when |textlock| is active or in the |cmdwin|', - textlock_allow_cmdwin = 'not allowed when |textlock| is active', + textlock = 'not allowed when |textlock| is active', fast = '|api-fast|', remote_only = '|RPC| only', lua_only = 'Lua |vim.api| only', diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 44604b205b..85c5f75540 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -325,7 +325,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buf, Integer start, Integer Boolean strict_indexing, ArrayOf(String) replacement, Arena *arena, Error *err) FUNC_API_SINCE(1) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { buf_T *b = api_buf_ensure_loaded(buf, err); @@ -485,7 +485,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buf, Integer start_row, Integ Integer end_row, Integer end_col, ArrayOf(String) replacement, Arena *arena, Error *err) FUNC_API_SINCE(7) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { MAXSIZE_TEMP_ARRAY(scratch, 1); if (replacement.size == 0) { diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index 3fbbc6c390..cd1c42a535 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -200,17 +200,13 @@ Boolean nvim_tabpage_is_valid(Tabpage tabpage) /// @param[out] err Error details, if any /// @return |tab-ID| of the new tabpage Tabpage nvim_open_tabpage(Buffer buf, Boolean enter, Dict(tabpage_config) *config, Error *err) - FUNC_API_SINCE(14) FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_SINCE(14) FUNC_API_TEXTLOCK { #define HAS_KEY_X(d, key) HAS_KEY(d, tabpage_config, key) buf_T *b = find_buffer_by_handle(buf, err); if (b == NULL) { return 0; } - if ((cmdwin_type != 0 && enter) || b == cmdwin_buf) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return 0; - } int after = -1; // Default to after current tabpage if (HAS_KEY_X(config, after)) { diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0b1517e97f..f898a08a0d 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -720,7 +720,7 @@ String nvim_get_current_line(Arena *arena, Error *err) /// @param[out] err Error details, if any void nvim_set_current_line(String line, Arena *arena, Error *err) FUNC_API_SINCE(1) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, arena, err); } @@ -730,7 +730,7 @@ void nvim_set_current_line(String line, Arena *arena, Error *err) /// @param[out] err Error details, if any void nvim_del_current_line(Arena *arena, Error *err) FUNC_API_SINCE(1) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err); } @@ -1042,8 +1042,6 @@ void nvim_set_current_win(Window win, Error *err) /// (always 'nomodified'). Also sets 'nomodeline' on the buffer. /// @param[out] err Error details, if any /// @return Buffer id, or 0 on error -/// -/// @see buf_open_scratch Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err) FUNC_API_SINCE(6) { @@ -1153,15 +1151,16 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err) /// @return Channel id, or 0 on error Integer nvim_open_term(Buffer buf, Dict(open_term) *opts, Error *err) FUNC_API_SINCE(7) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { buf_T *b = api_buf_ensure_loaded(buf, err); if (!b) { return 0; } - if (b == cmdwin_buf) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); + // Refuse to repurpose the cmdwin buffer. + if (bt_cmdwin(b)) { + api_set_error(err, kErrorTypeException, "%s", _(e_cmdwin)); return 0; } @@ -1376,7 +1375,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err) Boolean nvim_paste(uint64_t channel_id, String data, Boolean crlf, Integer phase, Arena *arena, Error *err) FUNC_API_SINCE(6) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { static bool cancelled = false; @@ -1438,7 +1437,7 @@ theend: void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Arena *arena, Error *err) FUNC_API_SINCE(6) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { yankreg_T reg[1] = { 0 }; VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, { @@ -1775,6 +1774,27 @@ void nvim__chan_set_detach(uint64_t channel_id, Boolean detach, Error *err) chan->detach = (bool)detach; } +/// Records the cmdwin scratchbuf and type, or clears both when type="" / buf=0. Internal use only. +/// +/// @param type ':', '/', '?' (first char only); empty to clear. +/// @param buf cmdwin buffer id, or 0 to clear. +/// @param[out] err Error details, if any. +void nvim__cmdwin_set(String type, Buffer buf, Error *err) + FUNC_API_SINCE(14) +{ + if (type.size == 0 || buf == 0) { + cmdwin_type = 0; + cmdwin_buf = NULL; + return; + } + buf_T *b = find_buffer_by_handle(buf, err); + if (ERROR_SET(err)) { + return; + } + cmdwin_type = (uint8_t)type.data[0]; + cmdwin_buf = b; +} + /// Gets information about a channel. /// /// See |nvim_list_uis()| for an example of how to get channel info. diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 880b716e03..4a9f4fedbd 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -201,16 +201,12 @@ /// /// @return |window-ID|, or 0 on error Window nvim_open_win(Buffer buf, Boolean enter, Dict(win_config) *config, Error *err) - FUNC_API_SINCE(6) FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_SINCE(6) FUNC_API_TEXTLOCK { buf_T *b = find_buffer_by_handle(buf, err); if (!b) { return 0; } - if ((cmdwin_type != 0 && enter) || b == cmdwin_buf) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return 0; - } bool is_split = HAS_KEY_X(config, split) || HAS_KEY_X(config, vertical); WinConfig fconfig = WIN_CONFIG_INIT; @@ -411,11 +407,6 @@ static bool win_can_move_tp(win_T *wp, tabpage_T *tp, Error *err) api_set_error(err, kErrorTypeException, "Cannot move autocmd window to another tabpage"); return false; } - // Can't move the cmdwin or its old curwin to a different tabpage. - if (wp == cmdwin_win || wp == cmdwin_old_curwin) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return false; - } return true; } diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index bdca9111bf..00042373d8 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -54,7 +54,7 @@ Buffer nvim_win_get_buf(Window win, Error *err) /// @param[out] err Error details, if any void nvim_win_set_buf(Window win, Buffer buf, Error *err) FUNC_API_SINCE(5) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { win_T *w = find_window_by_handle(win, err); buf_T *b = find_buffer_by_handle(buf, err); @@ -62,10 +62,8 @@ void nvim_win_set_buf(Window win, Buffer buf, Error *err) return; } - if (w == cmdwin_win || w == cmdwin_old_curwin || b == cmdwin_buf) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return; - } + // 'winfixbuf' on the cmdwin window prevents replacing its buffer; no + // separate cmdwin guard needed. win_set_buf(w, b, err); } @@ -352,10 +350,10 @@ Boolean nvim_win_is_valid(Window win) /// @param[out] err Error details, if any void nvim_win_hide(Window win, Error *err) FUNC_API_SINCE(7) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { win_T *w = find_window_by_handle(win, err); - if (!w || !can_close_in_cmdwin(w, err)) { + if (!w) { return; } @@ -381,10 +379,10 @@ void nvim_win_hide(Window win, Error *err) /// @param[out] err Error details, if any void nvim_win_close(Window win, Boolean force, Error *err) FUNC_API_SINCE(6) - FUNC_API_TEXTLOCK_ALLOW_CMDWIN + FUNC_API_TEXTLOCK { win_T *w = find_window_by_handle(win, err); - if (!w || !can_close_in_cmdwin(w, err)) { + if (!w) { return; } diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index bf9883ce24..812f45b8c0 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -1064,10 +1064,6 @@ static void do_arg_all(int count, int forceit, int keep_tabs) assert(firstwin != NULL); // satisfy coverity - if (cmdwin_type != 0) { - emsg(_(e_cmdwin)); - return; - } if (ARGCOUNT <= 0) { // Don't give an error message. We don't want it when the ":all" // command is in the .vimrc. diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index cf3761567d..cdd6ef294a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3631,6 +3631,13 @@ bool bt_prompt(buf_T *buf) return buf != NULL && buf->b_p_bt[0] == 'p'; } +/// @return true if "buf" is the |cmdwin| scratch buffer. +bool bt_cmdwin(const buf_T *buf) + FUNC_ATTR_PURE +{ + return buf != NULL && buf == cmdwin_buf; +} + /// Open a window for a number of buffers. void ex_buffer_all(exarg_T *eap) { @@ -4092,7 +4099,7 @@ char *buf_spname(buf_T *buf) if (buf->b_fname != NULL) { return buf->b_fname; } - if (buf == cmdwin_buf) { + if (bt_cmdwin(buf)) { return _("[Command Line]"); } if (bt_prompt(buf)) { @@ -4203,34 +4210,6 @@ void wipe_buffer(buf_T *buf, bool aucmd) } } -/// Creates or switches to a scratch buffer. :h special-buffers -/// Scratch buffer is: -/// - buftype=nofile bufhidden=hide noswapfile -/// - Always considered 'nomodified' -/// -/// @param bufnr Buffer to switch to, or 0 to create a new buffer. -/// @param bufname Buffer name, or NULL. -/// -/// @see curbufIsChanged() -/// -/// @return FAIL for failure, OK otherwise -int buf_open_scratch(handle_T bufnr, char *bufname) -{ - if (do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL) { - return FAIL; - } - if (bufname != NULL) { - apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); - setfname(curbuf, bufname, NULL, true); - apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); - } - set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL); - set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL); - set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL); - RESET_BINDING(curwin); - return OK; -} - bool buf_is_empty(buf_T *buf) { return buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, 1) == NUL; diff --git a/src/nvim/clipboard.c b/src/nvim/clipboard.c index 991b20986b..f58ed7d367 100644 --- a/src/nvim/clipboard.c +++ b/src/nvim/clipboard.c @@ -262,25 +262,3 @@ void end_batch_changes(void) set_clipboard(NUL, get_y_previous()); } } - -int save_batch_count(void) -{ - int save_count = batch_change_count; - batch_change_count = 0; - clipboard_delay_update = false; - if (clipboard_needs_update) { - clipboard_needs_update = false; - // unnamed ("implicit" clipboard) - set_clipboard(NUL, get_y_previous()); - } - return save_count; -} - -void restore_batch_count(int save_count) -{ - assert(batch_change_count == 0); - batch_change_count = save_count; - if (batch_change_count > 0) { - clipboard_delay_update = true; - } -} diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index c774a47bef..85e0269390 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1401,7 +1401,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b statuscol.sattrs = wlv.sattrs; statuscol.lnum = lnum; statuscol.foldinfo = foldinfo; - statuscol.width = win_col_off(wp) - (wp == cmdwin_win); + statuscol.width = win_col_off(wp); statuscol.sign_cul_id = use_cursor_line_highlight(wp, lnum) ? wlv.sign_cul_attr : 0; } else if (wlv.sign_cul_attr > 0) { wlv.sign_cul_attr = use_cursor_line_highlight(wp, lnum) ? syn_id2attr(wlv.sign_cul_attr) : 0; @@ -1758,14 +1758,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b assert(wlv.off == 0); - if (wp == cmdwin_win) { - // Draw the cmdline character. - draw_col_fill(&wlv, - schar_from_ascii(wlv.row == wlv.startrow ? cmdwin_type : ' '), - 1, - wlv.row == wlv.startrow ? win_hl_attr(wp, HLF_AT) : 0); - } - if (wlv.filler_todo > 0) { // nvim_buf_set_extmark: virt_lines_overflow int virt_rows_todo = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines); diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 44a5c98f00..77d0b134ae 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -740,13 +740,6 @@ static int insert_handle_key(InsertState *s) FALLTHROUGH; case Ctrl_C: // End input mode - if (s->c == Ctrl_C && cmdwin_type != 0) { - // Close the cmdline window. - cmdwin_result = K_IGNORE; - got_int = false; // don't stop executing autocommands et al - s->nomove = true; - return 0; // exit insert mode - } if (s->c == Ctrl_C && bt_prompt(curbuf)) { if (invoke_prompt_interrupt()) { if (!bt_prompt(curbuf)) { @@ -1107,11 +1100,6 @@ static int insert_handle_key(InsertState *s) } break; } - if (cmdwin_type != 0) { - // Execute the command in the cmdline window. - cmdwin_result = CAR; - return 0; - } if ((mod_mask & MOD_MASK_SHIFT) == 0 && bt_prompt(curbuf)) { prompt_invoke_callback(); if (!bt_prompt(curbuf)) { diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index df9b37af58..3f18ba9d0e 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -584,7 +584,7 @@ static dict_T *get_buffer_info(buf_T *buf) tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf)); tv_dict_add_nr(dict, S_LEN("hidden"), buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); - tv_dict_add_nr(dict, S_LEN("command"), buf == cmdwin_buf); + tv_dict_add_nr(dict, S_LEN("command"), bt_cmdwin(buf)); // Get a reference to buffer variables tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 02356b68c6..e51c9b082a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3602,6 +3602,11 @@ void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) shell_free_argv(argv); return; } + if (bt_cmdwin(curbuf)) { + emsg(_(e_cmdwin)); + shell_free_argv(argv); + return; + } if (curbuf->b_changed) { emsg(_("jobstart(...,{term=true}) requires unmodified buffer")); shell_free_argv(argv); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 2c22f0a97d..b81951d382 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -776,7 +776,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = xstrdup("preview"); } else if (wp->w_floating) { rettv->vval.v_string = xstrdup("popup"); - } else if (wp == cmdwin_win) { + } else if (bt_cmdwin(wp->w_buffer)) { rettv->vval.v_string = xstrdup("command"); } else if (bt_quickfix(wp->w_buffer)) { rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix")); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 469f12bff6..dafff2cf49 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2553,20 +2553,6 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum // If the current buffer was empty and has no file name, curbuf // is returned by buflist_new(), nothing to do here. if (buf != curbuf) { - // Should only be possible to get here if the cmdwin is closed, or - // if it's opening and its buffer hasn't been set yet (the new - // buffer is for it). - assert(cmdwin_buf == NULL); - - const int save_cmdwin_type = cmdwin_type; - win_T *const save_cmdwin_win = cmdwin_win; - win_T *const save_cmdwin_old_curwin = cmdwin_old_curwin; - - // BufLeave applies to the old buffer. - cmdwin_type = 0; - cmdwin_win = NULL; - cmdwin_old_curwin = NULL; - // Be careful: The autocommands may delete any buffer and change // the current buffer. // - If the buffer we are going to edit is deleted, give up. @@ -2582,10 +2568,6 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum set_bufref(&au_new_curbuf, buf); apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf); - cmdwin_type = save_cmdwin_type; - cmdwin_win = save_cmdwin_win; - cmdwin_old_curwin = save_cmdwin_old_curwin; - if (!bufref_valid(&au_new_curbuf)) { // New buffer has been deleted. delbuf_msg(new_name); // Frees new_name. diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index d09e448e61..f6b63133fe 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -23,38 +23,40 @@ local BUFNAME = 0x8000 local BUFUNL = 0x10000 local ARGOPT = 0x20000 local SBOXOK = 0x40000 -local CMDWIN = 0x80000 +local BUFLOCK_OK = 0x80000 -- Allowed when curbuf is `b_ro_locked`. Legacy name: CMDWIN. Implies LOCK_OK. local MODIFY = 0x100000 local FLAGS = 0x200000 -local LOCK_OK = 0x1000000 +local LOCK_OK = 0x1000000 -- Allowed when |textlock| is set. local PREVIEW = 0x8000000 local FILES = bit.bor(XFILE, EXTRA) local WORD1 = bit.bor(EXTRA, NOSPC) local FILE1 = bit.bor(FILES, NOSPC) M.flags = { - RANGE = RANGE, + BUFLOCK_OK = BUFLOCK_OK, DFLALL = DFLALL, + LOCK_OK = LOCK_OK, PREVIEW = PREVIEW, + RANGE = RANGE, } -- The following table is described in ex_cmds_defs.h file. M.cmds = { { command = 'append', - flags = bit.bor(BANG, RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(BANG, RANGE, ZEROR, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_append', }, { command = 'abbreviate', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'abclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abclear', }, @@ -72,13 +74,13 @@ M.cmds = { }, { command = 'amenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'anoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -138,25 +140,25 @@ M.cmds = { }, { command = 'ascii', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'do_ascii', }, { command = 'autocmd', - flags = bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_autocmd', }, { command = 'augroup', - flags = bit.bor(BANG, WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_autocmd', }, { command = 'aunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, @@ -180,13 +182,13 @@ M.cmds = { }, { command = 'badd', - flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_edit', }, { command = 'balt', - flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_edit', }, @@ -246,37 +248,37 @@ M.cmds = { }, { command = 'break', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_break', }, { command = 'breakadd', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_breakadd', }, { command = 'breakdel', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_breakdel', }, { command = 'breaklist', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_breaklist', }, { command = 'browse', - flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_wrongmodifier', }, { command = 'buffers', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'buflist_list', }, @@ -300,7 +302,7 @@ M.cmds = { }, { command = 'change', - flags = bit.bor(BANG, WHOLEFOLD, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(BANG, WHOLEFOLD, RANGE, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_change', }, @@ -318,13 +320,13 @@ M.cmds = { }, { command = 'cabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'cabclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abclear', }, @@ -360,13 +362,13 @@ M.cmds = { }, { command = 'call', - flags = bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_call', }, { command = 'catch', - flags = bit.bor(EXTRA, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_catch', }, @@ -408,7 +410,7 @@ M.cmds = { }, { command = 'cd', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, @@ -420,7 +422,7 @@ M.cmds = { }, { command = 'center', - flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_align', }, @@ -470,13 +472,13 @@ M.cmds = { }, { command = 'chdir', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, { command = 'changes', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_changes', }, @@ -488,7 +490,7 @@ M.cmds = { }, { command = 'checkpath', - flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BANG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_checkpath', }, @@ -506,7 +508,7 @@ M.cmds = { }, { command = 'clist', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'qf_list', }, @@ -518,31 +520,31 @@ M.cmds = { }, { command = 'close', - flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_WINDOWS', func = 'ex_close', }, { command = 'clearjumps', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_clearjumps', }, { command = 'cmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'cmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'cmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -566,25 +568,25 @@ M.cmds = { }, { command = 'cnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'cnoreabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'cnoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'copy', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_copymove', }, @@ -596,37 +598,37 @@ M.cmds = { }, { command = 'colorscheme', - flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_colorscheme', }, { command = 'command', - flags = bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_command', }, { command = 'comclear', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_comclear', }, { command = 'compiler', - flags = bit.bor(BANG, TRLBAR, WORD1, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, WORD1, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_compiler', }, { command = 'continue', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_continue', }, { command = 'confirm', - flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_wrongmodifier', }, @@ -638,7 +640,7 @@ M.cmds = { }, { command = 'const', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_let', }, @@ -674,19 +676,19 @@ M.cmds = { }, { command = 'cunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'cunabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'cunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, @@ -698,43 +700,43 @@ M.cmds = { }, { command = 'delete', - flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_operators', }, { command = 'delmarks', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_delmarks', }, { command = 'debug', - flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_debug', }, { command = 'debuggreedy', - flags = bit.bor(RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_debuggreedy', }, { command = 'defer', - flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_call', }, { command = 'delcommand', - flags = bit.bor(BANG, NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, NEEDARG, WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_delcommand', }, { command = 'delfunction', - flags = bit.bor(BANG, NEEDARG, WORD1, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, NEEDARG, WORD1, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_delfunction', }, @@ -746,7 +748,7 @@ M.cmds = { }, { command = 'display', - flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_display', }, @@ -794,7 +796,7 @@ M.cmds = { }, { command = 'digraphs', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_digraphs', }, @@ -806,19 +808,19 @@ M.cmds = { }, { command = 'dlist', - flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_findpat', }, { command = 'doautocmd', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_doautocmd', }, { command = 'doautoall', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_doautoall', }, @@ -830,7 +832,7 @@ M.cmds = { }, { command = 'dsearch', - flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_findpat', }, @@ -848,85 +850,85 @@ M.cmds = { }, { command = 'earlier', - flags = bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, EXTRA, NOSPC, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_later', }, { command = 'echo', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_echo', }, { command = 'echoerr', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_execute', }, { command = 'echohl', - flags = bit.bor(EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_echohl', }, { command = 'echomsg', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_execute', }, { command = 'echon', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_echo', }, { command = 'else', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_else', }, { command = 'elseif', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_else', }, { command = 'emenu', - flags = bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_emenu', }, { command = 'endif', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_endif', }, { command = 'endfunction', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_endfunction', }, { command = 'endfor', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_endwhile', }, { command = 'endtry', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_endtry', }, { command = 'endwhile', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_endwhile', }, @@ -938,7 +940,7 @@ M.cmds = { }, { command = 'eval', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_eval', }, @@ -950,13 +952,13 @@ M.cmds = { }, { command = 'execute', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_execute', }, { command = 'exit', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_exit', }, @@ -974,13 +976,13 @@ M.cmds = { }, { command = 'files', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'buflist_list', }, { command = 'filetype', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_filetype', }, @@ -998,13 +1000,13 @@ M.cmds = { }, { command = 'finally', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_finally', }, { command = 'finish', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_finish', }, @@ -1016,13 +1018,13 @@ M.cmds = { }, { command = 'fold', - flags = bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_fold', }, { command = 'foldclose', - flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_foldopen', }, @@ -1040,19 +1042,19 @@ M.cmds = { }, { command = 'foldopen', - flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_foldopen', }, { command = 'for', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_while', }, { command = 'function', - flags = bit.bor(EXTRA, BANG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, BANG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_function', }, @@ -1064,13 +1066,13 @@ M.cmds = { }, { command = 'global', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, DFLALL, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, DFLALL, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_global', }, { command = 'goto', - flags = bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_goto', }, @@ -1088,13 +1090,13 @@ M.cmds = { }, { command = 'gui', - flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_nogui', }, { command = 'gvim', - flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_nogui', }, @@ -1118,13 +1120,13 @@ M.cmds = { }, { command = 'helptags', - flags = bit.bor(NEEDARG, FILES, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, FILES, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_helptags', }, { command = 'highlight', - flags = bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_highlight', }, @@ -1136,7 +1138,7 @@ M.cmds = { }, { command = 'history', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_history', }, @@ -1148,25 +1150,25 @@ M.cmds = { }, { command = 'insert', - flags = bit.bor(BANG, RANGE, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(BANG, RANGE, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_append', }, { command = 'iabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'iabclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abclear', }, { command = 'if', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_if', }, @@ -1178,61 +1180,61 @@ M.cmds = { }, { command = 'ilist', - flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_findpat', }, { command = 'imap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'imapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'imenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'inoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'inoreabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'inoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'intro', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_intro', }, { command = 'iput', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_iput', }, { command = 'isearch', - flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_findpat', }, @@ -1244,37 +1246,37 @@ M.cmds = { }, { command = 'iunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'iunabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'iunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'join', - flags = bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_join', }, { command = 'jumps', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_jumps', }, { command = 'k', - flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_mark', }, @@ -1304,7 +1306,7 @@ M.cmds = { }, { command = 'list', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_print', }, @@ -1334,7 +1336,7 @@ M.cmds = { }, { command = 'language', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_language', }, @@ -1364,7 +1366,7 @@ M.cmds = { }, { command = 'later', - flags = bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, EXTRA, NOSPC, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_later', }, @@ -1394,13 +1396,13 @@ M.cmds = { }, { command = 'lcd', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, { command = 'lchdir', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, @@ -1418,7 +1420,7 @@ M.cmds = { }, { command = 'left', - flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_align', }, @@ -1430,7 +1432,7 @@ M.cmds = { }, { command = 'let', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_let', }, @@ -1516,19 +1518,19 @@ M.cmds = { }, { command = 'llist', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'qf_list', }, { command = 'lmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'lmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, @@ -1540,7 +1542,7 @@ M.cmds = { }, { command = 'lnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, @@ -1570,7 +1572,7 @@ M.cmds = { }, { command = 'loadkeymap', - flags = bit.bor(CMDWIN, LOCK_OK), + flags = bit.bor(BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_loadkeymap', }, @@ -1582,7 +1584,7 @@ M.cmds = { }, { command = 'lockvar', - flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_lockvar', }, @@ -1630,25 +1632,25 @@ M.cmds = { }, { command = 'lunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'lua', - flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_lua', }, { command = 'luado', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_luado', }, { command = 'luafile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_luafile', }, @@ -1672,7 +1674,7 @@ M.cmds = { }, { command = 'ls', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'buflist_list', }, @@ -1684,13 +1686,13 @@ M.cmds = { }, { command = 'move', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_copymove', }, { command = 'mark', - flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_mark', }, @@ -1702,49 +1704,49 @@ M.cmds = { }, { command = 'map', - flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'mapclear', - flags = bit.bor(EXTRA, BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'marks', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_marks', }, { command = 'match', - flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_match', }, { command = 'menu', - flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'menutranslate', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menutranslate', }, { command = 'messages', - flags = bit.bor(EXTRA, TRLBAR, RANGE, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, RANGE, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_messages', }, { command = 'mkexrc', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mkrc', }, @@ -1762,7 +1764,7 @@ M.cmds = { }, { command = 'mkvimrc', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mkrc', }, @@ -1774,19 +1776,19 @@ M.cmds = { }, { command = 'mode', - flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mode', }, { command = 'mzscheme', - flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK, SBOXOK), + flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, BUFLOCK_OK, LOCK_OK, SBOXOK), addr_type = 'ADDR_LINES', func = 'ex_script_ni', }, { command = 'mzfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_ni', }, @@ -1804,37 +1806,37 @@ M.cmds = { }, { command = 'nmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'nmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'nmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'nnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'nnoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'noremap', - flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, @@ -1846,19 +1848,19 @@ M.cmds = { }, { command = 'nohlsearch', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_nohlsearch', }, { command = 'noreabbrev', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, { command = 'noremenu', - flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -1870,49 +1872,49 @@ M.cmds = { }, { command = 'normal', - flags = bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_normal', }, { command = 'number', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_print', }, { command = 'nunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'nunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'oldfiles', - flags = bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_oldfiles', }, { command = 'omap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'omapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'omenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -1924,13 +1926,13 @@ M.cmds = { }, { command = 'onoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'onoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -1942,31 +1944,31 @@ M.cmds = { }, { command = 'ounmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'ounmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'ownsyntax', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_ownsyntax', }, { command = 'print', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, SBOXOK), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK, SBOXOK), addr_type = 'ADDR_LINES', func = 'ex_print', }, { command = 'packadd', - flags = bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_packadd', }, @@ -1978,7 +1980,7 @@ M.cmds = { }, { command = 'packloadall', - flags = bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_packloadall', }, @@ -2002,19 +2004,19 @@ M.cmds = { }, { command = 'perl', - flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_perl', }, { command = 'perldo', - flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_perldo', }, { command = 'perlfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_perlfile', }, @@ -2032,7 +2034,7 @@ M.cmds = { }, { command = 'popup', - flags = bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_popup', }, @@ -2056,13 +2058,13 @@ M.cmds = { }, { command = 'profile', - flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_profile', }, { command = 'profdel', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_breakdel', }, @@ -2128,85 +2130,85 @@ M.cmds = { }, { command = 'put', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_put', }, { command = 'pwd', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_pwd', }, { command = 'python', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_python3', }, { command = 'pydo', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_pydo3', }, { command = 'pyfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_py3file', }, { command = 'py3', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_python3', }, { command = 'py3do', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_pydo3', }, { command = 'python3', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_python3', }, { command = 'py3file', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_py3file', }, { command = 'pyx', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_python3', }, { command = 'pyxdo', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_pydo3', }, { command = 'pythonx', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_python3', }, { command = 'pyxfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_py3file', }, { command = 'quit', - flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_WINDOWS', func = 'ex_quit', }, @@ -2218,13 +2220,24 @@ M.cmds = { }, { command = 'qall', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_quitall', }, { command = 'read', - flags = bit.bor(BANG, RANGE, WHOLEFOLD, FILE1, ARGOPT, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor( + BANG, + RANGE, + WHOLEFOLD, + FILE1, + ARGOPT, + TRLBAR, + ZEROR, + BUFLOCK_OK, + LOCK_OK, + MODIFY + ), addr_type = 'ADDR_LINES', func = 'ex_read', }, @@ -2236,43 +2249,43 @@ M.cmds = { }, { command = 'redo', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_redo', }, { command = 'redir', - flags = bit.bor(BANG, FILES, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILES, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_redir', }, { command = 'redraw', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_redraw', }, { command = 'redrawstatus', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_redrawstatus', }, { command = 'redrawtabline', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_redrawtabline', }, { command = 'registers', - flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_display', }, { command = 'resize', - flags = bit.bor(RANGE, TRLBAR, WORD1, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, TRLBAR, WORD1, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_resize', }, @@ -2284,13 +2297,13 @@ M.cmds = { }, { command = 'retab', - flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, DFLALL, BANG, WORD1, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, DFLALL, BANG, WORD1, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_retab', }, { command = 'return', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_return', }, @@ -2302,7 +2315,7 @@ M.cmds = { }, { command = 'right', - flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_align', }, @@ -2314,13 +2327,13 @@ M.cmds = { }, { command = 'rshada', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_shada', }, { command = 'runtime', - flags = bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_runtime', }, @@ -2332,31 +2345,31 @@ M.cmds = { }, { command = 'ruby', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_ruby', }, { command = 'rubydo', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_rubydo', }, { command = 'rubyfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_rubyfile', }, { command = 'rviminfo', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_shada', }, { command = 'substitute', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, PREVIEW), addr_type = 'ADDR_LINES', func = 'ex_substitute', preview_func = 'ex_substitute_preview', @@ -2387,7 +2400,7 @@ M.cmds = { }, { command = 'saveas', - flags = bit.bor(BANG, FILE1, ARGOPT, CMDWIN, LOCK_OK, TRLBAR), + flags = bit.bor(BANG, FILE1, ARGOPT, BUFLOCK_OK, LOCK_OK, TRLBAR), addr_type = 'ADDR_NONE', func = 'ex_write', }, @@ -2447,37 +2460,37 @@ M.cmds = { }, { command = 'scriptnames', - flags = bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_scriptnames', }, { command = 'scriptencoding', - flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_scriptencoding', }, { command = 'set', - flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK), + flags = bit.bor(BANG, TRLBAR, EXTRA, BUFLOCK_OK, LOCK_OK, SBOXOK), addr_type = 'ADDR_NONE', func = 'ex_set', }, { command = 'setfiletype', - flags = bit.bor(TRLBAR, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_setfiletype', }, { command = 'setglobal', - flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK), + flags = bit.bor(BANG, TRLBAR, EXTRA, BUFLOCK_OK, LOCK_OK, SBOXOK), addr_type = 'ADDR_NONE', func = 'ex_set', }, { command = 'setlocal', - flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK), + flags = bit.bor(BANG, TRLBAR, EXTRA, BUFLOCK_OK, LOCK_OK, SBOXOK), addr_type = 'ADDR_NONE', func = 'ex_set', }, @@ -2495,25 +2508,25 @@ M.cmds = { }, { command = 'simalt', - flags = bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_ni', }, { command = 'sign', - flags = bit.bor(NEEDARG, RANGE, EXTRA, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, RANGE, EXTRA, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_sign', }, { command = 'silent', - flags = bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_wrongmodifier', }, { command = 'sleep', - flags = bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_sleep', }, @@ -2525,26 +2538,26 @@ M.cmds = { }, { command = 'smagic', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, PREVIEW), addr_type = 'ADDR_LINES', func = 'ex_submagic', preview_func = 'ex_submagic_preview', }, { command = 'smap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'smapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'smenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -2556,26 +2569,26 @@ M.cmds = { }, { command = 'snomagic', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, PREVIEW), addr_type = 'ADDR_LINES', func = 'ex_submagic', preview_func = 'ex_submagic_preview', }, { command = 'snoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'snoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'source', - flags = bit.bor(RANGE, DFLALL, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, BANG, FILE1, TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_source', }, @@ -2647,7 +2660,7 @@ M.cmds = { }, { command = 'stop', - flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BANG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_stop', }, @@ -2659,25 +2672,25 @@ M.cmds = { }, { command = 'startinsert', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_startinsert', }, { command = 'startgreplace', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_startinsert', }, { command = 'startreplace', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_startinsert', }, { command = 'stopinsert', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_stopinsert', }, @@ -2701,19 +2714,19 @@ M.cmds = { }, { command = 'sunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'sunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'suspend', - flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BANG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_stop', }, @@ -2725,19 +2738,19 @@ M.cmds = { }, { command = 'swapname', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_swapname', }, { command = 'syntax', - flags = bit.bor(EXTRA, NOTRLCOM, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_syntax', }, { command = 'syntime', - flags = bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, WORD1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_syntime', }, @@ -2749,19 +2762,19 @@ M.cmds = { }, { command = 't', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_copymove', }, { command = 'tcd', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, { command = 'tchdir', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_cd', }, @@ -2779,7 +2792,7 @@ M.cmds = { }, { command = 'tags', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'do_tags', }, @@ -2791,7 +2804,7 @@ M.cmds = { }, { command = 'tabclose', - flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_TABS', func = 'ex_tabclose', }, @@ -2845,7 +2858,7 @@ M.cmds = { }, { command = 'tabonly', - flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_TABS', func = 'ex_tabonly', }, @@ -2869,31 +2882,31 @@ M.cmds = { }, { command = 'tabs', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_tabs', }, { command = 'tcl', - flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_script_ni', }, { command = 'tcldo', - flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_ni', }, { command = 'tclfile', - flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, FILE1, NEEDARG, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_ni', }, { command = 'terminal', - flags = bit.bor(BANG, FILES, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILES, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_terminal', }, @@ -2905,7 +2918,7 @@ M.cmds = { }, { command = 'throw', - flags = bit.bor(EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NEEDARG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_throw', }, @@ -2923,37 +2936,37 @@ M.cmds = { }, { command = 'tlmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'tlnoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'tlunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'tmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'tmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'tmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, @@ -2965,7 +2978,7 @@ M.cmds = { }, { command = 'tnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, @@ -2995,7 +3008,7 @@ M.cmds = { }, { command = 'try', - flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_try', }, @@ -3007,37 +3020,37 @@ M.cmds = { }, { command = 'tunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'tunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'undo', - flags = bit.bor(BANG, RANGE, COUNT, ZEROR, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, RANGE, COUNT, ZEROR, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_undo', }, { command = 'undojoin', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_undojoin', }, { command = 'undolist', - flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_undolist', }, { command = 'unabbreviate', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_abbreviate', }, @@ -3055,31 +3068,31 @@ M.cmds = { }, { command = 'unlet', - flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unlet', }, { command = 'unlockvar', - flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_lockvar', }, { command = 'unmap', - flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'unmenu', - flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'unsilent', - flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_wrongmodifier', }, @@ -3091,25 +3104,25 @@ M.cmds = { }, { command = 'uptime', - flags = bit.bor(CMDWIN, LOCK_OK), + flags = bit.bor(BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_uptime', }, { command = 'vglobal', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, DFLALL, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, DFLALL, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_global', }, { command = 'version', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_version', }, { command = 'verbose', - flags = bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_wrongmodifier', }, @@ -3151,25 +3164,25 @@ M.cmds = { }, { command = 'vmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'vmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'vmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'vnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, @@ -3181,7 +3194,7 @@ M.cmds = { }, { command = 'vnoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, @@ -3193,19 +3206,19 @@ M.cmds = { }, { command = 'vunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'vunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'write', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_write', }, @@ -3217,13 +3230,13 @@ M.cmds = { }, { command = 'wall', - flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK, ARGOPT), + flags = bit.bor(BANG, TRLBAR, BUFLOCK_OK, LOCK_OK, ARGOPT), addr_type = 'ADDR_NONE', func = 'do_wqall', }, { command = 'while', - flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_while', }, @@ -3235,7 +3248,7 @@ M.cmds = { }, { command = 'wincmd', - flags = bit.bor(NEEDARG, WORD1, RANGE, COUNT, CMDWIN, LOCK_OK), + flags = bit.bor(NEEDARG, WORD1, RANGE, COUNT, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_wincmd', }, @@ -3247,7 +3260,7 @@ M.cmds = { }, { command = 'winpos', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_ni', }, @@ -3277,7 +3290,7 @@ M.cmds = { }, { command = 'wshada', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_shada', }, @@ -3289,13 +3302,13 @@ M.cmds = { }, { command = 'wviminfo', - flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(BANG, FILE1, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_shada', }, { command = 'xit', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_exit', }, @@ -3307,55 +3320,55 @@ M.cmds = { }, { command = 'xmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'xmapclear', - flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_mapclear', }, { command = 'xmenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'xnoremap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_map', }, { command = 'xnoremenu', - flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_OTHER', func = 'ex_menu', }, { command = 'xunmap', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_unmap', }, { command = 'xunmenu', - flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK), + flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_NONE', func = 'ex_menu', }, { command = 'yank', - flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_operators', }, { command = 'z', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, FLAGS, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_z', }, @@ -3363,56 +3376,56 @@ M.cmds = { { command = '!', enum = 'CMD_bang', - flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILES, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILES, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_bang', }, { command = '#', enum = 'CMD_pound', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_print', }, { command = '&', enum = 'CMD_and', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_substitute', }, { command = '<', enum = 'CMD_lshift', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_operators', }, { command = '=', enum = 'CMD_equal', - flags = bit.bor(RANGE, EXTRA, DFLALL, ARGOPT, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, EXTRA, DFLALL, ARGOPT, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_equal', }, { command = '>', enum = 'CMD_rshift', - flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_operators', }, { command = '@', enum = 'CMD_at', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, BUFLOCK_OK, LOCK_OK), addr_type = 'ADDR_LINES', func = 'ex_at', }, { command = '~', enum = 'CMD_tilde', - flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY), + flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, MODIFY), addr_type = 'ADDR_LINES', func = 'ex_substitute', }, diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index aa9bef9c68..9e7738fdc1 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -54,12 +54,12 @@ #define EX_BUFUNL 0x10000U // accepts unlisted buffer too #define EX_ARGOPT 0x20000U // allow "++opt=val" argument #define EX_SBOXOK 0x40000U // allowed in the sandbox -#define EX_CMDWIN 0x80000U // allowed in cmdline window +#define EX_BUFLOCK_OK 0x80000U // Command is allowed when curbuf is `b_ro_locked` (e.g. during + // a quickfix or diff critical section). Legacy name: EX_CMDWIN. + // Implies EX_LOCK_OK. #define EX_MODIFY 0x100000U // forbidden in non-'modifiable' buffer #define EX_FLAGS 0x200000U // allow flags after count in argument -#define EX_LOCK_OK 0x1000000U // command can be executed when textlock is - // set; when missing disallows editing another - // buffer when curbuf->b_ro_locked is set +#define EX_LOCK_OK 0x1000000U // Command allowed when |textlock| is set. EX_BUFLOCK_OK is per-buffer. #define EX_KEEPSCRIPT 0x4000000U // keep sctx of where command was invoked #define EX_PREVIEW 0x8000000U // allow incremental command preview #define EX_ARGSPACE 0x40000000U // completion: keep spaces in arg lead diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index cda4353484..e8dd3e9727 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1831,11 +1831,6 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) goto end; } if (!IS_USER_CMDIDX(eap->cmdidx)) { - if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) { - // Command not allowed in the command line window - errormsg = _(e_cmdwin); - goto end; - } if (text_locked() && !(eap->argt & EX_LOCK_OK)) { // Command not allowed when text is locked errormsg = _(get_text_locked_msg()); @@ -1846,7 +1841,7 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) // Do allow ":checktime" (it is postponed). // Do allow ":edit" (check for an argument later). // Do allow ":file" with no arguments - if (!(eap->argt & EX_CMDWIN) + if (!(eap->argt & EX_BUFLOCK_OK) && eap->cmdidx != CMD_checktime && eap->cmdidx != CMD_edit && !(eap->cmdidx == CMD_file && *eap->arg == NUL) @@ -2226,11 +2221,6 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter } if (!IS_USER_CMDIDX(ea.cmdidx)) { - if (cmdwin_type != 0 && !(ea.argt & EX_CMDWIN)) { - // Command not allowed in the command line window - errormsg = _(e_cmdwin); - goto doend; - } if (text_locked() && !(ea.argt & EX_LOCK_OK)) { // Command not allowed when text is locked errormsg = _(get_text_locked_msg()); @@ -2242,7 +2232,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter // Do allow ":checktime" (it is postponed). // Do allow ":edit" (check for an argument later). // Do allow ":file" with no arguments (check for an argument later). - if (!(ea.argt & EX_CMDWIN) + if (!(ea.argt & EX_BUFLOCK_OK) && ea.cmdidx != CMD_checktime && ea.cmdidx != CMD_edit && ea.cmdidx != CMD_file @@ -4875,10 +4865,6 @@ bool before_quit_autocmds(win_T *wp, bool quit_all, bool forceit) /// ":{nr}quit": quit window {nr} static void ex_quit(exarg_T *eap) { - if (cmdwin_type != 0) { - cmdwin_result = Ctrl_C; - return; - } // Don't quit while editing the command line. if (text_locked()) { text_locked_msg(); @@ -4951,13 +4937,6 @@ static void ex_cquit(exarg_T *eap) /// Returns FAIL when quitting should be aborted. int before_quit_all(exarg_T *eap) { - if (cmdwin_type != 0) { - cmdwin_result = eap->forceit - ? K_XF1 // open_cmdwin() takes care of this - : K_XF2; - return FAIL; - } - // Don't quit while editing the command line. if (text_locked()) { text_locked_msg(); @@ -5221,9 +5200,7 @@ static void ex_close(exarg_T *eap) { win_T *win = NULL; int winnr = 0; - if (cmdwin_type != 0) { - cmdwin_result = Ctrl_C; - } else if (!text_locked() && !curbuf_locked()) { + if (!text_locked() && !curbuf_locked()) { if (eap->addr_count == 0) { ex_win_close(eap->forceit, curwin, NULL); } else { @@ -5298,11 +5275,6 @@ void ex_win_close(int forceit, win_T *win, tabpage_T *tp) /// ":tabclose N": close tab page N. static void ex_tabclose(exarg_T *eap) { - if (cmdwin_type != 0) { - cmdwin_result = K_IGNORE; - return; - } - if (first_tabpage->tp_next == NULL) { emsg(_("E784: Cannot close last tab page")); return; @@ -5333,11 +5305,6 @@ static void ex_tabclose(exarg_T *eap) /// ":tabonly": close all tab pages except the current one static void ex_tabonly(exarg_T *eap) { - if (cmdwin_type != 0) { - cmdwin_result = K_IGNORE; - return; - } - if (first_tabpage->tp_next == NULL) { msg(_("Already only one tab page"), 0); return; @@ -5513,10 +5480,6 @@ static void ex_stop(exarg_T *eap) /// ":exit", ":xit" and ":wq": Write file and quit the current window. static void ex_exit(exarg_T *eap) { - if (cmdwin_type != 0) { - cmdwin_result = Ctrl_C; - return; - } // Don't quit while editing the command line. if (text_locked()) { text_locked_msg(); @@ -6182,7 +6145,7 @@ void do_exedit(exarg_T *eap, win_T *old_curwin) redraw_all_later(UPD_NOT_VALID); pending_exmode_active = true; - normal_enter(false, true); + normal_enter(true); pending_exmode_active = false; RedrawingDisabled = save_rd; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index dbbec988ce..b832f0126b 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -32,6 +32,9 @@ #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/vars.h" +#include "nvim/event/defs.h" +#include "nvim/event/loop.h" +#include "nvim/event/multiqueue.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" @@ -46,7 +49,9 @@ #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" +#include "nvim/lua/executor.h" #include "nvim/macros_defs.h" +#include "nvim/main.h" #include "nvim/map_defs.h" #include "nvim/mapping.h" #include "nvim/mark.h" @@ -226,9 +231,6 @@ static int cedit_key = -1; ///< key value of 'cedit' option static handle_T cmdpreview_bufnr = 0; static int cmdpreview_ns = 0; -static const char e_active_window_or_buffer_changed_or_deleted[] - = N_("E199: Active window or buffer changed or deleted"); - static void trigger_cmd_autocmd(int typechar, event_T evt) { char typestr[2] = { (char)typechar, NUL }; @@ -1480,11 +1482,10 @@ static int command_line_execute(VimState *state, int key) } } - if (s->c == cedit_key || s->c == K_CMDWIN) { - // TODO(vim): why is ex_normal_busy checked here? - if ((s->c == K_CMDWIN || ex_normal_busy == 0) - && got_int == false) { - // Open a window to edit the command line (and history). + if (s->c == cedit_key) { + // c_CTRL-F: Open cmdwin. Return Ctrl_C so the current cmdline cancels; when the user + // confirms/cancels cmdwin, it will reopen cmdline with the command pre-filled. + if (ex_normal_busy == 0 && got_int == false) { s->c = open_cmdwin(); s->some_key_typed = true; } @@ -3116,9 +3117,6 @@ int check_opt_wim(void) /// another window or buffer. True when editing the command line etc. bool text_locked(void) { - if (cmdwin_type != 0) { - return true; - } if (expr_map_locked()) { return true; } @@ -3134,11 +3132,7 @@ void text_locked_msg(void) const char *get_text_locked_msg(void) { - if (cmdwin_type != 0) { - return e_cmdwin; - } else { - return e_textlock; - } + return e_textlock; } /// Check for text, window or buffer locked. @@ -3726,10 +3720,8 @@ void cmdline_screen_cleared(void) CmdlineInfo *line = ccline.prev_ccline; while (prev_level > 0 && line) { if (line->level == prev_level) { - // don't redraw a cmdline already shown in the cmdline window - if (prev_level != cmdwin_level) { - line->redraw_state = kCmdRedrawAll; - } + // Always redraw (cmdwin is not special since #40312). + line->redraw_state = kCmdRedrawAll; prev_level--; } line = line->prev_ccline; @@ -4579,292 +4571,64 @@ const char *did_set_cedit(optset_T *args) return NULL; } -/// Open a window on the current command line and history. Allow editing in -/// the window. Returns when the window is closed. -/// Returns: -/// CR if the command is to be executed -/// Ctrl_C if it is to be abandoned -/// K_IGNORE if editing continues -static int open_cmdwin(void) +typedef struct { + int firstc; + char *content; // owned + int pos; +} CmdwinOpenArgs; + +/// Deferred event: opens cmdwin after the current cmdline-reader exits. (Can't use vim.schedule, +/// where the event could fire _during typeahead_; revisit after #40380). +static void open_cmdwin_event(void **argv) { - bufref_T old_curbuf; - bufref_T bufref; - win_T *old_curwin = curwin; - int i; - garray_T winsizes; - int save_restart_edit = restart_edit; - int save_State = State; - bool save_exmode = exmode_active; - bool save_cmdmsg_rl = cmdmsg_rl; - - // Can't do this when text or buffer is locked. - // Can't do this recursively. Can't do it when typing a password. - if (text_or_buf_locked() || cmdwin_type != 0 || cmdline_star > 0) { - beep_flush(); - return K_IGNORE; - } - - set_bufref(&old_curbuf, curbuf); - - // Save current window sizes. - win_size_save(&winsizes); - - // When using completion in Insert mode with = one can open the - // command line window, but we don't want the popup menu then. - pum_undisplay(true); - - // don't use a new tab page - cmdmod.cmod_tab = 0; - cmdmod.cmod_flags |= CMOD_NOSWAPFILE; - - // Create a window for the command-line buffer. - if (win_split((int)p_cwh, WSP_BOT) == FAIL) { - beep_flush(); - ga_clear(&winsizes); - return K_IGNORE; - } - // win_split() autocommands may have messed with the old window or buffer. - // Treat it as abandoning this command-line. - if (!win_valid(old_curwin) || curwin == old_curwin || !bufref_valid(&old_curbuf) - || old_curwin->w_buffer != old_curbuf.br_buf) { - beep_flush(); - ga_clear(&winsizes); - return Ctrl_C; - } - // Don't let quitting the More prompt make this fail. - got_int = false; - - // Set "cmdwin_..." variables before any autocommands may mess things up. - cmdwin_type = get_cmdline_type(); - cmdwin_level = ccline.level; - cmdwin_win = curwin; - cmdwin_old_curwin = old_curwin; - - // Create empty command-line buffer. Be especially cautious of BufLeave - // autocommands from do_ecmd(), as cmdwin restrictions do not apply to them! - const int newbuf_status = buf_open_scratch(0, NULL); - const bool cmdwin_valid = win_valid(cmdwin_win); - if (newbuf_status == FAIL || !cmdwin_valid || curwin != cmdwin_win || !win_valid(old_curwin) - || !bufref_valid(&old_curbuf) || old_curwin->w_buffer != old_curbuf.br_buf) { - if (newbuf_status == OK) { - set_bufref(&bufref, curbuf); - } - if (cmdwin_valid && !last_window(cmdwin_win)) { - win_close(cmdwin_win, true, false); - } - // win_close() autocommands may have already deleted the buffer. - if (newbuf_status == OK && bufref_valid(&bufref) && bufref.br_buf != curbuf) { - close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false, false); - } - - cmdwin_type = 0; - cmdwin_level = 0; - cmdwin_win = NULL; - cmdwin_old_curwin = NULL; - beep_flush(); - ga_clear(&winsizes); - return Ctrl_C; - } - cmdwin_buf = curbuf; - - // Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer. - set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL); - curbuf->b_p_ma = true; - curwin->w_p_fen = false; - curwin->w_p_rl = cmdmsg_rl; - cmdmsg_rl = false; - - // Don't allow switching to another buffer. - curbuf->b_ro_locked++; - - // Showing the prompt may have set need_wait_return, reset it. - need_wait_return = false; - - const int histtype = hist_char2type(cmdwin_type); - if (histtype == HIST_CMD || histtype == HIST_DEBUG) { - if (p_wc == TAB) { - add_map("", "", MODE_INSERT, true); - add_map("", "a", MODE_NORMAL, true); - } - set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL); - } - curbuf->b_ro_locked--; - - // Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin - // sets 'textwidth' to 78). - curbuf->b_p_tw = 0; - - // Fill the buffer with the history. - init_history(); - if (get_hislen() > 0 && histtype != HIST_INVALID) { - i = *get_hisidx(histtype); - if (i >= 0) { - linenr_T lnum = 0; - do { - if (++i == get_hislen()) { - i = 0; - } - if (get_histentry(histtype)[i].hisstr != NULL) { - ml_append(lnum++, get_histentry(histtype)[i].hisstr, 0, false); - } - } while (i != *get_hisidx(histtype)); - } - } - - // Replace the empty last line with the current command-line and put the - // cursor there. - ml_replace(curbuf->b_ml.ml_line_count, ccline.cmdbuff, true); - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - curwin->w_cursor.col = ccline.cmdpos; - changed_line_abv_curs(); - invalidate_botline_win(curwin); - ui_ext_cmdline_hide(false); - redraw_later(curwin, UPD_SOME_VALID); - - // No Ex mode here! - exmode_active = false; - - State = MODE_NORMAL; - check_cursor(curwin); - setmouse(); - clear_showcmd(); - - // Reset here so it can be set by a CmdwinEnter autocommand. - cmdwin_result = 0; - - // Trigger CmdwinEnter autocommands. - trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINENTER); - if (restart_edit != 0) { // autocmd with ":startinsert" - stuffcharReadbuff(K_NOP); - } - - i = RedrawingDisabled; - RedrawingDisabled = 0; - int save_count = save_batch_count(); - - // Call the main loop until or CTRL-C is typed. - normal_enter(true, false); - - RedrawingDisabled = i; - restore_batch_count(save_count); - - const bool save_KeyTyped = KeyTyped; - - // Trigger CmdwinLeave autocommands. - trigger_cmd_autocmd(cmdwin_type, EVENT_CMDWINLEAVE); - - // Restore KeyTyped in case it is modified by autocommands - KeyTyped = save_KeyTyped; - - cmdwin_type = 0; - cmdwin_level = 0; - cmdwin_buf = NULL; - cmdwin_win = NULL; - cmdwin_old_curwin = NULL; - - exmode_active = save_exmode; - - // Safety check: The old window or buffer was changed or deleted: It's a bug - // when this happens! - if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf) - || old_curwin->w_buffer != old_curbuf.br_buf) { - cmdwin_result = Ctrl_C; - emsg(_(e_active_window_or_buffer_changed_or_deleted)); - } else { - win_T *wp; - // autocmds may abort script processing - if (aborting() && cmdwin_result != K_IGNORE) { - cmdwin_result = Ctrl_C; - } - // Set the new command line from the cmdline buffer. - dealloc_cmdbuff(); - - if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed - const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; - size_t plen = (cmdwin_result == K_XF2) ? 2 : 3; - - if (histtype == HIST_CMD) { - // Execute the command directly. - ccline.cmdbuff = xmemdupz(p, plen); - ccline.cmdlen = (int)plen; - ccline.cmdbufflen = (int)plen + 1; - cmdwin_result = CAR; - } else { - // First need to cancel what we were doing. - stuffcharReadbuff(':'); - stuffReadbuff(p); - stuffcharReadbuff(CAR); - } - } else if (cmdwin_result == Ctrl_C) { - // :q or :close, don't execute any command - // and don't modify the cmd window. - ccline.cmdbuff = NULL; - } else { - ccline.cmdlen = get_cursor_line_len(); - ccline.cmdbufflen = ccline.cmdlen + 1; - ccline.cmdbuff = xstrnsave(get_cursor_line_ptr(), (size_t)ccline.cmdlen); - } - - if (ccline.cmdbuff == NULL) { - ccline.cmdbuff = xmemdupz("", 0); - ccline.cmdlen = 0; - ccline.cmdbufflen = 1; - ccline.cmdpos = 0; - cmdwin_result = Ctrl_C; - } else { - ccline.cmdpos = curwin->w_cursor.col; - // If the cursor is on the last character, it probably should be after it. - if (ccline.cmdpos == ccline.cmdlen - 1 || ccline.cmdpos > ccline.cmdlen) { - ccline.cmdpos = ccline.cmdlen; - } - if (cmdwin_result == K_IGNORE) { - ccline.cmdspos = cmd_screencol(ccline.cmdpos); - redrawcmd(); - } - } - - // Avoid command-line window first character being concealed. - curwin->w_p_cole = 0; - // First go back to the original window. - wp = curwin; - set_bufref(&bufref, curbuf); - skip_win_fix_cursor = true; - win_goto(old_curwin); - - // win_goto() may trigger an autocommand that already closes the - // cmdline window. - if (win_valid(wp) && wp != curwin) { - win_close(wp, true, false); - } - - // win_close() may have already wiped the buffer when 'bh' is - // set to 'wipe', autocommands may have closed other windows - if (bufref_valid(&bufref) && bufref.br_buf != curbuf) { - close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false, false); - } - - // Restore window sizes. - win_size_restore(&winsizes); - skip_win_fix_cursor = false; - } - - ga_clear(&winsizes); - restart_edit = save_restart_edit; - cmdmsg_rl = save_cmdmsg_rl; - - State = save_State; - may_trigger_modechanged(); - setmouse(); - setcursor(); - - return cmdwin_result; + CmdwinOpenArgs *a = argv[0]; + char fc[2] = { (char)a->firstc, 0 }; + typval_T tv_args[] = { + { .v_type = VAR_STRING, .vval.v_string = fc }, + { .v_type = VAR_STRING, .vval.v_string = a->content ? a->content : "" }, + { .v_type = VAR_NUMBER, .vval.v_number = a->pos + 1 }, + { .v_type = VAR_UNKNOWN }, + }; + nlua_call_vimfn("vim._core.cmdwin", "open", tv_args, NULL); + xfree(a->content); + xfree(a); } -/// @return true if in the cmdwin, not editing the command line. +/// Schedules cmdwin to open after the current cmdline-reader returns. Returns Ctrl_C so the cmdline +/// input loop unwinds, then `vim._core.cmdwin` does its work after typeahead. #40312 +static int open_cmdwin(void) +{ + // Disallow during textlock or when typing a password. + if (text_locked() || cmdline_star > 0) { + beep_flush(); + return K_IGNORE; + } + // Already open (also guarded in `vim._core.cmdwin`, but check here to avoid scheduling). + if (cmdwin_buf != NULL) { + beep_flush(); + return K_IGNORE; + } + // Disallow for expr-register and input()/inputlist(): no reentrant return path. #40407 + int ft = get_cmdline_type(); + if (ft != ':' && ft != '/' && ft != '?') { + beep_flush(); + return K_IGNORE; + } + + CmdwinOpenArgs *a = xmalloc(sizeof(*a)); + a->firstc = ft; + a->content = ccline.cmdbuff ? xstrnsave(ccline.cmdbuff, (size_t)ccline.cmdlen) : NULL; + a->pos = ccline.cmdpos; + // Intentionally not using vim.scheduled, see note on `open_cmdwin_event`. + loop_schedule_deferred(&main_loop, event_create(open_cmdwin_event, a)); + return Ctrl_C; +} + +/// @return true if curbuf is the cmdwin and we're not editing the command line. bool is_in_cmdwin(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return cmdwin_type != 0 && get_cmdline_type() == NUL; + return bt_cmdwin(curbuf) && get_cmdline_type() == NUL; } /// Get script string diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h index de7368cacb..84dd4442cb 100644 --- a/src/nvim/func_attr.h +++ b/src/nvim/func_attr.h @@ -222,8 +222,6 @@ # define FUNC_API_LUA_ONLY /// API function fails during textlock. # define FUNC_API_TEXTLOCK -/// API function fails during textlock, but allows cmdwin. -# define FUNC_API_TEXTLOCK_ALLOW_CMDWIN /// API function introduced at the given API level. # define FUNC_API_SINCE(X) /// API function deprecated since the given API level. diff --git a/src/nvim/globals.h b/src/nvim/globals.h index a5a9938c76..6385fe2804 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -735,12 +735,8 @@ EXTERN char *last_chdir_reason INIT( = NULL); EXTERN bool km_stopsel INIT( = false); EXTERN bool km_startsel INIT( = false); -EXTERN int cmdwin_type INIT( = 0); ///< type of cmdline window or 0 -EXTERN int cmdwin_result INIT( = 0); ///< result of cmdline window or 0 -EXTERN int cmdwin_level INIT( = 0); ///< cmdline recursion level -EXTERN buf_T *cmdwin_buf INIT( = NULL); ///< buffer of cmdline window or NULL -EXTERN win_T *cmdwin_win INIT( = NULL); ///< window of cmdline window or NULL -EXTERN win_T *cmdwin_old_curwin INIT( = NULL); ///< curwin before opening cmdline window or NULL +EXTERN int cmdwin_type INIT( = 0); ///< |cmdwin| type (':', '/', '?') or 0. +EXTERN buf_T *cmdwin_buf INIT( = NULL); ///< |cmdwin| scratch buffer, or NULL. EXTERN win_T *cmdline_win INIT( = NULL); ///< window in use by ext_cmdline EXTERN char no_lines_msg[] INIT( = N_("--No lines in buffer--")); @@ -801,8 +797,6 @@ EXTERN char windowsVersion[20] INIT( = { 0 }); /// overrules p_magic. Otherwise set to OPTION_MAGIC_NOT_SET. EXTERN optmagic_T magic_overruled INIT( = OPTION_MAGIC_NOT_SET); -/// Skip win_fix_cursor() call for 'splitkeep' when cmdwin is closed. -EXTERN bool skip_win_fix_cursor INIT( = false); /// Skip win_fix_scroll() call for 'splitkeep' when closing tab page. EXTERN bool skip_win_fix_scroll INIT( = false); /// Skip update_topline() call while executing win_fix_scroll(). diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 44b5ada7ab..188b4941c2 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2753,7 +2753,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval) compl_num_bests = 0; compl_ins_end_col = 0; - if (c == Ctrl_C && cmdwin_type != 0) { + if (c == Ctrl_C && bt_cmdwin(curbuf)) { // Avoid the popup menu remains displayed when leaving the // command line window. update_screen(); diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h index b0496218c1..bc3cf4e041 100644 --- a/src/nvim/keycodes.h +++ b/src/nvim/keycodes.h @@ -195,7 +195,7 @@ enum key_extra { // KE_CSI = 81, // Nvim doesn't need escaping CSI KE_SNR = 82, // KE_PLUG = 83, // - KE_CMDWIN = 84, // open command-line window from Command-line Mode + // KE_CMDWIN = 84, // Nvim "cmdwin" is not special. #40312 KE_C_LEFT = 85, // control-left KE_C_RIGHT = 86, // control-right @@ -448,7 +448,6 @@ enum key_extra { #define K_SNR TERMCAP2KEY(KS_EXTRA, KE_SNR) #define K_PLUG TERMCAP2KEY(KS_EXTRA, KE_PLUG) -#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN) #define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP) diff --git a/src/nvim/main.c b/src/nvim/main.c index 75b28cba05..e975d1bc8a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -684,7 +684,7 @@ int main(int argc, char **argv) ILOG("starting main loop"); // Main loop: never returns. - normal_enter(false, false); + normal_enter(false); #if defined(MSWIN) && !defined(MAKE_LIB) xfree(argv); diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index b74170ae0d..3177a68354 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -543,7 +543,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) } // click in a tab selects that tab page - if (is_click && cmdwin_type == 0 && mouse_col < Columns) { + if (is_click && mouse_col < Columns) { int tabnr = tab_page_click_defs[mouse_col].tabnr; in_tab_line = true; @@ -1415,19 +1415,11 @@ retnomove: && !sep_line_offset && (wp->w_p_rl ? col < wp->w_view_width - fdc - : col >= fdc + (wp != cmdwin_win ? 0 : 1)) + : col >= fdc) && (flags & MOUSE_MAY_STOP_VIS)))) { end_visual_mode(); redraw_curbuf_later(UPD_INVERTED); // delete the inversion } - if (cmdwin_type != 0 && wp != cmdwin_win) { - // A click outside the command-line window: Use modeless - // selection if possible. Allow dragging the status lines. - sep_line_offset = 0; - row = 0; - col += wp->w_wincol; - wp = cmdwin_win; - } // Only change window focus when not clicking on or dragging the // status line. Do change focus when releasing the mouse button // (MOUSE_FOCUS was set above if we dragged first). diff --git a/src/nvim/move.c b/src/nvim/move.c index 5bfee024bb..52353cb9aa 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -814,7 +814,6 @@ int win_col_off(win_T *wp) { return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL) ? (number_width(wp) + (*wp->w_p_stc == NUL)) : 0) - + ((wp != cmdwin_win) ? 0 : 1) + win_fdccol_count(wp) + (wp->w_scwidth * SIGN_WIDTH); } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b9ec196239..188bb5dac8 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -49,6 +49,7 @@ #include "nvim/highlight_defs.h" #include "nvim/indent_c.h" #include "nvim/keycodes.h" +#include "nvim/lua/executor.h" #include "nvim/macros_defs.h" #include "nvim/mapping.h" #include "nvim/mark.h" @@ -100,7 +101,6 @@ typedef struct { bool need_flushbuf; bool set_prevcount; bool previous_got_int; // `got_int` was true - bool cmdwin; // command-line window normal mode bool noexmode; // true if the normal mode was pushed from // ex mode (:global or :visual for example) bool toplevel; // top-level normal mode @@ -505,21 +505,19 @@ bool op_pending(void) /// Normal state entry point. This is called on: /// /// - Startup, In this case the function never returns. -/// - The command-line window is opened (`q:`). Returns when `cmdwin_result` != 0. /// - The :visual command is called from :global in ex mode, `:global/PAT/visual` /// for example. Returns when re-entering ex mode (because ex mode recursion is /// not allowed) /// /// This used to be called main_loop() on main.c -void normal_enter(bool cmdwin, bool noexmode) +void normal_enter(bool noexmode) { NormalState state; normal_state_init(&state); oparg_T *prev_oap = current_oap; current_oap = &state.oa; - state.cmdwin = cmdwin; state.noexmode = noexmode; - state.toplevel = (!cmdwin || cmdwin_result == 0) && !noexmode; + state.toplevel = !noexmode; state_enter(&state.state); current_oap = prev_oap; } @@ -1479,7 +1477,7 @@ static int normal_check(VimState *state) // Dict internally somewhere. // "may_garbage_collect" is reset in vgetc() which is invoked through // do_exmode() and normal_cmd(). - may_garbage_collect = !s->cmdwin && !s->noexmode; + may_garbage_collect = !s->noexmode; // Update w_curswant if w_set_curswant has been set. // Postponed until here to avoid computing w_virtcol too often. @@ -1493,11 +1491,6 @@ static int normal_check(VimState *state) return -1; } - if (s->cmdwin && cmdwin_result != 0) { - // command-line window and cmdwin_result is set - return 0; - } - normal_prepare(s); return 1; } @@ -3870,11 +3863,8 @@ static void nv_down(cmdarg_T *cap) // Quickfix window only: view the result under the cursor. qf_view_result(false); } else { - // In the cmdline window a executes the command. - if (cmdwin_type != 0 && cap->cmdchar == CAR) { - cmdwin_result = CAR; - } else if (bt_prompt(curbuf) && cap->cmdchar == CAR - && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) { + if (bt_prompt(curbuf) && cap->cmdchar == CAR + && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) { // In a prompt buffer a in the last line invokes the callback. prompt_invoke_callback(); if (restart_edit == 0) { @@ -6167,9 +6157,6 @@ static void nv_normal(cmdarg_T *cap) clear_cmdline = true; // unshow mode later } restart_edit = 0; - if (cmdwin_type != 0) { - cmdwin_result = Ctrl_C; - } if (VIsual_active) { end_visual_mode(); // stop Visual redraw_curbuf_later(UPD_INVERTED); @@ -6189,7 +6176,7 @@ static void nv_esc(cmdarg_T *cap) && cap->oap->regname == 0); if (cap->arg) { // true for CTRL-C - if (restart_edit == 0 && cmdwin_type == 0 && !VIsual_active && no_reason) { + if (restart_edit == 0 && !bt_cmdwin(curbuf) && !VIsual_active && no_reason) { if (anyBufIsChanged()) { msg(_("Type :qa! and press to abandon all changes" " and exit Nvim"), 0); @@ -6203,18 +6190,6 @@ static void nv_esc(cmdarg_T *cap) } restart_edit = 0; - - if (cmdwin_type != 0) { - cmdwin_result = K_IGNORE; - got_int = false; // don't stop executing autocommands et al. - return; - } - } else if (cmdwin_type != 0 && ex_normal_busy && typebuf_was_empty) { - // When :normal runs out of characters while in the command line window - // vgetorpeek() will repeatedly return ESC. Exit the cmdline window to - // break the loop. - cmdwin_result = K_IGNORE; - return; } if (VIsual_active) { @@ -6412,7 +6387,7 @@ static void nv_object(cmdarg_T *cap) } /// "q" command: Start/stop recording. -/// "q:", "q/", "q?": edit command-line in command-line window. +/// "q:", "q/", "q?": cmdwin. static void nv_record(cmdarg_T *cap) { if (cap->oap->op_type == OP_FORMAT) { @@ -6428,12 +6403,16 @@ static void nv_record(cmdarg_T *cap) } if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') { - if (cmdwin_type != 0) { + if (cmdwin_buf != NULL) { emsg(_(e_cmdline_window_already_open)); return; } - stuffcharReadbuff(cap->nchar); - stuffcharReadbuff(K_CMDWIN); + char fc[2] = { (char)cap->nchar, 0 }; + typval_T tv_args[] = { + { .v_type = VAR_STRING, .vval.v_string = fc }, + { .v_type = VAR_UNKNOWN }, + }; + nlua_call_vimfn("vim._core.cmdwin", "open", tv_args, NULL); } else { // (stop) recording into a named register, unless executing a // register. diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 024ac57d5a..8ee70eb75f 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -1137,7 +1137,7 @@ static bool pum_set_selected(int n, int repeat) && (Rows > 10) && (repeat <= 1) && (cur_cot_flags & (kOptCotFlagPreview | kOptCotFlagPopup)) - && !((cur_cot_flags & kOptCotFlagPreview) && cmdwin_type != 0)) { + && !((cur_cot_flags & kOptCotFlagPreview) && cmdwin_buf != NULL)) { win_T *curwin_save = curwin; tabpage_T *curtab_save = curtab; diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index b20a2bbd3f..c71a9990ec 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -761,9 +761,6 @@ int comp_textwidth(bool ff) // The width is the window width minus 'wrapmargin' minus all the // things that add to the margin. textwidth = curwin->w_view_width - (int)curbuf->b_p_wm; - if (curbuf == cmdwin_buf) { - textwidth -= 1; - } textwidth -= win_fdccol_count(curwin); textwidth -= curwin->w_scwidth; diff --git a/src/nvim/window.c b/src/nvim/window.c index 13c038fb88..994111d195 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -273,7 +273,7 @@ void do_window(int nchar, int Prenum, int xchar) #define CHECK_CMDWIN \ do { \ - if (cmdwin_type != 0) { \ + if (cmdwin_buf != NULL) { \ emsg(_(e_cmdwin)); \ return; \ } \ @@ -2694,23 +2694,6 @@ static bool can_close_floating_windows(tabpage_T *tp) return true; } -/// @return true if, considering the cmdwin, `win` is safe to close. -/// If false and `win` is the cmdwin, it is closed; otherwise, `err` is set. -bool can_close_in_cmdwin(win_T *win, Error *err) - FUNC_ATTR_NONNULL_ALL -{ - if (cmdwin_type != 0) { - if (win == cmdwin_win) { - cmdwin_result = Ctrl_C; - return false; - } else if (win == cmdwin_old_curwin) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return false; - } - } - return true; -} - /// Close the possibly last window in a tab page. /// /// @param win window to close @@ -3384,8 +3367,6 @@ void win_free_all(void) // avoid an error for switching tabpage with the cmdline window open cmdwin_type = 0; cmdwin_buf = NULL; - cmdwin_win = NULL; - cmdwin_old_curwin = NULL; while (first_tabpage->tp_next != NULL) { tabpage_close(true); @@ -4517,7 +4498,7 @@ tabpage_T *win_new_tabpage(int after, char *filename, bool enter, win_T **first) { tabpage_T *old_curtab = curtab; - if (enter && cmdwin_type != 0) { + if (enter && cmdwin_buf != NULL) { emsg(_(e_cmdwin)); return NULL; } @@ -6897,8 +6878,7 @@ static void win_fix_cursor(bool normal) { win_T *wp = curwin; - if (skip_win_fix_cursor - || !wp->w_do_win_fix_cursor + if (!wp->w_do_win_fix_cursor || wp->w_buffer->b_ml.ml_line_count < wp->w_view_height) { return; } diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c index e949aaf141..82ccfa9be2 100644 --- a/src/nvim/winfloat.c +++ b/src/nvim/winfloat.c @@ -79,22 +79,6 @@ win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err) || (win_tp != curtab && win_tp->tp_firstwin == wp && lastwin_nofloating(win_tp) == wp)) { api_set_error(err, kErrorTypeException, "Cannot change last window into float"); return NULL; - } else if (cmdwin_win != NULL && !cmdwin_win->w_floating) { - // cmdwin can't become the only non-float. Check for others. - bool other_nonfloat = false; - FOR_ALL_WINDOWS_IN_TAB(wp2, win_tp) { - if (wp2->w_floating) { - break; - } - if (wp2 != wp && wp2 != cmdwin_win) { - other_nonfloat = true; - break; - } - } - if (!other_nonfloat) { - api_set_error(err, kErrorTypeException, "%s", e_cmdwin); - return NULL; - } } tabpage_T *tp = win_tp == curtab ? NULL : win_tp; int dir; diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg index 0a596004e2..b9dd9a0434 100644 --- a/src/uncrustify.cfg +++ b/src/uncrustify.cfg @@ -3748,7 +3748,6 @@ set CLASS_COLON FUNC_API_REMOTE_ONLY set CLASS_COLON FUNC_API_RET_ALLOC set CLASS_COLON FUNC_API_SINCE set CLASS_COLON FUNC_API_TEXTLOCK -set CLASS_COLON FUNC_API_TEXTLOCK_ALLOW_CMDWIN set CLASS_COLON FUNC_ATTR_ALWAYS_INLINE set CLASS_COLON FUNC_ATTR_CONST set CLASS_COLON FUNC_ATTR_MALLOC diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index 3eecfdcc86..9193d96c4b 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -93,44 +93,18 @@ describe('api/tabpage', function() ) end) - it('checks textlock, cmdwin restrictions', function() + it('checks textlock restrictions', function() command('autocmd TextYankPost * ++once call nvim_open_tabpage(0, 0, {})') matches('E565:', pcall_err(command, 'yank')) eq(1, fn.tabpagenr('$')) - local other_buf = api.nvim_get_current_buf() - feed('q:') - -- OK when not entering and not opening a tabpage with the cmdwin's buffer. - matches('E11:', pcall_err(api.nvim_open_tabpage, 0, false, {})) - eq(1, fn.tabpagenr('$')) - matches('E11:', pcall_err(api.nvim_open_tabpage, other_buf, true, {})) - eq(1, fn.tabpagenr('$')) - local tp = api.nvim_open_tabpage(other_buf, false, {}) - eq(other_buf, api.nvim_win_get_buf(api.nvim_tabpage_get_win(tp))) - eq('command', fn.win_gettype()) - end) - - it('does not switch window when textlocked or in the cmdwin', function() - local target_win = api.nvim_get_current_win() - feed('q:') - local cur_win = api.nvim_get_current_win() - eq( - 'Vim:E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_tabpage_set_win, 0, target_win) - ) - eq(cur_win, api.nvim_get_current_win()) - command('quit!') - - exec(([[ + exec([[ new call setline(1, 'foo') - setlocal debug=throw indentexpr=nvim_tabpage_set_win(0,%d) - ]]):format(target_win)) - cur_win = api.nvim_get_current_win() - eq( - 'Vim(normal):E5555: API call: Vim:E565: Not allowed to change text or change window', - pcall_err(command, 'normal! ==') - ) + setlocal debug=throw indentexpr=nvim_tabpage_set_win(0,win_getid()) + ]]) + local cur_win = api.nvim_get_current_win() + matches('E565: Not allowed to change text or change window', pcall_err(command, 'normal! ==')) eq(cur_win, api.nvim_get_current_win()) end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index fa2f9ead36..7d89eaf00d 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -55,7 +55,7 @@ describe('API/win', function() eq('Invalid window id: 23', pcall_err(api.nvim_win_set_buf, 23, api.nvim_get_current_buf())) end) - it('disallowed in cmdwin if win=cmdwin_{old_cur}win or buf=cmdwin_buf', function() + it('in cmdwin #40312', function() local new_buf = api.nvim_create_buf(true, true) local old_win = api.nvim_get_current_win() local new_win = api.nvim_open_win(new_buf, false, { @@ -66,52 +66,16 @@ describe('API/win', function() height = 10, }) feed('q:') - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_buf, 0, new_buf) - ) - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_buf, old_win, new_buf) - ) - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_buf, new_win, 0) - ) - matches( - 'E11: Invalid in command%-line window; executes, CTRL%-C quits$', - pcall_err( - exec_lua, - [[ - local cmdwin_buf = vim.api.nvim_get_current_buf() - local new_win, new_buf = ... - vim._with({buf = new_buf}, function() - vim.api.nvim_win_set_buf(new_win, cmdwin_buf) - end) - ]], - new_win, - new_buf - ) - ) - matches( - 'E11: Invalid in command%-line window; executes, CTRL%-C quits$', - pcall_err( - exec_lua, - [[ - local cmdwin_win = vim.api.nvim_get_current_win() - local new_win, new_buf = ... - vim._with({win = new_win}, function() - vim.api.nvim_win_set_buf(cmdwin_win, new_buf) - end) - ]], - new_win, - new_buf - ) - ) - + n.poke_eventloop() + -- Replacing the cmdwin's own buffer is blocked by 'winfixbuf'. + matches('winfixbuf', pcall_err(api.nvim_win_set_buf, 0, new_buf)) + -- But other windows can be touched freely. local next_buf = api.nvim_create_buf(true, true) api.nvim_win_set_buf(new_win, next_buf) eq(next_buf, api.nvim_win_get_buf(new_win)) + -- Doesn't matter that old_win was the caller; no cmdwin guard. + api.nvim_win_set_buf(old_win, new_buf) + eq(new_buf, api.nvim_win_get_buf(old_win)) end) describe("with 'autochdir'", function() @@ -640,11 +604,9 @@ describe('API/win', function() eq({ newwin }, api.nvim_list_wins()) end) - it('in cmdline-window #9767', function() + it('in cmdwin #9767', function() command('split') eq(2, #api.nvim_list_wins()) - local oldbuf = api.nvim_get_current_buf() - local oldwin = api.nvim_get_current_win() local otherwin = api.nvim_open_win(0, false, { relative = 'editor', row = 10, @@ -652,62 +614,17 @@ describe('API/win', function() width = 10, height = 10, }) - -- Open cmdline-window. feed('q:') + n.poke_eventloop() eq(4, #api.nvim_list_wins()) eq(':', fn.getcmdwintype()) - -- Not allowed to close previous window from cmdline-window. - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_close, oldwin, true) - ) - -- Closing other windows is fine. + -- Closing other windows still works. api.nvim_win_close(otherwin, true) eq(false, api.nvim_win_is_valid(otherwin)) -- Close cmdline-window. api.nvim_win_close(0, true) eq(2, #api.nvim_list_wins()) eq('', fn.getcmdwintype()) - - -- Closing curwin in context of a different window shouldn't close cmdwin. - otherwin = api.nvim_open_win(0, false, { - relative = 'editor', - row = 10, - col = 10, - width = 10, - height = 10, - }) - feed('q:') - exec_lua( - [[ - vim._with({win = ...}, function() - vim.api.nvim_win_close(0, true) - end) - ]], - otherwin - ) - eq(false, api.nvim_win_is_valid(otherwin)) - eq(':', fn.getcmdwintype()) - -- Closing cmdwin in context of a non-previous window is still OK. - otherwin = api.nvim_open_win(oldbuf, false, { - relative = 'editor', - row = 10, - col = 10, - width = 10, - height = 10, - }) - exec_lua( - [[ - local otherwin, cmdwin = ... - vim._with({win = otherwin}, function() - vim.api.nvim_win_close(cmdwin, true) - end) - ]], - otherwin, - api.nvim_get_current_win() - ) - eq('', fn.getcmdwintype()) - eq(true, api.nvim_win_is_valid(otherwin)) end) it('closing current (float) window of another tabpage #15313', function() @@ -804,69 +721,11 @@ describe('API/win', function() eq({ oldwin }, api.nvim_list_wins()) eq({ oldbuf }, api.nvim_list_bufs()) end) - it('in the cmdwin', function() + it('in cmdwin', function() feed('q:') - -- Can close the cmdwin. + n.poke_eventloop() api.nvim_win_hide(0) eq('', fn.getcmdwintype()) - - local old_buf = api.nvim_get_current_buf() - local old_win = api.nvim_get_current_win() - local other_win = api.nvim_open_win(0, false, { - relative = 'win', - row = 3, - col = 3, - width = 12, - height = 3, - }) - feed('q:') - -- Cannot close the previous window. - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_hide, old_win) - ) - -- Can close other windows. - api.nvim_win_hide(other_win) - eq(false, api.nvim_win_is_valid(other_win)) - - -- Closing curwin in context of a different window shouldn't close cmdwin. - other_win = api.nvim_open_win(old_buf, false, { - relative = 'editor', - row = 10, - col = 10, - width = 10, - height = 10, - }) - exec_lua( - [[ - vim._with({win = ...}, function() - vim.api.nvim_win_hide(0) - end) - ]], - other_win - ) - eq(false, api.nvim_win_is_valid(other_win)) - eq(':', fn.getcmdwintype()) - -- Closing cmdwin in context of a non-previous window is still OK. - other_win = api.nvim_open_win(old_buf, false, { - relative = 'editor', - row = 10, - col = 10, - width = 10, - height = 10, - }) - exec_lua( - [[ - local otherwin, cmdwin = ... - vim._with({win = otherwin}, function() - vim.api.nvim_win_hide(cmdwin) - end) - ]], - other_win, - api.nvim_get_current_win() - ) - eq('', fn.getcmdwintype()) - eq(true, api.nvim_win_is_valid(other_win)) end) end) @@ -1453,54 +1312,19 @@ describe('API/win', function() end) describe('open_win', function() - it('disallowed in cmdwin if enter=true or buf=cmdwin_buf', function() + it('works while cmdwin is open #40312', function() + -- Legacy cmdwin blocked nvim_open_win with E11; now there is no such restriction. local new_buf = api.nvim_create_buf(true, true) feed('q:') - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_open_win, new_buf, true, { - relative = 'editor', - row = 5, - col = 5, - width = 5, - height = 5, - }) - ) - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_open_win, 0, false, { - relative = 'editor', - row = 5, - col = 5, - width = 5, - height = 5, - }) - ) - matches( - 'E11: Invalid in command%-line window; executes, CTRL%-C quits$', - pcall_err( - exec_lua, - [[ - local cmdwin_buf = vim.api.nvim_get_current_buf() - vim._with({buf = vim.api.nvim_create_buf(false, true)}, function() - vim.api.nvim_open_win(cmdwin_buf, false, { - relative='editor', row=5, col=5, width=5, height=5, - }) - end) - ]] - ) - ) - - eq( - new_buf, - api.nvim_win_get_buf(api.nvim_open_win(new_buf, false, { - relative = 'editor', - row = 5, - col = 5, - width = 5, - height = 5, - })) - ) + n.poke_eventloop() + local new_win = api.nvim_open_win(new_buf, false, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + eq(new_buf, api.nvim_win_get_buf(new_win)) end) it('aborts if buffer is invalid', function() @@ -3099,74 +2923,10 @@ describe('API/win', function() try_move_t2_wins_to_t1() end) - it('handles cmdwin and textlock restrictions', function() + it('handles textlock', function() command('tabnew') - local t2 = api.nvim_get_current_tabpage() local t2_win = api.nvim_get_current_win() command('tabfirst') - local t1_move_win = api.nvim_get_current_win() - command('split') - - -- Can't move the cmdwin, or its old curwin to a different tabpage. - local old_curwin = api.nvim_get_current_win() - feed('q:') - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_config, 0, { split = 'left', win = t2_win }) - ) - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_config, old_curwin, { split = 'left', win = t2_win }) - ) - -- But we can move other windows. - api.nvim_win_set_config(t1_move_win, { split = 'left', win = t2_win }) - eq(t2, api.nvim_win_get_tabpage(t1_move_win)) - command('quit!') - - -- Can't configure windows such that the cmdwin would become the only non-float. - command('only!') - feed('q:') - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err( - api.nvim_win_set_config, - old_curwin, - { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } - ) - ) - -- old_curwin is now no longer the only other non-float, so we can make it floating now. - local t1_new_win = api.nvim_open_win( - api.nvim_create_buf(true, true), - false, - { split = 'left', win = old_curwin } - ) - api.nvim_win_set_config( - old_curwin, - { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } - ) - eq('editor', api.nvim_win_get_config(old_curwin).relative) - -- ...which means we shouldn't be able to also make the new window floating too! - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err( - api.nvim_win_set_config, - t1_new_win, - { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } - ) - ) - -- Nothing ought to stop us from making the cmdwin itself floating, though... - api.nvim_win_set_config(0, { relative = 'editor', row = 0, col = 0, width = 5, height = 5 }) - eq('editor', api.nvim_win_get_config(0).relative) - -- We can't make our new window from before floating too, as it's now the only non-float. - eq( - 'Cannot change last window into float', - pcall_err( - api.nvim_win_set_config, - t1_new_win, - { relative = 'editor', row = 0, col = 0, width = 5, height = 5 } - ) - ) - command('quit!') exec(([[ new @@ -3732,21 +3492,13 @@ describe('API/win', function() eq({ false, 'Cannot move autocmd window to another tabpage' }, { float_ok, float_err }) end) - it('cannot move cmdwin between tabpages', function() + it('can move cmdwin between tabpages #40312', function() local other_tp_win = api.nvim_get_current_win() command('tabnew') - local old_curwin = api.nvim_get_current_win() feed('q:') + n.poke_eventloop() eq('command', fn.win_gettype()) - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_config, 0, { win = other_tp_win, split = 'right' }) - ) - -- Shouldn't move the old curwin from before we entered the cmdwin either. - eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', - pcall_err(api.nvim_win_set_config, old_curwin, { win = other_tp_win, split = 'right' }) - ) + api.nvim_win_set_config(0, { win = other_tp_win, split = 'right' }) end) it('minimal style persists through float-to-split and buffer change #37067', function() diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua index a8f0daded9..a8e185e6b7 100644 --- a/test/functional/autocmd/cmdline_spec.lua +++ b/test/functional/autocmd/cmdline_spec.lua @@ -157,27 +157,22 @@ describe('cmdline autocommands', function() ]]) end) - it('works with nested cmdline', function() + it('with nested cmdline', function() + -- Cmdwin is not supported in expr-register (=) cmdline. #40312 feed(':') eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg()) feed('=') eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg()) - feed('') - eq({ 'notification', 'CmdwinEnter', { {} } }, next_msg()) - feed(':') - eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg()) - feed('') - eq( - { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 3, abort = true } } }, - next_msg() - ) - feed('') - eq({ 'notification', 'CmdwinLeave', { {} } }, next_msg()) feed('1+2') eq( { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } }, next_msg() ) + feed('') + eq( + { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } }, + next_msg() + ) end) it('no crash with recursive use of v:event #19484', function() diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index 932dbb642c..93031a6b1c 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 cmdline_win_prevents_tab_switch(characters, completion_visible) + local function cmdwin_prevents_tab_switch(characters, completion_visible) return function() -- Add three tabs for a total of four command('tabnew') @@ -647,16 +647,11 @@ describe('tabpage/previous', function() eq(3, eval("tabpagenr('#')")) end end - it('cmdline-win prevents tab switch via g', cmdline_win_prevents_tab_switch('g', 0)) - it( - 'cmdline-win prevents tab switch via g', - cmdline_win_prevents_tab_switch('g', 1) - ) - it('cmdline-win prevents tab switch via ', cmdline_win_prevents_tab_switch('', 0)) - it( - 'cmdline-win prevents tab switch via :tabn #', - cmdline_win_prevents_tab_switch(':tabn #', 0) - ) + + 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(':tabs indicates correct prevtab curwin', function() -- Add three tabs for a total of four diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua index c59670be30..c8e4791869 100644 --- a/test/functional/core/main_spec.lua +++ b/test/functional/core/main_spec.lua @@ -220,6 +220,7 @@ describe('vim._core', function() ) local expected = { 'vim.F', + 'vim._core.cmdwin', 'vim._core.defaults', 'vim._core.editor', 'vim._core.ex_cmd', diff --git a/test/functional/editor/cmdwin_spec.lua b/test/functional/editor/cmdwin_spec.lua new file mode 100644 index 0000000000..85bfe8e6aa --- /dev/null +++ b/test/functional/editor/cmdwin_spec.lua @@ -0,0 +1,115 @@ +-- Tests for non-blocking cmdwin. #40312 + +local t = require('test.testutil') +local n = require('test.functional.testnvim')() + +local feed = n.feed +local api = n.api +local fn = n.fn +local exec_lua = n.exec_lua +local eq = t.eq + +describe('cmdwin', function() + before_each(n.clear) + + it('q: opens cmdwin', function() + feed('q:') + eq(':', fn.getcmdwintype()) + eq('[Command Line]', vim.fs.basename(api.nvim_buf_get_name(0))) + -- cmdwin-char is shown in window-local 'statuscolumn'. + eq('%#NonText#: ', api.nvim_get_option_value('statuscolumn', { win = 0 })) + + eq('nofile', api.nvim_get_option_value('buftype', { buf = 0 })) + eq('wipe', api.nvim_get_option_value('bufhidden', { buf = 0 })) + eq(false, api.nvim_get_option_value('swapfile', { buf = 0 })) + eq(true, api.nvim_get_option_value('winfixbuf', { win = 0 })) + + -- executes the cmdline + feed('ilet g:cmdwin_result = 42') + feed('') + eq(42, api.nvim_get_var('cmdwin_result')) + eq('', fn.getcmdwintype()) + end) + + it('q/ opens cmdwin with search history', function() + feed('q/') + eq('/', fn.getcmdwintype()) + end) + + it('c_CTRL-F opens cmdwin pre-filled with current cmdline', function() + feed(':echo "hi"') + n.poke_eventloop() + eq(':', fn.getcmdwintype()) + eq('echo "hi"', api.nvim_get_current_line()) + end) + + it(' in normal mode cancels without executing', function() + feed('q:') + feed('iecho "nope"') + feed('') + eq('', fn.getcmdwintype()) + -- v:errmsg should not contain a successful echo from the cancelled line. + end) + + it('async API calls work while cmdwin is open #40312', function() + feed('q:') + eq(':', fn.getcmdwintype()) + local ok, err = pcall(function() + local b = api.nvim_create_buf(true, false) + api.nvim_buf_delete(b, { force = true }) + end) + eq(true, ok, 'buf_delete unexpectedly failed: ' .. tostring(err)) + end) + + it('textlock does not include cmdwin #40312', function() + feed('q:') + -- Setting an option from API used to fail with E11 in cmdwin. + api.nvim_set_option_value('wildignore', '*.tmp', {}) + end) + + it('E1292 cannot nest cmdwin', function() + feed('q:') + eq(':', fn.getcmdwintype()) + feed('q:') + -- Still just one cmdwin. + eq(':', fn.getcmdwintype()) + local nwin = 0 + for _, w in ipairs(api.nvim_list_wins()) do + if api.nvim_get_option_value('winfixbuf', { win = w }) then + nwin = nwin + 1 + end + end + eq(1, nwin) + end) + + it(':quit closes cmdwin', function() + feed('q:') + eq(':', fn.getcmdwintype()) + feed(':q') + eq('', fn.getcmdwintype()) + end) + + it(':messages from inside cmdwin works #40312', function() + -- Before #40312, this raised E11 because text_locked() returned true for cmdwin. + exec_lua([[vim.api.nvim_echo({{'hello from history'}}, true, {})]]) + feed('q:') + eq(':', fn.getcmdwintype()) + n.command('messages') -- Previously E11; now actually runs. + end) + + it('CmdwinEnter/CmdwinLeave events', function() + exec_lua([[ + _G.events = {} + vim.api.nvim_create_autocmd('CmdwinEnter', { + callback = function(a) table.insert(_G.events, 'enter:'..a.match) end, + }) + vim.api.nvim_create_autocmd('CmdwinLeave', { + callback = function(a) table.insert(_G.events, 'leave:'..a.match) end, + }) + ]]) + feed('q:') + n.poke_eventloop() -- Ensure q: is processed before the mapping fires. + feed('') + eq({ 'enter::', 'leave::' }, exec_lua('return _G.events')) + end) +end) diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index 3828b78945..934b5e259f 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -1046,8 +1046,9 @@ describe('completion', function() screen:expect([[ | {2:[No Name] }| - {1::}foo faa fee f^ | - {1:~ }|*3 + {1:: } | + {1:: }foo faa fee f^ | + {1:~ }|*2 {3:[Command Line] }| {5:-- INSERT --} | ]]) @@ -1055,20 +1056,19 @@ describe('completion', function() screen:expect([[ | {2:[No Name] }| - {1::}foo faa fee foo^ | - {1:~ }{12: foo }{1: }| - {1:~ }{4: faa }{1: }| - {1:~ }{4: fee }{1: }| - {3:[Command Line] }| + {1:: } | + {1:: }foo faa fee foo^ | + {1:~ }{12: foo }{1: }| + {1:~ }{4: faa }{1: }| + {3:[Command Line}{4: fee }{3: }| {5:-- Keyword Local completion (^N^P) }{6:match 1 of 3} | ]]) feed('') + -- Non-blocking cmdwin (#40312): closes the cmdwin and drops back + -- into ":" cmdline mode pre-filled with the line under the cursor. screen:expect([[ | - {2:[No Name] }| - {1::}foo faa fee foo | - {1:~ }|*3 - {3:[Command Line] }| + {1:~ }|*6 :foo faa fee foo^ | ]]) end) diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua index 59862d5e77..c0412a8167 100644 --- a/test/functional/ex_cmds/append_spec.lua +++ b/test/functional/ex_cmds/append_spec.lua @@ -7,7 +7,6 @@ local dedent = t.dedent local exec = n.exec local feed = n.feed local clear = n.clear -local fn = n.fn local command = n.command local api = n.api @@ -33,30 +32,13 @@ local cmdtest = function(cmd, prep, ret1) feed(':' .. cmd .. '\nabc\ndef\n.\n') eq(ret1, buffer_contents()) end) - -- This used to crash since that commit as well. - it('opens empty cmdline window', function() - local hisline = '" Some comment to be stored in history' - feed(':' .. hisline .. '') - feed(':' .. cmd .. 'abcdef') - eq({ 'def' }, buffer_contents()) - eq(hisline, fn.histget(':', -2)) - eq(cmd, fn.histget(':')) - -- Test that command-line window was launched - eq('nofile', api.nvim_get_option_value('buftype', {})) - eq('n', fn.mode(1)) - feed('') - eq('c', fn.mode(1)) - feed('.') - eq('n', fn.mode(1)) - eq(ret1, buffer_contents()) - end) end) end cmdtest('insert', ' before', { 'abc', 'def', 'foo', 'bar', 'baz' }) cmdtest('append', ' after', { 'foo', 'abc', 'def', 'bar', 'baz' }) cmdtest('change', '', { 'abc', 'def', 'bar', 'baz' }) -describe('the first line is redrawn correctly after inserting text in an empty buffer', function() +describe('first line is redrawn correctly after :append/:insert in an empty buffer', function() local screen before_each(function() clear() diff --git a/test/functional/legacy/cmdwin_spec.lua b/test/functional/legacy/cmdwin_spec.lua deleted file mode 100644 index 8521ab5bc1..0000000000 --- a/test/functional/legacy/cmdwin_spec.lua +++ /dev/null @@ -1,97 +0,0 @@ -local n = require('test.functional.testnvim')() -local Screen = require('test.functional.ui.screen') - -local clear = n.clear -local command = n.command -local feed = n.feed - -describe('cmdwin', function() - before_each(clear) - - -- oldtest: Test_cmdwin_interrupted() - it('still uses a new buffer when interrupting more prompt on open', function() - local screen = Screen.new(30, 16) - command('set more') - command('autocmd WinNew * highlight') - feed('q:') - screen:expect({ any = vim.pesc('{6:-- More --}^') }) - feed('q') - screen:expect([[ - | - {1:~ }|*5 - {2:[No Name] }| - {1::}^ | - {1:~ }|*6 - {3:[Command Line] }| - | - ]]) - feed([[aecho 'done']]) - screen:expect([[ - | - {1:~ }|*5 - {2:[No Name] }| - {1::}echo 'done'^ | - {1:~ }|*6 - {3:[Command Line] }| - {5:-- INSERT --} | - ]]) - feed('') - screen:expect([[ - ^ | - {1:~ }|*14 - done | - ]]) - end) - - -- oldtest: Test_cmdwin_showcmd() - it('has correct showcmd', function() - local screen = Screen.new(60, 18) - command('set showcmd') - for _, keys in ipairs({ 'q:', ':' }) do - feed(keys) - local fmt = [[ - | - {1:~ }|*7 - {2:[No Name] }| - {1::}^ | - {1:~ }|*6 - {3:[Command Line] }| - : %s | - ]] - screen:expect(fmt:format(' ')) - feed('"') - screen:expect(fmt:format('" ')) - feed('x') - screen:expect(fmt:format('"x ')) - feed('y') - screen:expect(fmt:format('"xy ')) - feed('y') - screen:expect(fmt:format(' ')) - feed('') - n.poke_eventloop() - feed('') - screen:expect([[ - ^ | - {1:~ }|*16 - | - ]]) - end - end) - - -- oldtest: Test_cmdwin_no_prefix_on_wrapped_line() - it('prefix char is not drawn on wrapped screen line', function() - local screen = Screen.new(40, 12) - local cmd = 'echo "' .. ('a'):rep(40 - 8) .. '"XYZ' - feed(':' .. cmd .. '') - screen:expect([[ - | - {1:~ }| - {2:[No Name] }| - {1::}echo "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"| - XY^Z | - {1:~ }|*5 - {3:[Command Line] }| - | - ]]) - end) -end) diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 7cb5b2e356..5a46dd454b 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -240,7 +240,7 @@ local function test_cmdline(linegrid) ]]) end) - it('works with cmdline window', function() + it('with cmdwin', function() feed(':make') screen:expect { grid = [[ @@ -255,25 +255,22 @@ local function test_cmdline(linegrid) screen:expect([[ | {2:[No Name] }| - {1::}mak^e | + {1:: }mak^e | {3:[Command Line] }| | ]]) - -- nested cmdline + -- cmdwin is a plain window so `:yank` opens a top-level cmdline. No nesting allowed. #40312 feed(':yank') screen:expect { grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1:: }mak^e | {3:[Command Line] }| | ]], - cmdline = { - nil, - { firstc = ':', content = { { 'yank' } }, pos = 4 }, - }, + cmdline = { { firstc = ':', content = { { 'yank' } }, pos = 4 } }, } command('mode') @@ -281,14 +278,11 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1:: }mak^e | {3:[Command Line] }| | ]], - cmdline = { - nil, - { firstc = ':', content = { { 'yank' } }, pos = 4 }, - }, + cmdline = { { firstc = ':', content = { { 'yank' } }, pos = 4 } }, reset = true, } @@ -297,26 +291,14 @@ local function test_cmdline(linegrid) grid = [[ | {2:[No Name] }| - {1::}mak^e | + {1:: }mak^e | {3:[Command Line] }| | ]], - cmdline = { [2] = { abort = true } }, + cmdline = { { abort = true } }, } feed('') - screen:expect { - grid = [[ - ^ | - {2:[No Name] }| - {1::}make | - {3:[Command Line] }| - | - ]], - cmdline = { { firstc = ':', content = { { 'make' } }, pos = 4 } }, - } - - command('redraw!') screen:expect { grid = [[ ^ | @@ -918,20 +900,18 @@ describe('cmdline redraw', function() | {1:~ }|*3 {2:[No Name] }| - {1::}^a{17:bc} | - {1:~ }|*2 + {1:: } | + {1:: }^a{17:bc} | + {1:~ }| {3:[Command Line] }| {5:-- VISUAL --} | ]]) + -- Ctrl-C closes cmdwin and drops back into pre-filled cmdline. #40312 feed('') screen:expect([[ | - {1:~ }|*3 - {2:[No Name] }| - {1::}a{17:bc} | - {1:~ }|*2 - {3:[Command Line] }| - :^abc | + {1:~ }|*8 + :abc^ | ]]) end) diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 70e005f37f..ab8a5ccafc 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -1184,155 +1184,6 @@ describe('folded lines', function() end end) - it('in cmdline window', function() - feed_command('set foldmethod=manual foldcolumn=1') - feed_command('let x = 1') - feed_command('/alpha') - feed_command('/omega') - - feed('q:') - if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]| - {2:[No Name] }| - [4:---------------------------------------------]|*4 - {3:[Command Line] }| - [3:---------------------------------------------]| - ## grid 2 - {7: } | - ## grid 3 - : | - ## grid 4 - {1::}{7: }set foldmethod=manual foldcolumn=1 | - {1::}{7: }let x = 1 | - {1::}{7: }^ | - {1:~ }| - ]]) - else - screen:expect([[ - {7: } | - {2:[No Name] }| - {1::}{7: }set foldmethod=manual foldcolumn=1 | - {1::}{7: }let x = 1 | - {1::}{7: }^ | - {1:~ }| - {3:[Command Line] }| - : | - ]]) - end - - feed('kzfk') - if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]| - {2:[No Name] }| - [4:---------------------------------------------]|*4 - {3:[Command Line] }| - [3:---------------------------------------------]| - ## grid 2 - {7: } | - ## grid 3 - : | - ## grid 4 - {1::}{7:+}{13:^+-- 2 lines: set foldmethod=manual foldcol}| - {1::}{7: } | - {1:~ }|*2 - ]]) - else - screen:expect([[ - {7: } | - {2:[No Name] }| - {1::}{7:+}{13:^+-- 2 lines: set foldmethod=manual foldcol}| - {1::}{7: } | - {1:~ }|*2 - {3:[Command Line] }| - : | - ]]) - end - - feed('') - if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]|*7 - [3:---------------------------------------------]| - ## grid 2 - {7: }^ | - {1:~ }|*6 - ## grid 3 - : | - ]]) - else - screen:expect([[ - {7: }^ | - {1:~ }|*6 - : | - ]]) - end - - feed('/') - if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]| - {2:[No Name] }| - [5:---------------------------------------------]|*4 - {3:[Command Line] }| - [3:---------------------------------------------]| - ## grid 2 - {7: } | - ## grid 3 - / | - ## grid 5 - {1:/}{7: }alpha | - {1:/}{7: }{10:omega} | - {1:/}{7: }^ | - {1:~ }| - ]]) - else - screen:expect([[ - {7: } | - {2:[No Name] }| - {1:/}{7: }alpha | - {1:/}{7: }{10:omega} | - {1:/}{7: }^ | - {1:~ }| - {3:[Command Line] }| - / | - ]]) - end - - feed('ggzfG') - if multigrid then - screen:expect([[ - ## grid 1 - [2:---------------------------------------------]| - {2:[No Name] }| - [5:---------------------------------------------]|*4 - {3:[Command Line] }| - [3:---------------------------------------------]| - ## grid 2 - {7: } | - ## grid 3 - / | - ## grid 5 - {1:/}{7:+}{13:^+-- 3 lines: alpha························}| - {1:~ }|*3 - ]]) - else - screen:expect([[ - {7: } | - {2:[No Name] }| - {1:/}{7:+}{13:^+-- 3 lines: alpha························}| - {1:~ }|*3 - {3:[Command Line] }| - / | - ]]) - end - end) - it('foldcolumn autoresize', function() fn.setline(1, 'line 1') fn.setline(2, 'line 2') diff --git a/test/functional/ui/messages2_spec.lua b/test/functional/ui/messages2_spec.lua index caee40c68d..f19b4d2d6d 100644 --- a/test/functional/ui/messages2_spec.lua +++ b/test/functional/ui/messages2_spec.lua @@ -205,45 +205,55 @@ describe('messages2', function() ]]) feed(':') screen:expect([[ - foo |*5 - {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}^ | + x | + {1:~ }|*3 + ─────────────────────────────────────────────────────| + {1:: }echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1:: }^ | {1:~ }|*5 {3:[Command Line] 2,0-1 All}| | ]]) command('wincmd +') screen:expect([[ - foo |*4 - {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}^ | + x | + {1:~ }|*2 + ─────────────────────────────────────────────────────| + {1:: }echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1:: }^ | {1:~ }|*6 {3:[Command Line] 2,0-1 All}| | ]]) command('echo "foo"') screen:expect([[ - foo |*4 - {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}^ | + x | + {1:~ }|*2 + ─────────────────────────────────────────────────────| + {1:: }echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1:: }^ | {1:~ }|*6 {3:[Command Line] 2,0-1 All}| foo | ]]) + -- closes the cmdwin and drops back into pre-filled cmdline. The pager remains visible. feed('') screen:expect([[ - foo |*12 + x | + {1:~ }|*11 {3:[Pager] 1,1 Top}| {16::}^ | ]]) - -- Can enter pager from cmdwin. - feed('qq:') + feed('') + -- Can enter pager from cmdwin (use cmdwin.open() since "q" is consumed by the pager on_key + -- callback before nv_record can read it). + exec_lua([[require('vim._core.cmdwin').open(':')]]) screen:expect([[ x | {1:~ }|*3 ─────────────────────────────────────────────────────| - {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}^ | + {1:: }echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1:: }^ | {1:~ }|*5 {3:[Command Line] 2,0-1 All}| | @@ -251,9 +261,10 @@ describe('messages2', function() feed(':messages') screen:expect([[ ^foo | - foo |*11 + foo |*4 + {1:~ }|*7 {3:[Pager] 1,1 Top}| - | + {16::}{15:messages} | ]]) -- Cmdwin is restored after pager is closed. feed('q') @@ -261,12 +272,12 @@ describe('messages2', function() x | {1:~ }|*3 ─────────────────────────────────────────────────────| - {1::}echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | - {1::}messages | - {1::}^ | + {1:: }echo "foo" | echo "bar\nbaz\n"->repeat(&lines) | + {1:: }messages | + {1:: }^ | {1:~ }|*4 {3:[Command Line] 3,0-1 All}| - | + {16::}{15:messages} | ]]) -- Configured maximum height. command('quit | lua require("vim._core.ui2").enable({msg = {pager = {height = 2 } } })') @@ -278,7 +289,7 @@ describe('messages2', function() ^foo | foo | {3:[Pager] 1,1 Top}| - | + {16::}{15:messages} | ]]) end) diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index 2d29f85a15..a865ede425 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -4528,17 +4528,12 @@ describe('builtin popupmenu', function() :sign definex^ | ]]) - -- When the popup is open, entering the cmdline window should close the popup + -- When the popup is open, entering cmdwin should close the popup. feed('sign ') - screen:expect([[ - | - {2:[No Name] }| - {1::}sign define | - {1::}sign defin^e | - {1:~ }|*4 - {3:[Command Line] }| - :sign define | - ]]) + t.retry(nil, 2000, function() + eq(':', n.fn.getcmdwintype()) + end) + eq(0, n.fn.pumvisible()) feed(':q') -- After the last popup menu item, should show the original string diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index 616236a585..ee8a81e89e 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -962,6 +962,7 @@ describe('statuscolumn', function() end) it('works with cmdwin', function() + -- The cmdwin sets its own window-local 'statuscolumn' (cmdwin-char). feed(':set stc=%lq:k$') screen:expect([[ {8: 7}aaaaa | @@ -969,11 +970,11 @@ describe('statuscolumn', function() {8: 9}aaaaa | {8:10}aaaaa | {2:[No Name] [+] }| - {1::}{8:1}set stc=%^l | - {1::}{8:2} | + {1:: }set stc=%^l | + {1:: } | {1:~ }|*5 {3:[Command Line] }| - : | + :set stc=%l | ]]) end) diff --git a/test/functional/vimscript/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua index b36acbd312..b341c191d6 100644 --- a/test/functional/vimscript/api_functions_spec.lua +++ b/test/functional/vimscript/api_functions_spec.lua @@ -10,7 +10,6 @@ local insert, pcall_err = n.insert, t.pcall_err local matches = t.matches local api = n.api local feed = n.feed -local command = n.command describe('eval-API', function() before_each(clear) @@ -91,16 +90,22 @@ describe('eval-API', function() api.nvim_get_vvar('errmsg') ) - -- Some functions checking textlock (usually those that may change the current window or buffer) - -- also ought to not be usable in the cmdwin. + -- cmdwin behavior (changed since #40312). local old_win = api.nvim_get_current_win() feed('q:') + local cmdwin_win = api.nvim_get_current_win() eq( - 'E11: Invalid in command-line window; executes, CTRL-C quits', + 'Vim:E11: Invalid in command-line window; executes, CTRL-C quits', pcall_err(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) + eq(cmdwin_win, api.nvim_get_current_win()) - -- But others, like nvim_buf_set_lines(), which just changes text, is OK. + -- nvim_buf_set_lines() in the cmdwin buffer is OK. api.nvim_buf_set_lines(0, 0, -1, 1, { 'wow!' }) eq({ 'wow!' }, api.nvim_buf_get_lines(0, 0, -1, 1)) diff --git a/test/old/testdir/test_arglist.vim b/test/old/testdir/test_arglist.vim index f7e1ae227c..56e0b5bb78 100644 --- a/test/old/testdir/test_arglist.vim +++ b/test/old/testdir/test_arglist.vim @@ -623,6 +623,7 @@ endfunc " Test for ":all" not working when in the cmdline window func Test_all_not_allowed_from_cmdwin() + throw 'Skipped: Nvim supports cmdwin freedom #40312' au BufEnter * all next x " Use try/catch here, somehow assert_fails() doesn't work on MS-Windows diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim index 6887e284cd..a5711e8c5d 100644 --- a/test/old/testdir/test_autocmd.vim +++ b/test/old/testdir/test_autocmd.vim @@ -3911,6 +3911,9 @@ endfunc " Fuzzer found some strange combination that caused a crash. func Test_autocmd_normal_mess() + " Uses `q/` (cmdwin) in autocmd; with non-blocking cmdwin (#40312) the + " expected E1159 path now hits E1513 (winfixbuf) instead. + throw 'Skipped: Nvim supports cmdwin freedom #40312' " For unknown reason this hangs on MS-Windows CheckNotMSWindows @@ -3930,6 +3933,7 @@ func Test_autocmd_normal_mess() endfunc func Test_autocmd_closing_cmdwin() + throw 'Skipped: Nvim supports cmdwin freedom #40312' " For unknown reason this hangs on MS-Windows CheckNotMSWindows @@ -4082,6 +4086,9 @@ endfunc " Test for ModeChanged pattern func Test_mode_changes() + " Asserts `n -> c -> n` mode transitions for `q:`, but with the + " non-blocking cmdwin (#40312) `q:` enters cmdwin normal mode, not cmdline. + throw 'Skipped: Nvim supports cmdwin freedom #40312' let g:index = 0 let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'noV', 'n', 'V', 'v', 's', 'n'] func! TestMode() diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim index 6dd7543a2f..0008c4b4bf 100644 --- a/test/old/testdir/test_cmdline.vim +++ b/test/old/testdir/test_cmdline.vim @@ -1722,6 +1722,7 @@ func Test_getcmdtype_getcmdprompt() endfunc func Test_getcmdwintype() + throw "Skipped: Nvim supports cmdwin freedom #40312" call feedkeys("q/:let a = getcmdwintype()\:q\", 'x!') call assert_equal('/', a) @@ -1738,6 +1739,7 @@ func Test_getcmdwintype() endfunc func Test_getcmdwin_autocmd() + throw "Skipped: Nvim supports cmdwin freedom #40312" let s:seq = [] augroup CmdWin au WinEnter * call add(s:seq, 'WinEnter ' .. win_getid()) @@ -1854,6 +1856,7 @@ func Test_cmdline_overstrike() endfunc func Test_cmdwin_bug() + throw 'Skipped: Nvim supports cmdwin freedom #40312' let winid = win_getid() sp try @@ -1955,6 +1958,7 @@ func Test_buffers_lastused() endfunc func Test_cmdwin_feedkeys() + throw "Skipped: Nvim supports cmdwin freedom #40312" " This should not generate E488 call feedkeys("q:\", 'x') " Using feedkeys with q: only should automatically close the cmd window @@ -1966,6 +1970,7 @@ endfunc " Tests for the issues fixed in 7.4.441. " When 'cedit' is set to Ctrl-C, opening the command window hangs Vim func Test_cmdwin_cedit() + throw 'Skipped: Nvim supports cmdwin freedom #40312' exe "set cedit=\" normal! : call assert_equal(1, winnr('$')) @@ -2044,6 +2049,7 @@ func Test_cmdline_expand_special() endfunc func Test_cmdwin_jump_to_win() + throw "Skipped: Nvim supports cmdwin freedom #40312" call assert_fails('call feedkeys("q:\\\", "xt")', 'E11:') new set modified @@ -2060,6 +2066,7 @@ func Test_cmdwin_jump_to_win() endfunc func Test_cmdwin_tabpage() + throw "Skipped: Nvim supports cmdwin freedom #40312" tabedit call assert_fails("silent norm q/g :I\", 'E11:') tabclose! @@ -2553,6 +2560,7 @@ endfunc " Test for normal mode commands not supported in the cmd window func Test_cmdwin_blocked_commands() + throw 'Skipped: Nvim supports cmdwin freedom #40312' call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') call assert_fails('call feedkeys("q:\\", "xt")', 'E11:') @@ -2584,6 +2592,7 @@ endfunc " Close the Cmd-line window in insert mode using CTRL-C func Test_cmdwin_insert_mode_close() + throw "Skipped: Nvim supports cmdwin freedom #40312" %bw! let s = '' exe "normal q:a\let s='Hello'\" diff --git a/test/old/testdir/test_cmdwin.vim b/test/old/testdir/test_cmdwin.vim index 75ed96bcd3..fad01527d2 100644 --- a/test/old/testdir/test_cmdwin.vim +++ b/test/old/testdir/test_cmdwin.vim @@ -24,12 +24,14 @@ endfunc " Check that a :normal command can be used to stop Visual mode without side " effects. func Test_normal_escape() + throw 'Skipped: Nvim supports cmdwin freedom #40312' call feedkeys("q:i\" foo\:normal! \\\:\" bar\", 'ntx') call assert_equal('" bar', @:) endfunc " This was using a pointer to a freed buffer func Test_cmdwin_freed_buffer_ptr() + throw "Skipped: Nvim supports cmdwin freedom #40312" " this does not work on MS-Windows because renaming an open file fails CheckNotMSWindows @@ -94,6 +96,7 @@ func Test_cmdwin_restore_heights() endfunc func Test_cmdwin_temp_curwin() + throw "Skipped: Nvim supports cmdwin freedom #40312" func CheckWraps(expect_wrap) setlocal textwidth=0 wrapmargin=1 @@ -128,6 +131,7 @@ func Test_cmdwin_temp_curwin() endfunc func Test_cmdwin_interrupted() + throw "Skipped: Nvim supports cmdwin freedom #40312" func CheckInterrupted() call feedkeys("q::call assert_equal('', getcmdwintype())\:call assert_equal('', getcmdtype())\:q", 'ntx') endfunc @@ -193,6 +197,7 @@ func Test_cmdwin_interrupted() endfunc func Test_cmdwin_existing_bufname() + throw "Skipped: Nvim supports cmdwin freedom #40312" func CheckName() call assert_equal(1, getbufinfo('')[0].command) call assert_equal(0, getbufinfo('[Command Line]')[0].command) @@ -235,6 +240,7 @@ func Test_cmdwin_showcmd() endfunc func Test_cmdwin_cursor_position() + throw "Skipped: Nvim supports cmdwin freedom #40312" " When the cmdline fills the screen width exactly, pressing CTRL-F to open " the cmdwin should place the cursor on the last character, not past it. let cmd = 'echo "' .. repeat('a', &columns - 8) .. '"' diff --git a/test/old/testdir/test_menu.vim b/test/old/testdir/test_menu.vim index 84972b92df..397d353cfa 100644 --- a/test/old/testdir/test_menu.vim +++ b/test/old/testdir/test_menu.vim @@ -22,6 +22,7 @@ func Test_load_menu() endfunc func Test_buffer_menu_special_buffers() + throw "Skipped: Nvim supports cmdwin freedom #40312" " Load in runtime menus try source $VIMRUNTIME/menu.vim diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim index 53fc655dc4..4f57251036 100644 --- a/test/old/testdir/test_normal.vim +++ b/test/old/testdir/test_normal.vim @@ -3081,6 +3081,9 @@ endfunc " Test for CTRL-\ commands func Test_normal40_ctrl_bsl() + " Nvim #40312: includes a cmdwin assertion that doesn't translate + " (cmdwin is now a normal window so CTRL-\ CTRL-N is a no-op there). + throw 'Skipped: Nvim supports cmdwin freedom #40312' new call append(0, 'here are some words') exe "norm! 1gg0a\\" diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim index 633b45a506..d39417bb5c 100644 --- a/test/old/testdir/test_popup.vim +++ b/test/old/testdir/test_popup.vim @@ -2296,6 +2296,7 @@ endfunc " Test that Vim does not crash when completion inside cmdwin opens a 'info' " preview window. func Test_popup_complete_cmdwin_preview() + throw "Skipped: Nvim supports cmdwin freedom #40312" func! CompleteWithPreview(findstart, base) if a:findstart return getline('.')->strpart(0, col('.') - 1) diff --git a/test/old/testdir/test_tabpage.vim b/test/old/testdir/test_tabpage.vim index 83791b69ba..89da59fe46 100644 --- a/test/old/testdir/test_tabpage.vim +++ b/test/old/testdir/test_tabpage.vim @@ -711,6 +711,7 @@ endfunc " Test for closing the tab page from a command window func Test_tabpage_close_cmdwin() + throw 'Skipped: Nvim supports cmdwin freedom #40312' tabnew call feedkeys("q/:tabclose\\", 'xt') call assert_equal(2, tabpagenr('$')) diff --git a/test/old/testdir/test_usercommands.vim b/test/old/testdir/test_usercommands.vim index 79be3a47a3..8a0fba045f 100644 --- a/test/old/testdir/test_usercommands.vim +++ b/test/old/testdir/test_usercommands.vim @@ -836,6 +836,7 @@ endfunc " Test for using buffer-local user command from cmdwin. func Test_buflocal_usercmd_cmdwin() + throw 'Skipped: Nvim supports cmdwin freedom #40312' new command -buffer TestCmd edit Test " This used to crash Vim diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim index 9f76a76392..2dddaa6d53 100644 --- a/test/old/testdir/test_window_cmd.vim +++ b/test/old/testdir/test_window_cmd.vim @@ -1313,6 +1313,7 @@ func Run_noroom_for_newwindow_test(dir_arg) endfunc func Test_split_cmds_with_no_room() + throw "Skipped: Nvim supports cmdwin freedom #40312" call Run_noroom_for_newwindow_test('h') call Run_noroom_for_newwindow_test('v') endfunc @@ -1765,6 +1766,7 @@ endfunc " tabline, for each possible value of 'laststatus', 'scrolloff', " 'equalalways', and with the cursor at the top, middle and bottom. func Test_splitkeep_options() + throw "Skipped: Nvim supports cmdwin freedom #40312" " disallow window resizing " let save_WS = &t_WS " set t_WS= @@ -1894,6 +1896,7 @@ func Test_splitkeep_options() endfunc func Test_splitkeep_cmdwin_cursor_position() + throw 'Skipped: Nvim supports cmdwin freedom #40312' set splitkeep=screen call setline(1, range(&lines)) @@ -2205,6 +2208,7 @@ func Test_autocmd_window_force_room() endfunc func Test_win_gotoid_splitmove_textlock_cmdwin() + throw 'Skipped: Nvim supports cmdwin freedom #40312' call setline(1, 'foo') new let curwin = win_getid() From 5ddb4b672ebbd276b2008fa32466a968453b1780 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 19 Jun 2026 14:25:10 +0200 Subject: [PATCH 2/2] fix(ui2): "msg_history_show" error while in cmdwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Executing :messages while in cmdwin fails: Error in "msg_history_show" UI event handler (ns=nvim.ui2): Lua: …/_core/ui2/messages.lua:699: Invalid 'height': expected positive Integer stack traceback: [C]: in function 'nvim_win_set_config' …/_core/ui2/messages.lua:699: in function 'set_pos' …/_core/ui2/messages.lua:329: in function 'set_target_pos' …/_core/ui2/messages.lua:389: in function 'show_msg' …/_core/ui2/messages.lua:553: in function 'handler' …/_core/ui2.lua:161: in function 'ui_callback' …/_core/ui2.lua:210: in function <…/_core/ui2.lua:202> The bug: when `texth.all` is small (e.g. 0 from a hidden pager whose new content isn't laid out yet), or when the available height after subtracting the cmdwin is small, `math.min(min, …)` can yield 0, and `nvim_win_set_config` rejects `height=0`. Solution: Floor at 1. --- runtime/lua/vim/_core/ui2/messages.lua | 7 +++++-- test/functional/editor/cmdwin_spec.lua | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/runtime/lua/vim/_core/ui2/messages.lua b/runtime/lua/vim/_core/ui2/messages.lua index 46233e2900..86f7db7a32 100644 --- a/runtime/lua/vim/_core/ui2/messages.lua +++ b/runtime/lua/vim/_core/ui2/messages.lua @@ -624,13 +624,16 @@ local function win_row_height_border(tgt, min) local cfgmin = ui.cfg.msg[tgt].height --[[@as number]] min = math.min(min, cfgmin < 1 and math.ceil(o.lines * cfgmin) or cfgmin) if tgt ~= 'pager' then - return (tgt == 'msg' and 0 or 1) - ui.cmd.wmnumode, min, min < o.lines - ui.cmdheight + return (tgt == 'msg' and 0 or 1) - ui.cmd.wmnumode, + math.max(1, min), + min < o.lines - ui.cmdheight end local cmdwin = fn.getcmdwintype() ~= was_cmdwin and api.nvim_win_get_height(0) or 0 local global_stl = (cmdwin > 0 or o.laststatus == 3) and 1 or 0 local row = 1 - cmdwin - global_stl local top = min < o.lines - ui.cmdheight - global_stl - cmdwin - return row, math.min(min, o.lines - (top and 1 or 0) - ui.cmdheight - global_stl - cmdwin), top + local height = math.min(min, o.lines - (top and 1 or 0) - ui.cmdheight - global_stl - cmdwin) + return row, math.max(1, height), top end local function enter_pager() diff --git a/test/functional/editor/cmdwin_spec.lua b/test/functional/editor/cmdwin_spec.lua index 85bfe8e6aa..347b4edd3b 100644 --- a/test/functional/editor/cmdwin_spec.lua +++ b/test/functional/editor/cmdwin_spec.lua @@ -43,6 +43,13 @@ describe('cmdwin', function() eq('echo "hi"', api.nvim_get_current_line()) 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(' in normal mode cancels without executing', function() feed('q:') feed('iecho "nope"')