Skip to content

Commit e455f0b

Browse files
authored
Merge pull request neovim#13876 from jamessan/pty-term
fix(pty): Always use $TERM from the job's env dict
2 parents f4f6cce + 33f92fe commit e455f0b

File tree

7 files changed

+30
-27
lines changed

7 files changed

+30
-27
lines changed

runtime/doc/eval.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5607,7 +5607,6 @@ jobstart({cmd}[, {opts}]) *jobstart()*
56075607
before invoking `on_stderr`. |channel-buffered|
56085608
stdout_buffered: (boolean) Collect data until EOF (stream
56095609
closed) before invoking `on_stdout`. |channel-buffered|
5610-
TERM: (string) Sets the `pty` $TERM environment variable.
56115610
width: (number) Width of the `pty` terminal.
56125611

56135612
{opts} is passed as |self| dictionary to the callback; the

src/nvim/channel.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ static void close_cb(Stream *stream, void *data)
292292
/// directory if `cwd` is NULL
293293
/// @param[in] pty_width Width of the pty, ignored if `pty` is false
294294
/// @param[in] pty_height Height of the pty, ignored if `pty` is false
295-
/// @param[in] term_name `$TERM` for the pty
296295
/// @param[in] env Nvim's configured environment is used if this is NULL,
297296
/// otherwise defines all environment variables
298297
/// @param[out] status_out 0 for invalid arguments, > 0 for the channel id,
@@ -304,8 +303,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
304303
bool pty, bool rpc, bool overlapped, bool detach,
305304
const char *cwd,
306305
uint16_t pty_width, uint16_t pty_height,
307-
char *term_name, dict_T *env,
308-
varnumber_T *status_out)
306+
dict_T *env, varnumber_T *status_out)
309307
{
310308
assert(cwd == NULL || os_isdir_executable(cwd));
311309

@@ -318,7 +316,9 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
318316
if (detach) {
319317
EMSG2(_(e_invarg2), "terminal/pty job cannot be detached");
320318
shell_free_argv(argv);
321-
xfree(term_name);
319+
if (env) {
320+
tv_dict_free(env);
321+
}
322322
channel_destroy_early(chan);
323323
*status_out = 0;
324324
return NULL;
@@ -330,9 +330,6 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
330330
if (pty_height > 0) {
331331
chan->stream.pty.height = pty_height;
332332
}
333-
if (term_name) {
334-
chan->stream.pty.term_name = term_name;
335-
}
336333
} else {
337334
chan->stream.uv = libuv_process_init(&main_loop, chan);
338335
}
@@ -362,9 +359,6 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
362359
if (proc->env) {
363360
tv_dict_free(proc->env);
364361
}
365-
if (proc->type == kProcessTypePty) {
366-
xfree(chan->stream.pty.term_name);
367-
}
368362
channel_destroy_early(chan);
369363
*status_out = proc->status;
370364
return NULL;

src/nvim/eval/funcs.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4912,7 +4912,8 @@ static const char *required_env_vars[] = {
49124912

49134913
static dict_T *create_environment(const dictitem_T *job_env,
49144914
const bool clear_env,
4915-
const bool pty)
4915+
const bool pty,
4916+
const char * const pty_term_name)
49164917
{
49174918
dict_T * env = tv_dict_alloc();
49184919

@@ -4946,6 +4947,18 @@ static dict_T *create_environment(const dictitem_T *job_env,
49464947
}
49474948
}
49484949

4950+
// For a pty, we need a sane $TERM set. We can't rely on nvim's environment,
4951+
// because the child process is going to be communicating with nvim, not the
4952+
// parent terminal. Set a sane default, but let the user override it in the
4953+
// job's environment if they want.
4954+
if (pty) {
4955+
dictitem_T *dv = tv_dict_find(env, S_LEN("TERM"));
4956+
if (dv) {
4957+
tv_dict_item_remove(env, dv);
4958+
}
4959+
tv_dict_add_str(env, S_LEN("TERM"), pty_term_name);
4960+
}
4961+
49494962
if (job_env) {
49504963
tv_dict_extend(env, job_env->di_tv.vval.v_dict, "force");
49514964
}
@@ -5055,20 +5068,25 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
50555068
}
50565069
}
50575070

5058-
env = create_environment(job_env, clear_env, pty);
5059-
50605071
uint16_t width = 0, height = 0;
50615072
char *term_name = NULL;
50625073

50635074
if (pty) {
50645075
width = (uint16_t)tv_dict_get_number(job_opts, "width");
50655076
height = (uint16_t)tv_dict_get_number(job_opts, "height");
5066-
term_name = tv_dict_get_string(job_opts, "TERM", true);
5077+
// Legacy method, before env option existed, to specify $TERM. No longer
5078+
// documented, but still usable to avoid breaking scripts.
5079+
term_name = tv_dict_get_string(job_opts, "TERM", false);
5080+
if (!term_name) {
5081+
term_name = "ansi";
5082+
}
50675083
}
50685084

5085+
env = create_environment(job_env, clear_env, pty, term_name);
5086+
50695087
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty,
50705088
rpc, overlapped, detach, cwd, width, height,
5071-
term_name, env, &rettv->vval.v_number);
5089+
env, &rettv->vval.v_number);
50725090
if (chan) {
50735091
channel_create_event(chan, NULL);
50745092
}
@@ -7511,7 +7529,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
75117529
Channel *chan = channel_job_start(argv, CALLBACK_READER_INIT,
75127530
CALLBACK_READER_INIT, CALLBACK_NONE,
75137531
false, true, false, false, NULL, 0, 0,
7514-
NULL, NULL, &rettv->vval.v_number);
7532+
NULL, &rettv->vval.v_number);
75157533
if (chan) {
75167534
channel_create_event(chan, NULL);
75177535
}
@@ -10618,7 +10636,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
1061810636
}
1061910637
}
1062010638

10621-
env = create_environment(job_env, clear_env, pty);
10639+
env = create_environment(job_env, clear_env, pty, "xterm-256color");
1062210640

1062310641
const bool rpc = false;
1062410642
const bool overlapped = false;
@@ -10627,8 +10645,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
1062710645
Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit,
1062810646
pty, rpc, overlapped, detach, cwd,
1062910647
term_width, curwin->w_height_inner,
10630-
xstrdup("xterm-256color"), env,
10631-
&rettv->vval.v_number);
10648+
env, &rettv->vval.v_number);
1063210649
if (rettv->vval.v_number <= 0) {
1063310650
return;
1063410651
}

src/nvim/event/process.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,6 @@ static void process_close_event(void **argv)
270270
{
271271
Process *proc = argv[0];
272272
shell_free_argv(proc->argv);
273-
if (proc->type == kProcessTypePty) {
274-
xfree(((PtyProcess *)proc)->term_name);
275-
}
276273
if (proc->cb) { // "on_exit" for jobstart(). See channel_job_start().
277274
proc->cb(proc, proc->status, proc->data);
278275
}

src/nvim/os/pty_process_unix.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,6 @@ static void init_child(PtyProcess *ptyproc)
182182
char *prog = ptyproc->process.argv[0];
183183

184184
assert(proc->env);
185-
tv_dict_add_str(proc->env, S_LEN("TERM"),
186-
ptyproc->term_name ? ptyproc->term_name : "ansi");
187185
environ = tv_dict_to_env(proc->env);
188186
execvp(prog, proc->argv);
189187
ELOG("execvp failed: %s: %s", strerror(errno), prog);

src/nvim/os/pty_process_unix.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data)
1717
{
1818
PtyProcess rv;
1919
rv.process = process_init(loop, kProcessTypePty, data);
20-
rv.term_name = NULL;
2120
rv.width = 80;
2221
rv.height = 24;
2322
rv.tty_fd = -1;

src/nvim/os/pty_process_win.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data)
3737
{
3838
PtyProcess rv;
3939
rv.process = process_init(loop, kProcessTypePty, data);
40-
rv.term_name = NULL;
4140
rv.width = 80;
4241
rv.height = 24;
4342
rv.object.winpty = NULL;

0 commit comments

Comments
 (0)