mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(api): use arena for nvim_parse_cmd()
This commit is contained in:
parent
4cd43933d3
commit
2d8d35f838
@ -96,15 +96,15 @@
|
|||||||
/// - "belowright": |:belowright|.
|
/// - "belowright": |:belowright|.
|
||||||
/// - "topleft": |:topleft|.
|
/// - "topleft": |:topleft|.
|
||||||
/// - "botright": |:botright|.
|
/// - "botright": |:botright|.
|
||||||
Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err)
|
||||||
FUNC_API_SINCE(10) FUNC_API_FAST
|
FUNC_API_SINCE(10) FUNC_API_FAST
|
||||||
{
|
{
|
||||||
Dictionary result = ARRAY_DICT_INIT;
|
Dict(cmd) result = { 0 };
|
||||||
|
|
||||||
// Parse command line
|
// Parse command line
|
||||||
exarg_T ea;
|
exarg_T ea;
|
||||||
CmdParseInfo cmdinfo;
|
CmdParseInfo cmdinfo;
|
||||||
char *cmdline = string_to_cstr(str);
|
char *cmdline = arena_memdupz(arena, str.data, str.size);
|
||||||
const char *errormsg = NULL;
|
const char *errormsg = NULL;
|
||||||
|
|
||||||
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
|
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
|
||||||
@ -124,22 +124,23 @@ Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
|||||||
// otherwise split arguments by whitespace.
|
// otherwise split arguments by whitespace.
|
||||||
if (ea.argt & EX_NOSPC) {
|
if (ea.argt & EX_NOSPC) {
|
||||||
if (*ea.arg != NUL) {
|
if (*ea.arg != NUL) {
|
||||||
ADD(args, STRING_OBJ(cstrn_to_string(ea.arg, length)));
|
args = arena_array(arena, 1);
|
||||||
|
ADD_C(args, STRING_OBJ(cstrn_as_string(ea.arg, length)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t end = 0;
|
size_t end = 0;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char *buf = xcalloc(length, sizeof(char));
|
char *buf = arena_alloc(arena, length + 1, false);
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
args = arena_array(arena, uc_nargs_upper_bound(ea.arg, length));
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
done = uc_split_args_iter(ea.arg, length, &end, buf, &len);
|
done = uc_split_args_iter(ea.arg, length, &end, buf, &len);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
ADD(args, STRING_OBJ(cstrn_to_string(buf, len)));
|
ADD_C(args, STRING_OBJ(cstrn_as_string(buf, len)));
|
||||||
|
buf += len + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ucmd_T *cmd = NULL;
|
ucmd_T *cmd = NULL;
|
||||||
@ -149,40 +150,32 @@ Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
|||||||
cmd = USER_CMD_GA(&curbuf->b_ucmds, ea.useridx);
|
cmd = USER_CMD_GA(&curbuf->b_ucmds, ea.useridx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd != NULL) {
|
char *name = (cmd != NULL ? cmd->uc_name : get_command_name(NULL, ea.cmdidx));
|
||||||
PUT(result, "cmd", CSTR_TO_OBJ(cmd->uc_name));
|
PUT_KEY(result, cmd, cmd, cstr_as_string(name));
|
||||||
} else {
|
|
||||||
PUT(result, "cmd", CSTR_TO_OBJ(get_command_name(NULL, ea.cmdidx)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ea.argt & EX_RANGE) {
|
if (ea.argt & EX_RANGE) {
|
||||||
Array range = ARRAY_DICT_INIT;
|
Array range = arena_array(arena, 2);
|
||||||
if (ea.addr_count > 0) {
|
if (ea.addr_count > 0) {
|
||||||
if (ea.addr_count > 1) {
|
if (ea.addr_count > 1) {
|
||||||
ADD(range, INTEGER_OBJ(ea.line1));
|
ADD_C(range, INTEGER_OBJ(ea.line1));
|
||||||
}
|
}
|
||||||
ADD(range, INTEGER_OBJ(ea.line2));
|
ADD_C(range, INTEGER_OBJ(ea.line2));
|
||||||
}
|
}
|
||||||
PUT(result, "range", ARRAY_OBJ(range));
|
PUT_KEY(result, cmd, range, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ea.argt & EX_COUNT) {
|
if (ea.argt & EX_COUNT) {
|
||||||
if (ea.addr_count > 0) {
|
Integer count = ea.addr_count > 0 ? ea.line2 : (cmd != NULL ? cmd->uc_def : 0);
|
||||||
PUT(result, "count", INTEGER_OBJ(ea.line2));
|
PUT_KEY(result, cmd, count, count);
|
||||||
} else if (cmd != NULL) {
|
|
||||||
PUT(result, "count", INTEGER_OBJ(cmd->uc_def));
|
|
||||||
} else {
|
|
||||||
PUT(result, "count", INTEGER_OBJ(0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ea.argt & EX_REGSTR) {
|
if (ea.argt & EX_REGSTR) {
|
||||||
char reg[2] = { (char)ea.regname, NUL };
|
char reg[2] = { (char)ea.regname, NUL };
|
||||||
PUT(result, "reg", CSTR_TO_OBJ(reg));
|
PUT_KEY(result, cmd, reg, CSTR_TO_ARENA_STR(arena, reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
PUT(result, "bang", BOOLEAN_OBJ(ea.forceit));
|
PUT_KEY(result, cmd, bang, ea.forceit);
|
||||||
PUT(result, "args", ARRAY_OBJ(args));
|
PUT_KEY(result, cmd, args, args);
|
||||||
|
|
||||||
char nargs[2];
|
char nargs[2];
|
||||||
if (ea.argt & EX_EXTRA) {
|
if (ea.argt & EX_EXTRA) {
|
||||||
@ -201,9 +194,9 @@ Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
|||||||
nargs[0] = '0';
|
nargs[0] = '0';
|
||||||
}
|
}
|
||||||
nargs[1] = '\0';
|
nargs[1] = '\0';
|
||||||
PUT(result, "nargs", CSTR_TO_OBJ(nargs));
|
PUT_KEY(result, cmd, nargs, CSTR_TO_ARENA_OBJ(arena, nargs));
|
||||||
|
|
||||||
const char *addr;
|
char *addr;
|
||||||
switch (ea.addr_type) {
|
switch (ea.addr_type) {
|
||||||
case ADDR_LINES:
|
case ADDR_LINES:
|
||||||
addr = "line";
|
addr = "line";
|
||||||
@ -233,38 +226,37 @@ Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
|||||||
addr = "?";
|
addr = "?";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PUT(result, "addr", CSTR_TO_OBJ(addr));
|
PUT_KEY(result, cmd, addr, CSTR_AS_OBJ(addr));
|
||||||
PUT(result, "nextcmd", CSTR_TO_OBJ(ea.nextcmd));
|
PUT_KEY(result, cmd, nextcmd, CSTR_AS_OBJ(ea.nextcmd));
|
||||||
|
|
||||||
Dictionary mods = ARRAY_DICT_INIT;
|
// TODO(bfredl): nested keydict would be nice..
|
||||||
|
Dictionary mods = arena_dict(arena, 20);
|
||||||
|
|
||||||
Dictionary filter = ARRAY_DICT_INIT;
|
Dictionary filter = arena_dict(arena, 2);
|
||||||
PUT(filter, "pattern", cmdinfo.cmdmod.cmod_filter_pat
|
PUT_C(filter, "pattern", CSTR_TO_ARENA_OBJ(arena, cmdinfo.cmdmod.cmod_filter_pat));
|
||||||
? CSTR_TO_OBJ(cmdinfo.cmdmod.cmod_filter_pat)
|
PUT_C(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force));
|
||||||
: STATIC_CSTR_TO_OBJ(""));
|
PUT_C(mods, "filter", DICTIONARY_OBJ(filter));
|
||||||
PUT(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force));
|
|
||||||
PUT(mods, "filter", DICTIONARY_OBJ(filter));
|
|
||||||
|
|
||||||
PUT(mods, "silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SILENT));
|
PUT_C(mods, "silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SILENT));
|
||||||
PUT(mods, "emsg_silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT));
|
PUT_C(mods, "emsg_silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT));
|
||||||
PUT(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT));
|
PUT_C(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT));
|
||||||
PUT(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX));
|
PUT_C(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX));
|
||||||
PUT(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD));
|
PUT_C(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD));
|
||||||
PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1));
|
PUT_C(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1));
|
||||||
PUT(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1));
|
PUT_C(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1));
|
||||||
PUT(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE));
|
PUT_C(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE));
|
||||||
PUT(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM));
|
PUT_C(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM));
|
||||||
PUT(mods, "hide", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_HIDE));
|
PUT_C(mods, "hide", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_HIDE));
|
||||||
PUT(mods, "keepalt", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPALT));
|
PUT_C(mods, "keepalt", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPALT));
|
||||||
PUT(mods, "keepjumps", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPJUMPS));
|
PUT_C(mods, "keepjumps", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPJUMPS));
|
||||||
PUT(mods, "keepmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPMARKS));
|
PUT_C(mods, "keepmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPMARKS));
|
||||||
PUT(mods, "keeppatterns", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPPATTERNS));
|
PUT_C(mods, "keeppatterns", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPPATTERNS));
|
||||||
PUT(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS));
|
PUT_C(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS));
|
||||||
PUT(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE));
|
PUT_C(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE));
|
||||||
PUT(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT));
|
PUT_C(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT));
|
||||||
PUT(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR));
|
PUT_C(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR));
|
||||||
|
|
||||||
const char *split;
|
char *split;
|
||||||
if (cmdinfo.cmdmod.cmod_split & WSP_BOT) {
|
if (cmdinfo.cmdmod.cmod_split & WSP_BOT) {
|
||||||
split = "botright";
|
split = "botright";
|
||||||
} else if (cmdinfo.cmdmod.cmod_split & WSP_TOP) {
|
} else if (cmdinfo.cmdmod.cmod_split & WSP_TOP) {
|
||||||
@ -276,18 +268,17 @@ Dictionary nvim_parse_cmd(String str, Dict(empty) *opts, Error *err)
|
|||||||
} else {
|
} else {
|
||||||
split = "";
|
split = "";
|
||||||
}
|
}
|
||||||
PUT(mods, "split", CSTR_TO_OBJ(split));
|
PUT_C(mods, "split", CSTR_AS_OBJ(split));
|
||||||
|
|
||||||
PUT(result, "mods", DICTIONARY_OBJ(mods));
|
PUT_KEY(result, cmd, mods, mods);
|
||||||
|
|
||||||
Dictionary magic = ARRAY_DICT_INIT;
|
Dictionary magic = arena_dict(arena, 2);
|
||||||
PUT(magic, "file", BOOLEAN_OBJ(cmdinfo.magic.file));
|
PUT_C(magic, "file", BOOLEAN_OBJ(cmdinfo.magic.file));
|
||||||
PUT(magic, "bar", BOOLEAN_OBJ(cmdinfo.magic.bar));
|
PUT_C(magic, "bar", BOOLEAN_OBJ(cmdinfo.magic.bar));
|
||||||
PUT(result, "magic", DICTIONARY_OBJ(magic));
|
PUT_KEY(result, cmd, magic, magic);
|
||||||
|
|
||||||
undo_cmdmod(&cmdinfo.cmdmod);
|
undo_cmdmod(&cmdinfo.cmdmod);
|
||||||
end:
|
end:
|
||||||
xfree(cmdline);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@
|
|||||||
|
|
||||||
#define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s))
|
#define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s))
|
||||||
#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
|
#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
|
||||||
#define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(arena_string(arena, cstr_as_string(s)))
|
#define CSTR_TO_ARENA_STR(arena, s) arena_string(arena, cstr_as_string(s))
|
||||||
|
#define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(CSTR_TO_ARENA_STR(arena, s))
|
||||||
|
|
||||||
#define BUFFER_OBJ(s) ((Object) { \
|
#define BUFFER_OBJ(s) ((Object) { \
|
||||||
.type = kObjectTypeBuffer, \
|
.type = kObjectTypeBuffer, \
|
||||||
|
@ -1136,6 +1136,20 @@ bool uc_split_args_iter(const char *arg, size_t arglen, size_t *end, char *buf,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t uc_nargs_upper_bound(const char *arg, size_t arglen)
|
||||||
|
{
|
||||||
|
bool was_white = true; // space before first arg
|
||||||
|
size_t nargs = 0;
|
||||||
|
for (size_t i = 0; i < arglen; i++) {
|
||||||
|
bool is_white = ascii_iswhite(arg[i]);
|
||||||
|
if (was_white && !is_white) {
|
||||||
|
nargs++;
|
||||||
|
}
|
||||||
|
was_white = is_white;
|
||||||
|
}
|
||||||
|
return nargs;
|
||||||
|
}
|
||||||
|
|
||||||
/// split and quote args for <f-args>
|
/// split and quote args for <f-args>
|
||||||
static char *uc_split_args(const char *arg, char **args, const size_t *arglens, size_t argc,
|
static char *uc_split_args(const char *arg, char **args, const size_t *arglens, size_t argc,
|
||||||
size_t *lenp)
|
size_t *lenp)
|
||||||
|
Loading…
Reference in New Issue
Block a user