summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-07-30 16:52:24 +0200
committerBram Moolenaar <Bram@vim.org>2017-07-30 16:52:24 +0200
commit423802d1a282df35078539970eabf559186e1ec8 (patch)
tree0a252bea57b2e78f9407066ebe3ca0a0a093cbc1
parent68c4bdd53cb54b6c0dccb2dcee446ef42ef3dedd (diff)
patch 8.0.0813: cannot use a terminal window while the job is runningv8.0.0813
Problem: Cannot use Vim commands in a terminal window while the job is running. Solution: Implement Terminal Normal mode.
-rw-r--r--runtime/doc/terminal.txt46
-rw-r--r--src/main.c14
-rw-r--r--src/normal.c8
-rw-r--r--src/option.c12
-rw-r--r--src/proto/terminal.pro6
-rw-r--r--src/screen.c2
-rw-r--r--src/terminal.c398
-rw-r--r--src/version.c2
8 files changed, 351 insertions, 137 deletions
diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt
index 89689463ac..1054037838 100644
--- a/runtime/doc/terminal.txt
+++ b/runtime/doc/terminal.txt
@@ -1,4 +1,4 @@
-*terminal.txt* For Vim version 8.0. Last change: 2017 Jul 28
+*terminal.txt* For Vim version 8.0. Last change: 2017 Jul 30
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -33,24 +33,39 @@ Or to run a debugger: >
The job runs asynchronously from Vim, the window will be updated to show
output from the job, also while editing in any other window.
+
Typing ~
When the keyboard focus is in the terminal window, typed keys will be send to
the job. This uses a pty when possible. You can click outside of the
terminal window to move keyboard focus elsewhere.
-Navigate between windows with CTRL-W commands. E.g. CTRL-W CTRL-W moves focus
-to the next window. Use "CTRL-W :" to edit an Ex command. Use "CTRL-W ." to
-send a CTRL-W to the job in the terminal.
+CTRL-W can be used to navigate between windows and other CTRL-W commands, e.g.:
+ CTRL-W CTRL-W move focus to the next window
+ CTRL-W : enter an Ex command
+See |CTRL-W| for more commands.
+
+Special in the terminal window: *CTRL-W_.* *CTRL-W_N*
+ CTRL-W . send a CTRL-W to the job in the terminal
+ CTRL-W N go to Terminal Normal mode, see |Terminal-mode|
+
+See option 'termkey' for specifying another key instead of CTRL-W that
+will work like CTRL-W. However, typing 'termkey' twice sends 'termkey' to
+the job. For example:
+ 'termkey' CTRL-W move focus to the next window
+ 'termkey' : enter an Ex command
+ 'termkey' 'termkey' send 'termkey' to the job in the terminal
+ 'termkey' . send a CTRL-W to the job in the terminal
+ 'termkey' N go to terminal Normal mode, see below
+ 'termkey' CTRL-N same as CTRL-W N
-See option 'termkey' for specifying another key that precedes a Vim command.
-Typing 'termkey' twice sends 'termkey' to the job.
Size ~
See option 'termsize' for controlling the size of the terminal window.
(TODO: scrolling when the terminal is larger than the window)
+
Syntax ~
:ter[minal] [command] *:ter* *:terminal*
@@ -99,6 +114,25 @@ terminal. |term_setsize()| can be used only when in the first or second mode,
not when 'termsize' is "rowsXcols".
+Terminal Normal mode ~
+ *Terminal-mode*
+When the job is running the contents of the terminal is under control of the
+job. That includes the cursor position. The terminal contents can change at
+any time.
+
+Use CTRL-W N (or 'termkey' N) to go to Terminal Normal mode. Now the contents
+of the terminal window is under control of Vim, the job output is suspended.
+ *E946*
+In this mode you can move the cursor around with the usual Vim commands,
+Visually mark text, yank text, etc. But you cannot change the contents of the
+buffer. The commands that would start insert mode, such as 'i' and 'a',
+return control of the window to the job. Any pending output will now be
+displayed.
+
+In Terminal mode the statusline and window title show "(Terminal)". If the
+job ends while in Terminal mode this changes to "(Terminal-finished)".
+
+
Unix ~
On Unix a pty is used to make it possible to run all kinds of commands. You
diff --git a/src/main.c b/src/main.c
index 268c256270..81eb1a6799 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1356,11 +1356,17 @@ main_loop(
else
{
#ifdef FEAT_TERMINAL
- if (curbuf->b_term != NULL && oa.op_type == OP_NOP
- && oa.regname == NUL)
- terminal_loop();
+ if (term_use_loop() && oa.op_type == OP_NOP && oa.regname == NUL)
+ {
+ /* If terminal_loop() returns OK we got a key that is handled
+ * in Normal model. With FAIL the terminal was closed and the
+ * screen needs to be redrawn. */
+ if (terminal_loop() == OK)
+ normal_cmd(&oa, TRUE);
+ }
+ else
#endif
- normal_cmd(&oa, TRUE);
+ normal_cmd(&oa, TRUE);
}
}
}
diff --git a/src/normal.c b/src/normal.c
index c8e78410d9..e8f80f181b 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -9037,6 +9037,14 @@ nv_esc(cmdarg_T *cap)
static void
nv_edit(cmdarg_T *cap)
{
+#ifdef FEAT_TERMINAL
+ if (term_in_terminal_mode())
+ {
+ term_leave_terminal_mode();
+ return;
+ }
+#endif
+
/* <Insert> is equal to "i" */
if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS)
cap->cmdchar = 'i';
diff --git a/src/option.c b/src/option.c
index ad5892581d..6e4d1a5df6 100644
--- a/src/option.c
+++ b/src/option.c
@@ -8222,12 +8222,22 @@ set_bool_option(
}
#endif
-#ifdef FEAT_TITLE
/* when 'modifiable' is changed, redraw the window title */
else if ((int *)varp == &curbuf->b_p_ma)
{
+# ifdef FEAT_TERMINAL
+ /* Cannot set 'modifiable' when in Terminal mode. */
+ if (term_in_terminal_mode())
+ {
+ curbuf->b_p_ma = FALSE;
+ return (char_u *)N_("E946: Cannot make a terminal with running job modifiable");
+ }
+# endif
+# ifdef FEAT_TITLE
redraw_titles();
+# endif
}
+#ifdef FEAT_TITLE
/* when 'endofline' is changed, redraw the window title */
else if ((int *)varp == &curbuf->b_p_eol)
{
diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro
index daa7706485..6f5b3ab707 100644
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -2,11 +2,15 @@
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_in_terminal_mode(void);
+void term_leave_terminal_mode(void);
+int term_use_loop(void);
int terminal_loop(void);
void term_job_ended(job_T *job);
void term_channel_closed(channel_T *ch);
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);
int term_get_attr(buf_T *buf, linenr_T lnum, int col);
char_u *term_get_status_text(term_T *term);
@@ -16,8 +20,8 @@ void f_term_getjob(typval_T *argvars, typval_T *rettv);
void f_term_getline(typval_T *argvars, typval_T *rettv);
void f_term_getsize(typval_T *argvars, typval_T *rettv);
void f_term_list(typval_T *argvars, typval_T *rettv);
-void f_term_start(typval_T *argvars, typval_T *rettv);
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);
/* vim: set ft=c : */
diff --git a/src/screen.c b/src/screen.c
index a1e8b5fa05..baedea755b 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3245,7 +3245,7 @@ win_line(
#endif
#ifdef FEAT_TERMINAL
- if (term_is_finished(wp->w_buffer))
+ if (term_show_buffer(wp->w_buffer))
{
extra_check = TRUE;
get_term_attr = TRUE;
diff --git a/src/terminal.c b/src/terminal.c
index 1863b59861..b0ba8c1902 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -36,13 +36,23 @@
* that buffer, attributes come from the scrollback buffer tl_scrollback.
*
* TODO:
+ * - Problem with statusline (Zyx, Christian)
+ * - Make CTRL-W "" paste register content to the job?
+ * - in bash mouse clicks are inserting characters.
+ * - mouse scroll: when over other window, scroll that window.
* - For the scrollback buffer store lines in the buffer, only attributes in
* tl_scrollback.
+ * - Add term_status(): "" if not a terminal, "running" if job running,
+ * "finished" if finished, "running,vim" when job is running and in
+ * Terminal mode, "running,vim,pending" when job output is pending.
* - When the job ends:
* - Need an option or argument to drop the window+buffer right away, to be
- * used for a shell or Vim.
+ * used for a shell or Vim. 'termfinish'; "close", "open" (open window when
+ * job finishes).
+ * - add option values to the command:
+ * :term <24x80> <close> vim notes.txt
* - To set BS correctly, check get_stty(); Pass the fd of the pty.
- * - do not store terminal buffer in viminfo. Or prefix term:// ?
+ * - do not store terminal window in viminfo. Or prefix term:// ?
* - add a character in :ls output
* - when closing window and job has not ended, make terminal hidden?
* - when closing window and job has ended, make buffer hidden?
@@ -53,6 +63,8 @@
* - support minimal size when 'termsize' is empty?
* - implement "term" for job_start(): more job options when starting a
* terminal.
+ * - if the job in the terminal does not support the mouse, we can use the
+ * mouse in the Terminal window for copy/paste.
* - when 'encoding' is not utf-8, or the job is using another encoding, setup
* conversions.
* - In the GUI use a terminal emulator for :!cmd.
@@ -78,13 +90,17 @@ typedef struct sb_line_S {
struct terminal_S {
term_T *tl_next;
+ VTerm *tl_vterm;
+ job_T *tl_job;
+ buf_T *tl_buffer;
+
+ int tl_terminal_mode;
+ int tl_channel_closed;
+
#ifdef WIN3264
void *tl_winpty_config;
void *tl_winpty;
#endif
- VTerm *tl_vterm;
- job_T *tl_job;
- buf_T *tl_buffer;
/* last known vterm size */
int tl_rows;
@@ -553,6 +569,205 @@ term_job_running(term_T *term)
}
/*
+ * Add the last line of the scrollback buffer to the buffer in the window.
+ */
+ static void
+add_scrollback_line_to_buffer(term_T *term)
+{
+ linenr_T lnum = term->tl_scrollback.ga_len - 1;
+ sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data + lnum;
+ garray_T ga;
+ int c;
+ int col;
+ int i;
+
+ ga_init2(&ga, 1, 100);
+ for (col = 0; col < line->sb_cols; col += line->sb_cells[col].width)
+ {
+ if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
+ goto failed;
+ for (i = 0; (c = line->sb_cells[col].chars[i]) > 0 || i == 0; ++i)
+ ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
+ (char_u *)ga.ga_data + ga.ga_len);
+ }
+ if (ga_grow(&ga, 1) == FAIL)
+ goto failed;
+ *((char_u *)ga.ga_data + ga.ga_len) = NUL;
+ ml_append_buf(term->tl_buffer, lnum, ga.ga_data, ga.ga_len + 1, FALSE);
+
+ if (lnum == 0)
+ {
+ /* Delete the empty line that was in the empty buffer. */
+ curbuf = term->tl_buffer;
+ ml_delete(2, FALSE);
+ curbuf = curwin->w_buffer;
+ }
+
+failed:
+ ga_clear(&ga);
+}
+
+/*
+ * Add the current lines of the terminal to scrollback and to the buffer.
+ * Called after the job has ended and when switching to Terminal mode.
+ */
+ static void
+move_terminal_to_buffer(term_T *term)
+{
+ win_T *wp;
+ int len;
+ int lines_skipped = 0;
+ VTermPos pos;
+ VTermScreenCell cell;
+ VTermScreenCell *p;
+ VTermScreen *screen = vterm_obtain_screen(term->tl_vterm);
+
+ for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
+ {
+ len = 0;
+ for (pos.col = 0; pos.col < term->tl_cols; ++pos.col)
+ if (vterm_screen_get_cell(screen, pos, &cell) != 0
+ && cell.chars[0] != NUL)
+ len = pos.col + 1;
+
+ if (len == 0)
+ ++lines_skipped;
+ else
+ {
+ while (lines_skipped > 0)
+ {
+ /* Line was skipped, add an empty line. */
+ --lines_skipped;
+ if (ga_grow(&term->tl_scrollback, 1) == OK)
+ {
+ sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
+ + term->tl_scrollback.ga_len;
+
+ line->sb_cols = 0;
+ line->sb_cells = NULL;
+ ++term->tl_scrollback.ga_len;
+
+ add_scrollback_line_to_buffer(term);
+ }
+ }
+
+ p = (VTermScreenCell *)alloc((int)sizeof(VTermScreenCell) * len);
+ if (p != NULL && ga_grow(&term->tl_scrollback, 1) == OK)
+ {
+ sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
+ + term->tl_scrollback.ga_len;
+
+ for (pos.col = 0; pos.col < len; ++pos.col)
+ {
+ if (vterm_screen_get_cell(screen, pos, &cell) == 0)
+ vim_memset(p + pos.col, 0, sizeof(cell));
+ else
+ p[pos.col] = cell;
+ }
+ line->sb_cols = len;
+ line->sb_cells = p;
+ ++term->tl_scrollback.ga_len;
+
+ add_scrollback_line_to_buffer(term);
+ }
+ else
+ vim_free(p);
+ }
+ }
+
+ FOR_ALL_WINDOWS(wp)
+ {
+ if (wp->w_buffer == term->tl_buffer)
+ {
+ wp->w_cursor.lnum = term->tl_buffer->b_ml.ml_line_count;
+ wp->w_cursor.col = 0;
+ wp->w_valid = 0;
+ redraw_win_later(wp, NOT_VALID);
+ }
+ }
+}
+
+ static void
+set_terminal_mode(term_T *term, int on)
+{
+ term->tl_terminal_mode = on;
+ vim_free(term->tl_status_text);
+ term->tl_status_text = NULL;
+ if (term->tl_buffer == curbuf)
+ maketitle();
+}
+
+/*
+ * Called after the job if finished and Terminal mode is not active:
+ * Move the vterm contents into the scrollback buffer and free the vterm.
+ */
+ static void
+cleanup_vterm(term_T *term)
+{
+ move_terminal_to_buffer(term);
+ term_free_vterm(term);
+ set_terminal_mode(term, FALSE);
+}
+
+/*
+ * Switch from sending keys to the job to Terminal-Normal mode.
+ * Suspends updating the terminal window.
+ */
+ static void
+term_enter_terminal_mode()
+{
+ term_T *term = curbuf->b_term;
+
+ /* Append the current terminal contents to the buffer. */
+ move_terminal_to_buffer(term);
+
+ set_terminal_mode(term, TRUE);
+}
+
+/*
+ * Returns TRUE if the current window contains a terminal and we are in
+ * Terminal-Normal mode.
+ */
+ int
+term_in_terminal_mode()
+{
+ term_T *term = curbuf->b_term;
+
+ return term != NULL && term->tl_terminal_mode;
+}
+
+/*
+ * Switch from Terminal-Normal mode to sending keys to the job.
+ * Restores updating the terminal window.
+ */
+ void
+term_leave_terminal_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)
+ {
+ 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;
+ if (gap->ga_len == 0)
+ break;
+ }
+ check_cursor();
+
+ set_terminal_mode(term, FALSE);
+
+ if (term->tl_channel_closed)
+ cleanup_vterm(term);
+ redraw_buf_and_status_later(curbuf, NOT_VALID);
+}
+
+/*
* Get a key from the user without mapping.
* TODO: use terminal mode mappings.
*/
@@ -641,6 +856,21 @@ send_keys_to_term(term_T *term, int c, int typed)
}
/*
+ * Returns TRUE if the current window contains a terminal and we are sending
+ * keys to the job.
+ */
+ int
+term_use_loop()
+{
+ term_T *term = curbuf->b_term;
+
+ return term != NULL
+ && !term->tl_terminal_mode
+ && term->tl_vterm != NULL
+ && term_job_running(term);
+}
+
+/*
* Wait for input and send it to the job.
* Return when the start of a CTRL-W command is typed or anything else that
* should be handled as a Normal mode command.
@@ -653,10 +883,6 @@ terminal_loop(void)
int c;
int termkey = 0;
- if (curbuf->b_term->tl_vterm == NULL || !term_job_running(curbuf->b_term))
- /* job finished */
- return OK;
-
if (*curwin->w_p_tk != NUL)
termkey = string_to_key(curwin->w_p_tk, TRUE);
@@ -665,6 +891,7 @@ terminal_loop(void)
/* TODO: skip screen update when handling a sequence of keys. */
update_screen(0);
update_cursor(curbuf->b_term, FALSE);
+
c = term_vgetc();
if (curbuf->b_term->tl_vterm == NULL
|| !term_job_running(curbuf->b_term))
@@ -687,8 +914,15 @@ terminal_loop(void)
break;
if (termkey == 0 && c == '.')
+ {
/* "CTRL-W .": send CTRL-W to the job */
c = Ctrl_W;
+ }
+ else if (termkey == 0 && c == 'N')
+ {
+ term_enter_terminal_mode();
+ return FAIL;
+ }
else if (termkey == 0 || c != termkey)
{
stuffcharReadbuff(Ctrl_W);
@@ -704,6 +938,8 @@ terminal_loop(void)
/*
* Called when a job has finished.
+ * This updates the title and status, but does not close the vter, because
+ * there might still be pending output in the channel.
*/
void
term_job_ended(job_T *job)
@@ -891,118 +1127,10 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
line->sb_cells = p;
++term->tl_scrollback.ga_len;
++term->tl_scrollback_scrolled;
- }
- return 0; /* ignored */
-}
-
-/*
- * Fill the buffer with the scrollback lines and current lines of the terminal.
- * Called after the job has ended.
- */
- static void
-move_scrollback_to_buffer(term_T *term)
-{
- linenr_T lnum;
- garray_T ga;
- int c;
- int col;
- int i;
- win_T *wp;
- int len;
- int lines_skipped = 0;
- VTermPos pos;
- VTermScreenCell cell;
- VTermScreenCell *p;
- VTermScreen *screen = vterm_obtain_screen(term->tl_vterm);
- /* Append the the visible lines to the scrollback. */
- for (pos.row = 0; pos.row < term->tl_rows; ++pos.row)
- {
- len = 0;
- for (pos.col = 0; pos.col < term->tl_cols; ++pos.col)
- if (vterm_screen_get_cell(screen, pos, &cell) != 0
- && cell.chars[0] != NUL)
- len = pos.col + 1;
-
- if (len == 0)
- ++lines_skipped;
- else
- {
- while (lines_skipped > 0)
- {
- /* Line was skipped, add an empty line. */
- --lines_skipped;
- if (ga_grow(&term->tl_scrollback, 1) == OK)
- {
- sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
- + term->tl_scrollback.ga_len;
-
- line->sb_cols = 0;
- line->sb_cells = NULL;
- ++term->tl_scrollback.ga_len;
- }
- }
-
- p = (VTermScreenCell *)alloc((int)sizeof(VTermScreenCell) * len);
- if (p != NULL && ga_grow(&term->tl_scrollback, 1) == OK)
- {
- sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data
- + term->tl_scrollback.ga_len;
-
- for (pos.col = 0; pos.col < len; ++pos.col)
- {
- if (vterm_screen_get_cell(screen, pos, &cell) == 0)
- vim_memset(p + pos.col, 0, sizeof(cell));
- else
- p[pos.col] = cell;
- }
- line->sb_cols = len;
- line->sb_cells = p;
- ++term->tl_scrollback.ga_len;
- }
- else
- vim_free(p);
- }
- }
-
- /* Add the text to the buffer. */
- ga_init2(&ga, 1, 100);
- for (lnum = 0; lnum < term->tl_scrollback.ga_len; ++lnum)
- {
- sb_line_T *line = (sb_line_T *)term->tl_scrollback.ga_data + lnum;
-
- ga.ga_len = 0;
- for (col = 0; col < line->sb_cols; ++col)
- {
- if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
- goto failed;
- for (i = 0; (c = line->sb_cells[col].chars[i]) > 0 || i == 0; ++i)
- ga.ga_len += mb_char2bytes(c == NUL ? ' ' : c,
- (char_u *)ga.ga_data + ga.ga_len);
- }
- if (ga_grow(&ga, 1) == FAIL)
- goto failed;
- *((char_u *)ga.ga_data + ga.ga_len) = NUL;
- ml_append_buf(term->tl_buffer, lnum, ga.ga_data, ga.ga_len + 1, FALSE);
- }
-
- /* Delete the empty line that was in the empty buffer. */
- curbuf = term->tl_buffer;
- ml_delete(lnum + 1, FALSE);
- curbuf = curwin->w_buffer;
-
-failed:
- ga_clear(&ga);
-
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_buffer == term->tl_buffer)
- {
- wp->w_cursor.lnum = term->tl_buffer->b_ml.ml_line_count;
- wp->w_cursor.col = 0;
- wp->w_valid = 0;
- }
+ add_scrollback_line_to_buffer(term);
}
+ return 0; /* ignored */
}
static VTermScreenCallbacks screen_callbacks = {
@@ -1029,14 +1157,16 @@ term_channel_closed(channel_T *ch)
for (term = first_term; term != NULL; term = term->tl_next)
if (term->tl_job == ch->ch_job)
{
+ term->tl_channel_closed = TRUE;
+
vim_free(term->tl_title);
term->tl_title = NULL;
vim_free(term->tl_status_text);
term->tl_status_text = NULL;
- /* move the lines into the buffer and free the vterm */
- move_scrollback_to_buffer(term);
- term_free_vterm(term);
+ /* Unless in Terminal-Normal mode: clear the vterm. */
+ if (!term->tl_terminal_mode)
+ cleanup_vterm(term);
redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
did_one = TRUE;
@@ -1227,8 +1357,9 @@ term_update_window(win_T *wp)
VTermState *state;
VTermPos pos;
- if (term == NULL || term->tl_vterm == NULL)
+ if (term == NULL || term->tl_vterm == NULL || term->tl_terminal_mode)
return FAIL;
+
vterm = term->tl_vterm;
screen = vterm_obtain_screen(vterm);
state = vterm_obtain_state(vterm);
@@ -1347,6 +1478,18 @@ term_is_finished(buf_T *buf)
}
/*
+ * Return TRUE if "wp" is a terminal window where the job has finished or we
+ * are in Terminal-Normal mode.
+ */
+ int
+term_show_buffer(buf_T *buf)
+{
+ term_T *term = buf->b_term;
+
+ return term != NULL && (term->tl_vterm == NULL || term->tl_terminal_mode);
+}
+
+/*
* The current buffer is going to be changed. If there is terminal
* highlighting remove it now.
*/
@@ -1450,7 +1593,14 @@ term_get_status_text(term_T *term)
char_u *txt;
size_t len;
- if (term->tl_title != NULL)
+ if (term->tl_terminal_mode)
+ {
+ if (term_job_running(term))
+ txt = (char_u *)_("Terminal");
+ else
+ txt = (char_u *)_("Terminal-finished");
+ }
+ else if (term->tl_title != NULL)
txt = term->tl_title;
else if (term_job_running(term))
txt = (char_u *)_("running");
diff --git a/src/version.c b/src/version.c
index 7a3e04a174..9cc8e14486 100644
--- 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 */
/**/
+ 813,
+/**/
812,
/**/
811,