diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/clint.py | 2 | ||||
-rw-r--r-- | src/nvim/api/command.c | 67 | ||||
-rw-r--r-- | src/nvim/api/extmark.c | 2 | ||||
-rw-r--r-- | src/nvim/api/window.c | 2 | ||||
-rw-r--r-- | src/nvim/change.c | 2 | ||||
-rw-r--r-- | src/nvim/charset.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 53 | ||||
-rw-r--r-- | src/nvim/getchar.c | 2 | ||||
-rw-r--r-- | src/nvim/hashtab.c | 2 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 2 | ||||
-rw-r--r-- | src/nvim/lua/treesitter.c | 2 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 2 | ||||
-rw-r--r-- | src/nvim/path.c | 2 | ||||
-rw-r--r-- | src/nvim/textobject.c | 2 | ||||
-rw-r--r-- | src/nvim/window.c | 2 |
15 files changed, 104 insertions, 42 deletions
diff --git a/src/clint.py b/src/clint.py index c4ddbf706e..1a355e0218 100755 --- a/src/clint.py +++ b/src/clint.py @@ -202,7 +202,7 @@ _ERROR_CATEGORIES = [ 'whitespace/cast', ] -# The default state of the category filter. This is overrided by the --filter= +# The default state of the category filter. This is overridden by the --filter= # flag. By default all errors are on, so only add here categories that should be # off by default (i.e., categories that must be enabled by the --filter= flags). # All entries here should start with a '-' or '+', as in the --filter= flag. diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 53701a8c7c..8cd2c0f8b8 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -284,7 +284,11 @@ end: /// Unlike |nvim_command()| this command takes a structured Dictionary instead of a String. This /// allows for easier construction and manipulation of an Ex command. This also allows for things /// such as having spaces inside a command argument, expanding filenames in a command that otherwise -/// doesn't expand filenames, etc. +/// doesn't expand filenames, etc. Command arguments may also be Number, Boolean or String. +/// +/// The first argument may also be used instead of count for commands that support it in order to +/// make their usage simpler with |vim.cmd()|. For example, instead of +/// `vim.cmd.bdelete{ count = 2 }`, you may do `vim.cmd.bdelete(2)`. /// /// On execution error: fails with VimL error, updates v:errmsg. /// @@ -309,8 +313,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error char *cmdline = NULL; char *cmdname = NULL; - ArrayOf(String) args; - size_t argc = 0; + ArrayOf(String) args = ARRAY_DICT_INIT; String retv = (String)STRING_INIT; @@ -382,48 +385,70 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (cmd->args.type != kObjectTypeArray) { VALIDATION_ERROR("'args' must be an Array"); } - // Check if every argument is valid + + // Process all arguments. Convert non-String arguments to String and check if String arguments + // have non-whitespace characters. for (size_t i = 0; i < cmd->args.data.array.size; i++) { Object elem = cmd->args.data.array.items[i]; - if (elem.type != kObjectTypeString) { - VALIDATION_ERROR("Command argument must be a String"); - } else if (string_iswhite(elem.data.string)) { - VALIDATION_ERROR("Command argument must have non-whitespace characters"); + char *data_str; + + switch (elem.type) { + case kObjectTypeBoolean: + data_str = xcalloc(2, sizeof(char)); + data_str[0] = elem.data.boolean ? '1' : '0'; + data_str[1] = '\0'; + break; + case kObjectTypeBuffer: + case kObjectTypeWindow: + case kObjectTypeTabpage: + case kObjectTypeInteger: + data_str = xcalloc(NUMBUFLEN, sizeof(char)); + snprintf(data_str, NUMBUFLEN, "%" PRId64, elem.data.integer); + break; + case kObjectTypeString: + if (string_iswhite(elem.data.string)) { + VALIDATION_ERROR("String command argument must have at least one non-whitespace " + "character"); + } + data_str = xstrndup(elem.data.string.data, elem.data.string.size); + break; + default: + VALIDATION_ERROR("Invalid type for command argument"); + break; } + + ADD(args, STRING_OBJ(cstr_as_string(data_str))); } - argc = cmd->args.data.array.size; bool argc_valid; // Check if correct number of arguments is used. switch (ea.argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) { case EX_EXTRA | EX_NOSPC | EX_NEEDARG: - argc_valid = argc == 1; + argc_valid = args.size == 1; break; case EX_EXTRA | EX_NOSPC: - argc_valid = argc <= 1; + argc_valid = args.size <= 1; break; case EX_EXTRA | EX_NEEDARG: - argc_valid = argc >= 1; + argc_valid = args.size >= 1; break; case EX_EXTRA: argc_valid = true; break; default: - argc_valid = argc == 0; + argc_valid = args.size == 0; break; } if (!argc_valid) { VALIDATION_ERROR("Incorrect number of arguments supplied"); } - - args = cmd->args.data.array; } // Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()` // since it only ever checks the first argument. - set_cmd_addr_type(&ea, argc > 0 ? args.items[0].data.string.data : NULL); + set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL); if (HAS_KEY(cmd->range)) { if (!(ea.argt & EX_RANGE)) { @@ -627,7 +652,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error // Finally, build the command line string that will be stored inside ea.cmdlinep. // This also sets the values of ea.cmd, ea.arg, ea.args and ea.arglens. - build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc); + build_cmdline_str(&cmdline, &ea, &cmdinfo, args); ea.cmdlinep = &cmdline; garray_T capture_local; @@ -683,6 +708,7 @@ clear_ga: ga_clear(&capture_local); } end: + api_free_array(args); xfree(cmdline); xfree(cmdname); xfree(ea.args); @@ -712,8 +738,9 @@ static bool string_iswhite(String str) /// Build cmdline string for command, used by `nvim_cmd()`. static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, - ArrayOf(String) args, size_t argc) + ArrayOf(String) args) { + size_t argc = args.size; StringBuilder cmdline = KV_INITIAL_VALUE; kv_resize(cmdline, 32); // Make it big enough to handle most typical commands @@ -799,7 +826,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin } eap->argc = argc; - eap->arglens = xcalloc(argc, sizeof(size_t)); + eap->arglens = eap->argc > 0 ? xcalloc(argc, sizeof(size_t)) : NULL; size_t argstart_idx = cmdline.size; for (size_t i = 0; i < argc; i++) { String s = args.items[i].data.string; @@ -814,7 +841,7 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin // Now that all the arguments are appended, use the command index and argument indices to set the // values of eap->cmd, eap->arg and eap->args. eap->cmd = cmdline.items + cmdname_idx; - eap->args = xcalloc(argc, sizeof(char *)); + eap->args = eap->argc > 0 ? xcalloc(argc, sizeof(char *)) : NULL; size_t offset = argstart_idx; for (size_t i = 0; i < argc; i++) { offset++; // Account for space diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index c92a97519d..3b1b470629 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -389,7 +389,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// - virt_text : virtual text to link to this mark. /// A list of [text, highlight] tuples, each representing a /// text chunk with specified highlight. `highlight` element -/// can either be a a single highlight group, or an array of +/// can either be a single highlight group, or an array of /// multiple highlight groups that will be stacked /// (highest priority last). A highlight group can be supplied /// either as a string or as an integer, the latter which diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 59e806adb1..aaff00d640 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -430,7 +430,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err) /// Set highlight namespace for a window. This will use highlights defined in /// this namespace, but fall back to global highlights (ns=0) when missing. /// -/// This takes predecence over the 'winhighlight' option. +/// This takes precedence over the 'winhighlight' option. /// /// @param ns_id the namespace to use /// @param[out] err Error details, if any diff --git a/src/nvim/change.c b/src/nvim/change.c index ab550259c8..c9e57ab88f 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -999,7 +999,7 @@ int copy_indent(int size, char *src) /// "second_line_indent": indent for after ^^D in Insert mode or if flag /// OPENLINE_COM_LIST /// "did_do_comment" is set to true when intentionally putting the comment -/// leader in fromt of the new line. +/// leader in front of the new line. /// /// @param dir FORWARD or BACKWARD /// diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 0cc2189948..f5db03b0b4 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -650,7 +650,7 @@ static inline unsigned nr2hex(unsigned n) /// /// @param b /// -/// @reeturn Number of display cells. +/// @return Number of display cells. int byte2cells(int b) FUNC_ATTR_PURE { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 386f708f79..987fb439d7 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1339,6 +1339,20 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate) || ascii_iswhite(*p))) { long n = getdigits_long(&eap->arg, false, -1); eap->arg = skipwhite(eap->arg); + + if (eap->args != NULL) { + assert(eap->argc > 0 && eap->arg >= eap->args[0]); + // If eap->arg is still pointing to the first argument, just make eap->args[0] point to the + // same location. This is needed for usecases like vim.cmd.sleep('10m'). If eap->arg is + // pointing outside the first argument, shift arguments by 1. + if (eap->arg < eap->args[0] + eap->arglens[0]) { + eap->arglens[0] -= (size_t)(eap->arg - eap->args[0]); + eap->args[0] = eap->arg; + } else { + shift_cmd_args(eap); + } + } + if (n <= 0 && (eap->argt & EX_ZEROR) == 0) { if (errormsg != NULL) { *errormsg = _(e_zerocount); @@ -1512,6 +1526,30 @@ end: return retval; } +// Shift Ex-command arguments to the right. +static void shift_cmd_args(exarg_T *eap) +{ + assert(eap->args != NULL && eap->argc > 0); + + char **oldargs = eap->args; + size_t *oldarglens = eap->arglens; + + eap->argc--; + eap->args = eap->argc > 0 ? xcalloc(eap->argc, sizeof(char *)) : NULL; + eap->arglens = eap->argc > 0 ? xcalloc(eap->argc, sizeof(size_t)) : NULL; + + for (size_t i = 0; i < eap->argc; i++) { + eap->args[i] = oldargs[i + 1]; + eap->arglens[i] = oldarglens[i + 1]; + } + + // If there are no arguments, make eap->arg point to the end of string. + eap->arg = (eap->argc > 0 ? eap->args[0] : (oldargs[0] + oldarglens[0])); + + xfree(oldargs); + xfree(oldarglens); +} + static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) { // If filename expansion is enabled, expand filenames @@ -1551,15 +1589,7 @@ static int execute_cmd0(int *retv, exarg_T *eap, char **errormsg, bool preview) eap->args[0] + eap->arglens[0], (eap->argt & EX_BUFUNL) != 0, false, false); eap->addr_count = 1; - // Shift each argument by 1 - for (size_t i = 0; i < eap->argc - 1; i++) { - eap->args[i] = eap->args[i + 1]; - } - // Make the last argument point to the NUL terminator at the end of string - eap->args[eap->argc - 1] = eap->args[eap->argc - 1] + eap->arglens[eap->argc - 1]; - eap->argc -= 1; - - eap->arg = eap->args[0]; + shift_cmd_args(eap); } if (eap->line2 < 0) { // failed return FAIL; @@ -1658,6 +1688,11 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview) (void)hasFolding(eap->line2, NULL, &eap->line2); } + // Use first argument as count when possible + if (parse_count(eap, &errormsg, true) == FAIL) { + goto end; + } + // Execute the command execute_cmd0(&retv, eap, &errormsg, preview); diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index fd0acce25f..ef66e2d355 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2104,7 +2104,7 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth) } else { keylen = 0; } - if (keylen == 0) { // no simplication has been done + if (keylen == 0) { // no simplification has been done // If there was no mapping at all use the character from the // typeahead buffer right here. if (mp == NULL) { diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 3d0ab192b9..32d67621db 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -265,7 +265,7 @@ void hash_unlock(hashtab_T *ht) hash_may_resize(ht, 0); } -/// Resize hastable (new size can be given or automatically computed). +/// Resize hashtable (new size can be given or automatically computed). /// /// @param minitems Minimum number of items the new table should hold. /// If zero, new size will depend on currently used items: diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index fed39c6ed7..3508560e20 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -2034,7 +2034,7 @@ void highlight_changed(void) } } - // sentinel value. used when no hightlight namespace is active + // sentinel value. used when no highlight namespace is active highlight_attr[HLF_COUNT] = 0; // diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 64cace9ab4..79b11eca4a 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -1369,7 +1369,7 @@ static int query_inspect(lua_State *L) lua_rawseti(L, -2, nextitem++); // [retval, patterns, pat, pred] } // last predicate should have ended with TypeDone - lua_pop(L, 1); // [retval, patters, pat] + lua_pop(L, 1); // [retval, patterns, pat] lua_rawseti(L, -2, (int)i + 1); // [retval, patterns] } lua_setfield(L, -2, "patterns"); // [retval] diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 9766c8f3d9..750d2f342f 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -805,7 +805,7 @@ done: /// char *output = NULL; /// size_t nread = 0; /// char *argv[] = {"ls", "-la", NULL}; -/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread); +/// int exitcode = os_system(argv, NULL, 0, &output, &nread); /// /// @param argv The commandline arguments to be passed to the shell. `argv` /// will be consumed. diff --git a/src/nvim/path.c b/src/nvim/path.c index d1a7e14c9f..9295905415 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -575,7 +575,7 @@ bool path_has_exp_wildcard(const char_u *p) /// @param path The path to search. /// @param flags Flags for regexp expansion. /// - EW_ICASE: Ignore case. -/// - EW_NOERROR: Silence error messeges. +/// - EW_NOERROR: Silence error messages. /// - EW_NOTWILD: Add matches literally. /// @returns the number of matches found. static size_t path_expand(garray_T *gap, const char_u *path, int flags) diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c index 621efa44cf..e6b330cbf1 100644 --- a/src/nvim/textobject.c +++ b/src/nvim/textobject.c @@ -1503,7 +1503,7 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar) bool inside_quotes = false; // Looks like "i'" done before bool selected_quote = false; // Has quote inside selection int i; - bool restore_vis_bef = false; // resotre VIsual on abort + bool restore_vis_bef = false; // restore VIsual on abort // When 'selection' is "exclusive" move the cursor to where it would be // with 'selection' "inclusive", so that the logic is the same for both. diff --git a/src/nvim/window.c b/src/nvim/window.c index 5523c3df8b..adcf9cdd56 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -737,7 +737,7 @@ void win_set_minimal_style(win_T *wp) } // TODO(bfredl): this could use a highlight namespace directly, - // and avoid pecularities around window options + // and avoid peculiarities around window options char_u *old = (char_u *)wp->w_p_winhl; wp->w_p_winhl = ((*old == NUL) ? xstrdup("EndOfBuffer:") |