]> granicus.if.org Git - vim/commitdiff
patch 8.0.1076: term_start() does not take callbacks v8.0.1076
authorBram Moolenaar <Bram@vim.org>
Fri, 8 Sep 2017 18:47:00 +0000 (20:47 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 8 Sep 2017 18:47:00 +0000 (20:47 +0200)
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.

src/channel.c
src/proto/terminal.pro
src/terminal.c
src/version.c

index c401df2907420aa4824e92436c9856da7f8fc233..dfb8ac989f1e9b5acc70d134d3175d775a95bea3 100644 (file)
@@ -3692,13 +3692,10 @@ channel_send(
        {
            res = fd_write(fd, (char *)buf, len);
 #ifdef WIN32
-           if (channel->ch_named_pipe)
+           if (channel->ch_named_pipe && res < 0)
            {
-               if (res < 0)
-               {
-                   DisconnectNamedPipe((HANDLE)fd);
-                   ConnectNamedPipe((HANDLE)fd, NULL);
-               }
+               DisconnectNamedPipe((HANDLE)fd);
+               ConnectNamedPipe((HANDLE)fd, NULL);
            }
 #endif
 
@@ -4084,6 +4081,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
            if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds))
            {
                channel_read(channel, part, "channel_select_check");
+               FD_CLR(fd, rfds);
                --ret;
            }
        }
@@ -4093,6 +4091,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
                                            && FD_ISSET(in_part->ch_fd, wfds))
        {
            channel_write_input(channel);
+           FD_CLR(in_part->ch_fd, wfds);
            --ret;
        }
     }
index 3811ba7a51d45c0131657f3ca83491a957460293..639318d5180a71e10aad31755d6c9535bef94494 100644 (file)
@@ -3,6 +3,7 @@ void ex_terminal(exarg_T *eap);
 void free_terminal(buf_T *buf);
 void write_to_term(buf_T *buffer, char_u *msg, channel_T *channel);
 int term_job_running(term_T *term);
+int term_none_open(term_T *term);
 int term_in_normal_mode(void);
 void term_enter_job_mode(void);
 int send_keys_to_term(term_T *term, int c, int typed);
@@ -16,7 +17,6 @@ int term_update_window(win_T *wp);
 int term_is_finished(buf_T *buf);
 int term_show_buffer(buf_T *buf);
 void term_change_in_curbuf(void);
-void term_send_eof(channel_T *ch);
 int term_get_attr(buf_T *buf, linenr_T lnum, int col);
 char_u *term_get_status_text(term_T *term);
 int set_ref_in_term(int copyID);
@@ -35,5 +35,6 @@ void f_term_scrape(typval_T *argvars, typval_T *rettv);
 void f_term_sendkeys(typval_T *argvars, typval_T *rettv);
 void f_term_start(typval_T *argvars, typval_T *rettv);
 void f_term_wait(typval_T *argvars, typval_T *rettv);
+void term_send_eof(channel_T *ch);
 int terminal_enabled(void);
 /* vim: set ft=c : */
index eddca8ee70609acd357a80695b1eb4b93ae3e6a5..c4313eeabc7ef245883c230a9cc8c6d0a5922347 100644 (file)
@@ -245,7 +245,11 @@ setup_job_options(jobopt_T *opt, int rows, int cols)
        opt->jo_term_cols = cols;
 }
 
-    static void
+/*
+ * Start a terminal window and return its buffer.
+ * Returns NULL when failed.
+ */
+    static buf_T *
 term_start(typval_T *argvar, jobopt_T *opt, int forceit)
 {
     exarg_T    split_ea;
@@ -253,9 +257,10 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
     term_T     *term;
     buf_T      *old_curbuf = NULL;
     int                res;
+    buf_T      *newbuf;
 
     if (check_restricted() || check_secure())
-       return;
+       return NULL;
 
     if ((opt->jo_set & (JO_IN_IO + JO_OUT_IO + JO_ERR_IO))
                                         == (JO_IN_IO + JO_OUT_IO + JO_ERR_IO)
@@ -263,12 +268,12 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
        || (!(opt->jo_set & JO_ERR_IO) && (opt->jo_set & JO_ERR_BUF)))
     {
        EMSG(_(e_invarg));
-       return;
+       return NULL;
     }
 
     term = (term_T *)alloc_clear(sizeof(term_T));
     if (term == NULL)
-       return;
+       return NULL;
     term->tl_dirty_row_end = MAX_ROW;
     term->tl_cursor_visible = TRUE;
     term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
@@ -283,13 +288,13 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
        {
            no_write_message();
            vim_free(term);
-           return;
+           return NULL;
        }
        if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
                     ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
        {
            vim_free(term);
-           return;
+           return NULL;
        }
     }
     else if (opt->jo_hidden)
@@ -303,7 +308,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
        if (buf == NULL || ml_open(buf) == FAIL)
        {
            vim_free(term);
-           return;
+           return NULL;
        }
        old_curbuf = curbuf;
        --curbuf->b_nwindows;
@@ -333,7 +338,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
        {
            /* split failed */
            vim_free(term);
-           return;
+           return NULL;
        }
     }
     term->tl_buffer = curbuf;
@@ -419,6 +424,7 @@ term_start(typval_T *argvar, jobopt_T *opt, int forceit)
     else
        res = term_and_job_init(term, argvar, opt);
 
+    newbuf = curbuf;
     if (res == OK)
     {
        /* 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)
        /* Wiping out the buffer will also close the window and call
         * free_terminal(). */
        do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
+       return NULL;
     }
+    return newbuf;
 }
 
 /*
@@ -688,7 +696,7 @@ write_to_term(buf_T *buffer, char_u *msg, channel_T *channel)
            update_screen(0);
            update_cursor(term, TRUE);
        }
-       else
+       else if (buffer->b_nwindows > 0)
            redraw_after_callback(TRUE);
     }
 }
@@ -878,6 +886,20 @@ term_job_running(term_T *term)
                || term->tl_job->jv_channel->ch_keep_open);
 }
 
+/*
+ * Return TRUE if "term" has an active channel and used ":term NONE".
+ */
+    int
+term_none_open(term_T *term)
+{
+    /* Also consider the job finished when the channel is closed, to avoid a
+     * race condition when updating the title. */
+    return term != NULL
+       && term->tl_job != NULL
+       && channel_is_open(term->tl_job->jv_channel)
+       && term->tl_job->jv_channel->ch_keep_open;
+}
+
 /*
  * Add the last line of the scrollback buffer to the buffer in the window.
  */
@@ -2379,6 +2401,8 @@ term_get_status_text(term_T *term)
        }
        else if (term->tl_title != NULL)
            txt = term->tl_title;
+       else if (term_none_open(term))
+           txt = (char_u *)_("active");
        else if (term_job_running(term))
            txt = (char_u *)_("running");
        else
@@ -2858,11 +2882,13 @@ f_term_sendkeys(typval_T *argvars, typval_T *rettv)
 f_term_start(typval_T *argvars, typval_T *rettv)
 {
     jobopt_T   opt;
+    buf_T      *buf;
 
     init_job_options(&opt);
     if (argvars[1].v_type != VAR_UNKNOWN
            && get_job_options(&argvars[1], &opt,
                JO_TIMEOUT_ALL + JO_STOPONEXIT
+                   + JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK
                    + JO_EXIT_CB + JO_CLOSE_CALLBACK + JO_OUT_IO,
                JO2_TERM_NAME + JO2_TERM_FINISH + JO2_HIDDEN + JO2_TERM_OPENCMD
                    + JO2_TERM_COLS + JO2_TERM_ROWS + JO2_VERTICAL + JO2_CURWIN
@@ -2871,10 +2897,10 @@ f_term_start(typval_T *argvars, typval_T *rettv)
 
     if (opt.jo_vertical)
        cmdmod.split = WSP_VERT;
-    term_start(&argvars[0], &opt, FALSE);
+    buf = term_start(&argvars[0], &opt, FALSE);
 
-    if (curbuf->b_term != NULL)
-       rettv->vval.v_number = curbuf->b_fnum;
+    if (buf != NULL && buf->b_term != NULL)
+       rettv->vval.v_number = buf->b_fnum;
 }
 
 /*
@@ -3359,8 +3385,6 @@ term_and_job_init(
     static int
 create_pty_only(term_T *term, jobopt_T *opt)
 {
-    int ret;
-
     create_vterm(term, term->tl_rows, term->tl_cols);
 
     term->tl_job = job_alloc();
@@ -3371,9 +3395,7 @@ create_pty_only(term_T *term, jobopt_T *opt)
     /* behave like the job is already finished */
     term->tl_job->jv_status = JOB_FINISHED;
 
-    ret = mch_create_pty_channel(term->tl_job, opt);
-
-    return ret;
+    return mch_create_pty_channel(term->tl_job, opt);
 }
 
 /*
index f8a10e3f943b6ceb75f65fec7c507d4565076f1c..ad59f5e630c5baf7f178f7d90d8471ddcacd2509 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1076,
 /**/
     1075,
 /**/