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

Cherry-pick channel.txt change from:
d2f3a8b878

b_prompt_insert was already ported.
This commit is contained in:
Sean Dewar 2021-10-03 13:57:01 +01:00
parent afaad8b54e
commit 28134f4e78
No known key found for this signature in database
GPG Key ID: 08CC2C83AD41B581
4 changed files with 71 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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