# HG changeset patch # User Christian Brabandt # Date 1501273805 -7200 # Node ID f080b225a2a4466343232f0bd130d06e108524d9 # Parent e66872ac3815d205edffc5d28e8a7c7f1d5a7586 patch 8.0.0798: no highlighting in a terminal window with a finished job commit https://github.com/vim/vim/commit/63ecddab6d918214371ccaaeb10c118ae7c39d02 Author: Bram Moolenaar Date: Fri Jul 28 22:29:35 2017 +0200 patch 8.0.0798: no highlighting in a terminal window with a finished job Problem: No highlighting in a terminal window with a finished job. Solution: Highlight the text. diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -5,6 +5,9 @@ void write_to_term(buf_T *buffer, char_u int terminal_loop(void); void term_channel_closed(channel_T *ch); int term_update_window(win_T *wp); +int term_is_finished(buf_T *buf); +void term_change_in_curbuf(void); +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); /* vim: set ft=c : */ diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -3130,6 +3130,9 @@ win_line( #if defined(LINE_ATTR) int did_line_attr = 0; #endif +#ifdef FEAT_TERMINAL + int get_term_attr = FALSE; +#endif /* draw_state: items that are drawn in sequence: */ #define WL_START 0 /* nothing done yet */ @@ -3241,6 +3244,14 @@ win_line( draw_color_col = advance_color_col(VCOL_HLC, &color_cols); #endif +#ifdef FEAT_TERMINAL + if (term_is_finished(wp->w_buffer)) + { + extra_check = TRUE; + get_term_attr = TRUE; + } +#endif + #ifdef FEAT_SPELL if (wp->w_p_spell && *wp->w_s->b_p_spl != NUL @@ -4527,6 +4538,18 @@ win_line( int can_spell = TRUE; #endif +#ifdef FEAT_TERMINAL + if (get_term_attr) + { + syntax_attr = term_get_attr(wp->w_buffer, lnum, col); + + if (!attr_pri) + char_attr = syntax_attr; + else + char_attr = hl_combine_attr(syntax_attr, char_attr); + } +#endif + #ifdef FEAT_SYN_HL /* Get syntax attribute, unless still at the start of the line * (double-wide char that doesn't fit). */ diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -19,7 +19,7 @@ * Uses pseudo-tty's (pty's). * * For each terminal one VTerm is constructed. This uses libvterm. A copy of - * that library is in the libvterm directory. + * this library is in the libvterm directory. * * When a terminal window is opened, a job is started that will be connected to * the terminal emulator. @@ -32,16 +32,17 @@ * line range is stored in tl_dirty_row_start and tl_dirty_row_end. Once in a * while, if the terminal window is visible, the screen contents is drawn. * + * When the job ends the text is put in a buffer. Redrawing then happens from + * that buffer, attributes come from the scrollback buffer tl_scrollback. + * * TODO: + * - Patch for functions: Yasuhiro Matsumoto, #1871 * - For the scrollback buffer store lines in the buffer, only attributes in * tl_scrollback. * - When the job ends: - * - Display the scrollback buffer (but with attributes). - * Make the buffer not modifiable, drop attributes when making changes. * - Need an option or argument to drop the window+buffer right away, to be * used for a shell or Vim. * - To set BS correctly, check get_stty(); Pass the fd of the pty. - * - Patch for functions: Yasuhiro Matsumoto, #1871 * - do not store terminal buffer in viminfo. Or prefix term:// ? * - add a character in :ls output * - when closing window and job has not ended, make terminal hidden? @@ -254,6 +255,19 @@ ex_terminal(exarg_T *eap) } /* + * Free the scrollback buffer for "term". + */ + static void +free_scrollback(term_T *term) +{ + int i; + + for (i = 0; i < term->tl_scrollback.ga_len; ++i) + vim_free(((sb_line_T *)term->tl_scrollback.ga_data + i)->sb_cells); + ga_clear(&term->tl_scrollback); +} + +/* * Free a terminal and everything it refers to. * Kills the job if there is one. * Called when wiping out a buffer. @@ -263,7 +277,6 @@ free_terminal(buf_T *buf) { term_T *term = buf->b_term; term_T *tp; - int i; if (term == NULL) return; @@ -285,9 +298,7 @@ free_terminal(buf_T *buf) job_unref(term->tl_job); } - for (i = 0; i < term->tl_scrollback.ga_len; ++i) - vim_free(((sb_line_T *)term->tl_scrollback.ga_data + i) ->sb_cells); - ga_clear(&term->tl_scrollback); + free_scrollback(term); term_free_vterm(term); vim_free(term->tl_title); @@ -1218,6 +1229,48 @@ term_update_window(win_T *wp) } /* + * Return TRUE if "wp" is a terminal window where the job has finished. + */ + int +term_is_finished(buf_T *buf) +{ + return buf->b_term != NULL && buf->b_term->tl_vterm == NULL; +} + +/* + * The current buffer is going to be changed. If there is terminal + * highlighting remove it now. + */ + void +term_change_in_curbuf(void) +{ + term_T *term = curbuf->b_term; + + if (term_is_finished(curbuf) && term->tl_scrollback.ga_len > 0) + { + free_scrollback(term); + redraw_buf_later(term->tl_buffer, NOT_VALID); + } +} + +/* + * Get the screen attribute for a position in the buffer. + */ + int +term_get_attr(buf_T *buf, linenr_T lnum, int col) +{ + term_T *term = buf->b_term; + sb_line_T *line; + + if (lnum >= term->tl_scrollback.ga_len) + return 0; + line = (sb_line_T *)term->tl_scrollback.ga_data + lnum - 1; + if (col >= line->sb_cols) + return 0; + return cell2attr(line->sb_cells + col); +} + +/* * Set job options common for Unix and MS-Windows. */ static void diff --git a/src/undo.c b/src/undo.c --- a/src/undo.c +++ b/src/undo.c @@ -419,6 +419,10 @@ u_savecommon( } } #endif +#ifdef FEAT_TERMINAL + /* A change in a terminal buffer removes the highlighting. */ + term_change_in_curbuf(); +#endif #ifdef FEAT_AUTOCMD /* diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 798, +/**/ 797, /**/ 796,