mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #19584 from bfredl/terminal_c_BSL_c_O
implement <c-\><c-o> key for terminal mode
This commit is contained in:
		| @@ -5311,6 +5311,7 @@ mode([expr])	Return a string that indicates the current mode. | ||||
| 		   niV	    Normal using |i_CTRL-O| in |Virtual-Replace-mode| | ||||
| 		   nt	    Normal in |terminal-emulator| (insert goes to | ||||
| 				Terminal mode) | ||||
| 		   ntT	    Normal using |t_CTRL-\_CTRL-O| in |terminal-mode| | ||||
| 		   v	    Visual by character | ||||
| 		   vs	    Visual by character using |v_CTRL-O| in Select mode | ||||
| 		   V	    Visual by line | ||||
|   | ||||
| @@ -1101,8 +1101,11 @@ tag		command		action in Command-line editing mode	~ | ||||
| 5. Terminal mode				*terminal-mode-index* | ||||
|  | ||||
| In a |terminal| buffer all keys except CTRL-\ are forwarded to the terminal | ||||
| job.  If CTRL-\ is pressed, the next key is forwarded unless it is CTRL-N. | ||||
| job.  If CTRL-\ is pressed, the next key is forwarded unless it is CTRL-N | ||||
| or CTRL-O. | ||||
| Use |CTRL-\_CTRL-N| to go to Normal mode. | ||||
| Use |t_CTRL-\_CTRL-O| to execute one normal mode command and then return | ||||
| to terminal mode. | ||||
|  | ||||
|  | ||||
| You found it, Arthur!				*holy-grail* | ||||
|   | ||||
| @@ -458,7 +458,7 @@ Ex mode			Like Command-line mode, but after entering a command | ||||
| Terminal mode		In Terminal mode all input (except CTRL-\) is sent to | ||||
| 			the process running in the current |terminal| buffer. | ||||
| 			If CTRL-\ is pressed, the next key is sent unless it | ||||
| 			is CTRL-N (|CTRL-\_CTRL-N|). | ||||
| 			is CTRL-N (|CTRL-\_CTRL-N|) or CTRL-O (|t_CTRL-\_CTRL-O|). | ||||
| 			If the 'showmode' option is on "-- TERMINAL --" is shown | ||||
| 			at the bottom of the window. | ||||
|  | ||||
| @@ -550,7 +550,8 @@ Ex		 :vi	  --	  --	 --	    --	      -- | ||||
| *6 Go from Select mode to Insert mode by typing a printable character.  The | ||||
|    selection is deleted and the character is inserted. | ||||
|  | ||||
| 	*CTRL-\_CTRL-N* *i_CTRL-\_CTRL-N* *c_CTRL-\_CTRL-N* *v_CTRL-\_CTRL-N* | ||||
| 			*CTRL-\_CTRL-N* *i_CTRL-\_CTRL-N* *c_CTRL-\_CTRL-N* | ||||
| 				      *v_CTRL-\_CTRL-N* *t_CTRL-\_CTRL-N* | ||||
| Additionally the command CTRL-\ CTRL-N or <C-\><C-N> can be used to go to | ||||
| Normal mode from any other mode.  This can be used to make sure Vim is in | ||||
| Normal mode, without causing a beep like <Esc> would.  However, this does not | ||||
|   | ||||
| @@ -47,8 +47,10 @@ Input						*terminal-input* | ||||
|  | ||||
| To send input, enter |Terminal-mode| with |i|, |I|, |a|, |A| or | ||||
| |:startinsert|. In this mode all keys except <C-\> are sent to the underlying | ||||
| program. If <C-\> is pressed, the next key is sent unless it is <C-N>. Use | ||||
| <C-\><C-N> to return to normal-mode. |CTRL-\_CTRL-N| | ||||
| program. If <C-\> is pressed, the next key is sent unless it is <C-N> or <C-O>. | ||||
| Use <C-\><C-N> to return to normal mode. |CTRL-\_CTRL-N| | ||||
| Use <C-\><C-O> to execute one normal mode command and then return to terminal | ||||
| mode. *t_CTRL-\_CTRL-O* | ||||
|  | ||||
| Terminal-mode forces these local options: | ||||
|  | ||||
|   | ||||
| @@ -239,7 +239,8 @@ g8			Print the hex values of the bytes used in the | ||||
|  | ||||
| 			Type |i| to enter |Terminal-mode|, then keys are sent to | ||||
| 			the job running in the terminal. Type <C-\><C-N> to | ||||
| 			leave Terminal-mode. |CTRL-\_CTRL-N| | ||||
| 			leave Terminal-mode. |CTRL-\_CTRL-N|. Type <C-\><C-O> | ||||
| 			to execute a single normal mode command |t_CTRL-\_CTRL-O| | ||||
|  | ||||
| 			Fails if changes have been made to the current buffer, | ||||
| 			unless 'hidden' is set. | ||||
|   | ||||
| @@ -1223,10 +1223,10 @@ bool edit(int cmdchar, bool startln, long count) | ||||
|       // the value of `restart_edit` before `ex_normal` returns. | ||||
|       restart_edit = 'i'; | ||||
|       force_restart_edit = true; | ||||
|       return false; | ||||
|     } else { | ||||
|       terminal_enter(); | ||||
|       return terminal_enter(); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   // Don't allow inserting in the sandbox. | ||||
|   | ||||
| @@ -6026,7 +6026,11 @@ int showmode(void) | ||||
|           msg_puts_attr(_(" INSERT"), attr); | ||||
|         } else if (restart_edit == 'I' || restart_edit == 'i' | ||||
|                    || restart_edit == 'a' || restart_edit == 'A') { | ||||
|           msg_puts_attr(_(" (insert)"), attr); | ||||
|           if (curbuf->terminal) { | ||||
|             msg_puts_attr(_(" (terminal)"), attr); | ||||
|           } else { | ||||
|             msg_puts_attr(_(" (insert)"), attr); | ||||
|           } | ||||
|         } else if (restart_edit == 'R') { | ||||
|           msg_puts_attr(_(" (replace)"), attr); | ||||
|         } else if (restart_edit == 'V') { | ||||
|   | ||||
| @@ -211,12 +211,15 @@ void get_mode(char *buf) | ||||
|       buf[i++] = 'o'; | ||||
|       // to be able to detect force-linewise/blockwise/charwise operations | ||||
|       buf[i++] = (char)motion_force; | ||||
|     } else if (curbuf->terminal) { | ||||
|       buf[i++] = 't'; | ||||
|       if (restart_edit == 'I') { | ||||
|         buf[i++] = 'T'; | ||||
|       } | ||||
|     } else if (restart_edit == 'I' || restart_edit == 'R' | ||||
|                || restart_edit == 'V') { | ||||
|       buf[i++] = 'i'; | ||||
|       buf[i++] = (char)restart_edit; | ||||
|     } else if (curbuf->terminal) { | ||||
|       buf[i++] = 't'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -82,6 +82,7 @@ typedef struct terminal_state { | ||||
|   int save_rd;              // saved value of RedrawingDisabled | ||||
|   bool close; | ||||
|   bool got_bsl;             // if the last input was <C-\> | ||||
|   bool got_bsl_o;           // if left terminal mode with <c-\><c-o> | ||||
| } TerminalState; | ||||
|  | ||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||
| @@ -388,12 +389,11 @@ void terminal_check_size(Terminal *term) | ||||
| } | ||||
|  | ||||
| /// Implements MODE_TERMINAL state. :help Terminal-mode | ||||
| void terminal_enter(void) | ||||
| bool terminal_enter(void) | ||||
| { | ||||
|   buf_T *buf = curbuf; | ||||
|   assert(buf->terminal);  // Should only be called when curbuf has a terminal. | ||||
|   TerminalState state, *s = &state; | ||||
|   memset(s, 0, sizeof(TerminalState)); | ||||
|   TerminalState s[1] = { 0 }; | ||||
|   s->term = buf->terminal; | ||||
|   stop_insert_mode = false; | ||||
|  | ||||
| @@ -443,7 +443,9 @@ void terminal_enter(void) | ||||
|   s->state.check = terminal_check; | ||||
|   state_enter(&s->state); | ||||
|  | ||||
|   restart_edit = 0; | ||||
|   if (!s->got_bsl_o) { | ||||
|     restart_edit = 0; | ||||
|   } | ||||
|   State = save_state; | ||||
|   RedrawingDisabled = s->save_rd; | ||||
|   apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf); | ||||
| @@ -467,7 +469,11 @@ void terminal_enter(void) | ||||
|   if (curbuf->terminal == s->term && !s->close) { | ||||
|     terminal_check_cursor(); | ||||
|   } | ||||
|   unshowmode(true); | ||||
|   if (restart_edit) { | ||||
|     showmode(); | ||||
|   } else { | ||||
|     unshowmode(true); | ||||
|   } | ||||
|   ui_busy_stop(); | ||||
|   if (s->close) { | ||||
|     bool wipe = s->term->buf_handle != 0; | ||||
| @@ -477,6 +483,8 @@ void terminal_enter(void) | ||||
|       do_cmdline_cmd("bwipeout!"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return s->got_bsl_o; | ||||
| } | ||||
|  | ||||
| static void terminal_check_cursor(void) | ||||
| @@ -564,6 +572,14 @@ static int terminal_execute(VimState *state, int key) | ||||
|     } | ||||
|     FALLTHROUGH; | ||||
|  | ||||
|   case Ctrl_O: | ||||
|     if (s->got_bsl) { | ||||
|       s->got_bsl_o = true; | ||||
|       restart_edit = 'I'; | ||||
|       return 0; | ||||
|     } | ||||
|     FALLTHROUGH; | ||||
|  | ||||
|   default: | ||||
|     if (key == Ctrl_BSL && !s->got_bsl) { | ||||
|       s->got_bsl = true; | ||||
|   | ||||
| @@ -13,6 +13,7 @@ local exc_exec = helpers.exc_exec | ||||
| local matches = helpers.matches | ||||
| local exec_lua = helpers.exec_lua | ||||
| local sleep = helpers.sleep | ||||
| local funcs = helpers.funcs | ||||
|  | ||||
| describe(':terminal buffer', function() | ||||
|   local screen | ||||
| @@ -300,6 +301,44 @@ describe(':terminal buffer', function() | ||||
|     feed_command('put a')  -- register a is empty | ||||
|     helpers.assert_alive() | ||||
|   end) | ||||
|  | ||||
|   it([[can use temporary normal mode <c-\><c-o>]], function() | ||||
|     eq('t', funcs.mode(1)) | ||||
|     feed [[<c-\><c-o>]] | ||||
|     screen:expect{grid=[[ | ||||
|       tty ready                                         | | ||||
|       {2:^ }                                                 | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|       {3:-- (terminal) --}                                  | | ||||
|     ]]} | ||||
|     eq('ntT', funcs.mode(1)) | ||||
|  | ||||
|     feed [[:let g:x = 17]] | ||||
|     screen:expect{grid=[[ | ||||
|       tty ready                                         | | ||||
|       {2: }                                                 | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|       :let g:x = 17^                                     | | ||||
|     ]]} | ||||
|  | ||||
|     feed [[<cr>]] | ||||
|     screen:expect{grid=[[ | ||||
|       tty ready                                         | | ||||
|       {1: }                                                 | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|                                                         | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]]} | ||||
|     eq('t', funcs.mode(1)) | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe('No heap-buffer-overflow when using', function() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bfredl
					bfredl