aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/eval/funcs.c2
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/screen.c42
-rw-r--r--src/nvim/testdir/test_bufline.vim2
-rw-r--r--src/nvim/testdir/test_messages.vim59
-rw-r--r--src/nvim/testdir/test_normal.vim19
8 files changed, 114 insertions, 19 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 7ddff92632..e1473f30c8 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -4251,7 +4251,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
// Otherwise remove the mode message.
if (reg_recording != 0 || restart_edit != NUL) {
showmode();
- } else if (p_smd) {
+ } else if (p_smd && (got_int || !skip_showmode())) {
msg("");
}
// Exit Insert mode
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 609d2f0f7b..dafc27c4df 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2722,6 +2722,8 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
// getchar(): blocking wait.
// TODO(bfredl): deduplicate shared logic with state_enter ?
if (!char_avail()) {
+ // flush output before waiting
+ ui_flush();
(void)os_inchar(NULL, 0, -1, 0, main_loop.events);
if (!multiqueue_empty(main_loop.events)) {
state_handle_k_event();
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 545a2729e6..a8e15dfdd9 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -145,6 +145,7 @@ EXTERN int vgetc_char INIT(= 0);
EXTERN int cmdline_row;
EXTERN bool redraw_cmdline INIT(= false); // cmdline must be redrawn
+EXTERN bool redraw_mode INIT(= false); // mode must be redrawn
EXTERN bool clear_cmdline INIT(= false); // cmdline must be cleared
EXTERN bool mode_displayed INIT(= false); // mode is being displayed
EXTERN int cmdline_star INIT(= false); // cmdline is encrypted
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c28ffaa22e..a623c14a8e 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1284,7 +1284,7 @@ static void normal_redraw(NormalState *s)
update_screen(INVERTED);
} else if (must_redraw) {
update_screen(0);
- } else if (redraw_cmdline || clear_cmdline) {
+ } else if (redraw_cmdline || clear_cmdline || redraw_mode) {
showmode();
}
@@ -6930,6 +6930,10 @@ static void nv_esc(cmdarg_T *cap)
}
}
+ if (restart_edit != 0) {
+ redraw_mode = true; // remove "-- (insert) --"
+ }
+
restart_edit = 0;
if (cmdwin_type != 0) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 609c2e3017..8cc597fa99 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -591,7 +591,7 @@ int update_screen(int type)
// Clear or redraw the command line. Done last, because scrolling may
// mess up the command line.
- if (clear_cmdline || redraw_cmdline) {
+ if (clear_cmdline || redraw_cmdline || redraw_mode) {
showmode();
}
@@ -5821,12 +5821,26 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
}
}
-// Show the current mode and ruler.
-//
-// If clear_cmdline is true, clear the rest of the cmdline.
-// If clear_cmdline is false there may be a message there that needs to be
-// cleared only if a mode is shown.
-// Return the length of the message (0 if no message).
+/// @return true when postponing displaying the mode message: when not redrawing
+/// or inside a mapping.
+bool skip_showmode(void)
+{
+ // Call char_avail() only when we are going to show something, because it
+ // takes a bit of time. redrawing() may also call char_avail().
+ if (global_busy || msg_silent != 0 || !redrawing() || (char_avail() && !KeyTyped)) {
+ redraw_mode = true; // show mode later
+ return true;
+ }
+ return false;
+}
+
+/// Show the current mode and ruler.
+///
+/// If clear_cmdline is true, clear the rest of the cmdline.
+/// If clear_cmdline is false there may be a message there that needs to be
+/// cleared only if a mode is shown.
+/// If redraw_mode is true show or clear the mode.
+/// @return the length of the message (0 if no message).
int showmode(void)
{
bool need_clear;
@@ -5850,12 +5864,8 @@ int showmode(void)
|| restart_edit != NUL
|| VIsual_active));
if (do_mode || reg_recording != 0) {
- // Don't show mode right now, when not redrawing or inside a mapping.
- // Call char_avail() only when we are going to show something, because
- // it takes a bit of time.
- if (!redrawing() || (char_avail() && !KeyTyped) || msg_silent != 0) {
- redraw_cmdline = true; // show mode later
- return 0;
+ if (skip_showmode()) {
+ return 0; // show mode later
}
bool nwr_save = need_wait_return;
@@ -5989,7 +5999,7 @@ int showmode(void)
}
mode_displayed = true;
- if (need_clear || clear_cmdline) {
+ if (need_clear || clear_cmdline || redraw_mode) {
msg_clr_eos();
}
msg_didout = false; // overwrite this message
@@ -6001,6 +6011,9 @@ int showmode(void)
} else if (clear_cmdline && msg_silent == 0) {
// Clear the whole command line. Will reset "clear_cmdline".
msg_clr_cmdline();
+ } else if (redraw_mode) {
+ msg_pos_mode();
+ msg_clr_eos();
}
// NB: also handles clearing the showmode if it was empty or disabled
@@ -6018,6 +6031,7 @@ int showmode(void)
win_redr_ruler(last, true);
}
redraw_cmdline = false;
+ redraw_mode = false;
clear_cmdline = false;
return length;
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
index ffb8e3facd..579d3a5eb5 100644
--- a/src/nvim/testdir/test_bufline.vim
+++ b/src/nvim/testdir/test_bufline.vim
@@ -19,7 +19,7 @@ func Test_setbufline_getbufline()
let b = bufnr('%')
wincmd w
call assert_equal(1, setbufline(b, 5, ['x']))
- call assert_equal(1, setbufline(1234, 1, ['x']))
+ call assert_equal(1, setbufline(bufnr('$') + 1, 1, ['x']))
call assert_equal(0, setbufline(b, 4, ['d', 'e']))
call assert_equal(['c'], b->getbufline(3))
call assert_equal(['d'], getbufline(b, 4))
diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim
index a02d23b409..e181641a3b 100644
--- a/src/nvim/testdir/test_messages.vim
+++ b/src/nvim/testdir/test_messages.vim
@@ -95,6 +95,65 @@ func Test_echoerr()
call test_ignore_error('RESET')
endfunc
+func Test_mode_message_at_leaving_insert_by_ctrl_c()
+ if !has('terminal') || has('gui_running')
+ return
+ endif
+
+ " Set custom statusline built by user-defined function.
+ let testfile = 'Xtest.vim'
+ call writefile([
+ \ 'func StatusLine() abort',
+ \ ' return ""',
+ \ 'endfunc',
+ \ 'set statusline=%!StatusLine()',
+ \ 'set laststatus=2',
+ \ ], testfile)
+
+ let rows = 10
+ let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows})
+ call term_wait(buf, 200)
+ call assert_equal('run', job_status(term_getjob(buf)))
+
+ call term_sendkeys(buf, "i")
+ call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, rows))})
+ call term_sendkeys(buf, "\<C-C>")
+ call WaitForAssert({-> assert_match('^\s*$', term_getline(buf, rows))})
+
+ call term_sendkeys(buf, ":qall!\<CR>")
+ call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))})
+ exe buf . 'bwipe!'
+ call delete(testfile)
+endfunc
+
+func Test_mode_message_at_leaving_insert_with_esc_mapped()
+ if !has('terminal') || has('gui_running')
+ return
+ endif
+
+ " Set custom statusline built by user-defined function.
+ let testfile = 'Xtest.vim'
+ call writefile([
+ \ 'set laststatus=2',
+ \ 'inoremap <Esc> <Esc>00',
+ \ ], testfile)
+
+ let rows = 10
+ let buf = term_start([GetVimProg(), '--clean', '-S', testfile], {'term_rows': rows})
+ call term_wait(buf, 200)
+ call assert_equal('run', job_status(term_getjob(buf)))
+
+ call term_sendkeys(buf, "i")
+ call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, rows))})
+ call term_sendkeys(buf, "\<Esc>")
+ call WaitForAssert({-> assert_match('^\s*$', term_getline(buf, rows))})
+
+ call term_sendkeys(buf, ":qall!\<CR>")
+ call WaitForAssert({-> assert_equal('dead', job_status(term_getjob(buf)))})
+ exe buf . 'bwipe!'
+ call delete(testfile)
+endfunc
+
func Test_echospace()
set noruler noshowcmd laststatus=1
call assert_equal(&columns - 1, v:echospace)
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 7cb70aa2af..523b9b8781 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source view_util.vim
+source screendump.vim
func Setup_NewWindow()
10new
@@ -2038,9 +2039,9 @@ func Test_normal33_g_cmd2()
call assert_equal(2, line('.'))
call assert_fails(':norm! g;', 'E662')
call assert_fails(':norm! g,', 'E663')
- let &ul=&ul
+ let &ul = &ul
call append('$', ['a', 'b', 'c', 'd'])
- let &ul=&ul
+ let &ul = &ul
call append('$', ['Z', 'Y', 'X', 'W'])
let a = execute(':changes')
call assert_match('2\s\+0\s\+2', a)
@@ -2889,6 +2890,20 @@ func Test_message_when_using_ctrl_c()
bwipe!
endfunc
+func Test_mode_updated_after_ctrl_c()
+ CheckScreendump
+
+ let buf = RunVimInTerminal('', {'rows': 5})
+ call term_sendkeys(buf, "i")
+ call term_sendkeys(buf, "\<C-O>")
+ " wait a moment so that the "-- (insert) --" message is displayed
+ call TermWait(buf, 50)
+ call term_sendkeys(buf, "\<C-C>")
+ call VerifyScreenDump(buf, 'Test_mode_updated_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for '[m', ']m', '[M' and ']M'
" Jumping to beginning and end of methods in Java-like languages
func Test_java_motion()