aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt2
-rw-r--r--runtime/doc/builtin.txt2
-rw-r--r--runtime/doc/lua.txt15
-rw-r--r--runtime/doc/options.txt2
-rw-r--r--runtime/lua/vim/_editor.lua2
-rw-r--r--runtime/lua/vim/keymap.lua2
-rw-r--r--src/nvim/api/command.c10
-rw-r--r--src/nvim/api/ui.c4
-rw-r--r--src/nvim/autocmd.c9
-rw-r--r--src/nvim/cursor_shape.c2
-rw-r--r--src/nvim/eval/typval.c11
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/ex_cmds_defs.h56
-rw-r--r--src/nvim/ex_docmd.c618
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/indent_c.c2
-rw-r--r--src/nvim/insexpand.c1
-rw-r--r--src/nvim/keycodes.h90
-rw-r--r--src/nvim/lua/executor.c31
-rw-r--r--src/nvim/mapping.c17
-rw-r--r--src/nvim/memory.c2
-rw-r--r--src/nvim/ops.c2
-rw-r--r--src/nvim/os/env.c2
-rw-r--r--src/nvim/rbuffer.c2
-rw-r--r--src/nvim/regexp.c2
-rw-r--r--src/nvim/ui_client.c2
-rw-r--r--src/nvim/window.c1
-rw-r--r--test/functional/api/keymap_spec.lua6
-rw-r--r--test/functional/editor/completion_spec.lua6
-rw-r--r--test/functional/editor/tabpage_spec.lua2
-rw-r--r--test/functional/ui/statusline_spec.lua37
31 files changed, 487 insertions, 457 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 827d0318ab..be42b7c14e 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -348,7 +348,7 @@ callbacks. These callbacks are called frequently in various contexts;
|nvim_buf_attach()| will take keyword args for the callbacks. "on_lines" will
receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline},
-{new_lastline}, {old_byte_size}[, {old_utf32_size}, {old_utf16_size}]).
+{new_lastline}, {old_byte_size} [, {old_utf32_size}, {old_utf16_size}]).
Unlike remote channel events the text contents are not passed. The new text can
be accessed inside the callback as
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 61d04c6660..f0f47cddf4 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -5311,7 +5311,7 @@ mode([expr]) Return a string that indicates the current mode.
niV Normal using |i_CTRL-O| in |Virtual-Replace-mode|
nt Normal in |terminal-emulator| (insert goes to
Terminal mode)
- ntT Normal using |t_CTRL-\_CTRL-O| in |terminal-mode|
+ ntT Normal using |t_CTRL-\_CTRL-O| in |Terminal-mode|
v Visual by character
vs Visual by character using |v_CTRL-O| in Select mode
V Visual by line
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index c9505429c6..4062a35735 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -704,7 +704,7 @@ regex:match_str({str}) *regex:match_str()*
As any integer is truth-y, `regex:match()` can be directly used
as a condition in an if-statement.
-regex:match_line({bufnr}, {line_idx}[, {start}, {end}]) *regex:match_line()*
+regex:match_line({bufnr}, {line_idx} [, {start}, {end}]) *regex:match_line()*
Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and
{end} are supplied, match only this byte index range. Otherwise see
|regex:match_str()|. If {start} is used, then the returned byte
@@ -855,13 +855,13 @@ vim.empty_dict() *vim.empty_dict()*
Note: If numeric keys are present in the table, Nvim ignores the
metatable marker and converts the dict to a list/array anyway.
-vim.rpcnotify({channel}, {method}[, {args}...]) *vim.rpcnotify()*
+vim.rpcnotify({channel}, {method} [, {args}...]) *vim.rpcnotify()*
Sends {event} to {channel} via |RPC| and returns immediately. If
{channel} is 0, the event is broadcast to all channels.
This function also works in a fast callback |lua-loop-callbacks|.
-vim.rpcrequest({channel}, {method}[, {args}...]) *vim.rpcrequest()*
+vim.rpcrequest({channel}, {method} [, {args}...]) *vim.rpcrequest()*
Sends a request to {channel} to invoke {method} via |RPC| and blocks
until a response is received.
@@ -873,7 +873,7 @@ vim.stricmp({a}, {b}) *vim.stricmp()*
are equal, {a} is greater than {b} or {a} is lesser than {b},
respectively.
-vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
+vim.str_utfindex({str} [, {index}]) *vim.str_utfindex()*
Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
supplied, the length of the string is used. All indices are zero-based.
Returns two values: the UTF-32 and UTF-16 indices respectively.
@@ -883,7 +883,7 @@ vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()*
point each. An {index} in the middle of a UTF-8 sequence is rounded
upwards to the end of that sequence.
-vim.str_byteindex({str}, {index}[, {use_utf16}]) *vim.str_byteindex()*
+vim.str_byteindex({str}, {index} [, {use_utf16}]) *vim.str_byteindex()*
Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not
supplied, it defaults to false (use UTF-32). Returns the byte index.
@@ -1315,7 +1315,7 @@ cmd({command}) *vim.cmd()*
vim.cmd('write! myfile.txt')
vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
vim.cmd.write { args = { "myfile.txt" }, bang = true }
- vim.cmd.write {"myfile.txt", bang = true })
+ vim.cmd.write { "myfile.txt", bang = true }
-- Ex command :colorscheme blue
vim.cmd('colorscheme blue')
@@ -2229,7 +2229,8 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
• remap: (boolean) Make the mapping recursive.
This is the inverse of the "noremap" option from
|nvim_set_keymap()|. Default `false`.
- • replace_keycodes: (boolean) defaults to true.
+ • replace_keycodes: (boolean) defaults to true if
+ "expr" is true.
See also: ~
|nvim_set_keymap()|
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index ffeed6f977..9d03397821 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4210,7 +4210,7 @@ A jump table for the options with a short description can be found at |Q_op|.
The 'mousemodel' option is set by the |:behave| command.
- *'mousescroll'*
+ *'mousescroll'*
'mousescroll' string (default "ver:3,hor:6")
global
This option controls the number of lines / columns to scroll by when
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 094fb2f909..b8a7f71145 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -312,7 +312,7 @@ end
--- vim.cmd('write! myfile.txt')
--- vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
--- vim.cmd.write { args = { "myfile.txt" }, bang = true }
---- vim.cmd.write {"myfile.txt", bang = true })
+--- vim.cmd.write { "myfile.txt", bang = true }
---
--- -- Ex command :colorscheme blue
--- vim.cmd('colorscheme blue')
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index 0549f63180..7265beb56b 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -43,7 +43,7 @@ local keymap = {}
--- - remap: (boolean) Make the mapping recursive. This is the
--- inverse of the "noremap" option from |nvim_set_keymap()|.
--- Default `false`.
---- - replace_keycodes: (boolean) defaults to true.
+--- - replace_keycodes: (boolean) defaults to true if "expr" is true.
---@see |nvim_set_keymap()|
function keymap.set(mode, lhs, rhs, opts)
vim.validate({
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 33efa6b326..04242932c9 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -505,6 +505,11 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
OBJ_TO_BOOL(cmdinfo.magic.file, magic.file, ea.argt & EX_XFILE, "'magic.file'");
OBJ_TO_BOOL(cmdinfo.magic.bar, magic.bar, ea.argt & EX_TRLBAR, "'magic.bar'");
+ if (cmdinfo.magic.file) {
+ ea.argt |= EX_XFILE;
+ } else {
+ ea.argt &= ~EX_XFILE;
+ }
} else {
cmdinfo.magic.file = ea.argt & EX_XFILE;
cmdinfo.magic.bar = ea.argt & EX_TRLBAR;
@@ -939,7 +944,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts,
cmd_addr_T addr_type_arg = ADDR_NONE;
int compl = EXPAND_NOTHING;
char *compl_arg = NULL;
- char *rep = NULL;
+ const char *rep = NULL;
LuaRef luaref = LUA_NOREF;
LuaRef compl_luaref = LUA_NOREF;
LuaRef preview_luaref = LUA_NOREF;
@@ -1111,8 +1116,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts,
if (opts->desc.type == kObjectTypeString) {
rep = opts->desc.data.string.data;
} else {
- snprintf((char *)IObuff, IOSIZE, "<Lua function %d>", luaref);
- rep = (char *)IObuff;
+ rep = "";
}
break;
case kObjectTypeString:
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index aa7bed1132..6239e414a7 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -27,7 +27,7 @@ typedef struct {
uint64_t channel_id;
#define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data.
- /// guranteed size available for each new event (so packing of simple events
+ /// guaranteed size available for each new event (so packing of simple events
/// and the header of grid_line will never fail)
#define EVENT_BUF_SIZE 256
char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data
@@ -43,7 +43,7 @@ typedef struct {
// We start packing the two outermost msgpack arrays before knowing the total
// number of elements. Thus track the location where array size will need
- // to be written in the msgpack buffer, once the specifc array is finished.
+ // to be written in the msgpack buffer, once the specific array is finished.
char *nevents_pos;
char *ncalls_pos;
uint32_t nevents; ///< number of distinct events (top-level args to "redraw"
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 2b4c9c5b9c..bbb044fba3 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -196,9 +196,16 @@ static void aupat_show(AutoPat *ap, event_T event, int previous_group)
if (ac->desc != NULL) {
size_t msglen = 100;
char *msg = (char *)xmallocz(msglen);
- snprintf(msg, msglen, "%s [%s]", exec_to_string, ac->desc);
+ if (ac->exec.type == CALLABLE_CB) {
+ msg_puts_attr(exec_to_string, HL_ATTR(HLF_8));
+ snprintf(msg, msglen, " [%s]", ac->desc);
+ } else {
+ snprintf(msg, msglen, "%s [%s]", exec_to_string, ac->desc);
+ }
msg_outtrans(msg);
XFREE_CLEAR(msg);
+ } else if (ac->exec.type == CALLABLE_CB) {
+ msg_puts_attr(exec_to_string, HL_ATTR(HLF_8));
} else {
msg_outtrans(exec_to_string);
}
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 62cf60e03b..9c33b1a806 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -43,7 +43,7 @@ cursorentry_T shape_table[SHAPE_IDX_COUNT] =
};
/// Converts cursor_shapes into an Array of Dictionaries
-/// @param arena initialized arena where memory will be alocated
+/// @param arena initialized arena where memory will be allocated
///
/// @return Array of the form {[ "cursor_shape": ... ], ...}
Array mode_style_array(Arena *arena)
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index fd57b45e86..ff1808ed91 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -1657,13 +1657,14 @@ void callback_copy(Callback *dest, Callback *src)
/// Generate a string description of a callback
char *callback_to_string(Callback *cb)
{
- size_t msglen = 100;
+ if (cb->type == kCallbackLua) {
+ return nlua_funcref_str(cb->data.luaref);
+ }
+
+ const size_t msglen = 100;
char *msg = (char *)xmallocz(msglen);
switch (cb->type) {
- case kCallbackLua:
- snprintf(msg, msglen, "<lua: %d>", cb->data.luaref);
- break;
case kCallbackFuncref:
// TODO(tjdevries): Is this enough space for this?
snprintf(msg, msglen, "<vim function: %s>", cb->data.funcref);
@@ -1672,7 +1673,7 @@ char *callback_to_string(Callback *cb)
snprintf(msg, msglen, "<vim partial: %s>", cb->data.partial->pt_name);
break;
default:
- snprintf(msg, msglen, "%s", "");
+ *msg = '\0';
break;
}
return msg;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5ff1a9dd47..23e7660606 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -5054,7 +5054,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
int i;
// Specific tags that either have a specific replacement or won't go
- // throught the generic rules.
+ // through the generic rules.
static char *(except_tbl[][2]) = {
{ "*", "star" },
{ "g*", "gstar" },
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 052926fa1f..e80e47bcff 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -37,34 +37,34 @@
// 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and
// long name of the command.
-#define EX_RANGE 0x001 // allow a linespecs
-#define EX_BANG 0x002 // allow a ! after the command name
-#define EX_EXTRA 0x004 // allow extra args after command name
-#define EX_XFILE 0x008 // expand wildcards in extra part
-#define EX_NOSPC 0x010 // no spaces allowed in the extra part
-#define EX_DFLALL 0x020 // default file range is 1,$
-#define EX_WHOLEFOLD 0x040 // extend range to include whole fold also
- // when less than two numbers given
-#define EX_NEEDARG 0x080 // argument required
-#define EX_TRLBAR 0x100 // check for trailing vertical bar
-#define EX_REGSTR 0x200 // allow "x for register designation
-#define EX_COUNT 0x400 // allow count in argument, after command
-#define EX_NOTRLCOM 0x800 // no trailing comment allowed
-#define EX_ZEROR 0x1000 // zero line number allowed
-#define EX_CTRLV 0x2000 // do not remove CTRL-V from argument
-#define EX_CMDARG 0x4000 // allow "+command" argument
-#define EX_BUFNAME 0x8000 // accepts buffer name
-#define EX_BUFUNL 0x10000 // accepts unlisted buffer too
-#define EX_ARGOPT 0x20000 // allow "++opt=val" argument
-#define EX_SBOXOK 0x40000 // allowed in the sandbox
-#define EX_CMDWIN 0x80000 // allowed in cmdline window
-#define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer
-#define EX_FLAGS 0x200000 // allow flags after count in argument
-#define EX_LOCK_OK 0x1000000 // command can be executed when textlock is
- // set; when missing disallows editing another
- // buffer when current buffer is locked
-#define EX_KEEPSCRIPT 0x4000000 // keep sctx of where command was invoked
-#define EX_PREVIEW 0x8000000 // allow incremental command preview
+#define EX_RANGE 0x001u // allow a linespecs
+#define EX_BANG 0x002u // allow a ! after the command name
+#define EX_EXTRA 0x004u // allow extra args after command name
+#define EX_XFILE 0x008u // expand wildcards in extra part
+#define EX_NOSPC 0x010u // no spaces allowed in the extra part
+#define EX_DFLALL 0x020u // default file range is 1,$
+#define EX_WHOLEFOLD 0x040u // extend range to include whole fold also
+ // when less than two numbers given
+#define EX_NEEDARG 0x080u // argument required
+#define EX_TRLBAR 0x100u // check for trailing vertical bar
+#define EX_REGSTR 0x200u // allow "x for register designation
+#define EX_COUNT 0x400u // allow count in argument, after command
+#define EX_NOTRLCOM 0x800u // no trailing comment allowed
+#define EX_ZEROR 0x1000u // zero line number allowed
+#define EX_CTRLV 0x2000u // do not remove CTRL-V from argument
+#define EX_CMDARG 0x4000u // allow "+command" argument
+#define EX_BUFNAME 0x8000u // accepts buffer name
+#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_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 current buffer is locked
+#define EX_KEEPSCRIPT 0x4000000u // keep sctx of where command was invoked
+#define EX_PREVIEW 0x8000000u // allow incremental command preview
#define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed
#define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file
#define EX_WORD1 (EX_EXTRA | EX_NOSPC) // one extra word allowed
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index a7d91a47d7..e3d61ef7e2 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -1563,69 +1563,12 @@ err:
return false;
}
-/// Execute an Ex command using parsed command line information.
-/// Does not do any validation of the Ex command arguments.
-///
-/// @param eap Ex-command arguments
-/// @param cmdinfo Command parse information
-/// @param preview Execute command preview callback instead of actual command
-int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
+static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview)
{
- char *errormsg = NULL;
- int retv = 0;
-
-#define ERROR(msg) \
- do { \
- errormsg = msg; \
- goto end; \
- } while (0)
-
- cmdmod_T save_cmdmod = cmdmod;
- cmdmod = cmdinfo->cmdmod;
-
- // Apply command modifiers
- apply_cmdmod(&cmdmod);
-
- if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY)
- // allow :put in terminals
- && !(curbuf->terminal && eap->cmdidx == CMD_put)) {
- ERROR(_(e_modifiable));
- }
- if (!IS_USER_CMDIDX(eap->cmdidx)) {
- if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) {
- // Command not allowed in the command line window
- ERROR(_(e_cmdwin));
- }
- if (text_locked() && !(eap->argt & EX_LOCK_OK)) {
- // Command not allowed when text is locked
- ERROR(_(get_text_locked_msg()));
- }
- }
- // Disallow editing another buffer when "curbuf->b_ro_locked" is set.
- // 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)
- && eap->cmdidx != CMD_checktime
- && eap->cmdidx != CMD_edit
- && !(eap->cmdidx == CMD_file && *eap->arg == NUL)
- && !IS_USER_CMDIDX(eap->cmdidx)
- && curbuf_locked()) {
- ERROR(_(e_cannot_edit_other_buf));
- }
-
- if (((eap->argt & EX_WHOLEFOLD) || eap->addr_count >= 2) && !global_busy
- && eap->addr_type == ADDR_LINES) {
- // Put the first line at the start of a closed fold, put the last line
- // at the end of a closed fold.
- (void)hasFolding(eap->line1, &eap->line1, NULL);
- (void)hasFolding(eap->line2, NULL, &eap->line2);
- }
-
// If filename expansion is enabled, expand filenames
- if (cmdinfo->magic.file) {
- if (expand_filename(eap, eap->cmdlinep, &errormsg) == FAIL) {
- goto end;
+ if (eap->argt & EX_XFILE) {
+ if (expand_filename(eap, eap->cmdlinep, errormsg) == FAIL) {
+ return FAIL;
}
}
@@ -1670,29 +1613,104 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
eap->arg = eap->args[0];
}
if (eap->line2 < 0) { // failed
- goto end;
+ return FAIL;
}
}
+ // The :try command saves the emsg_silent flag, reset it here when
+ // ":silent! try" was used, it should only apply to :try itself.
+ if (eap->cmdidx == CMD_try && cmdmod.cmod_did_esilent > 0) {
+ emsg_silent -= cmdmod.cmod_did_esilent;
+ if (emsg_silent < 0) {
+ emsg_silent = 0;
+ }
+ cmdmod.cmod_did_esilent = 0;
+ }
+
// Execute the command
if (IS_USER_CMDIDX(eap->cmdidx)) {
// Execute a user-defined command.
- retv = do_ucmd(eap, preview);
+ *retv = do_ucmd(eap, preview);
} else {
// Call the function to execute the command or the preview callback.
eap->errmsg = NULL;
if (preview) {
- retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, cmdpreview_get_ns(),
- cmdpreview_get_bufnr());
+ *retv = (cmdnames[eap->cmdidx].cmd_preview_func)(eap, cmdpreview_get_ns(),
+ cmdpreview_get_bufnr());
} else {
(cmdnames[eap->cmdidx].cmd_func)(eap);
}
if (eap->errmsg != NULL) {
- errormsg = _(eap->errmsg);
+ *errormsg = _(eap->errmsg);
}
}
+ return OK;
+}
+
+/// Execute an Ex command using parsed command line information.
+/// Does not do any validation of the Ex command arguments.
+///
+/// @param eap Ex-command arguments
+/// @param cmdinfo Command parse information
+/// @param preview Execute command preview callback instead of actual command
+int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
+{
+ char *errormsg = NULL;
+ int retv = 0;
+
+#define ERROR(msg) \
+ do { \
+ errormsg = msg; \
+ goto end; \
+ } while (0)
+
+ cmdmod_T save_cmdmod = cmdmod;
+ cmdmod = cmdinfo->cmdmod;
+
+ // Apply command modifiers
+ apply_cmdmod(&cmdmod);
+
+ if (!MODIFIABLE(curbuf) && (eap->argt & EX_MODIFY)
+ // allow :put in terminals
+ && !(curbuf->terminal && eap->cmdidx == CMD_put)) {
+ ERROR(_(e_modifiable));
+ }
+ if (!IS_USER_CMDIDX(eap->cmdidx)) {
+ if (cmdwin_type != 0 && !(eap->argt & EX_CMDWIN)) {
+ // Command not allowed in the command line window
+ ERROR(_(e_cmdwin));
+ }
+ if (text_locked() && !(eap->argt & EX_LOCK_OK)) {
+ // Command not allowed when text is locked
+ ERROR(_(get_text_locked_msg()));
+ }
+ }
+ // Disallow editing another buffer when "curbuf->b_ro_locked" is set.
+ // 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)
+ && eap->cmdidx != CMD_checktime
+ && eap->cmdidx != CMD_edit
+ && !(eap->cmdidx == CMD_file && *eap->arg == NUL)
+ && !IS_USER_CMDIDX(eap->cmdidx)
+ && curbuf_locked()) {
+ ERROR(_(e_cannot_edit_other_buf));
+ }
+
+ if (((eap->argt & EX_WHOLEFOLD) || eap->addr_count >= 2) && !global_busy
+ && eap->addr_type == ADDR_LINES) {
+ // Put the first line at the start of a closed fold, put the last line
+ // at the end of a closed fold.
+ (void)hasFolding(eap->line1, &eap->line1, NULL);
+ (void)hasFolding(eap->line2, NULL, &eap->line2);
+ }
+
+ // Execute the command
+ execute_cmd0(&retv, eap, &errormsg, preview);
+
end:
if (errormsg != NULL && *errormsg != NUL) {
emsg(errormsg);
@@ -1704,6 +1722,142 @@ end:
#undef ERROR
}
+static void profile_cmd(const exarg_T *eap, cstack_T *cstack, LineGetter fgetline, void *cookie)
+{
+ // Count this line for profiling if skip is TRUE.
+ if (do_profiling == PROF_YES
+ && (!eap->skip || cstack->cs_idx == 0
+ || (cstack->cs_idx > 0
+ && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) {
+ int skip = did_emsg || got_int || current_exception;
+
+ if (eap->cmdidx == CMD_catch) {
+ skip = !skip && !(cstack->cs_idx >= 0
+ && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN)
+ && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT));
+ } else if (eap->cmdidx == CMD_else || eap->cmdidx == CMD_elseif) {
+ skip = skip || !(cstack->cs_idx >= 0
+ && !(cstack->cs_flags[cstack->cs_idx]
+ & (CSF_ACTIVE | CSF_TRUE)));
+ } else if (eap->cmdidx == CMD_finally) {
+ skip = false;
+ } else if (eap->cmdidx != CMD_endif
+ && eap->cmdidx != CMD_endfor
+ && eap->cmdidx != CMD_endtry
+ && eap->cmdidx != CMD_endwhile) {
+ skip = eap->skip;
+ }
+
+ if (!skip) {
+ if (getline_equal(fgetline, cookie, get_func_line)) {
+ func_line_exec(getline_cookie(fgetline, cookie));
+ } else if (getline_equal(fgetline, cookie, getsourceline)) {
+ script_line_exec();
+ }
+ }
+ }
+}
+
+static bool skip_cmd(const exarg_T *eap)
+{
+ // Skip the command when it's not going to be executed.
+ // The commands like :if, :endif, etc. always need to be executed.
+ // Also make an exception for commands that handle a trailing command
+ // themselves.
+ if (eap->skip) {
+ switch (eap->cmdidx) {
+ // commands that need evaluation
+ case CMD_while:
+ case CMD_endwhile:
+ case CMD_for:
+ case CMD_endfor:
+ case CMD_if:
+ case CMD_elseif:
+ case CMD_else:
+ case CMD_endif:
+ case CMD_try:
+ case CMD_catch:
+ case CMD_finally:
+ case CMD_endtry:
+ case CMD_function:
+ break;
+
+ // Commands that handle '|' themselves. Check: A command should
+ // either have the EX_TRLBAR flag, appear in this list or appear in
+ // the list at ":help :bar".
+ case CMD_aboveleft:
+ case CMD_and:
+ case CMD_belowright:
+ case CMD_botright:
+ case CMD_browse:
+ case CMD_call:
+ case CMD_confirm:
+ case CMD_const:
+ case CMD_delfunction:
+ case CMD_djump:
+ case CMD_dlist:
+ case CMD_dsearch:
+ case CMD_dsplit:
+ case CMD_echo:
+ case CMD_echoerr:
+ case CMD_echomsg:
+ case CMD_echon:
+ case CMD_eval:
+ case CMD_execute:
+ case CMD_filter:
+ case CMD_help:
+ case CMD_hide:
+ case CMD_ijump:
+ case CMD_ilist:
+ case CMD_isearch:
+ case CMD_isplit:
+ case CMD_keepalt:
+ case CMD_keepjumps:
+ case CMD_keepmarks:
+ case CMD_keeppatterns:
+ case CMD_leftabove:
+ case CMD_let:
+ case CMD_lockmarks:
+ case CMD_lockvar:
+ case CMD_lua:
+ case CMD_match:
+ case CMD_mzscheme:
+ case CMD_noautocmd:
+ case CMD_noswapfile:
+ case CMD_perl:
+ case CMD_psearch:
+ case CMD_python:
+ case CMD_py3:
+ case CMD_python3:
+ case CMD_pythonx:
+ case CMD_pyx:
+ case CMD_return:
+ case CMD_rightbelow:
+ case CMD_ruby:
+ case CMD_silent:
+ case CMD_smagic:
+ case CMD_snomagic:
+ case CMD_substitute:
+ case CMD_syntax:
+ case CMD_tab:
+ case CMD_tcl:
+ case CMD_throw:
+ case CMD_tilde:
+ case CMD_topleft:
+ case CMD_unlet:
+ case CMD_unlockvar:
+ case CMD_verbose:
+ case CMD_vertical:
+ case CMD_wincmd:
+ break;
+
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
/// Execute one Ex command.
///
/// If 'sourcing' is TRUE, the command will be included in the error message.
@@ -1724,16 +1878,11 @@ end:
static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter fgetline,
void *cookie)
{
- char *p;
- linenr_T lnum;
char *errormsg = NULL; // error message
- char *after_modifier = NULL;
- exarg_T ea;
- cmdmod_T save_cmdmod;
const int save_reg_executing = reg_executing;
const bool save_pending_end_reg_executing = pending_end_reg_executing;
- char *cmd;
+ exarg_T ea;
memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
ea.line2 = 1;
@@ -1749,11 +1898,9 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
--quitmore;
}
- /*
- * Reset browse, confirm, etc.. They are restored when returning, for
- * recursive calls.
- */
- save_cmdmod = cmdmod;
+ // Reset browse, confirm, etc.. They are restored when returning, for
+ // recursive calls.
+ cmdmod_T save_cmdmod = cmdmod;
// "#!anything" is handled like a comment.
if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!') {
@@ -1775,7 +1922,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
}
apply_cmdmod(&cmdmod);
- after_modifier = ea.cmd;
+ char *after_modifier = ea.cmd;
ea.skip = (did_emsg
|| got_int
@@ -1786,45 +1933,14 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// 3. Skip over the range to find the command. Let "p" point to after it.
//
// We need the command to know what kind of range it uses.
- cmd = ea.cmd;
+ char *cmd = ea.cmd;
ea.cmd = skip_range(ea.cmd, NULL);
if (*ea.cmd == '*') {
ea.cmd = skipwhite(ea.cmd + 1);
}
- p = find_ex_command(&ea, NULL);
-
- // Count this line for profiling if skip is TRUE.
- if (do_profiling == PROF_YES
- && (!ea.skip || cstack->cs_idx == 0
- || (cstack->cs_idx > 0
- && (cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)))) {
- int skip = did_emsg || got_int || current_exception;
-
- if (ea.cmdidx == CMD_catch) {
- skip = !skip && !(cstack->cs_idx >= 0
- && (cstack->cs_flags[cstack->cs_idx] & CSF_THROWN)
- && !(cstack->cs_flags[cstack->cs_idx] & CSF_CAUGHT));
- } else if (ea.cmdidx == CMD_else || ea.cmdidx == CMD_elseif) {
- skip = skip || !(cstack->cs_idx >= 0
- && !(cstack->cs_flags[cstack->cs_idx]
- & (CSF_ACTIVE | CSF_TRUE)));
- } else if (ea.cmdidx == CMD_finally) {
- skip = false;
- } else if (ea.cmdidx != CMD_endif
- && ea.cmdidx != CMD_endfor
- && ea.cmdidx != CMD_endtry
- && ea.cmdidx != CMD_endwhile) {
- skip = ea.skip;
- }
+ char *p = find_ex_command(&ea, NULL);
- if (!skip) {
- if (getline_equal(fgetline, cookie, get_func_line)) {
- func_line_exec(getline_cookie(fgetline, cookie));
- } else if (getline_equal(fgetline, cookie, getsourceline)) {
- script_line_exec();
- }
- }
- }
+ profile_cmd(&ea, cstack, fgetline, cookie);
// May go to debug mode. If this happens and the ">quit" debug command is
// used, throw an interrupt exception and skip the next command.
@@ -1855,19 +1971,13 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend;
}
- /*
- * 5. Parse the command.
- */
+ // 5. Parse the command.
- /*
- * Skip ':' and any white space
- */
+ // Skip ':' and any white space
ea.cmd = skip_colon_white(ea.cmd, true);
- /*
- * If we got a line, but no command, then go to the line.
- * If we find a '|' or '\n' we set ea.nextcmd.
- */
+ // If we got a line, but no command, then go to the line.
+ // If we find a '|' or '\n' we set ea.nextcmd.
if (*ea.cmd == NUL || *ea.cmd == '"'
|| (ea.nextcmd = (char *)check_nextcmd((char_u *)ea.cmd)) != NULL) {
// strange vi behaviour:
@@ -1947,12 +2057,12 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
const int ni = is_cmd_ni(ea.cmdidx);
// Forced commands.
- if (*p == '!' && ea.cmdidx != CMD_substitute
- && ea.cmdidx != CMD_smagic && ea.cmdidx != CMD_snomagic) {
+ ea.forceit = *p == '!'
+ && ea.cmdidx != CMD_substitute
+ && ea.cmdidx != CMD_smagic
+ && ea.cmdidx != CMD_snomagic;
+ if (ea.forceit) {
p++;
- ea.forceit = true;
- } else {
- ea.forceit = false;
}
// 6. Parse arguments. Then check for errors.
@@ -2012,10 +2122,8 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend;
}
- /*
- * Don't complain about the range if it is not used
- * (could happen if line_count is accidentally set to 0).
- */
+ // Don't complain about the range if it is not used
+ // (could happen if line_count is accidentally set to 0).
if (!ea.skip && !ni && (ea.argt & EX_RANGE)) {
// If the range is backwards, ask for confirmation and, if given, swap
// ea.line1 & ea.line2 so it's forwards again.
@@ -2030,7 +2138,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend;
}
}
- lnum = ea.line1;
+ linenr_T lnum = ea.line1;
ea.line1 = ea.line2;
ea.line2 = lnum;
}
@@ -2054,34 +2162,24 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
(void)hasFolding(ea.line2, NULL, &ea.line2);
}
- /*
- * For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
- * option here, so things like % get expanded.
- */
+ // For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
+ // option here, so things like % get expanded.
p = replace_makeprg(&ea, p, cmdlinep);
if (p == NULL) {
goto doend;
}
- /*
- * Skip to start of argument.
- * Don't do this for the ":!" command, because ":!! -l" needs the space.
- */
- if (ea.cmdidx == CMD_bang) {
- ea.arg = p;
- } else {
- ea.arg = skipwhite(p);
- }
+ // Skip to start of argument.
+ // Don't do this for the ":!" command, because ":!! -l" needs the space.
+ ea.arg = ea.cmdidx == CMD_bang ? p : skipwhite(p);
// ":file" cannot be run with an argument when "curbuf->b_ro_locked" is set
if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) {
goto doend;
}
- /*
- * Check for "++opt=val" argument.
- * Must be first, allow ":w ++enc=utf8 !cmd"
- */
+ // Check for "++opt=val" argument.
+ // Must be first, allow ":w ++enc=utf8 !cmd"
if (ea.argt & EX_ARGOPT) {
while (ea.arg[0] == '+' && ea.arg[1] == '+') {
if (getargopt(&ea) == FAIL && !ni) {
@@ -2103,9 +2201,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
++ea.arg;
ea.usefilter = TRUE;
}
- }
-
- if (ea.cmdidx == CMD_read) {
+ } else if (ea.cmdidx == CMD_read) {
if (ea.forceit) {
ea.usefilter = TRUE; // :r! filter if ea.forceit
ea.forceit = FALSE;
@@ -2113,9 +2209,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
++ea.arg;
ea.usefilter = TRUE;
}
- }
-
- if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
+ } else if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
ea.amount = 1;
while (*ea.arg == *ea.cmd) { // count number of '>' or '<'
ea.arg++;
@@ -2124,18 +2218,14 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
ea.arg = skipwhite(ea.arg);
}
- /*
- * Check for "+command" argument, before checking for next command.
- * Don't do this for ":read !cmd" and ":write !cmd".
- */
+ // Check for "+command" argument, before checking for next command.
+ // Don't do this for ":read !cmd" and ":write !cmd".
if ((ea.argt & EX_CMDARG) && !ea.usefilter) {
ea.do_ecmd_cmd = getargcmd(&ea.arg);
}
- /*
- * Check for '|' to separate commands and '"' to start comments.
- * Don't do this for ":read !cmd" and ":write !cmd".
- */
+ // Check for '|' to separate commands and '"' to start comments.
+ // Don't do this for ":read !cmd" and ":write !cmd".
if ((ea.argt & EX_TRLBAR) && !ea.usefilter) {
separate_nextcmd(&ea);
} else if (ea.cmdidx == CMD_bang
@@ -2146,18 +2236,18 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
// Check for <newline> to end a shell command.
// Also do this for ":read !cmd", ":write !cmd" and ":global".
// Any others?
- for (p = ea.arg; *p; p++) {
+ for (char *s = ea.arg; *s; s++) {
// Remove one backslash before a newline, so that it's possible to
// pass a newline to the shell and also a newline that is preceded
// with a backslash. This makes it impossible to end a shell
// command in a backslash, but that doesn't appear useful.
// Halving the number of backslashes is incompatible with previous
// versions.
- if (*p == '\\' && p[1] == '\n') {
- STRMOVE(p, p + 1);
- } else if (*p == '\n') {
- ea.nextcmd = p + 1;
- *p = NUL;
+ if (*s == '\\' && s[1] == '\n') {
+ STRMOVE(s, s + 1);
+ } else if (*s == '\n') {
+ ea.nextcmd = s + 1;
+ *s = NUL;
break;
}
}
@@ -2173,9 +2263,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend;
}
- /*
- * Check for flags: 'l', 'p' and '#'.
- */
+ // Check for flags: 'l', 'p' and '#'.
if (ea.argt & EX_FLAGS) {
get_flags(&ea);
}
@@ -2191,173 +2279,21 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
goto doend;
}
- /*
- * Skip the command when it's not going to be executed.
- * The commands like :if, :endif, etc. always need to be executed.
- * Also make an exception for commands that handle a trailing command
- * themselves.
- */
- if (ea.skip) {
- switch (ea.cmdidx) {
- // commands that need evaluation
- case CMD_while:
- case CMD_endwhile:
- case CMD_for:
- case CMD_endfor:
- case CMD_if:
- case CMD_elseif:
- case CMD_else:
- case CMD_endif:
- case CMD_try:
- case CMD_catch:
- case CMD_finally:
- case CMD_endtry:
- case CMD_function:
- break;
-
- // Commands that handle '|' themselves. Check: A command should
- // either have the EX_TRLBAR flag, appear in this list or appear in
- // the list at ":help :bar".
- case CMD_aboveleft:
- case CMD_and:
- case CMD_belowright:
- case CMD_botright:
- case CMD_browse:
- case CMD_call:
- case CMD_confirm:
- case CMD_const:
- case CMD_delfunction:
- case CMD_djump:
- case CMD_dlist:
- case CMD_dsearch:
- case CMD_dsplit:
- case CMD_echo:
- case CMD_echoerr:
- case CMD_echomsg:
- case CMD_echon:
- case CMD_eval:
- case CMD_execute:
- case CMD_filter:
- case CMD_help:
- case CMD_hide:
- case CMD_ijump:
- case CMD_ilist:
- case CMD_isearch:
- case CMD_isplit:
- case CMD_keepalt:
- case CMD_keepjumps:
- case CMD_keepmarks:
- case CMD_keeppatterns:
- case CMD_leftabove:
- case CMD_let:
- case CMD_lockmarks:
- case CMD_lockvar:
- case CMD_lua:
- case CMD_match:
- case CMD_mzscheme:
- case CMD_noautocmd:
- case CMD_noswapfile:
- case CMD_perl:
- case CMD_psearch:
- case CMD_python:
- case CMD_py3:
- case CMD_python3:
- case CMD_pythonx:
- case CMD_pyx:
- case CMD_return:
- case CMD_rightbelow:
- case CMD_ruby:
- case CMD_silent:
- case CMD_smagic:
- case CMD_snomagic:
- case CMD_substitute:
- case CMD_syntax:
- case CMD_tab:
- case CMD_tcl:
- case CMD_throw:
- case CMD_tilde:
- case CMD_topleft:
- case CMD_unlet:
- case CMD_unlockvar:
- case CMD_verbose:
- case CMD_vertical:
- case CMD_wincmd:
- break;
-
- default:
- goto doend;
- }
- }
-
- if (ea.argt & EX_XFILE) {
- if (expand_filename(&ea, cmdlinep, &errormsg) == FAIL) {
- goto doend;
- }
- }
-
- /*
- * Accept buffer name. Cannot be used at the same time with a buffer
- * number. Don't do this for a user command.
- */
- if ((ea.argt & EX_BUFNAME) && *ea.arg != NUL && ea.addr_count == 0
- && !IS_USER_CMDIDX(ea.cmdidx)) {
- /*
- * :bdelete, :bwipeout and :bunload take several arguments, separated
- * by spaces: find next space (skipping over escaped characters).
- * The others take one argument: ignore trailing spaces.
- */
- if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bwipeout
- || ea.cmdidx == CMD_bunload) {
- p = skiptowhite_esc(ea.arg);
- } else {
- p = ea.arg + STRLEN(ea.arg);
- while (p > ea.arg && ascii_iswhite(p[-1])) {
- p--;
- }
- }
- ea.line2 = buflist_findpat(ea.arg, p, (ea.argt & EX_BUFUNL) != 0,
- false, false);
- if (ea.line2 < 0) { // failed
- goto doend;
- }
- ea.addr_count = 1;
- ea.arg = skipwhite(p);
- }
-
- // The :try command saves the emsg_silent flag, reset it here when
- // ":silent! try" was used, it should only apply to :try itself.
- if (ea.cmdidx == CMD_try && cmdmod.cmod_did_esilent > 0) {
- emsg_silent -= cmdmod.cmod_did_esilent;
- if (emsg_silent < 0) {
- emsg_silent = 0;
- }
- cmdmod.cmod_did_esilent = 0;
+ if (skip_cmd(&ea)) {
+ goto doend;
}
// 7. Execute the command.
- if (IS_USER_CMDIDX(ea.cmdidx)) {
- /*
- * Execute a user-defined command.
- */
- do_ucmd(&ea, false);
- } else {
- /*
- * Call the function to execute the command.
- */
- ea.errmsg = NULL;
- (cmdnames[ea.cmdidx].cmd_func)(&ea);
- if (ea.errmsg != NULL) {
- errormsg = _(ea.errmsg);
- }
+ int retv = 0;
+ if (execute_cmd0(&retv, &ea, &errormsg, false) == FAIL) {
+ goto doend;
}
- /*
- * If the command just executed called do_cmdline(), any throw or ":return"
- * or ":finish" encountered there must also check the cstack of the still
- * active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught
- * exception, or reanimate a returned function or finished script file and
- * return or finish it again.
- */
+ // If the command just executed called do_cmdline(), any throw or ":return"
+ // or ":finish" encountered there must also check the cstack of the still
+ // active do_cmdline() that called this do_one_cmd(). Rethrow an uncaught
+ // exception, or reanimate a returned function or finished script file and
+ // return or finish it again.
if (need_rethrow) {
do_throw(cstack);
} else if (check_cstack) {
@@ -2383,7 +2319,7 @@ doend:
STRCPY(IObuff, errormsg);
errormsg = (char *)IObuff;
}
- append_command(*cmdlinep);
+ append_command(*ea.cmdlinep);
}
emsg(errormsg);
}
@@ -5504,7 +5440,7 @@ char *uc_validate_name(char *name)
/// This function takes ownership of compl_arg, compl_luaref, and luaref.
///
/// @return OK if the command is created, FAIL otherwise.
-int uc_add_command(char *name, size_t name_len, char *rep, uint32_t argt, long def, int flags,
+int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, long def, int flags,
int compl, char *compl_arg, LuaRef compl_luaref, LuaRef preview_luaref,
cmd_addr_T addr_type, LuaRef luaref, bool force)
FUNC_ATTR_NONNULL_ARG(1, 3)
@@ -5826,6 +5762,16 @@ static void uc_list(char *name, size_t name_len)
IObuff[len] = '\0';
msg_outtrans((char *)IObuff);
+ if (cmd->uc_luaref != LUA_NOREF) {
+ char *fn = nlua_funcref_str(cmd->uc_luaref);
+ msg_puts_attr(fn, HL_ATTR(HLF_8));
+ xfree(fn);
+ // put the description on a new line
+ if (*cmd->uc_rep != NUL) {
+ msg_puts("\n ");
+ }
+ }
+
msg_outtrans_special(cmd->uc_rep, false,
name_len == 0 ? Columns - 47 : 0);
if (p_verbose > 0) {
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 4a5841ca6e..28ff0cbd59 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1737,7 +1737,7 @@ static bool at_ins_compl_key(void)
|| ((compl_cont_status & CONT_LOCAL) && (c == Ctrl_N || c == Ctrl_P));
}
-/// Check if typebuf.tb_buf[] contains a modifer plus key that can be changed
+/// Check if typebuf.tb_buf[] contains a modifier plus key that can be changed
/// into just a key, apply that.
/// Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off + "max_offset"].
/// @return the length of the replaced bytes, 0 if nothing changed, -1 for error.
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index b89ab19226..c5e030ce25 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -2002,7 +2002,7 @@ int get_c_indent(void)
}
// #defines and so on go at the left when included in 'cinkeys',
- // exluding pragmas when customized in 'cinoptions'
+ // excluding pragmas when customized in 'cinoptions'
if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', true))) {
const char_u *const directive = (char_u *)skipwhite((char *)theline + 1);
if (curbuf->b_ind_pragma == 0 || STRNCMP(directive, "pragma", 6) != 0) {
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 2fc8f1dadc..a64d8e8f00 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -825,7 +825,6 @@ static void ins_compl_longest_match(compl_T *match)
/// Add an array of matches to the list of matches.
/// Frees matches[].
static void ins_compl_add_matches(int num_matches, char **matches, int icase)
- FUNC_ATTR_NONNULL_ALL
{
int add_r = OK;
Direction dir = compl_direction;
diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h
index f6c576f6ee..c4d984ee17 100644
--- a/src/nvim/keycodes.h
+++ b/src/nvim/keycodes.h
@@ -7,10 +7,8 @@
//
// Any special key code sequences are replaced by these codes.
-//
-// For MS-DOS some keys produce codes larger than 0xff. They are split into two
-// chars, the first one is K_NUL.
-//
+/// For MS-DOS some keys produce codes larger than 0xff. They are split into two
+/// chars, the first one is K_NUL.
#define K_NUL (0xce) // for MS-DOS: special key follows
/// K_SPECIAL is the first byte of a special key code and is always followed by
@@ -59,13 +57,13 @@
#define KS_SELECT 245
#define K_SELECT_STRING (char_u *)"\200\365X"
-// Used a termcap entry that produces a normal character.
+/// Used a termcap entry that produces a normal character.
#define KS_KEY 242
-// Used for click in a tab pages label.
+/// Used for click in a tab pages label.
#define KS_TABLINE 240
-// Used for menu in a tab pages line.
+/// Used for menu in a tab pages line.
#define KS_TABMENU 239
/// Filler used after KS_SPECIAL and others
@@ -89,18 +87,19 @@
#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \
KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b))
-// Codes for keys that do not have a termcap name.
-// The numbers are fixed to make sure that recorded key sequences remain valid.
-// Add new entries at the end, not halfway.
-//
-// K_SPECIAL KS_EXTRA KE_xxx
-//
-// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL).
+/// Codes for keys that do not have a termcap name.
+/// The numbers are fixed to make sure that recorded key sequences remain valid.
+/// Add new entries at the end, not halfway.
+///
+/// K_SPECIAL KS_EXTRA KE_xxx
+///
+/// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL).
enum key_extra {
KE_S_UP = 4, // shift-up
- KE_S_DOWN = 5, // shift-down
+ KE_S_DOWN = 5, // shift-down
- KE_S_F1 = 6, // shifted function keys
+ // shifted function keys
+ KE_S_F1 = 6,
KE_S_F2 = 7,
KE_S_F3 = 8,
KE_S_F4 = 9,
@@ -141,7 +140,7 @@ enum key_extra {
KE_S_F36 = 41,
KE_S_F37 = 42,
- KE_MOUSE = 43, // mouse event start
+ KE_MOUSE = 43, // mouse event start
// Symbols for pseudo keys which are translated from the real key symbols
// above.
@@ -153,14 +152,14 @@ enum key_extra {
KE_MIDDLERELEASE = 49, // Middle mouse button release
KE_RIGHTMOUSE = 50, // Right mouse button click
KE_RIGHTDRAG = 51, // Drag with right mouse button down
- KE_RIGHTRELEASE = 52, // Right mouse button release
+ KE_RIGHTRELEASE = 52, // Right mouse button release
- KE_IGNORE = 53, // Ignored mouse drag/release
+ KE_IGNORE = 53, // Ignored mouse drag/release
KE_TAB = 54, // unshifted TAB key
- KE_S_TAB_OLD = 55, // shifted TAB key (no longer used)
+ KE_S_TAB_OLD = 55, // shifted TAB key (no longer used)
- // , KE_SNIFF_UNUSED = 56 // obsolete
+ // KE_SNIFF_UNUSED = 56, // obsolete
KE_XF1 = 57, // extra vt100 function keys for xterm
KE_XF2 = 58,
KE_XF3 = 59,
@@ -175,7 +174,7 @@ enum key_extra {
KE_XRIGHT = 68,
KE_LEFTMOUSE_NM = 69, // non-mappable Left mouse button click
- KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release
+ KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release
KE_S_XF1 = 71, // vt100 shifted function keys for xterm
KE_S_XF2 = 72,
@@ -188,20 +187,20 @@ enum key_extra {
KE_MOUSEDOWN = 75, // scroll wheel pseudo-button Down
KE_MOUSEUP = 76, // scroll wheel pseudo-button Up
KE_MOUSELEFT = 77, // scroll wheel pseudo-button Left
- KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right
+ KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right
KE_KINS = 79, // keypad Insert key
- KE_KDEL = 80, // keypad Delete key
+ KE_KDEL = 80, // keypad Delete key
// KE_CSI = 81, // Nvim doesn't need escaping CSI
KE_SNR = 82, // <SNR>
KE_PLUG = 83, // <Plug>
- KE_CMDWIN = 84, // open command-line window from Command-line Mode
+ KE_CMDWIN = 84, // open command-line window from Command-line Mode
KE_C_LEFT = 85, // control-left
KE_C_RIGHT = 86, // control-right
KE_C_HOME = 87, // control-home
- KE_C_END = 88, // control-end
+ KE_C_END = 88, // control-end
KE_X1MOUSE = 89, // X1/X2 mouse-buttons
KE_X1DRAG = 90,
@@ -210,16 +209,16 @@ enum key_extra {
KE_X2DRAG = 93,
KE_X2RELEASE = 94,
- KE_DROP = 95, // DnD data is available
- // , KE_CURSORHOLD = 96 // CursorHold event
- KE_NOP = 97, // no-op: does nothing
- // , KE_FOCUSGAINED = 98 // focus gained
- // , KE_FOCUSLOST = 99 // focus lost
- KE_MOUSEMOVE = 100, // mouse moved with no button down
- // , KE_CANCEL = 101 // return from vgetc
+ KE_DROP = 95, // DnD data is available
+ // KE_CURSORHOLD = 96, // CursorHold event
+ KE_NOP = 97, // no-op: does nothing
+ // KE_FOCUSGAINED = 98, // focus gained
+ // KE_FOCUSLOST = 99, // focus lost
+ KE_MOUSEMOVE = 100, // mouse moved with no button down
+ // KE_CANCEL = 101, // return from vgetc()
KE_EVENT = 102, // event
- KE_LUA = 103, // lua special key
- KE_COMMAND = 104, // <Cmd> special key
+ KE_LUA = 103, // Lua special key
+ KE_COMMAND = 104, // <Cmd> special key
};
// the three byte codes are replaced with the following int when using vgetc()
@@ -259,7 +258,8 @@ enum key_extra {
#define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT)
#define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT)
-#define K_F1 TERMCAP2KEY('k', '1') // function keys
+// function keys
+#define K_F1 TERMCAP2KEY('k', '1')
#define K_F2 TERMCAP2KEY('k', '2')
#define K_F3 TERMCAP2KEY('k', '3')
#define K_F4 TERMCAP2KEY('k', '4')
@@ -463,13 +463,13 @@ enum key_extra {
/// Current longest is <M-C-S-T-D-A-4-ScrollWheelRight> (length includes '<' and '>').
#define MAX_KEY_NAME_LEN 32
-// Maximum length of a special key event as tokens. This includes modifiers.
-// The longest event is something like <M-C-S-T-4-LeftDrag> which would be the
-// following string of tokens:
-//
-// <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KE_LEFTDRAG>.
-//
-// This is a total of 6 tokens, and is currently the longest one possible.
+/// Maximum length of a special key event as tokens. This includes modifiers.
+/// The longest event is something like <M-C-S-T-4-LeftDrag> which would be the
+/// following string of tokens:
+///
+/// <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KE_LEFTDRAG>.
+///
+/// This is a total of 6 tokens, and is currently the longest one possible.
#define MAX_KEY_CODE_LEN 6
#define FLAG_CPO_BSLASH 0x01
@@ -477,7 +477,7 @@ enum key_extra {
? 0 \
: FLAG_CPO_BSLASH)
-// Flags for replace_termcodes()
+/// Flags for replace_termcodes()
enum {
REPTERM_FROM_PART = 1,
REPTERM_DO_LT = 2,
@@ -485,7 +485,7 @@ enum {
REPTERM_NO_SIMPLIFY = 8,
};
-// Flags for find_special_key()
+/// Flags for find_special_key()
enum {
FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL
FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 17157ccdc2..197a209e97 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -2076,3 +2076,34 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
return retv;
}
+
+/// String representation of a Lua function reference
+///
+/// @return Allocated string
+char *nlua_funcref_str(LuaRef ref)
+{
+ lua_State *const lstate = global_lstate;
+ StringBuilder str = KV_INITIAL_VALUE;
+ kv_resize(str, 16);
+
+ if (!lua_checkstack(lstate, 1)) {
+ goto plain;
+ }
+ nlua_pushref(lstate, ref);
+ if (!lua_isfunction(lstate, -1)) {
+ lua_pop(lstate, 1);
+ goto plain;
+ }
+
+ lua_Debug ar;
+ if (lua_getinfo(lstate, ">S", &ar) && *ar.source == '@' && ar.linedefined >= 0) {
+ char *src = home_replace_save(NULL, ar.source + 1);
+ kv_printf(str, "<Lua %d: %s:%d>", ref, src, ar.linedefined);
+ xfree(src);
+ return str.items;
+ }
+
+plain:
+ kv_printf(str, "<Lua %d>", ref);
+ return str.items;
+}
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 520a91491a..342b1b0d47 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -196,9 +196,9 @@ static void showmap(mapblock_T *mp, bool local)
// Use false below if we only want things like <Up> to show up as such on
// the rhs, and not M-x etc, true gets both -- webb
if (mp->m_luaref != LUA_NOREF) {
- char msg[100];
- snprintf(msg, sizeof(msg), "<Lua function %d>", mp->m_luaref);
- msg_puts_attr(msg, HL_ATTR(HLF_8));
+ char *str = nlua_funcref_str(mp->m_luaref);
+ msg_puts_attr(str, HL_ATTR(HLF_8));
+ xfree(str);
} else if (mp->m_str[0] == NUL) {
msg_puts_attr("<Nop>", HL_ATTR(HLF_8));
} else {
@@ -235,7 +235,7 @@ static void showmap(mapblock_T *mp, bool local)
/// @param[in] orig_lhs Original mapping LHS, with characters to replace.
/// @param[in] orig_lhs_len `strlen` of orig_lhs.
/// @param[in] orig_rhs Original mapping RHS, with characters to replace.
-/// @param[in] rhs_lua Lua reference for Lua maps.
+/// @param[in] rhs_lua Lua reference for Lua mappings.
/// @param[in] orig_rhs_len `strlen` of orig_rhs.
/// @param[in] cpo_flags See param docs for @ref replace_termcodes.
/// @param[out] mapargs MapArguments struct holding the replaced strings.
@@ -1633,7 +1633,7 @@ int makemap(FILE *fd, buf_T *buf)
continue;
}
- // skip lua mappings and mappings that contain a <SNR> (script-local thing),
+ // skip Lua mappings and mappings that contain a <SNR> (script-local thing),
// they probably don't work when loaded again
if (mp->m_luaref != LUA_NOREF) {
continue;
@@ -2110,10 +2110,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
rettv->vval.v_string = str2special_save((char *)rhs, false, false);
}
} else if (rhs_lua != LUA_NOREF) {
- size_t msglen = 100;
- char *msg = (char *)xmalloc(msglen);
- snprintf(msg, msglen, "<Lua function %d>", mp->m_luaref);
- rettv->vval.v_string = msg;
+ rettv->vval.v_string = nlua_funcref_str(mp->m_luaref);
}
} else {
tv_dict_alloc_ret(rettv);
@@ -2601,7 +2598,7 @@ fail_and_free:
///
/// @param mode The abbreviation for the mode
/// @param buf The buffer to get the mapping array. NULL for global
-/// @param from_lua Whether it is called from internal lua api.
+/// @param from_lua Whether it is called from internal Lua api.
/// @returns Array of maparg()-like dictionaries describing mappings
ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua)
{
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index a74fcf6137..5ae7f7bbe3 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -546,7 +546,7 @@ void arena_start(Arena *arena, ArenaMem *reuse_blk)
/// Finnish the allocations in an arena.
///
-/// This does not immedately free the memory, but leaves existing allocated
+/// This does not immediately free the memory, but leaves existing allocated
/// objects valid, and returns an opaque ArenaMem handle, which can be used to
/// free the allocations using `arena_mem_free`, when the objects allocated
/// from the arena are not needed anymore.
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 660902b10b..53612be697 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -4889,7 +4889,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
linenr_T amount = Prenum1;
// do_addsub() might trigger re-evaluation of 'foldexpr' halfway, when the
- // buffer is not completly updated yet. Postpone updating folds until before
+ // buffer is not completely updated yet. Postpone updating folds until before
// the call to changed_lines().
disable_fold_update++;
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 9c93057fe7..eaa56ffe63 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -1143,7 +1143,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
/// Like home_replace, store the replaced string in allocated memory.
/// @param buf When not NULL, check for help files
/// @param src Input file name
-char *home_replace_save(buf_T *buf, char *src)
+char *home_replace_save(buf_T *buf, const char *src)
FUNC_ATTR_NONNULL_RET
{
size_t len = 3; // space for "~/" and trailing NUL
diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c
index 6407ac172e..2f718e9c2e 100644
--- a/src/nvim/rbuffer.c
+++ b/src/nvim/rbuffer.c
@@ -156,7 +156,7 @@ void rbuffer_consumed(RBuffer *buf, size_t count)
/// Use instead of rbuffer_consumed to use rbuffer in a linear, non-cyclic fashion.
///
-/// This is generally usefull if we can guarantee to parse all input
+/// This is generally useful if we can guarantee to parse all input
/// except some small incomplete token, like when parsing msgpack.
void rbuffer_consumed_compact(RBuffer *buf, size_t count)
FUNC_ATTR_NONNULL_ALL
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index c2a9c90dda..fbbf904f8b 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -1649,7 +1649,7 @@ static void clear_submatch_list(staticList10_T *sl)
/// vim_regexec_multi() match.
///
/// If "flags" has REGSUB_COPY really copy into "dest[destlen]".
-/// Oterwise nothing is copied, only compue the length of the result.
+/// Otherwise nothing is copied, only compute the length of the result.
///
/// If "flags" has REGSUB_MAGIC then behave like 'magic' is set.
///
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index 09e971f03f..a586fec3bf 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -53,7 +53,7 @@ UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len,
/// Placeholder for _sync_ requests with 'redraw' method name
///
/// async 'redraw' events, which are expected when nvim acts as an ui client.
-/// get handled in msgpack_rpc/unpacker.c and directy dispatched to handlers
+/// get handled in msgpack_rpc/unpacker.c and directly dispatched to handlers
/// of specific ui events, like ui_client_event_grid_resize and so on.
Object handle_ui_client_redraw(uint64_t channel_id, Array args, Error *error)
{
diff --git a/src/nvim/window.c b/src/nvim/window.c
index c7f038850e..b737215616 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5518,6 +5518,7 @@ void win_setheight_win(int height, win_T *win)
msg_row = row;
msg_col = 0;
redraw_all_later(NOT_VALID);
+ redraw_cmdline = true;
}
}
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index eb2a467a8b..a93a4544ff 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -822,7 +822,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(string.match(exec_lua[[return vim.api.nvim_exec(':nmap asdf', true)]],
- "^\nn asdf <Lua function %d+>"))
+ "^\nn asdf <Lua %d+>"))
end)
it ('mapcheck() returns lua mapping correctly', function()
@@ -830,7 +830,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(string.match(funcs.mapcheck('asdf', 'n'),
- "^<Lua function %d+>"))
+ "^<Lua %d+>"))
end)
it ('maparg() returns lua mapping correctly', function()
@@ -838,7 +838,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
vim.api.nvim_set_keymap ('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
assert.truthy(string.match(funcs.maparg('asdf', 'n'),
- "^<Lua function %d+>"))
+ "^<Lua %d+>"))
local mapargs = funcs.maparg('asdf', 'n', false, true)
assert(type(mapargs.callback) == 'number', 'callback is not luaref number')
mapargs.callback = nil
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua
index e27da0947f..6cdac3c079 100644
--- a/test/functional/editor/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -1253,4 +1253,10 @@ describe('completion', function()
feed('ifoo#<C-X><C-U>')
assert_alive()
end)
+
+ it('does not crash when using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
+ feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>')
+ expect('colorscheme NOSUCHCOLORSCHEME')
+ assert_alive()
+ end)
end)
diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua
index 7dd0b9f154..849a02c28b 100644
--- a/test/functional/editor/tabpage_spec.lua
+++ b/test/functional/editor/tabpage_spec.lua
@@ -59,7 +59,7 @@ describe('tabpage', function()
screen:set_default_attr_ids({
[0] = {bold = true, foreground = Screen.colors.Blue},
[1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {reverse = true}, -- StatusLineNC, TabLineFill
+ [2] = {reverse = true}, -- TabLineFill
[3] = {bold = true}, -- TabLineSel
[4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine
[5] = {bold = true, foreground = Screen.colors.Magenta},
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
index 69a2d2f4ed..f3735c8e4c 100644
--- a/test/functional/ui/statusline_spec.lua
+++ b/test/functional/ui/statusline_spec.lua
@@ -407,3 +407,40 @@ it('statusline does not crash if it has Arabic characters #19447', function()
command('redraw!')
assert_alive()
end)
+
+it('statusline is redrawn with :resize from <Cmd> mapping #19629', function()
+ clear()
+ local screen = Screen.new(40, 8)
+ screen:set_default_attr_ids({
+ [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [1] = {bold = true, reverse = true}, -- StatusLine
+ })
+ screen:attach()
+ exec([[
+ set laststatus=2
+ nnoremap <Up> <cmd>resize -1<CR>
+ nnoremap <Down> <cmd>resize +1<CR>
+ ]])
+ feed('<Up>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:[No Name] }|
+ |
+ |
+ ]])
+ feed('<Down>')
+ screen:expect([[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:[No Name] }|
+ |
+ ]])
+end)