From 915dda3f96b3619769bc93dab19841138fcb7eaf Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 14 Jun 2021 11:56:43 -0600 Subject: feat(job): add parameter to close stdin Some programs behave differently when they detect that stdin is being piped. This can be problematic when these programs are used with the job control API where stdin is attached, but not typically used. It is possible to run the job using a PTY which circumvents this problem, but that includes a lot of overhead when simply closing the stdin pipe would suffice. To enable this behavior, add a new parameter to the jobstart options dict called "stdin" with two valid values: "pipe" (the default) implements the existing behavior of opening a channel for stdin and "null" which disconnects stdin (or, if you prefer, connects it to /dev/null). This is extensible so that other modes can be added in the future. --- src/nvim/eval/funcs.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval/funcs.c') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1ba31bfe68..22c6951e2c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5181,6 +5181,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool pty = false; bool clear_env = false; bool overlapped = false; + ChannelStdinMode stdin = kChannelStdinPipe; CallbackReader on_stdout = CALLBACK_READER_INIT, on_stderr = CALLBACK_READER_INIT; Callback on_exit = CALLBACK_NONE; @@ -5195,6 +5196,17 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) clear_env = tv_dict_get_number(job_opts, "clear_env") != 0; overlapped = tv_dict_get_number(job_opts, "overlapped") != 0; + char *s = tv_dict_get_string(job_opts, "stdin", false); + if (s) { + if (!strncmp(s, "null", NUMBUFLEN)) { + stdin = kChannelStdinNull; + } else if (!strncmp(s, "pipe", NUMBUFLEN)) { + // Nothing to do, default value + } else { + EMSG3(_(e_invargNval), "stdin", s); + } + } + if (pty && rpc) { EMSG2(_(e_invarg2), "job cannot have both 'pty' and 'rpc' options set"); shell_free_argv(argv); @@ -5251,8 +5263,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) env = create_environment(job_env, clear_env, pty, term_name); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty, - rpc, overlapped, detach, cwd, width, height, - env, &rettv->vval.v_number); + rpc, overlapped, detach, stdin, cwd, width, + height, env, &rettv->vval.v_number); if (chan) { channel_create_event(chan, NULL); } @@ -7732,8 +7744,9 @@ 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, false, NULL, 0, 0, - NULL, &rettv->vval.v_number); + false, true, false, false, + kChannelStdinPipe, NULL, 0, 0, NULL, + &rettv->vval.v_number); if (chan) { channel_create_event(chan, NULL); } @@ -10849,9 +10862,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) const bool rpc = false; const bool overlapped = false; const bool detach = false; + ChannelStdinMode stdin = kChannelStdinPipe; uint16_t term_width = MAX(0, curwin->w_width_inner - win_col_off(curwin)); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, - pty, rpc, overlapped, detach, cwd, + pty, rpc, overlapped, detach, stdin, cwd, term_width, curwin->w_height_inner, env, &rettv->vval.v_number); if (rettv->vval.v_number <= 0) { -- cgit From 008b83f5a28eeb449f76f420f56648a1b5f45b5c Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 12 Jul 2021 11:55:20 -0600 Subject: Rename stdin to stdin_mode stdin is a macro in Windows builds. --- src/nvim/eval/funcs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval/funcs.c') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 22c6951e2c..7e191176d9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5181,7 +5181,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool pty = false; bool clear_env = false; bool overlapped = false; - ChannelStdinMode stdin = kChannelStdinPipe; + ChannelStdinMode stdin_mode = kChannelStdinPipe; CallbackReader on_stdout = CALLBACK_READER_INIT, on_stderr = CALLBACK_READER_INIT; Callback on_exit = CALLBACK_NONE; @@ -5199,7 +5199,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) char *s = tv_dict_get_string(job_opts, "stdin", false); if (s) { if (!strncmp(s, "null", NUMBUFLEN)) { - stdin = kChannelStdinNull; + stdin_mode = kChannelStdinNull; } else if (!strncmp(s, "pipe", NUMBUFLEN)) { // Nothing to do, default value } else { @@ -5263,8 +5263,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) env = create_environment(job_env, clear_env, pty, term_name); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty, - rpc, overlapped, detach, stdin, cwd, width, - height, env, &rettv->vval.v_number); + rpc, overlapped, detach, stdin_mode, cwd, + width, height, env, &rettv->vval.v_number); if (chan) { channel_create_event(chan, NULL); } @@ -10862,11 +10862,11 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) const bool rpc = false; const bool overlapped = false; const bool detach = false; - ChannelStdinMode stdin = kChannelStdinPipe; + ChannelStdinMode stdin_mode = kChannelStdinPipe; uint16_t term_width = MAX(0, curwin->w_width_inner - win_col_off(curwin)); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, - pty, rpc, overlapped, detach, stdin, cwd, - term_width, curwin->w_height_inner, + pty, rpc, overlapped, detach, stdin_mode, + cwd, term_width, curwin->w_height_inner, env, &rettv->vval.v_number); if (rettv->vval.v_number <= 0) { return; -- cgit