aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2022-08-03 00:08:17 -0600
committerJosh Rahm <joshuarahm@gmail.com>2022-08-03 00:08:17 -0600
commit9449e1b8d273ff78eb894c588110ffa0c17d6ee3 (patch)
tree9e4470c33bd4187d9f42f0b2c4aaa995310c5be8 /src/nvim/api
parent308e1940dcd64aa6c344c403d4f9e0dda58d9c5c (diff)
parentb8dcbcc732baf84fc48d6b272c3ade0bcb129b3b (diff)
downloadrneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.tar.gz
rneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.tar.bz2
rneovim-9449e1b8d273ff78eb894c588110ffa0c17d6ee3.zip
Merge remote-tracking branch 'upstream/master' into rahm
Diffstat (limited to 'src/nvim/api')
-rw-r--r--src/nvim/api/buffer.c6
-rw-r--r--src/nvim/api/command.c52
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/api/options.c28
-rw-r--r--src/nvim/api/private/defs.h1
-rw-r--r--src/nvim/api/private/helpers.h12
-rw-r--r--src/nvim/api/ui.c21
-rw-r--r--src/nvim/api/vim.c47
8 files changed, 86 insertions, 82 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 806b649ce6..1b1a161226 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -538,9 +538,9 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
Integer end_row, Integer end_col, ArrayOf(String) replacement, Error *err)
FUNC_API_SINCE(7)
{
- FIXED_TEMP_ARRAY(scratch, 1);
+ MAXSIZE_TEMP_ARRAY(scratch, 1);
if (replacement.size == 0) {
- scratch.items[0] = STRING_OBJ(STATIC_CSTR_AS_STRING(""));
+ ADD_C(scratch, STRING_OBJ(STATIC_CSTR_AS_STRING("")));
replacement = scratch;
}
@@ -932,7 +932,7 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
-/// @returns Array of maparg()-like dictionaries describing mappings.
+/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle.
ArrayOf(Dictionary) nvim_buf_get_keymap(uint64_t channel_id, Buffer buffer, String mode, Error *err)
FUNC_API_SINCE(3)
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 4c2404a0d8..33efa6b326 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -306,7 +306,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
char *cmdline = NULL;
char *cmdname = NULL;
- char **args = NULL;
+ ArrayOf(String) args;
size_t argc = 0;
String retv = (String)STRING_INIT;
@@ -412,22 +412,15 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
if (!argc_valid) {
- argc = 0; // Ensure that args array isn't erroneously freed at the end.
VALIDATION_ERROR("Incorrect number of arguments supplied");
}
- if (argc != 0) {
- args = xcalloc(argc, sizeof(char *));
-
- for (size_t i = 0; i < argc; i++) {
- args[i] = string_to_cstr(cmd->args.data.array.items[i].data.string);
- }
- }
+ 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[0] : NULL);
+ set_cmd_addr_type(&ea, argc > 0 ? args.items[0].data.string.data : NULL);
if (HAS_KEY(cmd->range)) {
if (!(ea.argt & EX_RANGE)) {
@@ -600,7 +593,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
OBJ_TO_CMOD_FLAG(CMOD_SILENT, mods.silent, false, "'mods.silent'");
OBJ_TO_CMOD_FLAG(CMOD_ERRSILENT, mods.emsg_silent, false, "'mods.emsg_silent'");
- OBJ_TO_CMOD_FLAG(CMOD_UNSILENT, mods.silent, false, "'mods.unsilent'");
+ OBJ_TO_CMOD_FLAG(CMOD_UNSILENT, mods.unsilent, false, "'mods.unsilent'");
OBJ_TO_CMOD_FLAG(CMOD_SANDBOX, mods.sandbox, false, "'mods.sandbox'");
OBJ_TO_CMOD_FLAG(CMOD_NOAUTOCMD, mods.noautocmd, false, "'mods.noautocmd'");
OBJ_TO_CMOD_FLAG(CMOD_BROWSE, mods.browse, false, "'mods.browse'");
@@ -676,10 +669,6 @@ end:
xfree(cmdname);
xfree(ea.args);
xfree(ea.arglens);
- for (size_t i = 0; i < argc; i++) {
- xfree(args[i]);
- }
- xfree(args);
return retv;
@@ -704,12 +693,11 @@ static bool string_iswhite(String str)
}
/// Build cmdline string for command, used by `nvim_cmd()`.
-///
-/// @return OK or FAIL.
-static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char **args,
- size_t argc)
+static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo,
+ ArrayOf(String) args, size_t argc)
{
StringBuilder cmdline = KV_INITIAL_VALUE;
+ kv_resize(cmdline, 32); // Make it big enough to handle most typical commands
// Add command modifiers
if (cmdinfo->cmdmod.cmod_tab != 0) {
@@ -779,11 +767,11 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
// Keep the index of the position where command name starts, so eap->cmd can point to it.
size_t cmdname_idx = cmdline.size;
- kv_printf(cmdline, "%s", eap->cmd);
+ kv_concat(cmdline, eap->cmd);
// Command bang.
if (eap->argt & EX_BANG && eap->forceit) {
- kv_printf(cmdline, "!");
+ kv_concat(cmdline, "!");
}
// Command register.
@@ -791,29 +779,35 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
kv_printf(cmdline, " %c", eap->regname);
}
- // 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));
+ size_t argstart_idx = cmdline.size;
for (size_t i = 0; i < argc; i++) {
- argidx[i] = cmdline.size + 1; // add 1 to account for the space.
- eap->arglens[i] = STRLEN(args[i]);
- kv_printf(cmdline, " %s", args[i]);
+ String s = args.items[i].data.string;
+ eap->arglens[i] = s.size;
+ kv_concat(cmdline, " ");
+ kv_concat_len(cmdline, s.data, s.size);
}
+ // Done appending to cmdline, ensure it is NUL terminated
+ kv_push(cmdline, NUL);
+
// 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 *));
+ size_t offset = argstart_idx;
for (size_t i = 0; i < argc; i++) {
- eap->args[i] = cmdline.items + argidx[i];
+ offset++; // Account for space
+ eap->args[i] = cmdline.items + offset;
+ offset += eap->arglens[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;
+ eap->arg = argc > 0 ? eap->args[0] :
+ cmdline.items + cmdline.size - 1; // Subtract 1 to account for NUL
// 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);
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 1f1fa1e63a..a764fb069b 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -39,6 +39,7 @@ return {
"unique";
"callback";
"desc";
+ "replace_keycodes";
};
get_commands = {
"builtin";
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index 4ed676e613..867584dd71 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -104,20 +104,20 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
long numval = 0;
char *stringval = NULL;
- int result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type, from,
- true, err);
+ getoption_T result = access_option_value_for(name.data, &numval, &stringval, scope, opt_type,
+ from, true, err);
if (ERROR_SET(err)) {
return rv;
}
switch (result) {
- case 0:
+ case gov_string:
rv = STRING_OBJ(cstr_as_string(stringval));
break;
- case 1:
+ case gov_number:
rv = INTEGER_OBJ(numval);
break;
- case 2:
+ case gov_bool:
switch (numval) {
case 0:
case 1:
@@ -280,7 +280,7 @@ Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
return get_option_from(buf, SREQ_BUF, name, err);
}
-/// Sets a buffer option value. Passing 'nil' as value deletes the option (only
+/// Sets a buffer option value. Passing `nil` as value deletes the option (only
/// works if there's a global fallback)
///
/// @param channel_id
@@ -318,7 +318,7 @@ Object nvim_win_get_option(Window window, String name, Error *err)
return get_option_from(win, SREQ_WIN, name, err);
}
-/// Sets a window option value. Passing 'nil' as value deletes the option(only
+/// Sets a window option value. Passing `nil` as value deletes the option (only
/// works if there's a global fallback)
///
/// @param channel_id
@@ -338,7 +338,7 @@ void nvim_win_set_option(uint64_t channel_id, Window window, String name, Object
set_option_to(channel_id, win, SREQ_WIN, name, value, err);
}
-/// Gets the value of a global or local(buffer, window) option.
+/// Gets the value of a global or local (buffer, window) option.
///
/// @param from If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
/// to the window or buffer.
@@ -393,7 +393,7 @@ Object get_option_from(void *from, int type, String name, Error *err)
return rv;
}
-/// Sets the value of a global or local(buffer, window) option.
+/// Sets the value of a global or local (buffer, window) option.
///
/// @param to If `type` is `SREQ_WIN` or `SREQ_BUF`, this must be a pointer
/// to the window or buffer.
@@ -483,8 +483,8 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
});
}
-static int access_option_value(char *key, long *numval, char **stringval, int opt_flags, bool get,
- Error *err)
+static getoption_T access_option_value(char *key, long *numval, char **stringval, int opt_flags,
+ bool get, Error *err)
{
if (get) {
return get_option_value(key, numval, stringval, opt_flags);
@@ -501,13 +501,13 @@ static int access_option_value(char *key, long *numval, char **stringval, int op
}
}
-static int access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
- int opt_type, void *from, bool get, Error *err)
+static getoption_T access_option_value_for(char *key, long *numval, char **stringval, int opt_flags,
+ int opt_type, void *from, bool get, Error *err)
{
bool need_switch = false;
switchwin_T switchwin;
aco_save_T aco;
- int result = 0;
+ getoption_T result = 0;
try_start();
switch (opt_type) {
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index b1e0dd364c..9c7e59e4b3 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -36,6 +36,7 @@ typedef enum {
kMessageTypeRequest = 0,
kMessageTypeResponse = 1,
kMessageTypeNotification = 2,
+ kMessageTypeRedrawEvent = 3,
} MessageType;
/// Mask for all internal calls
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index a4348d8b44..1441da853c 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -74,18 +74,18 @@
#define ADD_C(array, item) \
kv_push_c(array, item)
-#define FIXED_TEMP_ARRAY(name, fixsize) \
- Array name = ARRAY_DICT_INIT; \
- Object name##__items[fixsize]; \
- name.size = fixsize; \
- name.items = name##__items; \
-
#define MAXSIZE_TEMP_ARRAY(name, maxsize) \
Array name = ARRAY_DICT_INIT; \
Object name##__items[maxsize]; \
name.capacity = maxsize; \
name.items = name##__items; \
+#define MAXSIZE_TEMP_DICT(name, maxsize) \
+ Dictionary name = ARRAY_DICT_INIT; \
+ KeyValuePair name##__items[maxsize]; \
+ name.capacity = maxsize; \
+ name.items = name##__items; \
+
#define cbuf_as_string(d, s) ((String) { .data = d, .size = s })
#define STATIC_CSTR_AS_STRING(s) ((String) { .data = s, .size = sizeof(s) - 1 })
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 54ce838b9b..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"
@@ -748,8 +748,10 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt
UIData *data = ui->data;
Array args = data->call_buf;
ADD_C(args, INTEGER_OBJ(id));
- ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(rgb_attrs, true)));
- ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(cterm_attrs, false)));
+ MAXSIZE_TEMP_DICT(rgb, 16);
+ MAXSIZE_TEMP_DICT(cterm, 16);
+ ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&rgb, rgb_attrs, true)));
+ ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&cterm, cterm_attrs, false)));
if (ui->ui_ext[kUIHlState]) {
ADD_C(args, ARRAY_OBJ(info));
@@ -758,9 +760,6 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt
}
push_call(ui, "hl_attr_define", args);
- // TODO(bfredl): could be elided
- api_free_dictionary(kv_A(args, 1).data.dictionary);
- api_free_dictionary(kv_A(args, 2).data.dictionary);
}
static void remote_ui_highlight_set(UI *ui, int id)
@@ -772,11 +771,9 @@ static void remote_ui_highlight_set(UI *ui, int id)
return;
}
data->hl_id = id;
- Dictionary hl = hlattrs2dict(syn_attr2entry(id), ui->rgb);
-
- ADD_C(args, DICTIONARY_OBJ(hl));
+ MAXSIZE_TEMP_DICT(dict, 16);
+ ADD_C(args, DICTIONARY_OBJ(hlattrs2dict(&dict, syn_attr2entry(id), ui->rgb)));
push_call(ui, "highlight_set", args);
- api_free_dictionary(kv_A(args, 0).data.dictionary);
}
/// "true" cursor used only for input focus
@@ -963,7 +960,7 @@ static Array translate_contents(UI *ui, Array contents)
Array new_item = ARRAY_DICT_INIT;
int attr = (int)item.items[0].data.integer;
if (attr) {
- Dictionary rgb_attrs = hlattrs2dict(syn_attr2entry(attr), ui->rgb);
+ Dictionary rgb_attrs = hlattrs2dict(NULL, syn_attr2entry(attr), ui->rgb);
ADD(new_item, DICTIONARY_OBJ(rgb_attrs));
} else {
ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 56516b2ac7..e2f58dba62 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -37,6 +37,7 @@
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
+#include "nvim/insexpand.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
@@ -472,10 +473,10 @@ Object nvim_exec_lua(String code, Array args, Error *err)
Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
FUNC_API_SINCE(7)
{
- FIXED_TEMP_ARRAY(args, 3);
- args.items[0] = STRING_OBJ(msg);
- args.items[1] = INTEGER_OBJ(log_level);
- args.items[2] = DICTIONARY_OBJ(opts);
+ MAXSIZE_TEMP_ARRAY(args, 3);
+ ADD_C(args, STRING_OBJ(msg));
+ ADD_C(args, INTEGER_OBJ(log_level));
+ ADD_C(args, DICTIONARY_OBJ(opts));
return nlua_exec(STATIC_CSTR_AS_STRING("return vim.notify(...)"), args, err);
}
@@ -1009,10 +1010,10 @@ static void term_write(char *buf, size_t size, void *data)
if (cb == LUA_NOREF) {
return;
}
- FIXED_TEMP_ARRAY(args, 3);
- args.items[0] = INTEGER_OBJ((Integer)chan->id);
- args.items[1] = BUFFER_OBJ(terminal_buf(chan->term));
- args.items[2] = STRING_OBJ(((String){ .data = buf, .size = size }));
+ MAXSIZE_TEMP_ARRAY(args, 3);
+ ADD_C(args, INTEGER_OBJ((Integer)chan->id));
+ ADD_C(args, BUFFER_OBJ(terminal_buf(chan->term)));
+ ADD_C(args, STRING_OBJ(((String){ .data = buf, .size = size })));
textlock++;
nlua_call_ref(cb, "input", args, false, NULL);
textlock--;
@@ -1410,7 +1411,7 @@ Dictionary nvim_get_mode(void)
/// Gets a list of global (non-buffer-local) |mapping| definitions.
///
/// @param mode Mode short-name ("n", "i", "v", ...)
-/// @returns Array of maparg()-like dictionaries describing mappings.
+/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key is always zero.
ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
FUNC_API_SINCE(3)
@@ -1422,8 +1423,8 @@ ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode)
///
/// To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
///
-/// Unlike |:map|, leading/trailing whitespace is accepted as part of the {lhs}
-/// or {rhs}. Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
+/// Unlike |:map|, leading/trailing whitespace is accepted as part of the {lhs} or {rhs}.
+/// Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
///
/// Example:
/// <pre>
@@ -1440,13 +1441,15 @@ 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: 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 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.
+/// When "expr" is true, "replace_keycodes" (boolean) can be used to replace keycodes
+/// in the resulting string (see |nvim_replace_termcodes()|), and a Lua callback
+/// returning `nil` is equivalent to returning an empty string.
/// @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)
@@ -2256,3 +2259,11 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
return result;
}
+
+void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
+ FUNC_API_REMOTE_ONLY
+{
+ // TODO(bfredl): consider printing message to user, as will be relevant
+ // if we fork nvim processes as async workers
+ ELOG("async error on channel %" PRId64 ": %s", channel_id, data.size ? data.data : "");
+}