aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
authorMatthieu Coudron <mattator@gmail.com>2018-11-09 23:57:00 +0900
committerJames McCoy <jamessan@jamessan.com>2019-12-11 21:07:13 -0500
commit19b6237087ebcf45427ceb6943d23ce33b39567f (patch)
treef333dc24b4d91f691c8ba38f1582ff3d58ce71fd /src/nvim/eval.c
parentf3fcaedfad59684e6f57ff0bb131b75a3c7fdcaa (diff)
downloadrneovim-19b6237087ebcf45427ceb6943d23ce33b39567f.tar.gz
rneovim-19b6237087ebcf45427ceb6943d23ce33b39567f.tar.bz2
rneovim-19b6237087ebcf45427ceb6943d23ce33b39567f.zip
jobstart now supports env/clear_env
to modify the environment of the launched job.
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index e99c41a915..00a0aecf4b 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -12577,6 +12577,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
bool executable = true;
char **argv = tv_to_argv(&argvars[0], NULL, &executable);
+ char **env = NULL;
if (!argv) {
rettv->vval.v_number = executable ? 0 : -1;
return; // Did error message in tv_to_argv.
@@ -12594,6 +12595,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
bool detach = false;
bool rpc = false;
bool pty = false;
+ bool clear_env = false;
CallbackReader on_stdout = CALLBACK_READER_INIT,
on_stderr = CALLBACK_READER_INIT;
Callback on_exit = CALLBACK_NONE;
@@ -12604,6 +12606,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
detach = tv_dict_get_number(job_opts, "detach") != 0;
rpc = tv_dict_get_number(job_opts, "rpc") != 0;
pty = tv_dict_get_number(job_opts, "pty") != 0;
+ clear_env = tv_dict_get_number(job_opts, "clear_env") != 0;
if (pty && rpc) {
EMSG2(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set");
shell_free_argv(argv);
@@ -12620,6 +12623,47 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
return;
}
}
+ dictitem_T *item;
+ item = tv_dict_find(job_opts, S_LEN("env"));
+ if (item) {
+ size_t custom_env_size = (size_t)tv_dict_len(item->di_tv.vval.v_dict);
+ size_t i = 0;
+ size_t env_size = 0;
+ if (item->di_tv.v_type != VAR_DICT) {
+ EMSG2(_(e_invarg2), "env");
+ return;
+ }
+
+ if (clear_env) {
+ // + 1 for last null entry
+ env = xmalloc((custom_env_size + 1) * sizeof(*env));
+ env_size = 0;
+ } else {
+ char **genv = os_getfullenv();
+ for (env = genv; *env; env++) {
+ env_size++;
+ }
+ env = xmalloc((custom_env_size + env_size + 1) * sizeof(*env));
+
+ for (i = 0; i < env_size; i++) {
+ env[i] = xstrdup(genv[i]);
+ }
+ }
+ assert(env); // env must be allocated at this point
+
+ TV_DICT_ITER(item->di_tv.vval.v_dict, var, {
+ const char *str = tv_get_string(&var->di_tv);
+ assert(str);
+ size_t len = STRLEN(var->di_key) + strlen(str) + strlen("=") + 1;
+ env[i] = xmalloc(len);
+ snprintf(env[i], len, "%s=%s", (char *)var->di_key, str);
+ i++;
+ });
+
+ // must be null terminated
+ env[env_size + custom_env_size] = NULL;
+ }
+
if (!common_job_callbacks(job_opts, &on_stdout, &on_stderr, &on_exit)) {
shell_free_argv(argv);
@@ -12637,8 +12681,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty,
- rpc, detach, cwd, width, height, term_name,
- &rettv->vval.v_number);
+ rpc, detach, cwd, width, height,
+ term_name, env, &rettv->vval.v_number);
if (chan) {
channel_create_event(chan, NULL);
}
@@ -14933,7 +14977,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
Channel *chan = channel_job_start(argv, CALLBACK_READER_INIT,
CALLBACK_READER_INIT, CALLBACK_NONE,
- false, true, false, NULL, 0, 0, NULL,
+ false, true, false, NULL, 0, 0, NULL, NULL,
&rettv->vval.v_number);
if (chan) {
channel_create_event(chan, NULL);
@@ -18320,7 +18364,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit,
true, false, false, cwd,
term_width, curwin->w_height_inner,
- xstrdup("xterm-256color"),
+ xstrdup("xterm-256color"), NULL,
&rettv->vval.v_number);
if (rettv->vval.v_number <= 0) {
return;