diff options
Diffstat (limited to 'src/nvim/api')
-rw-r--r-- | src/nvim/api/private/helpers.c | 159 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 60 | ||||
-rw-r--r-- | src/nvim/api/vimscript.c | 18 |
3 files changed, 114 insertions, 123 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 542e5c4953..dcede27bcb 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -1707,144 +1707,113 @@ bool string_iswhite(String str) return true; } -// Add modifier string for command into the command line. Includes trailing whitespace if non-empty. -// @return OK or FAIL. -static int add_cmd_modifier_str(char *cmdline, size_t *pos, const size_t bufsize, - CmdParseInfo *cmdinfo) +/// Build cmdline string for command, used by `nvim_cmd()`. +/// +/// @return OK or FAIL. +void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char **args, + size_t argc) { -#define APPEND_MODIFIER(...) \ - do { \ - if (*pos < bufsize) { \ - *pos += (size_t)snprintf(cmdline + *pos, bufsize - *pos, __VA_ARGS__); \ - } \ - if (*pos < bufsize) { \ - cmdline[*pos] = ' '; \ - *pos += 1; \ - } else { \ - goto err; \ - } \ - } while (0) - -#define APPEND_MODIFIER_IF(cond, mod) \ - do { \ - if (cond) { \ - APPEND_MODIFIER(mod); \ - } \ - } while (0) + StringBuilder cmdline = KV_INITIAL_VALUE; + // Add command modifiers if (cmdinfo->cmdmod.tab != 0) { - APPEND_MODIFIER("%dtab", cmdinfo->cmdmod.tab - 1); + kv_printf(cmdline, "%dtab ", cmdinfo->cmdmod.tab - 1); } if (cmdinfo->verbose != -1) { - APPEND_MODIFIER("%ldverbose", cmdinfo->verbose); + kv_printf(cmdline, "%ldverbose ", cmdinfo->verbose); + } + + if (cmdinfo->emsg_silent) { + kv_concat(cmdline, "silent! "); + } else if (cmdinfo->silent) { + kv_concat(cmdline, "silent "); } switch (cmdinfo->cmdmod.split & (WSP_ABOVE | WSP_BELOW | WSP_TOP | WSP_BOT)) { case WSP_ABOVE: - APPEND_MODIFIER("aboveleft"); + kv_concat(cmdline, "aboveleft "); break; case WSP_BELOW: - APPEND_MODIFIER("belowright"); + kv_concat(cmdline, "belowright "); break; case WSP_TOP: - APPEND_MODIFIER("topleft"); + kv_concat(cmdline, "topleft "); break; case WSP_BOT: - APPEND_MODIFIER("botright"); + kv_concat(cmdline, "botright "); break; default: break; } - APPEND_MODIFIER_IF(cmdinfo->cmdmod.split & WSP_VERT, "vertical"); - - if (cmdinfo->emsg_silent) { - APPEND_MODIFIER("silent!"); - } else if (cmdinfo->silent) { - APPEND_MODIFIER("silent"); - } - - APPEND_MODIFIER_IF(cmdinfo->sandbox, "sandbox"); - APPEND_MODIFIER_IF(cmdinfo->noautocmd, "noautocmd"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.browse, "browse"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.confirm, "confirm"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.hide, "hide"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepalt, "keepalt"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepjumps, "keepjumps"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.keepmarks, "keepmarks"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.keeppatterns, "keeppatterns"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.lockmarks, "lockmarks"); - APPEND_MODIFIER_IF(cmdinfo->cmdmod.noswapfile, "noswapfile"); - - return OK; -err: - return FAIL; - -#undef APPEND_MODIFIER -#undef APPEND_MODIFIER_IF -} - -/// Build cmdline string for command, used by `nvim_cmd()`. -/// -/// @return OK or FAIL. -int build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char **args, - size_t argc) -{ - const size_t bufsize = IOSIZE; - size_t pos = 0; - char *cmdline = xcalloc(bufsize, sizeof(char)); - -#define CMDLINE_APPEND(...) \ +#define CMDLINE_APPEND_IF(cond, str) \ do { \ - if (pos < bufsize) { \ - pos += (size_t)snprintf(cmdline + pos, bufsize - pos, __VA_ARGS__); \ - } else { \ - goto err; \ + if (cond) { \ + kv_concat(cmdline, str); \ } \ } while (0) - // Command modifiers. - if (add_cmd_modifier_str(cmdline, &pos, bufsize, cmdinfo) == FAIL) { - goto err; - } + CMDLINE_APPEND_IF(cmdinfo->cmdmod.split & WSP_VERT, "vertical "); + CMDLINE_APPEND_IF(cmdinfo->sandbox, "sandbox "); + CMDLINE_APPEND_IF(cmdinfo->noautocmd, "noautocmd "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.browse, "browse "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.confirm, "confirm "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.hide, "hide "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.keepalt, "keepalt "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.keepjumps, "keepjumps "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.keepmarks, "keepmarks "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.keeppatterns, "keeppatterns "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.lockmarks, "lockmarks "); + CMDLINE_APPEND_IF(cmdinfo->cmdmod.noswapfile, "noswapfile "); +#undef CMDLINE_APPEND_IF // Command range / count. if (eap->argt & EX_RANGE) { if (eap->addr_count == 1) { - CMDLINE_APPEND("%ld", eap->line2); + kv_printf(cmdline, "%ld", eap->line2); } else if (eap->addr_count > 1) { - CMDLINE_APPEND("%ld,%ld", eap->line1, eap->line2); + kv_printf(cmdline, "%ld,%ld", eap->line1, eap->line2); eap->addr_count = 2; // Make sure address count is not greater than 2 } } // Keep the index of the position where command name starts, so eap->cmd can point to it. - size_t cmdname_idx = pos; - CMDLINE_APPEND("%s", eap->cmd); - eap->cmd = cmdline + cmdname_idx; + size_t cmdname_idx = cmdline.size; + kv_printf(cmdline, "%s", eap->cmd); // Command bang. if (eap->argt & EX_BANG && eap->forceit) { - CMDLINE_APPEND("!"); + kv_printf(cmdline, "!"); } // Command register. if (eap->argt & EX_REGSTR && eap->regname) { - CMDLINE_APPEND(" %c", eap->regname); + kv_printf(cmdline, " %c", eap->regname); } - // Iterate through each argument and store the starting position and length of each argument in - // the cmdline string in `eap->args` and `eap->arglens`, respectively. - eap->args = xcalloc(argc, sizeof(char *)); + // Iterate through each argument and store the starting index and length of each argument + size_t *argidx = xcalloc(argc, sizeof(size_t)); + eap->argc = argc; eap->arglens = xcalloc(argc, sizeof(size_t)); for (size_t i = 0; i < argc; i++) { - eap->args[i] = cmdline + pos + 1; // add 1 to skip the leading space. + argidx[i] = cmdline.size + 1; // add 1 to account for the space. eap->arglens[i] = STRLEN(args[i]); - CMDLINE_APPEND(" %s", args[i]); + kv_printf(cmdline, " %s", args[i]); } - eap->argc = argc; - // If there isn't an argument, make eap->arg point to end of cmd - eap->arg = argc > 0 ? eap->args[0] : cmdline + pos; + + // 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 *)); + for (size_t i = 0; i < argc; i++) { + eap->args[i] = cmdline.items + argidx[i]; + } + // If there isn't an argument, make eap->arg point to end of cmdline. + eap->arg = argc > 0 ? eap->args[0] : cmdline.items + cmdline.size; + + // Finally, make cmdlinep point to the cmdline string. + *cmdlinep = cmdline.items; + xfree(argidx); // Replace, :make and :grep with 'makeprg' and 'grepprg'. char *p = replace_makeprg(eap, eap->arg, cmdlinep); @@ -1854,12 +1823,4 @@ int build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char eap->arg = p; eap->args[0] = p; } - - *cmdlinep = cmdline; - return OK; -err: - xfree(cmdline); - return FAIL; - -#undef CMDLINE_APPEND } diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 09bf032daa..a257dd6478 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -126,22 +126,43 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err) /// Sets a highlight group. /// -/// Note: Unlike the `:highlight` command which can update a highlight group, -/// this function completely replaces the definition. For example: -/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group 'Visual'. +/// @note Unlike the `:highlight` command which can update a highlight group, +/// this function completely replaces the definition. For example: +/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group +/// 'Visual'. +/// +/// @note The fg and bg keys also accept the string values `"fg"` or `"bg"` +/// which act as aliases to the corresponding foreground and background +/// values of the Normal group. If the Normal group has not been defined, +/// using these values results in an error. /// /// @param ns_id Namespace id for this highlight |nvim_create_namespace()|. /// Use 0 to set a highlight group globally |:highlight|. /// @param name Highlight group name, e.g. "ErrorMsg" -/// @param val Highlight definition map, like |synIDattr()|. In -/// addition, the following keys are recognized: +/// @param val Highlight definition map, accepts the following keys: +/// - fg (or foreground): color name or "#RRGGBB", see note. +/// - bg (or background): color name or "#RRGGBB", see note. +/// - sp (or special): color name or "#RRGGBB" +/// - blend: integer between 0 and 100 +/// - bold: boolean +/// - standout: boolean +/// - underline: boolean +/// - underlineline: boolean +/// - undercurl: boolean +/// - underdot: boolean +/// - underdash: boolean +/// - strikethrough: boolean +/// - italic: boolean +/// - reverse: boolean +/// - nocombine: boolean +/// - link: name of another highlight group to link to, see |:hi-link|. +/// Additionally, the following keys are recognized: /// - default: Don't override existing definition |:hi-default| /// - ctermfg: Sets foreground of cterm color |highlight-ctermfg| /// - ctermbg: Sets background of cterm color |highlight-ctermbg| -/// - cterm: cterm attribute map, like -/// |highlight-args|. -/// Note: Attributes default to those set for `gui` -/// if not set. +/// - cterm: cterm attribute map, like |highlight-args|. If not set, +/// cterm attributes will match those from the attribute map +/// documented above. /// @param[out] err Error details, if any /// // TODO(bfredl): val should take update vs reset flag @@ -1601,12 +1622,13 @@ ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode) /// or "!" for |:map!|, or empty string for |:map|. /// @param lhs Left-hand-side |{lhs}| of the mapping. /// @param rhs Right-hand-side |{rhs}| of the mapping. -/// @param opts Optional parameters map. Accepts all |:map-arguments| -/// as keys excluding |<buffer>| but including |noremap| and "desc". -/// "desc" can be used to give a description to keymap. -/// When called from Lua, also accepts a "callback" key that takes -/// a Lua function to call when the mapping is executed. -/// Values are Booleans. Unknown key is an error. +/// @param opts Optional parameters map: keys are |:map-arguments|, values +/// are booleans (default false). Accepts all |:map-arguments| as +/// keys excluding |<buffer>| but including |noremap| and "desc". +/// Unknown key is an error. "desc" can be used to give a +/// description to the mapping. When called from Lua, also accepts a +/// "callback" key that takes a Lua function to call when the +/// mapping is executed. /// @param[out] err Error details, if any. void nvim_set_keymap(uint64_t channel_id, String mode, String lhs, String rhs, Dict(keymap) *opts, Error *err) @@ -2275,6 +2297,14 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * bool use_tabline = false; bool highlights = false; + if (str.size < 2 || memcmp(str.data, "%!", 2)) { + const char *const errmsg = check_stl_option((char_u *)str.data); + if (errmsg) { + api_set_error(err, kErrorTypeValidation, "%s", errmsg); + return result; + } + } + if (HAS_KEY(opts->winid)) { if (opts->winid.type != kObjectTypeInteger) { api_set_error(err, kErrorTypeValidation, "winid must be an integer"); diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 02f406d686..b8f7b33cd5 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -34,7 +34,7 @@ /// Unlike |nvim_command()| this function supports heredocs, script-scope (s:), /// etc. /// -/// On execution error: fails with VimL error, does not update v:errmsg. +/// On execution error: fails with VimL error, updates v:errmsg. /// /// @see |execute()| /// @see |nvim_command()| @@ -98,7 +98,7 @@ theend: /// Executes an Ex command. /// -/// On execution error: fails with VimL error, does not update v:errmsg. +/// On execution error: fails with VimL error, updates v:errmsg. /// /// Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script /// or an Ex command directly, use |nvim_exec()|. To construct an Ex command using a structured @@ -118,7 +118,7 @@ void nvim_command(String command, Error *err) /// Evaluates a VimL |expression|. /// Dictionaries and Lists are recursively expanded. /// -/// On execution error: fails with VimL error, does not update v:errmsg. +/// On execution error: fails with VimL error, updates v:errmsg. /// /// @param expr VimL expression string /// @param[out] err Error details, if any @@ -226,7 +226,7 @@ free_vim_args: /// Calls a VimL function with the given arguments. /// -/// On execution error: fails with VimL error, does not update v:errmsg. +/// On execution error: fails with VimL error, updates v:errmsg. /// /// @param fn Function to call /// @param args Function arguments packed in an Array @@ -240,7 +240,7 @@ Object nvim_call_function(String fn, Array args, Error *err) /// Calls a VimL |Dictionary-function| with the given arguments. /// -/// On execution error: fails with VimL error, does not update v:errmsg. +/// On execution error: fails with VimL error, updates v:errmsg. /// /// @param dict Dictionary, or String evaluating to a VimL |self| dict /// @param fn Name of the function defined on the VimL dict @@ -996,6 +996,8 @@ end: /// such as having spaces inside a command argument, expanding filenames in a command that otherwise /// doesn't expand filenames, etc. /// +/// On execution error: fails with VimL error, updates v:errmsg. +/// /// @see |nvim_exec()| /// @see |nvim_command()| /// @@ -1058,7 +1060,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error if (p != NULL && ea.cmdidx == CMD_SIZE && ASCII_ISUPPER(*ea.cmd) && has_event(EVENT_CMDUNDEFINED)) { p = xstrdup(cmdname); - int ret = apply_autocmds(EVENT_CMDUNDEFINED, (char_u *)p, (char_u *)p, true, NULL); + int ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, true, NULL); xfree(p); // If the autocommands did something and didn't cause an error, try // finding the command again. @@ -1290,9 +1292,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. - if (build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc) == FAIL) { - goto end; - } + build_cmdline_str(&cmdline, &ea, &cmdinfo, args, argc); ea.cmdlinep = &cmdline; garray_T capture_local; |