Skip to content

Commit 3c51840

Browse files
committed
patch 8.0.1076: term_start() does not take callbacks
Problem: term_start() does not take callbacks. When using two terminals without a job only one is read from. A terminal without a window returns the wrong pty. Solution: Support "callback", "out_cb" and "err_cb". Fix terminal without a window. Fix reading from multiple channels.
1 parent 1a735d6 commit 3c51840

4 files changed

Lines changed: 48 additions & 24 deletions

File tree

src/channel.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3692,13 +3692,10 @@ channel_send(
36923692
{
36933693
res = fd_write(fd, (char *)buf, len);
36943694
#ifdef WIN32
3695-
if (channel->ch_named_pipe)
3695+
if (channel->ch_named_pipe && res < 0)
36963696
{
3697-
if (res < 0)
3698-
{
3699-
DisconnectNamedPipe((HANDLE)fd);
3700-
ConnectNamedPipe((HANDLE)fd, NULL);
3701-
}
3697+
DisconnectNamedPipe((HANDLE)fd);
3698+
ConnectNamedPipe((HANDLE)fd, NULL);
37023699
}
37033700
#endif
37043701

@@ -4084,6 +4081,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
40844081
if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds))
40854082
{
40864083
channel_read(channel, part, "channel_select_check");
4084+
FD_CLR(fd, rfds);
40874085
--ret;
40884086
}
40894087
}
@@ -4093,6 +4091,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
40934091
&& FD_ISSET(in_part->ch_fd, wfds))
40944092
{
40954093
channel_write_input(channel);
4094+
FD_CLR(in_part->ch_fd, wfds);
40964095
--ret;
40974096
}
40984097
}

src/proto/terminal.pro

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ void ex_terminal(exarg_T *eap);
33
void free_terminal(buf_T *buf);
44
void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
55
int term_job_running(term_T *term);
6+
int term_none_open(term_T *term);
67
int term_in_normal_mode(void);
78
void term_enter_job_mode(void);
89
int send_keys_to_term(term_T *term, int c, int typed);
@@ -16,7 +17,6 @@ int term_update_window(win_T *wp);
1617
int term_is_finished(buf_T *buf);
1718
int term_show_buffer(buf_T *buf);
1819
void term_change_in_curbuf(void);
19-
void term_send_eof(channel_T *ch);
2020
int term_get_attr(buf_T *buf, linenr_T lnum, int col);
2121
char_u *term_get_status_text(term_T *term);
2222
int set_ref_in_term(int copyID);
@@ -35,5 +35,6 @@ void f_term_scrape(typval_T *argvars, typval_T *rettv);
3535
void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
3636
void f_term_start(typval_T *argvars, typval_T *rettv);
3737
void f_term_wait(typval_T *argvars, typval_T *rettv);
38+
void term_send_eof(channel_T *ch);
3839
int terminal_enabled(void);
3940
/* vim: set ft=c : */

src/terminal.c

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -245,30 +245,35 @@ setup_job_options(jobopt_T *opt, int rows, int cols)
245245
opt->jo_term_cols = cols;
246246
}
247247

248-
static void
248+
/*
249+
* Start a terminal window and return its buffer.
250+
* Returns NULL when failed.
251+
*/
252+
static buf_T *
249253
term_start(typval_T *argvar, jobopt_T *opt, int forceit)
250254
{
251255
exarg_T split_ea;
252256
win_T *old_curwin = curwin;
253257
term_T *term;
254258
buf_T *old_curbuf = NULL;
255259
int res;
260+
buf_T *newbuf;
256261

257262
if (check_restricted() || check_secure())
258-
return;
263+
return NULL;
259264

260265
if ((opt->jo_set & (JO_IN_IO + JO_OUT_IO + JO_ERR_IO))
261266
== (JO_IN_IO + JO_OUT_IO + JO_ERR_IO)
262267
|| (!(opt->jo_set & JO_OUT_IO) && (opt->jo_set & JO_OUT_BUF))
263268
|| (!(opt->jo_set & JO_ERR_IO) && (opt->jo_set & JO_ERR_BUF)))
264269
{
265270
EMSG(_(e_invarg));
266-
return;
271+
return NULL;
267272
}
268273

269274
term = (term_T *)alloc_clear(sizeof(term_T));
270275
if (term == NULL)
271-
return;
276+
return NULL;
272277
term->tl_dirty_row_end = MAX_ROW;
273278
term->tl_cursor_visible = TRUE;
274279
term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
@@ -283,13 +288,13 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
283288
{
284289
no_write_message();
285290
vim_free(term);
286-
return;
291+
return NULL;
287292
}
288293
if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
289294
ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
290295
{
291296
vim_free(term);
292-
return;
297+
return NULL;
293298
}
294299
}
295300
else if (opt->jo_hidden)
@@ -303,7 +308,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
303308
if (buf == NULL || ml_open(buf) == FAIL)
304309
{
305310
vim_free(term);
306-
return;
311+
return NULL;
307312
}
308313
old_curbuf = curbuf;
309314
--curbuf->b_nwindows;
@@ -333,7 +338,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
333338
{
334339
/* split failed */
335340
vim_free(term);
336-
return;
341+
return NULL;
337342
}
338343
}
339344
term->tl_buffer = curbuf;
@@ -419,6 +424,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
419424
else
420425
res = term_and_job_init(term, argvar, opt);
421426

427+
newbuf = curbuf;
422428
if (res == OK)
423429
{
424430
/* Get and remember the size we ended up with. Update the pty. */
@@ -453,7 +459,9 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
453459
/* Wiping out the buffer will also close the window and call
454460
* free_terminal(). */
455461
do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
462+
return NULL;
456463
}
464+
return newbuf;
457465
}
458466

459467
/*
@@ -688,7 +696,7 @@ write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
688696
update_screen(0);
689697
update_cursor(term, TRUE);
690698
}
691-
else
699+
else if (buffer->b_nwindows > 0)
692700
redraw_after_callback(TRUE);
693701
}
694702
}
@@ -878,6 +886,20 @@ term_job_running(term_T *term)
878886
|| term->tl_job->jv_channel->ch_keep_open);
879887
}
880888

889+
/*
890+
* Return TRUE if "term" has an active channel and used ":term NONE".
891+
*/
892+
int
893+
term_none_open(term_T *term)
894+
{
895+
/* Also consider the job finished when the channel is closed, to avoid a
896+
* race condition when updating the title. */
897+
return term != NULL
898+
&& term->tl_job != NULL
899+
&& channel_is_open(term->tl_job->jv_channel)
900+
&& term->tl_job->jv_channel->ch_keep_open;
901+
}
902+
881903
/*
882904
* Add the last line of the scrollback buffer to the buffer in the window.
883905
*/
@@ -2379,6 +2401,8 @@ term_get_status_text(term_T *term)
23792401
}
23802402
else if (term->tl_title != NULL)
23812403
txt = term->tl_title;
2404+
else if (term_none_open(term))
2405+
txt = (char_u *)_("active");
23822406
else if (term_job_running(term))
23832407
txt = (char_u *)_("running");
23842408
else
@@ -2858,11 +2882,13 @@ f_term_sendkeys(typval_T *argvars, typval_T *rettv)
28582882
f_term_start(typval_T *argvars, typval_T *rettv)
28592883
{
28602884
jobopt_T opt;
2885+
buf_T *buf;
28612886

28622887
init_job_options(&opt);
28632888
if (argvars[1].v_type != VAR_UNKNOWN
28642889
&& get_job_options(&argvars[1], &opt,
28652890
JO_TIMEOUT_ALL + JO_STOPONEXIT
2891+
+ JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK
28662892
+ JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO,
28672893
JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
28682894
+ JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
@@ -2871,10 +2897,10 @@ f_term_start(typval_T *argvars, typval_T *rettv)
28712897

28722898
if (opt.jo_vertical)
28732899
cmdmod.split = WSP_VERT;
2874-
term_start(&argvars[0], &opt, FALSE);
2900+
buf = term_start(&argvars[0], &opt, FALSE);
28752901

2876-
if (curbuf->b_term != NULL)
2877-
rettv->vval.v_number = curbuf->b_fnum;
2902+
if (buf != NULL && buf->b_term != NULL)
2903+
rettv->vval.v_number = buf->b_fnum;
28782904
}
28792905

28802906
/*
@@ -3359,8 +3385,6 @@ term_and_job_init(
33593385
static int
33603386
create_pty_only(term_T *term, jobopt_T *opt)
33613387
{
3362-
int ret;
3363-
33643388
create_vterm(term, term->tl_rows, term->tl_cols);
33653389

33663390
term->tl_job = job_alloc();
@@ -3371,9 +3395,7 @@ create_pty_only(term_T *term, jobopt_T *opt)
33713395
/* behave like the job is already finished */
33723396
term->tl_job->jv_status = JOB_FINISHED;
33733397

3374-
ret = mch_create_pty_channel(term->tl_job, opt);
3375-
3376-
return ret;
3398+
return mch_create_pty_channel(term->tl_job, opt);
33773399
}
33783400

33793401
/*

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+
1076,
772774
/**/
773775
1075,
774776
/**/

0 commit comments

Comments
 (0)