diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7c0d1b3d32..d8c2e73150 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -84,7 +84,6 @@ #include "nvim/os/channel.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" -#include "nvim/os/msgpack_rpc_helpers.h" #include "nvim/os/dl.h" #include "nvim/os/provider.h" @@ -6307,6 +6306,8 @@ static struct fst { {"acos", 1, 1, f_acos}, /* WJMc */ {"add", 2, 2, f_add}, {"and", 2, 2, f_and}, + {"api_close", 1, 1, f_api_close}, + {"api_spawn", 1, 2, f_api_spawn}, {"append", 2, 2, f_append}, {"argc", 0, 0, f_argc}, {"argidx", 0, 0, f_argidx}, @@ -7054,6 +7055,83 @@ static void f_and(typval_T *argvars, typval_T *rettv) & get_tv_number_chk(&argvars[1], NULL); } +// "api_close(prog, argv)" function +static void f_api_close(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_NUMBER) { + // Wrong argument types + EMSG(_(e_invarg)); + return; + } + + rettv->vval.v_number = channel_close(argvars[0].vval.v_number); +} + + +// "api_spawn(prog, argv)" function +static void f_api_spawn(typval_T *argvars, typval_T *rettv) +{ + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + + if (argvars[0].v_type != VAR_STRING + || (argvars[1].v_type != VAR_LIST && argvars[1].v_type != VAR_UNKNOWN)) { + // Wrong argument types + EMSG(_(e_invarg)); + return; + } + + list_T *args = NULL; + int argsl = 0; + if (argvars[1].v_type == VAR_LIST) { + args = argvars[1].vval.v_list; + argsl = args->lv_len; + // Assert that all list items are strings + for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { + if (arg->li_tv.v_type != VAR_STRING) { + EMSG(_(e_invarg)); + return; + } + } + } + + // Allocate extra memory for the argument vector and the NULL pointer + int argvl = argsl + 2; + char **argv = xmalloc(sizeof(char_u *) * argvl); + + // Copy program name + argv[0] = xstrdup((char *)argvars[0].vval.v_string); + + int i = 1; + // Copy arguments to the vector + if (argsl > 0) { + for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) { + argv[i++] = xstrdup((char *)arg->li_tv.vval.v_string); + } + } + + // The last item of argv must be NULL + argv[i] = NULL; + uint64_t channel_id = channel_from_job(argv); + + if (!channel_id) { + EMSG(_(e_api_spawn_failed)); + } + + rettv->vval.v_number = (varnumber_T)channel_id; +} + /* * "append(lnum, string/list)" function */ @@ -12718,14 +12796,18 @@ static void f_send_call(typval_T *argvars, typval_T *rettv) return; } + if (errored) { + vim_report_error(result.data.string); + goto end; + } + Error conversion_error = {.set = false}; - if (errored || !object_to_vim(result, rettv, &conversion_error)) { - EMSG(errored ? - result.data.string.data : - _("Error converting the call result")); + if (!object_to_vim(result, rettv, &conversion_error)) { + EMSG(_("Error converting the call result")); } - msgpack_rpc_free_object(result); +end: + api_free_object(result); } // "send_event()" function @@ -19239,7 +19321,7 @@ static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv) Error err = {.set = false}; object_to_vim(result, rettv, &err); - msgpack_rpc_free_object(result); + api_free_object(result); if (err.set) { EMSG("Error converting value back to vim"); |