diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/edit.c | 29 | ||||
-rw-r--r-- | src/nvim/testdir/test_prompt_buffer.vim | 7 | ||||
-rw-r--r-- | src/nvim/window.c | 39 |
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); |