1
0
forked from aniani/vim

patch 8.0.1810: buffer of a terminal only updated in Terminal-Normal mode

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.
This commit is contained in:
Bram Moolenaar
2018-05-10 18:05:56 +02:00
parent b946482190
commit 56bc8e299c
5 changed files with 115 additions and 20 deletions

View File

@@ -1206,7 +1206,7 @@ profile_zero(proftime_T *tm)
static timer_T *first_timer = NULL; static timer_T *first_timer = NULL;
static long last_timer_id = 0; static long last_timer_id = 0;
static long long
proftime_time_left(proftime_T *due, proftime_T *now) proftime_time_left(proftime_T *due, proftime_T *now)
{ {
# ifdef WIN3264 # ifdef WIN3264
@@ -1424,6 +1424,10 @@ check_due_timer(void)
next_due = this_due; next_due = this_due;
} }
#endif #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; return current_id != last_timer_id ? 1 : next_due;
} }

View File

@@ -19,6 +19,7 @@ float_T profile_float(proftime_T *tm);
void profile_setlimit(long msec, proftime_T *tm); void profile_setlimit(long msec, proftime_T *tm);
int profile_passed_limit(proftime_T *tm); int profile_passed_limit(proftime_T *tm);
void profile_zero(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); timer_T *create_timer(long msec, int repeat);
long check_due_timer(void); long check_due_timer(void);
timer_T *find_timer(long id); timer_T *find_timer(long id);

View 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_job_running(term_T *term);
int term_none_open(term_T *term); int term_none_open(term_T *term);
int term_try_stop_job(buf_T *buf); 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); int term_in_normal_mode(void);
void term_enter_job_mode(void); void term_enter_job_mode(void);
int send_keys_to_term(term_T *term, int c, int typed); int send_keys_to_term(term_T *term, int c, int typed);

View File

@@ -43,8 +43,6 @@
* - Win32: Redirecting output works but includes escape sequences. * - Win32: Redirecting output works but includes escape sequences.
* - Win32: Make terminal used for :!cmd in the GUI work better. Allow for * - Win32: Make terminal used for :!cmd in the GUI work better. Allow for
* redirection. * 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 * - When the job only outputs lines, we could handle resizing the terminal
* better: store lines separated by line breaks, instead of screen lines, * better: store lines separated by line breaks, instead of screen lines,
* then when the window is resized redraw those 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. */ /* Range of screen rows to update. Zero based. */
int tl_dirty_row_start; /* MAX_ROW if nothing dirty */ int tl_dirty_row_start; /* MAX_ROW if nothing dirty */
int tl_dirty_row_end; /* row below last one to update */ 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 */ int tl_postponed_scroll; /* to be scrolled up */
garray_T tl_scrollback; garray_T tl_scrollback;
@@ -1441,6 +1443,29 @@ add_empty_scrollback(term_T *term, cellattr_T *fill_attr, int lnum)
return FALSE; 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. * 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. * 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) if (term->tl_vterm == NULL)
return; 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); screen = vterm_obtain_screen(term->tl_vterm);
fill_attr = new_fill_attr = term->tl_default_color; fill_attr = new_fill_attr = term->tl_default_color;
for (pos.row = 0; pos.row < term->tl_rows; ++pos.row) for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
{ {
len = 0; 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. */ /* Obtain the current background color. */
vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm), vterm_state_get_default_colors(vterm_obtain_state(term->tl_vterm),
&term->tl_default_color.fg, &term->tl_default_color.bg); &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 static void
set_terminal_mode(term_T *term, int normal_mode) set_terminal_mode(term_T *term, int normal_mode)
{ {
@@ -1638,20 +1713,6 @@ term_in_normal_mode(void)
term_enter_job_mode() term_enter_job_mode()
{ {
term_T *term = curbuf->b_term; 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); set_terminal_mode(term, FALSE);
@@ -2174,6 +2235,12 @@ theend:
in_terminal_loop = NULL; in_terminal_loop = NULL;
if (restore_cursor) if (restore_cursor)
prepare_restore_cursor_props(); 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; return ret;
} }
@@ -2390,6 +2457,20 @@ cell2attr(VTermScreenCellAttrs cellattrs, VTermColor cellfg, VTermColor cellbg)
return 0; 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 static int
handle_damage(VTermRect rect, void *user) 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_start = MIN(term->tl_dirty_row_start, rect.start_row);
term->tl_dirty_row_end = MAX(term->tl_dirty_row_end, rect.end_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); redraw_buf_later(term->tl_buffer, SOME_VALID);
return 1; 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_start = MIN(term->tl_dirty_row_start, dest.start_row);
term->tl_dirty_row_end = MIN(term->tl_dirty_row_end, dest.end_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 /* Note sure if the scrolling will work correctly, let's do a complete
* redraw later. */ * redraw later. */
@@ -2594,6 +2677,10 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
{ {
term_T *term = (term_T *)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 /* If the number of lines that are stored goes over 'termscrollback' then
* delete the first 10%. */ * delete the first 10%. */
if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl) if (term->tl_scrollback.ga_len >= term->tl_buffer->b_p_twsl)

View File

@@ -761,6 +761,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1810,
/**/ /**/
1809, 1809,
/**/ /**/