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
commit 0806c882cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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|
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

View File

@ -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*

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
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

View File

@ -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:

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
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.

View File

@ -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.

View File

@ -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') {

View File

@ -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';
}
}

View File

@ -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;

View File

@ -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()