aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Dewar <seandewar@users.noreply.github.com>2021-10-03 13:57:01 +0100
committerSean Dewar <seandewar@users.noreply.github.com>2021-12-07 11:34:24 +0000
commit28134f4e78819c2bbf0344326b9d44f21eb0d736 (patch)
treef83a2f888368a0302203e04ae09bdbf51c779e6c
parentafaad8b54ebd2ad4ba2145f4069f5017cace3c8f (diff)
downloadrneovim-28134f4e78819c2bbf0344326b9d44f21eb0d736.tar.gz
rneovim-28134f4e78819c2bbf0344326b9d44f21eb0d736.tar.bz2
rneovim-28134f4e78819c2bbf0344326b9d44f21eb0d736.zip
vim-patch:8.1.0035: not easy to switch between prompt buffer and other windows
Problem: Not easy to switch between prompt buffer and other windows. Solution: Accept CTRL-W commands in Insert mode. Start and stop Insert mode as one would expect. https://github.com/vim/vim/commit/6d41c78e353b630bc1a72cbff9160311d2a81e8c Cherry-pick channel.txt change from: https://github.com/vim/vim/commit/d2f3a8b8787333abf2300d38836b196955f10c00 b_prompt_insert was already ported.
-rw-r--r--runtime/doc/channel.txt5
-rw-r--r--src/nvim/edit.c29
-rw-r--r--src/nvim/testdir/test_prompt_buffer.vim7
-rw-r--r--src/nvim/window.c39
4 files changed, 71 insertions, 9 deletions
diff --git a/runtime/doc/channel.txt b/runtime/doc/channel.txt
index 656bb10c45..5f376a600e 100644
--- a/runtime/doc/channel.txt
+++ b/runtime/doc/channel.txt
@@ -210,6 +210,11 @@ effective prompt text for a buffer, with |prompt_getprompt()|.
The user can go to Normal mode and navigate through the buffer. This can be
useful to see older output or copy text.
+The CTRL-W key can be used to start a window command, such as CTRL-W w to
+switch to the next window. This also works in Insert mode (use Shift-CTRL-W
+to delete a word). When leaving the window Insert mode will be stopped. When
+coming back to the prompt window Insert mode will be restored.
+
Any command that starts Insert mode, such as "a", "i", "A" and "I", will move
the cursor to the last line. "A" will move to the end of the line, "I" to the
start of the line.
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index fe69da7fcb..16601d327d 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -655,10 +655,17 @@ static int insert_check(VimState *state)
static int insert_execute(VimState *state, int key)
{
+ InsertState *const s = (InsertState *)state;
+ if (stop_insert_mode) {
+ // Insert mode ended, possibly from a callback.
+ s->count = 0;
+ s->nomove = true;
+ return 0;
+ }
+
if (key == K_IGNORE || key == K_NOP) {
return -1; // get another key
}
- InsertState *s = (InsertState *)state;
s->c = key;
// Don't want K_EVENT with cursorhold for the second key, e.g., after CTRL-V.
@@ -984,6 +991,15 @@ static int insert_handle_key(InsertState *s)
break;
case Ctrl_W: // delete word before the cursor
+ if (bt_prompt(curbuf) && (mod_mask & MOD_MASK_SHIFT) == 0) {
+ // In a prompt window CTRL-W is used for window commands.
+ // Use Shift-CTRL-W to delete a word.
+ stuffcharReadbuff(Ctrl_W);
+ restart_edit = 'i';
+ s->nomove = true;
+ s->count = 0;
+ return 0;
+ }
s->did_backspace = ins_bs(s->c, BACKSPACE_WORD, &s->inserted_space);
auto_format(false, true);
break;
@@ -1653,6 +1669,17 @@ static void init_prompt(int cmdchar_todo)
coladvance(MAXCOL);
changed_bytes(curbuf->b_ml.ml_line_count, 0);
}
+
+ // Insert always starts after the prompt, allow editing text after it.
+ if (Insstart_orig.lnum != curwin->w_cursor.lnum || Insstart_orig.col != (colnr_T)STRLEN(prompt)) {
+ Insstart.lnum = curwin->w_cursor.lnum;
+ Insstart.col = STRLEN(prompt);
+ Insstart_orig = Insstart;
+ Insstart_textlen = Insstart.col;
+ Insstart_blank_vcol = MAXCOL;
+ arrow_used = false;
+ }
+
if (cmdchar_todo == 'A') {
coladvance(MAXCOL);
}
diff --git a/src/nvim/testdir/test_prompt_buffer.vim b/src/nvim/testdir/test_prompt_buffer.vim
index c59a00afcc..fde97a66a8 100644
--- a/src/nvim/testdir/test_prompt_buffer.vim
+++ b/src/nvim/testdir/test_prompt_buffer.vim
@@ -145,10 +145,9 @@ func Test_prompt_buffer_edit()
call assert_beeps("normal! \<C-X>")
" pressing CTRL-W in the prompt buffer should trigger the window commands
call assert_equal(1, winnr())
- " In Nvim, CTRL-W commands aren't usable from insert mode in a prompt buffer
- " exe "normal A\<C-W>\<C-W>"
- " call assert_equal(2, winnr())
- " wincmd w
+ exe "normal A\<C-W>\<C-W>"
+ call assert_equal(2, winnr())
+ wincmd w
close!
call assert_equal(0, prompt_setprompt([], ''))
endfunc
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 3e6e42dec2..1da6c3704f 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2229,6 +2229,28 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
}
}
+static void leaving_window(win_T *const win)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // When leaving a prompt window stop Insert mode and perhaps restart
+ // it when entering that window again.
+ win->w_buffer->b_prompt_insert = restart_edit;
+ restart_edit = NUL;
+
+ // When leaving the window (or closing the window) was done from a
+ // callback we need to break out of the Insert mode loop.
+ if (State & INSERT) {
+ stop_insert_mode = true;
+ }
+}
+
+static void entering_window(win_T *const win)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // When entering the prompt window may restart Insert mode.
+ restart_edit = win->w_buffer->b_prompt_insert;
+}
+
/// Closes all windows for buffer `buf`.
///
/// @param keep_curwin don't close `curwin`
@@ -2367,6 +2389,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
shell_new_rows();
}
}
+ entering_window(curwin);
// Since goto_tabpage_tp above did not trigger *Enter autocommands, do
// that now.
@@ -2434,10 +2457,10 @@ int win_close(win_T *win, bool free_buf)
}
if (win == curwin) {
- /*
- * Guess which window is going to be the new current window.
- * This may change because of the autocommands (sigh).
- */
+ leaving_window(curwin);
+
+ // Guess which window is going to be the new current window.
+ // This may change because of the autocommands (sigh).
if (!win->w_floating) {
wp = frame2win(win_altframe(win, NULL));
} else {
@@ -3801,6 +3824,8 @@ int win_new_tabpage(int after, char_u *filename)
lastused_tabpage = old_curtab;
+ entering_window(curwin);
+
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
@@ -3956,6 +3981,7 @@ static int leave_tabpage(buf_T *new_curbuf, bool trigger_leave_autocmds)
{
tabpage_T *tp = curtab;
+ leaving_window(curwin);
reset_VIsual_and_resel(); // stop Visual mode
if (trigger_leave_autocmds) {
if (new_curbuf != curbuf) {
@@ -4478,6 +4504,10 @@ static void win_enter_ext(win_T *const wp, const int flags)
return;
}
+ if (!curwin_invalid) {
+ leaving_window(curwin);
+ }
+
if (!curwin_invalid && (flags & WEE_TRIGGER_LEAVE_AUTOCMDS)) {
// Be careful: If autocommands delete the window, return now.
if (wp->w_buffer != curbuf) {
@@ -4525,6 +4555,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
fix_current_dir();
+ entering_window(curwin);
// Careful: autocommands may close the window and make "wp" invalid
if (flags & WEE_TRIGGER_NEW_AUTOCMDS) {
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);