4040 * - MS-Windows: no redraw for 'updatetime' #1915
4141 * - in bash mouse clicks are inserting characters.
4242 * - mouse scroll: when over other window, scroll that window.
43+ * - add argument to term_wait() for waiting time.
4344 * - For the scrollback buffer store lines in the buffer, only attributes in
4445 * tl_scrollback.
4546 * - When the job ends:
@@ -146,7 +147,7 @@ static term_T *first_term = NULL;
146147/*
147148 * Functions with separate implementation for MS-Windows and Unix-like systems.
148149 */
149- static int term_and_job_init (term_T * term , int rows , int cols , char_u * cmd );
150+ static int term_and_job_init (term_T * term , int rows , int cols , char_u * cmd , jobopt_T * opt );
150151static void term_report_winsize (term_T * term , int rows , int cols );
151152static void term_free_vterm (term_T * term );
152153
@@ -185,15 +186,49 @@ set_term_and_win_size(term_T *term)
185186}
186187
187188/*
188- * ":terminal": open a terminal window and execute a job in it.
189+ * Initialize job options for a terminal job.
190+ * Caller may overrule some of them.
189191 */
190- void
191- ex_terminal (exarg_T * eap )
192+ static void
193+ init_job_options (jobopt_T * opt )
194+ {
195+ clear_job_options (opt );
196+
197+ opt -> jo_mode = MODE_RAW ;
198+ opt -> jo_out_mode = MODE_RAW ;
199+ opt -> jo_err_mode = MODE_RAW ;
200+ opt -> jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE ;
201+
202+ opt -> jo_io [PART_OUT ] = JIO_BUFFER ;
203+ opt -> jo_io [PART_ERR ] = JIO_BUFFER ;
204+ opt -> jo_set |= JO_OUT_IO + JO_ERR_IO ;
205+
206+ opt -> jo_modifiable [PART_OUT ] = 0 ;
207+ opt -> jo_modifiable [PART_ERR ] = 0 ;
208+ opt -> jo_set |= JO_OUT_MODIFIABLE + JO_ERR_MODIFIABLE ;
209+
210+ opt -> jo_set |= JO_OUT_BUF + JO_ERR_BUF ;
211+ }
212+
213+ /*
214+ * Set job options mandatory for a terminal job.
215+ */
216+ static void
217+ setup_job_options (jobopt_T * opt , int rows , int cols )
218+ {
219+ opt -> jo_io_buf [PART_OUT ] = curbuf -> b_fnum ;
220+ opt -> jo_io_buf [PART_ERR ] = curbuf -> b_fnum ;
221+ opt -> jo_pty = TRUE;
222+ opt -> jo_term_rows = rows ;
223+ opt -> jo_term_cols = cols ;
224+ }
225+
226+ static void
227+ term_start (char_u * cmd , jobopt_T * opt )
192228{
193229 exarg_T split_ea ;
194230 win_T * old_curwin = curwin ;
195231 term_T * term ;
196- char_u * cmd = eap -> arg ;
197232
198233 if (check_restricted () || check_secure ())
199234 return ;
@@ -256,9 +291,10 @@ ex_terminal(exarg_T *eap)
256291 (char_u * )"terminal" , OPT_FREE |OPT_LOCAL , 0 );
257292
258293 set_term_and_win_size (term );
294+ setup_job_options (opt , term -> tl_rows , term -> tl_cols );
259295
260296 /* System dependent: setup the vterm and start the job in it. */
261- if (term_and_job_init (term , term -> tl_rows , term -> tl_cols , cmd ) == OK )
297+ if (term_and_job_init (term , term -> tl_rows , term -> tl_cols , cmd , opt ) == OK )
262298 {
263299 /* store the size we ended up with */
264300 vterm_get_size (term -> tl_vterm , & term -> tl_rows , & term -> tl_cols );
@@ -273,6 +309,20 @@ ex_terminal(exarg_T *eap)
273309 }
274310}
275311
312+ /*
313+ * ":terminal": open a terminal window and execute a job in it.
314+ */
315+ void
316+ ex_terminal (exarg_T * eap )
317+ {
318+ jobopt_T opt ;
319+
320+ init_job_options (& opt );
321+ /* TODO: get options from before the command */
322+
323+ term_start (eap -> arg , & opt );
324+ }
325+
276326/*
277327 * Free the scrollback buffer for "term".
278328 */
@@ -965,8 +1015,7 @@ terminal_loop(void)
9651015 update_cursor (curbuf -> b_term , FALSE);
9661016
9671017 c = term_vgetc ();
968- if (curbuf -> b_term -> tl_vterm == NULL
969- || !term_job_running (curbuf -> b_term ))
1018+ if (!term_use_loop ())
9701019 /* job finished while waiting for a character */
9711020 break ;
9721021
@@ -993,8 +1042,7 @@ terminal_loop(void)
9931042#ifdef FEAT_CMDL_INFO
9941043 clear_showcmd ();
9951044#endif
996- if (curbuf -> b_term -> tl_vterm == NULL
997- || !term_job_running (curbuf -> b_term ))
1045+ if (!term_use_loop ())
9981046 /* job finished while waiting for a character */
9991047 break ;
10001048
@@ -1613,35 +1661,6 @@ term_get_attr(buf_T *buf, linenr_T lnum, int col)
16131661 return cell2attr (line -> sb_cells + col );
16141662}
16151663
1616- /*
1617- * Set job options common for Unix and MS-Windows.
1618- */
1619- static void
1620- setup_job_options (jobopt_T * opt , int rows , int cols )
1621- {
1622- clear_job_options (opt );
1623- opt -> jo_mode = MODE_RAW ;
1624- opt -> jo_out_mode = MODE_RAW ;
1625- opt -> jo_err_mode = MODE_RAW ;
1626- opt -> jo_set = JO_MODE | JO_OUT_MODE | JO_ERR_MODE ;
1627-
1628- opt -> jo_io [PART_OUT ] = JIO_BUFFER ;
1629- opt -> jo_io [PART_ERR ] = JIO_BUFFER ;
1630- opt -> jo_set |= JO_OUT_IO + JO_ERR_IO ;
1631-
1632- opt -> jo_modifiable [PART_OUT ] = 0 ;
1633- opt -> jo_modifiable [PART_ERR ] = 0 ;
1634- opt -> jo_set |= JO_OUT_MODIFIABLE + JO_ERR_MODIFIABLE ;
1635-
1636- opt -> jo_io_buf [PART_OUT ] = curbuf -> b_fnum ;
1637- opt -> jo_io_buf [PART_ERR ] = curbuf -> b_fnum ;
1638- opt -> jo_pty = TRUE;
1639- opt -> jo_set |= JO_OUT_BUF + JO_ERR_BUF ;
1640-
1641- opt -> jo_term_rows = rows ;
1642- opt -> jo_term_cols = cols ;
1643- }
1644-
16451664/*
16461665 * Create a new vterm and initialize it.
16471666 */
@@ -2089,12 +2108,19 @@ f_term_sendkeys(typval_T *argvars, typval_T *rettv)
20892108f_term_start (typval_T * argvars , typval_T * rettv )
20902109{
20912110 char_u * cmd = get_tv_string_chk (& argvars [0 ]);
2092- exarg_T ea ;
2111+ jobopt_T opt ;
20932112
20942113 if (cmd == NULL )
20952114 return ;
2096- ea .arg = cmd ;
2097- ex_terminal (& ea );
2115+ init_job_options (& opt );
2116+ /* TODO: allow more job options */
2117+ if (argvars [1 ].v_type != VAR_UNKNOWN
2118+ && get_job_options (& argvars [1 ], & opt ,
2119+ JO_TIMEOUT_ALL + JO_STOPONEXIT
2120+ + JO_EXIT_CB + JO_CLOSE_CALLBACK ) == FAIL )
2121+ return ;
2122+
2123+ term_start (cmd , & opt );
20982124
20992125 if (curbuf -> b_term != NULL )
21002126 rettv -> vval .v_number = curbuf -> b_fnum ;
@@ -2109,19 +2135,40 @@ f_term_wait(typval_T *argvars, typval_T *rettv UNUSED)
21092135 buf_T * buf = term_get_buf (argvars );
21102136
21112137 if (buf == NULL )
2138+ {
2139+ ch_log (NULL , "term_wait(): invalid argument" );
21122140 return ;
2141+ }
21132142
21142143 /* Get the job status, this will detect a job that finished. */
2115- if (buf -> b_term -> tl_job != NULL )
2116- (void )job_status (buf -> b_term -> tl_job );
2144+ if (buf -> b_term -> tl_job == NULL
2145+ || STRCMP (job_status (buf -> b_term -> tl_job ), "dead" ) == 0 )
2146+ {
2147+ /* The job is dead, keep reading channel I/O until the channel is
2148+ * closed. */
2149+ while (buf -> b_term != NULL && !buf -> b_term -> tl_channel_closed )
2150+ {
2151+ mch_char_avail ();
2152+ parse_queued_messages ();
2153+ ui_delay (10L , FALSE);
2154+ }
2155+ mch_char_avail ();
2156+ parse_queued_messages ();
2157+ }
2158+ else
2159+ {
2160+ mch_char_avail ();
2161+ parse_queued_messages ();
21172162
2118- /* Check for any pending channel I/O. */
2119- vpeekc_any ();
2120- ui_delay (10L , FALSE);
2163+ /* Wait for 10 msec for any channel I/O. */
2164+ /* TODO: use delay from optional argument */
2165+ ui_delay (10L , TRUE);
2166+ mch_char_avail ();
21212167
2122- /* Flushing messages on channels is hopefully sufficient.
2123- * TODO: is there a better way? */
2124- parse_queued_messages ();
2168+ /* Flushing messages on channels is hopefully sufficient.
2169+ * TODO: is there a better way? */
2170+ parse_queued_messages ();
2171+ }
21252172}
21262173
21272174# ifdef WIN3264
@@ -2209,12 +2256,11 @@ dyn_winpty_init(void)
22092256 * Return OK or FAIL.
22102257 */
22112258 static int
2212- term_and_job_init (term_T * term , int rows , int cols , char_u * cmd )
2259+ term_and_job_init (term_T * term , int rows , int cols , char_u * cmd , jobopt_T * opt )
22132260{
22142261 WCHAR * p ;
22152262 channel_T * channel = NULL ;
22162263 job_T * job = NULL ;
2217- jobopt_T opt ;
22182264 DWORD error ;
22192265 HANDLE jo = NULL , child_process_handle , child_thread_handle ;
22202266 void * winpty_err ;
@@ -2298,8 +2344,7 @@ term_and_job_init(term_T *term, int rows, int cols, char_u *cmd)
22982344
22992345 create_vterm (term , rows , cols );
23002346
2301- setup_job_options (& opt , rows , cols );
2302- channel_set_job (channel , job , & opt );
2347+ channel_set_job (channel , job , opt );
23032348
23042349 job -> jv_channel = channel ;
23052350 job -> jv_proc_info .hProcess = child_process_handle ;
@@ -2381,18 +2426,17 @@ term_report_winsize(term_T *term, int rows, int cols)
23812426 * Return OK or FAIL.
23822427 */
23832428 static int
2384- term_and_job_init (term_T * term , int rows , int cols , char_u * cmd )
2429+ term_and_job_init (term_T * term , int rows , int cols , char_u * cmd , jobopt_T * opt )
23852430{
23862431 typval_T argvars [2 ];
2387- jobopt_T opt ;
23882432
23892433 create_vterm (term , rows , cols );
23902434
23912435 /* TODO: if the command is "NONE" only create a pty. */
23922436 argvars [0 ].v_type = VAR_STRING ;
23932437 argvars [0 ].vval .v_string = cmd ;
2394- setup_job_options ( & opt , rows , cols );
2395- term -> tl_job = job_start (argvars , & opt );
2438+
2439+ term -> tl_job = job_start (argvars , opt );
23962440 if (term -> tl_job != NULL )
23972441 ++ term -> tl_job -> jv_refcount ;
23982442
0 commit comments