diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index fd1d24e3e8..493b590971 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -5848,9 +5848,13 @@ mode([expr]) Return a string that indicates the current mode. S Select by line CTRL-S Select blockwise i Insert + ic Insert mode completion |compl-generic| + ix Insert mode |i_CTRL-X| completion R Replace |R| + Rc Replace mode completion |compl-generic| Rv Virtual Replace |gR| - c Command-line + Rx Replace mode |i_CTRL-X| completion + c Command-line editing cv Vim Ex mode |gQ| ce Normal Ex mode |Q| r Hit-enter prompt diff --git a/src/evalfunc.c b/src/evalfunc.c index 1cd22f8080..6b98897c21 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -7802,21 +7802,26 @@ f_mode(typval_T *argvars, typval_T *rettv) } else #endif - if (State & REPLACE_FLAG) - buf[0] = 'R'; - else - buf[0] = 'i'; + { + if (State & REPLACE_FLAG) + buf[0] = 'R'; + else + buf[0] = 'i'; +#ifdef FEAT_INS_EXPAND + if (ins_compl_active()) + buf[1] = 'c'; + else if (ctrl_x_mode == 1) + buf[1] = 'x'; +#endif + } } - else if (State & CMDLINE) + else if ((State & CMDLINE) || exmode_active) { buf[0] = 'c'; - if (exmode_active) + if (exmode_active == EXMODE_VIM) buf[1] = 'v'; - } - else if (exmode_active) - { - buf[0] = 'c'; - buf[1] = 'e'; + else if (exmode_active == EXMODE_NORMAL) + buf[1] = 'e'; } else { diff --git a/src/screen.c b/src/screen.c index c11bcca46f..c01a4ee9bc 100644 --- a/src/screen.c +++ b/src/screen.c @@ -777,6 +777,57 @@ update_screen(int type) #endif } +#if defined(FEAT_SIGNS) || defined(FEAT_GUI) || defined(FEAT_CONCEAL) +/* + * Prepare for updating one or more windows. + * Caller must check for "updating_screen" already set to avoid recursiveness. + */ + static void +update_prepare(void) +{ + cursor_off(); + updating_screen = TRUE; +#ifdef FEAT_GUI + /* Remove the cursor before starting to do anything, because scrolling may + * make it difficult to redraw the text under it. */ + if (gui.in_use) + gui_undraw_cursor(); +#endif +#ifdef FEAT_SEARCH_EXTRA + start_search_hl(); +#endif +} + +/* + * Finish updating one or more windows. + */ + static void +update_finish(void) +{ + if (redraw_cmdline) + showmode(); + +# ifdef FEAT_SEARCH_EXTRA + end_search_hl(); +# endif + + updating_screen = FALSE; + +# ifdef FEAT_GUI + gui_may_resize_shell(); + + /* Redraw the cursor and update the scrollbars when all screen updating is + * done. */ + if (gui.in_use) + { + out_flush(); /* required before updating the cursor */ + gui_update_cursor(FALSE, FALSE); + gui_update_scrollbars(FALSE); + } +# endif +} +#endif + #if defined(FEAT_CONCEAL) || defined(PROTO) /* * Return TRUE if the cursor line in window "wp" may be concealed, according @@ -826,17 +877,12 @@ update_single_line(win_T *wp, linenr_T lnum) /* Don't do anything if the screen structures are (not yet) valid. */ if (!screen_valid(TRUE) || updating_screen) return; - updating_screen = TRUE; if (lnum >= wp->w_topline && lnum < wp->w_botline && foldedCount(wp, lnum, &win_foldinfo) == 0) { -# ifdef FEAT_GUI - /* Remove the cursor before starting to do anything, because scrolling - * may make it difficult to redraw the text under it. */ - if (gui.in_use) - gui_undraw_cursor(); -# endif + update_prepare(); + row = 0; for (j = 0; j < wp->w_lines_valid; ++j) { @@ -856,68 +902,10 @@ update_single_line(win_T *wp, linenr_T lnum) } row += wp->w_lines[j].wl_size; } -# ifdef FEAT_GUI - /* Redraw the cursor */ - if (gui.in_use) - { - out_flush(); /* required before updating the cursor */ - gui_update_cursor(FALSE, FALSE); - } -# endif + + update_finish(); } need_cursor_line_redraw = FALSE; - updating_screen = FALSE; -} -#endif - -#if defined(FEAT_SIGNS) || defined(FEAT_GUI) -/* - * Prepare for updating one or more windows. - * Caller must check for "updating_screen" already set to avoid recursiveness. - */ - static void -update_prepare(void) -{ - cursor_off(); - updating_screen = TRUE; -#ifdef FEAT_GUI - /* Remove the cursor before starting to do anything, because scrolling may - * make it difficult to redraw the text under it. */ - if (gui.in_use) - gui_undraw_cursor(); -#endif -#ifdef FEAT_SEARCH_EXTRA - start_search_hl(); -#endif -} - -/* - * Finish updating one or more windows. - */ - static void -update_finish(void) -{ - if (redraw_cmdline) - showmode(); - -# ifdef FEAT_SEARCH_EXTRA - end_search_hl(); -# endif - - updating_screen = FALSE; - -# ifdef FEAT_GUI - gui_may_resize_shell(); - - /* Redraw the cursor and update the scrollbars when all screen updating is - * done. */ - if (gui.in_use) - { - out_flush(); /* required before updating the cursor */ - gui_update_cursor(FALSE, FALSE); - gui_update_scrollbars(FALSE); - } -# endif } #endif diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index c7028d2a66..c2260c7b7f 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -153,12 +153,13 @@ endif " Names of flaky tests. let s:flaky = [ - \ 'Test_reltime()', - \ 'Test_nb_basic()', - \ 'Test_communicate()', \ 'Test_close_and_exit_cb()', + \ 'Test_collapse_buffers()', + \ 'Test_communicate()', + \ 'Test_nb_basic()', \ 'Test_pipe_through_sort_all()', \ 'Test_pipe_through_sort_some()' + \ 'Test_reltime()', \ ] " Locate Test_ functions and execute them. diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 38f772378f..e2dcb4fb76 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -304,4 +304,89 @@ func Test_toupper() call assert_equal("Ⱥ Ⱦ", toupper("ⱥ ⱦ")) endfunc +" Tests for the mode() function +let current_modes = '' +func! Save_mode() + let g:current_modes = mode(0) . '-' . mode(1) + return '' +endfunc +func! Test_mode() + new + call append(0, ["Blue Ball Black", "Brown Band Bowl", ""]) + + inoremap =Save_mode() + + normal! 3G + exe "normal i\\" + call assert_equal('i-i', g:current_modes) + exe "normal i\uBa\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iBro\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iBa\\\u" + call assert_equal('i-ix', g:current_modes) + exe "normal iBa\\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iBro\\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iBro\\\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iCom\\\u" + call assert_equal('i-ic', g:current_modes) + exe "normal iCom\\\\u" + call assert_equal('i-ic', g:current_modes) + + exe "normal RBa\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RBro\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RBa\\\u" + call assert_equal('R-Rx', g:current_modes) + exe "normal RBa\\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RBro\\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RBro\\\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RCom\\\u" + call assert_equal('R-Rc', g:current_modes) + exe "normal RCom\\\\u" + call assert_equal('R-Rc', g:current_modes) + + call assert_equal('n', mode(0)) + call assert_equal('n', mode(1)) + + " How to test operator-pending mode? + + call feedkeys("v", 'xt') + call assert_equal('v', mode()) + call assert_equal('v', mode(1)) + call feedkeys("\V", 'xt') + call assert_equal('V', mode()) + call assert_equal('V', mode(1)) + call feedkeys("\\", 'xt') + call assert_equal("\", mode()) + call assert_equal("\", mode(1)) + call feedkeys("\", 'xt') + + call feedkeys("gh", 'xt') + call assert_equal('s', mode()) + call assert_equal('s', mode(1)) + call feedkeys("\gH", 'xt') + call assert_equal('S', mode()) + call assert_equal('S', mode(1)) + call feedkeys("\g\", 'xt') + call assert_equal("\", mode()) + call assert_equal("\", mode(1)) + call feedkeys("\", 'xt') + + call feedkeys(":echo \=Save_mode()\\", 'xt') + call assert_equal('c-c', g:current_modes) + call feedkeys("gQecho \=Save_mode()\\vi\", 'xt') + call assert_equal('c-cv', g:current_modes) + " How to test Ex mode? + + bwipe! + iunmap +endfunc diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 306eb2faea..fa8012ad41 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -110,6 +110,8 @@ func Test_map_langmap() call feedkeys(":call append(line('$'), '+')\", "xt") call assert_equal('+', getline('$')) + iunmap a + iunmap c set nomodified endfunc @@ -120,7 +122,7 @@ func Test_map_feedkeys() $-1 call feedkeys("0qqdw.ifoo\qj0@q\", "xt") call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$'))) - unmap . + nunmap . set nomodified endfunc diff --git a/src/testdir/unix.vim b/src/testdir/unix.vim index 2290ec9cbd..b82c63c389 100644 --- a/src/testdir/unix.vim +++ b/src/testdir/unix.vim @@ -2,9 +2,12 @@ " Always use "sh", don't use the value of "$SHELL". set shell=sh -" While some tests overwrite $HOME to prevent them from polluting user files, -" we need to remember the original value so that we can tell external systems -" where to ask about their own user settings. -let g:tester_HOME = $HOME +" Only when the +eval feature is present. +if 1 + " While some tests overwrite $HOME to prevent them from polluting user files, + " we need to remember the original value so that we can tell external systems + " where to ask about their own user settings. + let g:tester_HOME = $HOME +endif source setup.vim diff --git a/src/version.c b/src/version.c index b09c634158..3d3ba5fe1a 100644 --- a/src/version.c +++ b/src/version.c @@ -779,6 +779,14 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 286, +/**/ + 285, +/**/ + 284, +/**/ + 283, /**/ 282, /**/