aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/edit.c29
-rw-r--r--src/nvim/testdir/test_prompt_buffer.vim7
-rw-r--r--src/nvim/window.c39
3 files changed, 66 insertions, 9 deletions
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);