aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/command.c
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-08-01 14:01:19 +0200
committerbfredl <bjorn.linse@gmail.com>2023-08-07 13:11:15 +0200
commit7bc93e0e2f246dd78026a3472d929a0fe450f70d (patch)
tree9e5b99830c3f08e0ffd75c7a0533b39033490a5b /src/nvim/api/command.c
parentc01e624b0762b24a4988bf9474a57d5b6278d180 (diff)
downloadrneovim-7bc93e0e2f246dd78026a3472d929a0fe450f70d.tar.gz
rneovim-7bc93e0e2f246dd78026a3472d929a0fe450f70d.tar.bz2
rneovim-7bc93e0e2f246dd78026a3472d929a0fe450f70d.zip
refactor(api): use typed keysets
Initially this is just for geting rid of boilerplate, but eventually the types could get exposed as metadata
Diffstat (limited to 'src/nvim/api/command.c')
-rw-r--r--src/nvim/api/command.c240
1 files changed, 92 insertions, 148 deletions
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 75140beb88..2b09cfc4b2 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -341,16 +341,6 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
} \
} while (0)
-#define OBJ_TO_CMOD_FLAG(flag, value, default, varname) \
- do { \
- if (api_object_to_bool(value, varname, default, err)) { \
- cmdinfo.cmdmod.cmod_flags |= (flag); \
- } \
- if (ERROR_SET(err)) { \
- goto end; \
- } \
- } while (0)
-
#define VALIDATE_MOD(cond, mod_, name_) \
do { \
if (!(cond)) { \
@@ -359,18 +349,14 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
} \
} while (0)
- bool output;
- OBJ_TO_BOOL(output, opts->output, false, "'output'");
-
- VALIDATE_R(HAS_KEY(cmd->cmd), "cmd", {
+ VALIDATE_R(HAS_KEY(cmd, cmd, cmd), "cmd", {
goto end;
});
- VALIDATE_EXP((cmd->cmd.type == kObjectTypeString && cmd->cmd.data.string.data[0] != NUL),
- "cmd", "non-empty String", NULL, {
+ VALIDATE_EXP((cmd->cmd.data[0] != NUL), "cmd", "non-empty String", NULL, {
goto end;
});
- cmdname = string_to_cstr(cmd->cmd.data.string);
+ cmdname = string_to_cstr(cmd->cmd);
ea.cmd = cmdname;
char *p = find_ex_command(&ea, NULL);
@@ -407,15 +393,11 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
// Parse command arguments since it's needed to get the command address type.
- if (HAS_KEY(cmd->args)) {
- VALIDATE_T("args", kObjectTypeArray, cmd->args.type, {
- goto end;
- });
-
+ if (HAS_KEY(cmd, cmd, args)) {
// 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];
+ for (size_t i = 0; i < cmd->args.size; i++) {
+ Object elem = cmd->args.items[i];
char *data_str;
switch (elem.type) {
@@ -477,16 +459,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
// since it only ever checks the first argument.
set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL);
- if (HAS_KEY(cmd->range)) {
- VALIDATE_MOD((ea.argt & EX_RANGE), "range", cmd->cmd.data.string.data);
- VALIDATE_T("range", kObjectTypeArray, cmd->range.type, {
- goto end;
- });
- VALIDATE_EXP((cmd->range.data.array.size <= 2), "range", "<=2 elements", NULL, {
+ if (HAS_KEY(cmd, cmd, range)) {
+ VALIDATE_MOD((ea.argt & EX_RANGE), "range", cmd->cmd.data);
+ VALIDATE_EXP((cmd->range.size <= 2), "range", "<=2 elements", NULL, {
goto end;
});
- Array range = cmd->range.data.array;
+ Array range = cmd->range;
ea.addr_count = (int)range.size;
for (size_t i = 0; i < range.size; i++) {
@@ -519,22 +498,21 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
}
- if (HAS_KEY(cmd->count)) {
- VALIDATE_MOD((ea.argt & EX_COUNT), "count", cmd->cmd.data.string.data);
- VALIDATE_EXP((cmd->count.type == kObjectTypeInteger && cmd->count.data.integer >= 0),
- "count", "non-negative Integer", NULL, {
+ if (HAS_KEY(cmd, cmd, count)) {
+ VALIDATE_MOD((ea.argt & EX_COUNT), "count", cmd->cmd.data);
+ VALIDATE_EXP((cmd->count >= 0), "count", "non-negative Integer", NULL, {
goto end;
});
- set_cmd_count(&ea, (linenr_T)cmd->count.data.integer, true);
+ set_cmd_count(&ea, (linenr_T)cmd->count, true);
}
- if (HAS_KEY(cmd->reg)) {
- VALIDATE_MOD((ea.argt & EX_REGSTR), "register", cmd->cmd.data.string.data);
- VALIDATE_EXP((cmd->reg.type == kObjectTypeString && cmd->reg.data.string.size == 1),
- "reg", "single character", cmd->reg.data.string.data, {
+ if (HAS_KEY(cmd, cmd, reg)) {
+ VALIDATE_MOD((ea.argt & EX_REGSTR), "register", cmd->cmd.data);
+ VALIDATE_EXP((cmd->reg.size == 1),
+ "reg", "single character", cmd->reg.data, {
goto end;
});
- char regname = cmd->reg.data.string.data[0];
+ char regname = cmd->reg.data[0];
VALIDATE((regname != '='), "%s", "Cannot use register \"=", {
goto end;
});
@@ -545,22 +523,17 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
ea.regname = (uint8_t)regname;
}
- OBJ_TO_BOOL(ea.forceit, cmd->bang, false, "'bang'");
- VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data.string.data);
+ ea.forceit = cmd->bang;
+ VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data);
- if (HAS_KEY(cmd->magic)) {
- VALIDATE_T_DICT("magic", cmd->magic, {
- goto end;
- });
-
- Dict(cmd_magic) magic = { 0 };
- if (!api_dict_to_keydict(&magic, KeyDict_cmd_magic_get_field,
- cmd->magic.data.dictionary, err)) {
+ if (HAS_KEY(cmd, cmd, magic)) {
+ Dict(cmd_magic) magic[1] = { 0 };
+ if (!api_dict_to_keydict(magic, KeyDict_cmd_magic_get_field, cmd->magic, err)) {
goto end;
}
- 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'");
+ cmdinfo.magic.file = HAS_KEY(magic, cmd_magic, file) ? magic->file : (ea.argt & EX_XFILE);
+ cmdinfo.magic.bar = HAS_KEY(magic, cmd_magic, bar) ? magic->bar : (ea.argt & EX_TRLBAR);
if (cmdinfo.magic.file) {
ea.argt |= EX_XFILE;
} else {
@@ -571,89 +544,63 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
cmdinfo.magic.bar = ea.argt & EX_TRLBAR;
}
- if (HAS_KEY(cmd->mods)) {
- VALIDATE_T_DICT("mods", cmd->mods, {
- goto end;
- });
-
- Dict(cmd_mods) mods = { 0 };
- if (!api_dict_to_keydict(&mods, KeyDict_cmd_mods_get_field, cmd->mods.data.dictionary, err)) {
+ if (HAS_KEY(cmd, cmd, mods)) {
+ Dict(cmd_mods) mods[1] = { 0 };
+ if (!api_dict_to_keydict(mods, KeyDict_cmd_mods_get_field, cmd->mods, err)) {
goto end;
}
- if (HAS_KEY(mods.filter)) {
- VALIDATE_T_DICT("mods.filter", mods.filter, {
- goto end;
- });
-
- Dict(cmd_mods_filter) filter = { 0 };
+ if (HAS_KEY(mods, cmd_mods, filter)) {
+ Dict(cmd_mods_filter) filter[1] = { 0 };
if (!api_dict_to_keydict(&filter, KeyDict_cmd_mods_filter_get_field,
- mods.filter.data.dictionary, err)) {
+ mods->filter, err)) {
goto end;
}
- if (HAS_KEY(filter.pattern)) {
- VALIDATE_T2(filter.pattern, kObjectTypeString, {
- goto end;
- });
-
- OBJ_TO_BOOL(cmdinfo.cmdmod.cmod_filter_force, filter.force, false, "'mods.filter.force'");
+ if (HAS_KEY(filter, cmd_mods_filter, pattern)) {
+ cmdinfo.cmdmod.cmod_filter_force = filter->force;
// "filter! // is not no-op, so add a filter if either the pattern is non-empty or if filter
// is inverted.
- if (*filter.pattern.data.string.data != NUL || cmdinfo.cmdmod.cmod_filter_force) {
- cmdinfo.cmdmod.cmod_filter_pat = string_to_cstr(filter.pattern.data.string);
+ if (*filter->pattern.data != NUL || cmdinfo.cmdmod.cmod_filter_force) {
+ cmdinfo.cmdmod.cmod_filter_pat = string_to_cstr(filter->pattern);
cmdinfo.cmdmod.cmod_filter_regmatch.regprog = vim_regcomp(cmdinfo.cmdmod.cmod_filter_pat,
RE_MAGIC);
}
}
}
- if (HAS_KEY(mods.tab)) {
- VALIDATE_T2(mods.tab, kObjectTypeInteger, {
- goto end;
- });
- if ((int)mods.tab.data.integer >= 0) {
+ if (HAS_KEY(mods, cmd_mods, tab)) {
+ if ((int)mods->tab >= 0) {
// Silently ignore negative integers to allow mods.tab to be set to -1.
- cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1;
+ cmdinfo.cmdmod.cmod_tab = (int)mods->tab + 1;
}
}
- if (HAS_KEY(mods.verbose)) {
- VALIDATE_T2(mods.verbose, kObjectTypeInteger, {
- goto end;
- });
- if ((int)mods.verbose.data.integer >= 0) {
+ if (HAS_KEY(mods, cmd_mods, verbose)) {
+ if ((int)mods->verbose >= 0) {
// Silently ignore negative integers to allow mods.verbose to be set to -1.
- cmdinfo.cmdmod.cmod_verbose = (int)mods.verbose.data.integer + 1;
+ cmdinfo.cmdmod.cmod_verbose = (int)mods->verbose + 1;
}
}
- bool vertical;
- OBJ_TO_BOOL(vertical, mods.vertical, false, "'mods.vertical'");
- cmdinfo.cmdmod.cmod_split |= (vertical ? WSP_VERT : 0);
+ cmdinfo.cmdmod.cmod_split |= (mods->vertical ? WSP_VERT : 0);
- bool horizontal;
- OBJ_TO_BOOL(horizontal, mods.horizontal, false, "'mods.horizontal'");
- cmdinfo.cmdmod.cmod_split |= (horizontal ? WSP_HOR : 0);
+ cmdinfo.cmdmod.cmod_split |= (mods->horizontal ? WSP_HOR : 0);
- if (HAS_KEY(mods.split)) {
- VALIDATE_T2(mods.split, kObjectTypeString, {
- goto end;
- });
-
- if (*mods.split.data.string.data == NUL) {
+ if (HAS_KEY(mods, cmd_mods, split)) {
+ if (*mods->split.data == NUL) {
// Empty string, do nothing.
- } else if (strcmp(mods.split.data.string.data, "aboveleft") == 0
- || strcmp(mods.split.data.string.data, "leftabove") == 0) {
+ } else if (strcmp(mods->split.data, "aboveleft") == 0
+ || strcmp(mods->split.data, "leftabove") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_ABOVE;
- } else if (strcmp(mods.split.data.string.data, "belowright") == 0
- || strcmp(mods.split.data.string.data, "rightbelow") == 0) {
+ } else if (strcmp(mods->split.data, "belowright") == 0
+ || strcmp(mods->split.data, "rightbelow") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_BELOW;
- } else if (strcmp(mods.split.data.string.data, "topleft") == 0) {
+ } else if (strcmp(mods->split.data, "topleft") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_TOP;
- } else if (strcmp(mods.split.data.string.data, "botright") == 0) {
+ } else if (strcmp(mods->split.data, "botright") == 0) {
cmdinfo.cmdmod.cmod_split |= WSP_BOT;
} else {
VALIDATE_S(false, "mods.split", "", {
@@ -662,20 +609,25 @@ 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.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'");
- OBJ_TO_CMOD_FLAG(CMOD_CONFIRM, mods.confirm, false, "'mods.confirm'");
- OBJ_TO_CMOD_FLAG(CMOD_HIDE, mods.hide, false, "'mods.hide'");
- OBJ_TO_CMOD_FLAG(CMOD_KEEPALT, mods.keepalt, false, "'mods.keepalt'");
- OBJ_TO_CMOD_FLAG(CMOD_KEEPJUMPS, mods.keepjumps, false, "'mods.keepjumps'");
- OBJ_TO_CMOD_FLAG(CMOD_KEEPMARKS, mods.keepmarks, false, "'mods.keepmarks'");
- OBJ_TO_CMOD_FLAG(CMOD_KEEPPATTERNS, mods.keeppatterns, false, "'mods.keeppatterns'");
- OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods.lockmarks, false, "'mods.lockmarks'");
- OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods.noswapfile, false, "'mods.noswapfile'");
+#define OBJ_TO_CMOD_FLAG(flag, value) \
+ if (value) { \
+ cmdinfo.cmdmod.cmod_flags |= (flag); \
+ }
+
+ OBJ_TO_CMOD_FLAG(CMOD_SILENT, mods->silent);
+ OBJ_TO_CMOD_FLAG(CMOD_ERRSILENT, mods->emsg_silent);
+ OBJ_TO_CMOD_FLAG(CMOD_UNSILENT, mods->unsilent);
+ OBJ_TO_CMOD_FLAG(CMOD_SANDBOX, mods->sandbox);
+ OBJ_TO_CMOD_FLAG(CMOD_NOAUTOCMD, mods->noautocmd);
+ OBJ_TO_CMOD_FLAG(CMOD_BROWSE, mods->browse);
+ OBJ_TO_CMOD_FLAG(CMOD_CONFIRM, mods->confirm);
+ OBJ_TO_CMOD_FLAG(CMOD_HIDE, mods->hide);
+ OBJ_TO_CMOD_FLAG(CMOD_KEEPALT, mods->keepalt);
+ OBJ_TO_CMOD_FLAG(CMOD_KEEPJUMPS, mods->keepjumps);
+ OBJ_TO_CMOD_FLAG(CMOD_KEEPMARKS, mods->keepmarks);
+ OBJ_TO_CMOD_FLAG(CMOD_KEEPPATTERNS, mods->keeppatterns);
+ OBJ_TO_CMOD_FLAG(CMOD_LOCKMARKS, mods->lockmarks);
+ OBJ_TO_CMOD_FLAG(CMOD_NOSWAPFILE, mods->noswapfile);
if (cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT) {
// CMOD_ERRSILENT must imply CMOD_SILENT, otherwise apply_cmdmod() and undo_cmdmod() won't
@@ -699,13 +651,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
garray_T * const save_capture_ga = capture_ga;
const int save_msg_col = msg_col;
- if (output) {
+ if (opts->output) {
ga_init(&capture_local, 1, 80);
capture_ga = &capture_local;
}
TRY_WRAP(err, {
- if (output) {
+ if (opts->output) {
msg_silent++;
msg_col = 0; // prevent leading spaces
}
@@ -714,7 +666,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
execute_cmd(&ea, &cmdinfo, false);
});
- if (output) {
+ if (opts->output) {
capture_ga = save_capture_ga;
msg_silent = save_msg_silent;
// Put msg_col back where it was, since nothing should have been written.
@@ -726,7 +678,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
goto clear_ga;
}
- if (output && capture_local.ga_len > 1) {
+ if (opts->output && capture_local.ga_len > 1) {
retv = (String){
.data = capture_local.ga_data,
.size = (size_t)capture_local.ga_len,
@@ -740,7 +692,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
goto end;
}
clear_ga:
- if (output) {
+ if (opts->output) {
ga_clear(&capture_local);
}
end:
@@ -1037,7 +989,7 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
name.data, {
goto err;
});
- VALIDATE((!HAS_KEY(opts->range) || !HAS_KEY(opts->count)), "%s",
+ VALIDATE((!HAS_KEY(opts, user_command, range) || !HAS_KEY(opts, user_command, count)), "%s",
"Cannot use both 'range' and 'count'", {
goto err;
});
@@ -1075,13 +1027,14 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
goto err;
});
}
- } else if (HAS_KEY(opts->nargs)) {
+ } else if (HAS_KEY(opts, user_command, nargs)) {
VALIDATE_S(false, "nargs", "", {
goto err;
});
}
- VALIDATE((!HAS_KEY(opts->complete) || argt), "%s", "'complete' used without 'nargs'", {
+ VALIDATE((!HAS_KEY(opts, user_command, complete) || argt),
+ "%s", "'complete' used without 'nargs'", {
goto err;
});
@@ -1101,7 +1054,7 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
argt |= EX_RANGE | EX_ZEROR;
def = opts->range.data.integer;
addr_type_arg = ADDR_LINES;
- } else if (HAS_KEY(opts->range)) {
+ } else if (HAS_KEY(opts, user_command, range)) {
VALIDATE_S(false, "range", "", {
goto err;
});
@@ -1117,13 +1070,13 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
argt |= EX_COUNT | EX_ZEROR | EX_RANGE;
addr_type_arg = ADDR_OTHER;
def = opts->count.data.integer;
- } else if (HAS_KEY(opts->count)) {
+ } else if (HAS_KEY(opts, user_command, count)) {
VALIDATE_S(false, "count", "", {
goto err;
});
}
- if (HAS_KEY(opts->addr)) {
+ if (HAS_KEY(opts, user_command, addr)) {
VALIDATE_T("addr", kObjectTypeString, opts->addr.type, {
goto err;
});
@@ -1139,31 +1092,23 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
}
}
- if (api_object_to_bool(opts->bang, "bang", false, err)) {
+ if (opts->bang) {
argt |= EX_BANG;
- } else if (ERROR_SET(err)) {
- goto err;
}
- if (api_object_to_bool(opts->bar, "bar", false, err)) {
+ if (opts->bar) {
argt |= EX_TRLBAR;
- } else if (ERROR_SET(err)) {
- goto err;
}
- if (api_object_to_bool(opts->register_, "register", false, err)) {
+ if (opts->register_) {
argt |= EX_REGSTR;
- } else if (ERROR_SET(err)) {
- goto err;
}
- if (api_object_to_bool(opts->keepscript, "keepscript", false, err)) {
+ if (opts->keepscript) {
argt |= EX_KEEPSCRIPT;
- } else if (ERROR_SET(err)) {
- goto err;
}
- bool force = api_object_to_bool(opts->force, "force", true, err);
+ bool force = GET_BOOL_OR_TRUE(opts, user_command, force);
if (ERROR_SET(err)) {
goto err;
}
@@ -1178,13 +1123,13 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
"complete", opts->complete.data.string.data, {
goto err;
});
- } else if (HAS_KEY(opts->complete)) {
+ } else if (HAS_KEY(opts, user_command, complete)) {
VALIDATE_EXP(false, "complete", "Function or String", NULL, {
goto err;
});
}
- if (HAS_KEY(opts->preview)) {
+ if (HAS_KEY(opts, user_command, preview)) {
VALIDATE_T("preview", kObjectTypeLuaRef, opts->preview.type, {
goto err;
});
@@ -1254,13 +1199,12 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
FUNC_API_SINCE(4)
{
bool global = (buffer == -1);
- bool builtin = api_object_to_bool(opts->builtin, "builtin", false, err);
if (ERROR_SET(err)) {
return (Dictionary)ARRAY_DICT_INIT;
}
if (global) {
- if (builtin) {
+ if (opts->builtin) {
api_set_error(err, kErrorTypeValidation, "builtin=true not implemented");
return (Dictionary)ARRAY_DICT_INIT;
}
@@ -1268,7 +1212,7 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
}
buf_T *buf = find_buffer_by_handle(buffer, err);
- if (builtin || !buf) {
+ if (opts->builtin || !buf) {
return (Dictionary)ARRAY_DICT_INIT;
}
return commands_array(buf);