aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/private/helpers.c159
-rw-r--r--src/nvim/api/vim.c60
-rw-r--r--src/nvim/api/vimscript.c18
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;