changeset 11985:d036c1c8537d v8.0.0873

patch 8.0.0873: in terminal cannot use CTRL- CTRL-N to start Visual mode commit https://github.com/vim/vim/commit/aaa8a35fbd38d5e6cc57ae60a8477e787d695a20 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Aug 5 20:17:00 2017 +0200 patch 8.0.0873: in terminal cannot use CTRL-\ CTRL-N to start Visual mode Problem: In a terminal window cannot use CTRL-\ CTRL-N to start Visual mode. Solution: After CTRL-\ CTRL-N enter Terminal-Normal mode for one command.
author Christian Brabandt <cb@256bit.org>
date Sat, 05 Aug 2017 20:30:03 +0200
parents 829a855d3204
children ca2801834b85
files src/main.c src/proto/terminal.pro src/terminal.c src/version.c
diffstat 4 files changed, 58 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/main.c
+++ b/src/main.c
@@ -1356,7 +1356,9 @@ main_loop(
 	else
 	{
 #ifdef FEAT_TERMINAL
-	    if (term_use_loop() && oa.op_type == OP_NOP && oa.regname == NUL)
+	    if (term_use_loop(TRUE)
+		    && oa.op_type == OP_NOP && oa.regname == NUL
+		    && !VIsual_active)
 	    {
 		/* If terminal_loop() returns OK we got a key that is handled
 		 * in Normal model.  With FAIL the terminal was closed and the
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -6,7 +6,7 @@ int term_job_running(term_T *term);
 int term_in_terminal_mode(void);
 void term_leave_terminal_mode(void);
 int send_keys_to_term(term_T *term, int c, int typed);
-int term_use_loop(void);
+int term_use_loop(int once);
 int terminal_loop(void);
 void term_job_ended(job_T *job);
 void term_channel_closed(channel_T *ch);
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -115,7 +115,7 @@ struct terminal_S {
     int		tl_tty_fd;
     char_u	*tl_tty_name;
 
-    int		tl_terminal_mode;
+    int		tl_terminal_mode; /* 0, TMODE_ONCE or TMODE_LOOP */
     int		tl_channel_closed;
 
 #ifdef WIN3264
@@ -144,6 +144,9 @@ struct terminal_S {
     int		tl_cursor_visible;
 };
 
+#define TMODE_ONCE 1	    /* CTRL-\ CTRL-N used */
+#define TMODE_LOOP 2	    /* CTRL-W N used */
+
 /*
  * List of all active terminals.
  */
@@ -459,7 +462,7 @@ term_write_job_output(term_T *term, char
     static void
 update_cursor(term_T *term, int redraw)
 {
-    if (term->tl_terminal_mode)
+    if (term->tl_terminal_mode != 0)
 	return;
     setcursor();
     if (redraw && term->tl_buffer == curbuf)
@@ -492,7 +495,7 @@ write_to_term(buf_T *buffer, char_u *msg
     ch_log(channel, "writing %d bytes to terminal", (int)len);
     term_write_job_output(term, msg, len);
 
-    if (!term->tl_terminal_mode)
+    if (term->tl_terminal_mode == 0)
     {
 	/* TODO: only update once in a while. */
 	update_screen(0);
@@ -805,9 +808,9 @@ move_terminal_to_buffer(term_T *term)
 }
 
     static void
-set_terminal_mode(term_T *term, int on)
+set_terminal_mode(term_T *term, int mode)
 {
-    term->tl_terminal_mode = on;
+    term->tl_terminal_mode = mode;
     vim_free(term->tl_status_text);
     term->tl_status_text = NULL;
     if (term->tl_buffer == curbuf)
@@ -823,22 +826,35 @@ cleanup_vterm(term_T *term)
 {
     move_terminal_to_buffer(term);
     term_free_vterm(term);
-    set_terminal_mode(term, FALSE);
+    set_terminal_mode(term, 0);
 }
 
 /*
- * Switch from sending keys to the job to Terminal-Normal mode.
+ * Switch from Terminal-Job mode to Terminal-Normal mode.
  * Suspends updating the terminal window.
  */
     static void
-term_enter_terminal_mode()
+term_enter_terminal_mode(int 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);
+    set_terminal_mode(term, mode);
+
+    if (mode == TMODE_ONCE)
+    {
+	/* Move the window cursor to the position of the cursor in the
+	 * terminal. */
+	curwin->w_cursor.lnum = term->tl_scrollback_scrolled
+						 + term->tl_cursor_pos.row + 1;
+	check_cursor();
+	coladvance(term->tl_cursor_pos.col);
+
+	/* Display the same lines as in the terminal. */
+	curwin->w_topline = term->tl_scrollback_scrolled + 1;
+    }
 }
 
 /*
@@ -850,11 +866,11 @@ term_in_terminal_mode()
 {
     term_T *term = curbuf->b_term;
 
-    return term != NULL && term->tl_terminal_mode;
+    return term != NULL && term->tl_terminal_mode != 0;
 }
 
 /*
- * Switch from Terminal-Normal mode to sending keys to the job.
+ * Switch from Terminal-Normal mode to Terminal-Job mode.
  * Restores updating the terminal window.
  */
     void
@@ -877,7 +893,7 @@ term_leave_terminal_mode()
     }
     check_cursor();
 
-    set_terminal_mode(term, FALSE);
+    set_terminal_mode(term, 0);
 
     if (term->tl_channel_closed)
 	cleanup_vterm(term);
@@ -1037,12 +1053,13 @@ term_paste_register(int prev_c UNUSED)
  * keys to the job.
  */
     int
-term_use_loop()
+term_use_loop(int once)
 {
     term_T *term = curbuf->b_term;
 
     return term != NULL
-	&& !term->tl_terminal_mode
+	&& (once ? term->tl_terminal_mode != TMODE_LOOP
+		 : term->tl_terminal_mode == 0)
 	&& term->tl_vterm != NULL
 	&& term_job_running(term);
 }
@@ -1060,6 +1077,13 @@ terminal_loop(void)
     int		c;
     int		termkey = 0;
 
+    if (curbuf->b_term->tl_terminal_mode != 0)
+    {
+	/* Got back from TMODE_ONCE, enter Terminal-Job mode. */
+	term_leave_terminal_mode();
+	update_cursor(curbuf->b_term, TRUE);
+    }
+
     if (*curwin->w_p_tk != NUL)
 	termkey = string_to_key(curwin->w_p_tk, TRUE);
     position_cursor(curwin, &curbuf->b_term->tl_cursor_pos);
@@ -1073,7 +1097,7 @@ terminal_loop(void)
 	update_cursor(curbuf->b_term, FALSE);
 
 	c = term_vgetc();
-	if (!term_use_loop())
+	if (!term_use_loop(FALSE))
 	    /* job finished while waiting for a character */
 	    break;
 
@@ -1100,15 +1124,18 @@ terminal_loop(void)
 #ifdef FEAT_CMDL_INFO
 	    clear_showcmd();
 #endif
-	    if (!term_use_loop())
+	    if (!term_use_loop(FALSE))
 		/* job finished while waiting for a character */
 		break;
 
 	    if (prev_c == Ctrl_BSL)
 	    {
 		if (c == Ctrl_N)
+		{
 		    /* CTRL-\ CTRL-N : execute one Normal mode command. */
+		    term_enter_terminal_mode(TMODE_ONCE);
 		    return OK;
+		}
 		/* Send both keys to the terminal. */
 		send_keys_to_term(curbuf->b_term, prev_c, TRUE);
 	    }
@@ -1119,7 +1146,7 @@ terminal_loop(void)
 	    }
 	    else if (c == 'N')
 	    {
-		term_enter_terminal_mode();
+		term_enter_terminal_mode(TMODE_LOOP);
 		return FAIL;
 	    }
 	    else if (c == '"')
@@ -1222,7 +1249,7 @@ handle_movecursor(
 	if (wp->w_buffer == term->tl_buffer)
 	    position_cursor(wp, &pos);
     }
-    if (term->tl_buffer == curbuf && !term->tl_terminal_mode)
+    if (term->tl_buffer == curbuf && term->tl_terminal_mode == 0)
     {
 	may_toggle_cursor(term);
 	update_cursor(term, term->tl_cursor_visible);
@@ -1358,7 +1385,7 @@ term_channel_closed(channel_T *ch)
 	    term->tl_status_text = NULL;
 
 	    /* Unless in Terminal-Normal mode: clear the vterm. */
-	    if (!term->tl_terminal_mode)
+	    if (term->tl_terminal_mode == 0)
 		cleanup_vterm(term);
 
 	    redraw_buf_and_status_later(term->tl_buffer, NOT_VALID);
@@ -1558,7 +1585,7 @@ term_update_window(win_T *wp)
     VTermState	*state;
     VTermPos	pos;
 
-    if (term == NULL || term->tl_vterm == NULL || term->tl_terminal_mode)
+    if (term == NULL || term->tl_vterm == NULL || term->tl_terminal_mode != 0)
 	return FAIL;
 
     vterm = term->tl_vterm;
@@ -1687,7 +1714,8 @@ term_show_buffer(buf_T *buf)
 {
     term_T *term = buf->b_term;
 
-    return term != NULL && (term->tl_vterm == NULL || term->tl_terminal_mode);
+    return term != NULL
+		    && (term->tl_vterm == NULL || term->tl_terminal_mode != 0);
 }
 
 /*
@@ -1770,7 +1798,7 @@ term_get_status_text(term_T *term)
 	char_u *txt;
 	size_t len;
 
-	if (term->tl_terminal_mode)
+	if (term->tl_terminal_mode != 0)
 	{
 	    if (term_job_running(term))
 		txt = (char_u *)_("Terminal");
@@ -1997,7 +2025,7 @@ f_term_getstatus(typval_T *argvars, typv
 	STRCPY(val, "running");
     else
 	STRCPY(val, "finished");
-    if (term->tl_terminal_mode)
+    if (term->tl_terminal_mode != 0)
 	STRCAT(val, ",terminal");
     rettv->vval.v_string = vim_strsave(val);
 }
@@ -2159,7 +2187,7 @@ f_term_sendkeys(typval_T *argvars, typva
 	msg += MB_PTR2LEN(msg);
     }
 
-    if (!term->tl_terminal_mode)
+    if (term->tl_terminal_mode == 0)
     {
 	/* TODO: only update once in a while. */
 	update_screen(0);
--- 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 */
 /**/
+    873,
+/**/
     872,
 /**/
     871,