]> granicus.if.org Git - vim/commitdiff
patch 8.0.1810: buffer of a terminal only updated in Terminal-Normal mode v8.0.1810
authorBram Moolenaar <Bram@vim.org>
Thu, 10 May 2018 16:05:56 +0000 (18:05 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 10 May 2018 16:05:56 +0000 (18:05 +0200)
Problem:    Buffer of a terminal only updated in Terminal-Normal mode.
Solution:   Copy the terminal window content to the buffer when in
            Terminal-Job mode.

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

index 7fa4907bdaf3f0fba8f51e34fc3e3317af0f681e..d27d0cdf593ddbcb25a411ccd12c36e8d7c65f06 100644 (file)
@@ -1206,7 +1206,7 @@ profile_zero(proftime_T *tm)
 static timer_T *first_timer = NULL;
 static long    last_timer_id = 0;
 
-    static long
+    long
 proftime_time_left(proftime_T *due, proftime_T *now)
 {
 #  ifdef WIN3264
@@ -1424,6 +1424,10 @@ check_due_timer(void)
            next_due = this_due;
     }
 #endif
+#ifdef FEAT_TERMINAL
+    /* Some terminal windows may need their buffer updated. */
+    next_due = term_check_timers(next_due, &now);
+#endif
 
     return current_id != last_timer_id ? 1 : next_due;
 }
index a7d19d768fec7821115aadf33162e8dbac43257f..ac9b291e5c7bfb8186c99a0eff37b2c42e1fb2ff 100644 (file)
@@ -1,5 +1,5 @@
 /* ex_cmds2.c */
-int has_watchexpr (void);
+int has_watchexpr(void);
 void do_debug(char_u *cmd);
 void ex_debug(exarg_T *eap);
 void dbg_check_breakpoint(exarg_T *eap);
@@ -19,6 +19,7 @@ float_T profile_float(proftime_T *tm);
 void profile_setlimit(long msec, proftime_T *tm);
 int profile_passed_limit(proftime_T *tm);
 void profile_zero(proftime_T *tm);
+long proftime_time_left(proftime_T *due, proftime_T *now);
 timer_T *create_timer(long msec, int repeat);
 long check_due_timer(void);
 timer_T *find_timer(long id);
index f97f025d58e7294cf483c6963700a05df6dd721f..93c6ab53c6cad7645f38d831488c17fd7361cafe 100644 (file)
@@ -9,6 +9,7 @@ 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_try_stop_job(buf_T *buf);
+int term_check_timers(int next_due_arg, proftime_T *now);
 int term_in_normal_mode(void);
 void term_enter_job_mode(void);
 int send_keys_to_term(term_T *term, int c, int typed);
index 0c483e140c17a5a5d97b05fdf3c93d1a455fc2c3..6e5b1002c2366f690a570cca8d78ba9ac3ee9113 100644 (file)
@@ -43,8 +43,6 @@
  * - Win32: Redirecting output works but includes escape sequences.
  * - Win32: Make terminal used for :!cmd in the GUI work better.  Allow for
  *   redirection.
- * - Copy text in the vterm to the Vim buffer once in a while, so that
- *   completion works.
  * - When the job only outputs lines, we could handle resizing the terminal
  *   better: store lines separated by line breaks, instead of screen lines,
  *   then when the window is resized redraw those lines.
@@ -131,7 +129,11 @@ struct terminal_S {
     /* Range of screen rows to update.  Zero based. */
     int                tl_dirty_row_start; /* MAX_ROW if nothing dirty */
     int                tl_dirty_row_end;   /* row below last one to update */
-
+    int                tl_dirty_snapshot;  /* text updated after making snapshot */
+#ifdef FEAT_TIMERS
+    int                tl_timer_set;
+    proftime_T tl_timer_due;
+#endif
     int                tl_postponed_scroll;    /* to be scrolled up */
 
     garray_T   tl_scrollback;
@@ -1441,6 +1443,29 @@ add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum)
     return FALSE;
 }
 
+/*
+ * Remove the terminal contents from the scrollback and the buffer.
+ * Used before adding a new scrollback line or updating the buffer for lines
+ * displayed in the terminal.
+ */
+    static void
+cleanup_scrollback(term_T *term)
+{
+    sb_line_T  *line;
+    garray_T   *gap;
+
+    gap = &term->tl_scrollback;
+    while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled
+                                                           && gap->ga_len > 0)
+    {
+       ml_delete(curbuf->b_ml.ml_line_count, FALSE);
+       line = (sb_line_T *)gap->ga_data + gap->ga_len - 1;
+       vim_free(line->sb_cells);
+       --gap->ga_len;
+    }
+    check_cursor();
+}
+
 /*
  * Add the current lines of the terminal to scrollback and to the buffer.
  * Called after the job has ended and when switching to Terminal-Normal mode.
@@ -1459,9 +1484,22 @@ move_terminal_to_buffer(term_T *term)
 
     if (term->tl_vterm == NULL)
        return;
+
+    /* Nothing to do if the buffer already has the lines and nothing was
+     * changed. */
+    if (!term->tl_dirty_snapshot
+                 && curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled)
+       return;
+
+    ch_log(term->tl_job == NULL ? NULL : term->tl_job->jv_channel,
+                                 "Adding terminal window snapshot to buffer");
+
+    /* First remove the lines that were appended before, they might be
+     * outdated. */
+    cleanup_scrollback(term);
+
     screen = vterm_obtain_screen(term->tl_vterm);
     fill_attr = new_fill_attr = term->tl_default_color;
-
     for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
     {
        len = 0;
@@ -1548,6 +1586,11 @@ move_terminal_to_buffer(term_T *term)
        }
     }
 
+    term->tl_dirty_snapshot = FALSE;
+#ifdef FEAT_TIMERS
+    term->tl_timer_set = FALSE;
+#endif
+
     /* Obtain the current background color. */
     vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
                       &term->tl_default_color.fg, &term->tl_default_color.bg);
@@ -1571,6 +1614,38 @@ move_terminal_to_buffer(term_T *term)
     }
 }
 
+#if defined(FEAT_TIMERS) || defined(PROTO)
+/*
+ * Check if any terminal timer expired.  If so, copy text from the terminal to
+ * the buffer.
+ * Return the time until the next timer will expire.
+ */
+    int
+term_check_timers(int next_due_arg, proftime_T *now)
+{
+    term_T  *term;
+    int            next_due = next_due_arg;
+
+    for (term = first_term; term != NULL; term = term->tl_next)
+    {
+       if (term->tl_timer_set && !term->tl_normal_mode)
+       {
+           long    this_due = proftime_time_left(&term->tl_timer_due, now);
+
+           if (this_due <= 1)
+           {
+               term->tl_timer_set = FALSE;
+               move_terminal_to_buffer(term);
+           }
+           else if (next_due == -1 || next_due > this_due)
+               next_due = this_due;
+       }
+    }
+
+    return next_due;
+}
+#endif
+
     static void
 set_terminal_mode(term_T *term, int normal_mode)
 {
@@ -1638,20 +1713,6 @@ term_in_normal_mode(void)
 term_enter_job_mode()
 {
     term_T     *term = curbuf->b_term;
-    sb_line_T  *line;
-    garray_T   *gap;
-
-    /* Remove the terminal contents from the scrollback and the buffer. */
-    gap = &term->tl_scrollback;
-    while (curbuf->b_ml.ml_line_count > term->tl_scrollback_scrolled
-                                                           && gap->ga_len > 0)
-    {
-       ml_delete(curbuf->b_ml.ml_line_count, FALSE);
-       line = (sb_line_T *)gap->ga_data + gap->ga_len - 1;
-       vim_free(line->sb_cells);
-       --gap->ga_len;
-    }
-    check_cursor();
 
     set_terminal_mode(term, FALSE);
 
@@ -2174,6 +2235,12 @@ theend:
     in_terminal_loop = NULL;
     if (restore_cursor)
        prepare_restore_cursor_props();
+
+    /* Move a snapshot of the screen contents to the buffer, so that completion
+     * works in other buffers. */
+    if (curbuf->b_term != NULL)
+       move_terminal_to_buffer(curbuf->b_term);
+
     return ret;
 }
 
@@ -2390,6 +2457,20 @@ cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg)
     return 0;
 }
 
+    static void
+set_dirty_snapshot(term_T *term)
+{
+    term->tl_dirty_snapshot = TRUE;
+#ifdef FEAT_TIMERS
+    if (!term->tl_normal_mode)
+    {
+       /* Update the snapshot after 100 msec of not getting updates. */
+       profile_setlimit(100L, &term->tl_timer_due);
+       term->tl_timer_set = TRUE;
+    }
+#endif
+}
+
     static int
 handle_damage(VTermRect rect, void *user)
 {
@@ -2397,6 +2478,7 @@ handle_damage(VTermRect rect, void *user)
 
     term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, rect.start_row);
     term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_row);
+    set_dirty_snapshot(term);
     redraw_buf_later(term->tl_buffer, SOME_VALID);
     return 1;
 }
@@ -2443,6 +2525,7 @@ handle_moverect(VTermRect dest, VTermRect src, void *user)
 
     term->tl_dirty_row_start = MIN(term->tl_dirty_row_start, dest.start_row);
     term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_row);
+    set_dirty_snapshot(term);
 
     /* Note sure if the scrolling will work correctly, let's do a complete
      * redraw later. */
@@ -2594,6 +2677,10 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
 {
     term_T     *term = (term_T *)user;
 
+    /* First remove the lines that were appended before, the pushed line goes
+     * above it. */
+    cleanup_scrollback(term);
+
     /* If the number of lines that are stored goes over 'termscrollback' then
      * delete the first 10%. */
     if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl)
index b71b384f1b971d83353414c44672022452b9bc72..59b25bf921f5637dc5d8bf01fc8ed2884a321616 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1810,
 /**/
     1809,
 /**/