Skip to content

Commit

Permalink
api/msgpack-rpc: Expose channel_from_job to vimscript as api_spawn
Browse files Browse the repository at this point in the history
  • Loading branch information
tarruda committed Sep 9, 2014
1 parent 7c90700 commit acf17db
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/nvim/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -6307,6 +6307,7 @@ static struct fst {
{"acos", 1, 1, f_acos}, /* WJMc */
{"add", 2, 2, f_add},
{"and", 2, 2, f_and},
{"api_spawn", 1, 2, f_api_spawn},
{"append", 2, 2, f_append},
{"argc", 0, 0, f_argc},
{"argidx", 0, 0, f_argidx},
Expand Down Expand Up @@ -7054,6 +7055,64 @@ static void f_and(typval_T *argvars, typval_T *rettv)
& get_tv_number_chk(&argvars[1], NULL);
}

// "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
*/
Expand Down
1 change: 1 addition & 0 deletions src/nvim/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ EXTERN garray_T error_ga
* Excluded are errors that are only used once and debugging messages.
*/
EXTERN char_u e_abort[] INIT(= N_("E470: Command aborted"));
EXTERN char_u e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job"));
EXTERN char_u e_argreq[] INIT(= N_("E471: Argument required"));
EXTERN char_u e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &"));
EXTERN char_u e_cmdwin[] INIT(= N_(
Expand Down

0 comments on commit acf17db

Please sign in to comment.