aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2022-07-30 22:07:58 +0200
committerbfredl <bjorn.linse@gmail.com>2022-08-02 13:54:41 +0200
commit9092540315bef8a685a06825073d05c394bf6575 (patch)
treef3c6ad62ae0ad2133818949a06cbd39269129190
parent0a049c322fda5f2bb124429086c2713ff99c7142 (diff)
downloadrneovim-9092540315bef8a685a06825073d05c394bf6575.tar.gz
rneovim-9092540315bef8a685a06825073d05c394bf6575.tar.bz2
rneovim-9092540315bef8a685a06825073d05c394bf6575.zip
feat(terminal): implement <c-\><c-o> for terminal mode
this works similar to <c-o> or <c-\><c-o> in insert mode
-rw-r--r--runtime/doc/builtin.txt1
-rw-r--r--runtime/doc/index.txt5
-rw-r--r--runtime/doc/intro.txt5
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt6
-rw-r--r--runtime/doc/various.txt3
-rw-r--r--src/nvim/edit.c4
-rw-r--r--src/nvim/screen.c6
-rw-r--r--src/nvim/state.c7
-rw-r--r--src/nvim/terminal.c26
-rw-r--r--test/functional/terminal/buffer_spec.lua39
10 files changed, 86 insertions, 16 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index e2a8e098d2..61d04c6660 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -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
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index 25b98ae4ab..7d8a89887a 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -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*
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index 92ba7b4079..ae80935032 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -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
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index a7be9ff98f..546f92e92f 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -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:
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 9eb6470962..cae9c76030 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -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.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index e7a8f81813..5861e4c52b 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -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.
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 80f6f75fea..0d3b936c48 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -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') {
diff --git a/src/nvim/state.c b/src/nvim/state.c
index be8017ea83..d6cca71ad8 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -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';
}
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index fc02d9d53a..c23aff00cb 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -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;
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index ec3066c20d..23430a620b 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -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()