Merge pull request #19584 from bfredl/terminal_c_BSL_c_O

implement <c-\><c-o> key for terminal mode
This commit is contained in:
bfredl
2022-08-02 14:53:20 +02:00
committed by GitHub
10 changed files with 86 additions and 16 deletions

View File

@@ -5311,6 +5311,7 @@ mode([expr]) Return a string that indicates the current mode.
niV Normal using |i_CTRL-O| in |Virtual-Replace-mode| niV Normal using |i_CTRL-O| in |Virtual-Replace-mode|
nt Normal in |terminal-emulator| (insert goes to nt Normal in |terminal-emulator| (insert goes to
Terminal mode) Terminal mode)
ntT Normal using |t_CTRL-\_CTRL-O| in |terminal-mode|
v Visual by character v Visual by character
vs Visual by character using |v_CTRL-O| in Select mode vs Visual by character using |v_CTRL-O| in Select mode
V Visual by line V Visual by line

View File

@@ -1101,8 +1101,11 @@ tag command action in Command-line editing mode ~
5. Terminal mode *terminal-mode-index* 5. Terminal mode *terminal-mode-index*
In a |terminal| buffer all keys except CTRL-\ are forwarded to the terminal 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 |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* You found it, Arthur! *holy-grail*

View File

@@ -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 Terminal mode In Terminal mode all input (except CTRL-\) is sent to
the process running in the current |terminal| buffer. the process running in the current |terminal| buffer.
If CTRL-\ is pressed, the next key is sent unless it 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 If the 'showmode' option is on "-- TERMINAL --" is shown
at the bottom of the window. 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 *6 Go from Select mode to Insert mode by typing a printable character. The
selection is deleted and the character is inserted. 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 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 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 Normal mode, without causing a beep like <Esc> would. However, this does not

View File

@@ -47,8 +47,10 @@ Input *terminal-input*
To send input, enter |Terminal-mode| with |i|, |I|, |a|, |A| or 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 |: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 program. If <C-\> is pressed, the next key is sent unless it is <C-N> or <C-O>.
<C-\><C-N> to return to normal-mode. |CTRL-\_CTRL-N| 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: Terminal-mode forces these local options:

View File

@@ -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 Type |i| to enter |Terminal-mode|, then keys are sent to
the job running in the terminal. Type <C-\><C-N> 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, Fails if changes have been made to the current buffer,
unless 'hidden' is set. unless 'hidden' is set.

View File

@@ -1223,10 +1223,10 @@ bool edit(int cmdchar, bool startln, long count)
// the value of `restart_edit` before `ex_normal` returns. // the value of `restart_edit` before `ex_normal` returns.
restart_edit = 'i'; restart_edit = 'i';
force_restart_edit = true; force_restart_edit = true;
return false;
} else { } else {
terminal_enter(); return terminal_enter();
} }
return false;
} }
// Don't allow inserting in the sandbox. // Don't allow inserting in the sandbox.

View File

@@ -6026,7 +6026,11 @@ int showmode(void)
msg_puts_attr(_(" INSERT"), attr); msg_puts_attr(_(" INSERT"), attr);
} else if (restart_edit == 'I' || restart_edit == 'i' } else if (restart_edit == 'I' || restart_edit == 'i'
|| restart_edit == 'a' || restart_edit == 'A') { || 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') { } else if (restart_edit == 'R') {
msg_puts_attr(_(" (replace)"), attr); msg_puts_attr(_(" (replace)"), attr);
} else if (restart_edit == 'V') { } else if (restart_edit == 'V') {

View File

@@ -211,12 +211,15 @@ void get_mode(char *buf)
buf[i++] = 'o'; buf[i++] = 'o';
// to be able to detect force-linewise/blockwise/charwise operations // to be able to detect force-linewise/blockwise/charwise operations
buf[i++] = (char)motion_force; 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' } else if (restart_edit == 'I' || restart_edit == 'R'
|| restart_edit == 'V') { || restart_edit == 'V') {
buf[i++] = 'i'; buf[i++] = 'i';
buf[i++] = (char)restart_edit; buf[i++] = (char)restart_edit;
} else if (curbuf->terminal) {
buf[i++] = 't';
} }
} }

View File

@@ -82,6 +82,7 @@ typedef struct terminal_state {
int save_rd; // saved value of RedrawingDisabled int save_rd; // saved value of RedrawingDisabled
bool close; bool close;
bool got_bsl; // if the last input was <C-\> bool got_bsl; // if the last input was <C-\>
bool got_bsl_o; // if left terminal mode with <c-\><c-o>
} TerminalState; } TerminalState;
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -388,12 +389,11 @@ void terminal_check_size(Terminal *term)
} }
/// Implements MODE_TERMINAL state. :help Terminal-mode /// Implements MODE_TERMINAL state. :help Terminal-mode
void terminal_enter(void) bool terminal_enter(void)
{ {
buf_T *buf = curbuf; buf_T *buf = curbuf;
assert(buf->terminal); // Should only be called when curbuf has a terminal. assert(buf->terminal); // Should only be called when curbuf has a terminal.
TerminalState state, *s = &state; TerminalState s[1] = { 0 };
memset(s, 0, sizeof(TerminalState));
s->term = buf->terminal; s->term = buf->terminal;
stop_insert_mode = false; stop_insert_mode = false;
@@ -443,7 +443,9 @@ void terminal_enter(void)
s->state.check = terminal_check; s->state.check = terminal_check;
state_enter(&s->state); state_enter(&s->state);
restart_edit = 0; if (!s->got_bsl_o) {
restart_edit = 0;
}
State = save_state; State = save_state;
RedrawingDisabled = s->save_rd; RedrawingDisabled = s->save_rd;
apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf); apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf);
@@ -467,7 +469,11 @@ void terminal_enter(void)
if (curbuf->terminal == s->term && !s->close) { if (curbuf->terminal == s->term && !s->close) {
terminal_check_cursor(); terminal_check_cursor();
} }
unshowmode(true); if (restart_edit) {
showmode();
} else {
unshowmode(true);
}
ui_busy_stop(); ui_busy_stop();
if (s->close) { if (s->close) {
bool wipe = s->term->buf_handle != 0; bool wipe = s->term->buf_handle != 0;
@@ -477,6 +483,8 @@ void terminal_enter(void)
do_cmdline_cmd("bwipeout!"); do_cmdline_cmd("bwipeout!");
} }
} }
return s->got_bsl_o;
} }
static void terminal_check_cursor(void) static void terminal_check_cursor(void)
@@ -564,6 +572,14 @@ static int terminal_execute(VimState *state, int key)
} }
FALLTHROUGH; FALLTHROUGH;
case Ctrl_O:
if (s->got_bsl) {
s->got_bsl_o = true;
restart_edit = 'I';
return 0;
}
FALLTHROUGH;
default: default:
if (key == Ctrl_BSL && !s->got_bsl) { if (key == Ctrl_BSL && !s->got_bsl) {
s->got_bsl = true; s->got_bsl = true;

View File

@@ -13,6 +13,7 @@ local exc_exec = helpers.exc_exec
local matches = helpers.matches local matches = helpers.matches
local exec_lua = helpers.exec_lua local exec_lua = helpers.exec_lua
local sleep = helpers.sleep local sleep = helpers.sleep
local funcs = helpers.funcs
describe(':terminal buffer', function() describe(':terminal buffer', function()
local screen local screen
@@ -300,6 +301,44 @@ describe(':terminal buffer', function()
feed_command('put a') -- register a is empty feed_command('put a') -- register a is empty
helpers.assert_alive() helpers.assert_alive()
end) 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) end)
describe('No heap-buffer-overflow when using', function() describe('No heap-buffer-overflow when using', function()