Skip to content

Commit e88fc7a

Browse files
committed
patch 8.0.1052: term_start() does not allow in_io, out_io and err_io options
Problem: term_start() does not allow in_io, out_io and err_io options. Solution: Add JO_OUT_IO to get_job_options().
1 parent 9d654a8 commit e88fc7a

3 files changed

Lines changed: 74 additions & 30 deletions

File tree

src/terminal.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
*
4040
* TODO:
4141
* - ":term NONE" does not work in MS-Windows.
42-
* - test for writing lines to terminal job does not work on MS-Windows
4342
* - implement term_setsize()
4443
* - add test for giving error for invalid 'termsize' value.
4544
* - support minimal size when 'termsize' is "rows*cols".
@@ -48,16 +47,6 @@
4847
* - GUI: when 'confirm' is set and trying to exit Vim, dialog offers to save
4948
* changes to "!shell".
5049
* (justrajdeep, 2017 Aug 22)
51-
* - command argument with spaces doesn't work #1999
52-
* :terminal ls dir\ with\ spaces
53-
* - implement job options when starting a terminal. Allow:
54-
* "in_io", "in_top", "in_bot", "in_name", "in_buf"
55-
"out_io", "out_name", "out_buf", "out_modifiable", "out_msg"
56-
"err_io", "err_name", "err_buf", "err_modifiable", "err_msg"
57-
* Check that something is connected to the terminal.
58-
* Test: "cat" reading from a file or buffer
59-
* "ls" writing stdout to a file or buffer
60-
* shell writing stderr to a file or buffer
6150
* - For the GUI fill termios with default values, perhaps like pangoterm:
6251
* http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134
6352
* - if the job in the terminal does not support the mouse, we can use the
@@ -219,16 +208,6 @@ init_job_options(jobopt_T *opt)
219208
opt->jo_out_mode = MODE_RAW;
220209
opt->jo_err_mode = MODE_RAW;
221210
opt->jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE;
222-
223-
opt->jo_io[PART_OUT] = JIO_BUFFER;
224-
opt->jo_io[PART_ERR] = JIO_BUFFER;
225-
opt->jo_set |= JO_OUT_IO + JO_ERR_IO;
226-
227-
opt->jo_modifiable[PART_OUT] = 0;
228-
opt->jo_modifiable[PART_ERR] = 0;
229-
opt->jo_set |= JO_OUT_MODIFIABLE + JO_ERR_MODIFIABLE;
230-
231-
opt->jo_set |= JO_OUT_BUF + JO_ERR_BUF;
232211
}
233212

234213
/*
@@ -237,8 +216,24 @@ init_job_options(jobopt_T *opt)
237216
static void
238217
setup_job_options(jobopt_T *opt, int rows, int cols)
239218
{
240-
opt->jo_io_buf[PART_OUT] = curbuf->b_fnum;
241-
opt->jo_io_buf[PART_ERR] = curbuf->b_fnum;
219+
if (!(opt->jo_set & JO_OUT_IO))
220+
{
221+
/* Connect stdout to the terminal. */
222+
opt->jo_io[PART_OUT] = JIO_BUFFER;
223+
opt->jo_io_buf[PART_OUT] = curbuf->b_fnum;
224+
opt->jo_modifiable[PART_OUT] = 0;
225+
opt->jo_set |= JO_OUT_IO + JO_OUT_BUF + JO_OUT_MODIFIABLE;
226+
}
227+
228+
if (!(opt->jo_set & JO_ERR_IO))
229+
{
230+
/* Connect stderr to the terminal. */
231+
opt->jo_io[PART_ERR] = JIO_BUFFER;
232+
opt->jo_io_buf[PART_ERR] = curbuf->b_fnum;
233+
opt->jo_modifiable[PART_ERR] = 0;
234+
opt->jo_set |= JO_ERR_IO + JO_ERR_BUF + JO_ERR_MODIFIABLE;
235+
}
236+
242237
opt->jo_pty = TRUE;
243238
if ((opt->jo_set2 & JO2_TERM_ROWS) == 0)
244239
opt->jo_term_rows = rows;
@@ -258,6 +253,15 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
258253
if (check_restricted() || check_secure())
259254
return;
260255

256+
if ((opt->jo_set & (JO_IN_IO + JO_OUT_IO + JO_ERR_IO))
257+
== (JO_IN_IO + JO_OUT_IO + JO_ERR_IO)
258+
|| (!(opt->jo_set & JO_OUT_IO) && (opt->jo_set & JO_OUT_BUF))
259+
|| (!(opt->jo_set & JO_ERR_IO) && (opt->jo_set & JO_ERR_BUF)))
260+
{
261+
EMSG(_(e_invarg));
262+
return;
263+
}
264+
261265
term = (term_T *)alloc_clear(sizeof(term_T));
262266
if (term == NULL)
263267
return;
@@ -2833,11 +2837,10 @@ f_term_start(typval_T *argvars, typval_T *rettv)
28332837
jobopt_T opt;
28342838

28352839
init_job_options(&opt);
2836-
/* TODO: allow more job options */
28372840
if (argvars[1].v_type != VAR_UNKNOWN
28382841
&& get_job_options(&argvars[1], &opt,
28392842
JO_TIMEOUT_ALL + JO_STOPONEXIT
2840-
+ JO_EXIT_CB + JO_CLOSE_CALLBACK,
2843+
+ JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO,
28412844
JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
28422845
+ JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
28432846
+ JO2_CWD + JO2_ENV + JO2_EOF_CHARS) == FAIL)
@@ -3254,7 +3257,6 @@ term_and_job_init(
32543257
{
32553258
create_vterm(term, term->tl_rows, term->tl_cols);
32563259

3257-
/* TODO: if the command is "NONE" only create a pty. */
32583260
term->tl_job = job_start(argvar, opt);
32593261
if (term->tl_job != NULL)
32603262
++term->tl_job->jv_refcount;

src/testdir/test_terminal.vim

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,8 @@ func Test_terminal_scrape_123()
164164
call term_wait(1234)
165165

166166
call term_wait(buf)
167-
if has('win32')
168-
" TODO: this should not be needed
169-
sleep 100m
170-
endif
167+
let g:buf = buf
168+
call WaitFor('len(term_scrape(g:buf, 1)) > 0')
171169
call Check_123(buf)
172170

173171
" Must still work after the job ended.
@@ -573,3 +571,45 @@ func Test_terminal_special_chars()
573571
call delete('Xdir with spaces', 'rf')
574572
bwipe
575573
endfunc
574+
575+
func Test_terminal_wrong_options()
576+
call assert_fails('call term_start(&shell, {
577+
\ "in_io": "file",
578+
\ "in_name": "xxx",
579+
\ "out_io": "file",
580+
\ "out_name": "xxx",
581+
\ "err_io": "file",
582+
\ "err_name": "xxx"
583+
\ })', 'E474:')
584+
call assert_fails('call term_start(&shell, {
585+
\ "out_buf": bufnr("%")
586+
\ })', 'E474:')
587+
call assert_fails('call term_start(&shell, {
588+
\ "err_buf": bufnr("%")
589+
\ })', 'E474:')
590+
endfunc
591+
592+
func Test_terminal_redir_file()
593+
let cmd = Get_cat_123_cmd()
594+
let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'})
595+
call term_wait(buf)
596+
call WaitFor('len(readfile("Xfile")) > 0')
597+
call assert_match('123', readfile('Xfile')[0])
598+
call delete('Xfile')
599+
600+
if has('unix')
601+
let buf = term_start('xyzabc', {'err_io': 'file', 'err_name': 'Xfile'})
602+
call term_wait(buf)
603+
call WaitFor('len(readfile("Xfile")) > 0')
604+
call assert_match('executing job failed', readfile('Xfile')[0])
605+
call delete('Xfile')
606+
607+
call writefile(['one line'], 'Xfile')
608+
let buf = term_start('cat', {'in_io': 'file', 'in_name': 'Xfile'})
609+
call term_wait(buf)
610+
call WaitFor('term_getline(' . buf . ', 1) == "one line"')
611+
call assert_equal('one line', term_getline(buf, 1))
612+
bwipe
613+
call delete('Xfile')
614+
endif
615+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,8 @@ static char *(features[]) =
769769

770770
static int included_patches[] =
771771
{ /* Add new patch number below this line */
772+
/**/
773+
1052,
772774
/**/
773775
1051,
774776
/**/

0 commit comments

Comments
 (0)