To: vim_dev@googlegroups.com Subject: Patch 8.0.1810 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1810 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. Files: src/terminal.c, src/proto/terminal.pro, src/ex_cmds2.c, src/proto/ex_cmds2.pro *** ../vim-8.0.1809/src/terminal.c 2018-05-07 20:10:08.375909886 +0200 --- src/terminal.c 2018-05-10 18:05:19.925323334 +0200 *************** *** 43,50 **** * - 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. --- 43,48 ---- *************** *** 131,137 **** /* 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_postponed_scroll; /* to be scrolled up */ garray_T tl_scrollback; --- 129,139 ---- /* 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; *************** *** 1442,1447 **** --- 1444,1472 ---- } /* + * 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,1467 **** if (term->tl_vterm == NULL) return; 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; --- 1484,1505 ---- 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,1553 **** --- 1586,1596 ---- } } + 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,1576 **** --- 1614,1651 ---- } } + #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,1657 **** 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); --- 1713,1718 ---- *************** *** 2174,2179 **** --- 2235,2246 ---- 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,2395 **** --- 2457,2476 ---- 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,2402 **** --- 2478,2484 ---- 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,2448 **** --- 2525,2531 ---- 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,2599 **** --- 2677,2686 ---- { 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) *** ../vim-8.0.1809/src/proto/terminal.pro 2018-05-06 16:40:12.239619606 +0200 --- src/proto/terminal.pro 2018-05-10 17:41:50.027043157 +0200 *************** *** 9,14 **** --- 9,15 ---- 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); *** ../vim-8.0.1809/src/ex_cmds2.c 2018-04-29 12:22:49.163522596 +0200 --- src/ex_cmds2.c 2018-05-10 17:43:02.902550999 +0200 *************** *** 1206,1212 **** static timer_T *first_timer = NULL; static long last_timer_id = 0; ! static long proftime_time_left(proftime_T *due, proftime_T *now) { # ifdef WIN3264 --- 1206,1212 ---- static timer_T *first_timer = NULL; static long last_timer_id = 0; ! long proftime_time_left(proftime_T *due, proftime_T *now) { # ifdef WIN3264 *************** *** 1424,1429 **** --- 1424,1433 ---- 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; } *** ../vim-8.0.1809/src/proto/ex_cmds2.pro 2018-03-29 15:55:30.874510195 +0200 --- src/proto/ex_cmds2.pro 2018-05-10 17:43:32.950348530 +0200 *************** *** 1,5 **** /* ex_cmds2.c */ ! int has_watchexpr (void); void do_debug(char_u *cmd); void ex_debug(exarg_T *eap); void dbg_check_breakpoint(exarg_T *eap); --- 1,5 ---- /* ex_cmds2.c */ ! int has_watchexpr(void); void do_debug(char_u *cmd); void ex_debug(exarg_T *eap); void dbg_check_breakpoint(exarg_T *eap); *************** *** 19,24 **** --- 19,25 ---- 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); *** ../vim-8.0.1809/src/version.c 2018-05-10 15:09:45.893646659 +0200 --- src/version.c 2018-05-10 18:01:04.163352696 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 1810, /**/ -- When I look deep into your eyes, I see JPEG artifacts. I can tell by the pixels that we're wrong for each other. (xkcd) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///