diff options
36 files changed, 1646 insertions, 278 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 8d0738dd29..3958fb05e9 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1407,16 +1407,20 @@ void set_curbuf(buf_T *buf, int action) } if (bufref_valid(&prevbufref) && !aborting()) { win_T *previouswin = curwin; - if (prevbuf == curbuf) - u_sync(FALSE); - close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf, - unload ? action : (action == DOBUF_GOTO - && !P_HID(prevbuf) - && !bufIsChanged( - prevbuf)) ? DOBUF_UNLOAD : 0, FALSE); - if (curwin != previouswin && win_valid(previouswin)) - /* autocommands changed curwin, Grr! */ + if (prevbuf == curbuf) { + u_sync(false); + } + close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, + prevbuf, + unload + ? action + : (action == DOBUF_GOTO && !buf_hide(prevbuf) + && !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0, + false); + if (curwin != previouswin && win_valid(previouswin)) { + // autocommands changed curwin, Grr! curwin = previouswin; + } } } /* An autocommand may have deleted "buf", already entered it (e.g., when @@ -4413,12 +4417,12 @@ do_arg_all ( } wp->w_arg_idx = i; - if (i == opened_len && !keep_tabs) { /* close this window */ - if (P_HID(buf) || forceit || buf->b_nwindows > 1 + if (i == opened_len && !keep_tabs) { // close this window + if (buf_hide(buf) || forceit || buf->b_nwindows > 1 || !bufIsChanged(buf)) { /* If the buffer was changed, and we would like to hide it, * try autowriting. */ - if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) { + if (!buf_hide(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) { bufref_T bufref; set_bufref(&bufref, buf); (void)autowrite(buf, false); @@ -4433,7 +4437,7 @@ do_arg_all ( && (first_tabpage->tp_next == NULL || !had_tab)) { use_firstwin = true; } else { - win_close(wp, !P_HID(buf) && !bufIsChanged(buf)); + win_close(wp, !buf_hide(buf) && !bufIsChanged(buf)); // check if autocommands removed the next window if (!win_valid(wpnext)) { // start all over... @@ -4511,14 +4515,15 @@ do_arg_all ( new_curwin = curwin; new_curtab = curtab; } - (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL, - ECMD_ONE, - ((P_HID(curwin->w_buffer) - || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0) - + ECMD_OLDBUF, curwin); - if (use_firstwin) - ++autocmd_no_leave; - use_firstwin = FALSE; + (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL, ECMD_ONE, + ((buf_hide(curwin->w_buffer) + || bufIsChanged(curwin->w_buffer)) + ? ECMD_HIDE : 0) + ECMD_OLDBUF, + curwin); + if (use_firstwin) { + autocmd_no_leave++; + } + use_firstwin = false; } os_breakcheck(); @@ -4705,14 +4710,14 @@ void ex_buffer_all(exarg_T *eap) * Close superfluous windows. */ for (wp = lastwin; open_wins > count; ) { - r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer) - || autowrite(wp->w_buffer, FALSE) == OK); + r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer) + || autowrite(wp->w_buffer, false) == OK); if (!win_valid(wp)) { /* BufWrite Autocommands made the window invalid, start over */ wp = lastwin; } else if (r) { - win_close(wp, !P_HID(wp->w_buffer)); - --open_wins; + win_close(wp, !buf_hide(wp->w_buffer)); + open_wins--; wp = lastwin; } else { wp = wp->w_prev; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 9cfcecf8ad..2873f76ce0 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2013,9 +2013,10 @@ int getfile(int fnum, char_u *ffname, char_u *sfname, int setpm, linenr_T lnum, } else other = (fnum != curbuf->b_fnum); - if (other) - ++no_wait_return; /* don't wait for autowrite message */ - if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf) + if (other) { + no_wait_return++; // don't wait for autowrite message + } + if (other && !forceit && curbuf->b_nwindows == 1 && !buf_hide(curbuf) && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL) { if (p_confirm && p_write) dialog_changed(curbuf, FALSE); @@ -2032,17 +2033,19 @@ int getfile(int fnum, char_u *ffname, char_u *sfname, int setpm, linenr_T lnum, if (setpm) setpcmark(); if (!other) { - if (lnum != 0) + if (lnum != 0) { curwin->w_cursor.lnum = lnum; + } check_cursor_lnum(); beginline(BL_SOL | BL_FIX); - retval = 0; /* it's in the same file */ + retval = 0; // it's in the same file } else if (do_ecmd(fnum, ffname, sfname, NULL, lnum, - (P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0), - curwin) == OK) - retval = -1; /* opened another file */ - else - retval = 1; /* error encountered */ + (buf_hide(curbuf) ? ECMD_HIDE : 0) + + (forceit ? ECMD_FORCEIT : 0), curwin) == OK) { + retval = -1; // opened another file + } else { + retval = 1; // error encountered + } theend: xfree(free_me); diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 5975ca43e6..821c050c50 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -1343,7 +1343,7 @@ void dialog_changed(buf_T *buf, int checkall) /// hidden, autowriting it or unloading it. bool can_abandon(buf_T *buf, int forceit) { - return P_HID(buf) + return buf_hide(buf) || !bufIsChanged(buf) || buf->b_nwindows > 1 || autowrite(buf, forceit) == OK @@ -1860,12 +1860,12 @@ void do_argfile(exarg_T *eap, int argn) // if 'hidden' set, only check for changed file when re-editing // the same buffer other = true; - if (P_HID(curbuf)) { + if (buf_hide(curbuf)) { p = (char_u *)fix_fname((char *)alist_name(&ARGLIST[argn])); other = otherfile(p); xfree(p); } - if ((!P_HID(curbuf) || !other) + if ((!buf_hide(curbuf) || !other) && check_changed(curbuf, CCGD_AW | (other ? 0 : CCGD_MULTWIN) | (eap->forceit ? CCGD_FORCEIT : 0) @@ -1885,7 +1885,7 @@ void do_argfile(exarg_T *eap, int argn) // argument index. if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL, eap, ECMD_LAST, - (P_HID(curwin->w_buffer) ? ECMD_HIDE : 0) + (buf_hide(curwin->w_buffer) ? ECMD_HIDE : 0) + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL) { curwin->w_arg_idx = old_arg_idx; } else if (eap->cmdidx != CMD_argdo) { @@ -1902,7 +1902,7 @@ void ex_next(exarg_T *eap) // check for changed buffer now, if this fails the argument list is not // redefined. - if (P_HID(curbuf) + if (buf_hide(curbuf) || eap->cmdidx == CMD_snext || !check_changed(curbuf, CCGD_AW | (eap->forceit ? CCGD_FORCEIT : 0) @@ -2008,7 +2008,7 @@ void ex_listdo(exarg_T *eap) if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo - || P_HID(curbuf) + || buf_hide(curbuf) || !check_changed(curbuf, CCGD_AW | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) { @@ -3840,7 +3840,7 @@ void ex_drop(exarg_T *eap) // to split the current window or data could be lost. // Skip the check if the 'hidden' option is set, as in this case the // buffer won't be lost. - if (!P_HID(curbuf)) { + if (!buf_hide(curbuf)) { emsg_off++; split = check_changed(curbuf, CCGD_AW | CCGD_EXCMD); emsg_off--; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index aebc395f56..e1d28b4a9c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5986,13 +5986,12 @@ static void ex_quit(exarg_T *eap) return; } - /* - * If there are more files or windows we won't exit. - */ - if (check_more(FALSE, eap->forceit) == OK && only_one_window()) - exiting = TRUE; - if ((!P_HID(curbuf) - && check_changed(curbuf, (p_awa ? CCGD_AW : 0) + // If there are more files or windows we won't exit. + if (check_more(false, eap->forceit) == OK && only_one_window()) { + exiting = true; + } + if ((!buf_hide(wp->w_buffer) + && check_changed(wp->w_buffer, (p_awa ? CCGD_AW : 0) | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) || check_more(true, eap->forceit) == FAIL @@ -6008,8 +6007,8 @@ static void ex_quit(exarg_T *eap) if (only_one_window() && (ONE_WINDOW || eap->addr_count == 0)) { getout(0); } - /* close window; may free buffer */ - win_close(wp, !P_HID(wp->w_buffer) || eap->forceit); + // close window; may free buffer + win_close(wp, !buf_hide(wp->w_buffer) || eap->forceit); } } @@ -6108,7 +6107,7 @@ ex_win_close ( buf_T *buf = win->w_buffer; need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1); - if (need_hide && !P_HID(buf) && !forceit) { + if (need_hide && !buf_hide(buf) && !forceit) { if ((p_confirm || cmdmod.confirm) && p_write) { bufref_T bufref; set_bufref(&bufref, buf); @@ -6124,11 +6123,12 @@ ex_win_close ( } - /* free buffer when not hiding it or when it's a scratch buffer */ - if (tp == NULL) - win_close(win, !need_hide && !P_HID(buf)); - else - win_close_othertab(win, !need_hide && !P_HID(buf), tp); + // free buffer when not hiding it or when it's a scratch buffer + if (tp == NULL) { + win_close(win, !need_hide && !buf_hide(buf)); + } else { + win_close_othertab(win, !need_hide && !buf_hide(buf), tp); + } } /* @@ -6359,7 +6359,7 @@ static void ex_exit(exarg_T *eap) getout(0); } // Quit current window, may free the buffer. - win_close(curwin, !P_HID(curwin->w_buffer)); + win_close(curwin, !buf_hide(curwin->w_buffer)); } } @@ -6929,24 +6929,23 @@ do_exedit ( empty buffer */ setpcmark(); if (do_ecmd(0, (eap->cmdidx == CMD_enew ? NULL : eap->arg), - NULL, eap, - eap->do_ecmd_lnum, - (P_HID(curbuf) ? ECMD_HIDE : 0) - + (eap->forceit ? ECMD_FORCEIT : 0) - // After a split we can use an existing buffer. - + (old_curwin != NULL ? ECMD_OLDBUF : 0) - + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 ) - , old_curwin == NULL ? curwin : NULL) == FAIL) { - /* Editing the file failed. If the window was split, close it. */ + NULL, eap, eap->do_ecmd_lnum, + (buf_hide(curbuf) ? ECMD_HIDE : 0) + + (eap->forceit ? ECMD_FORCEIT : 0) + // After a split we can use an existing buffer. + + (old_curwin != NULL ? ECMD_OLDBUF : 0) + + (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0) + , old_curwin == NULL ? curwin : NULL) == FAIL) { + // Editing the file failed. If the window was split, close it. if (old_curwin != NULL) { need_hide = (curbufIsChanged() && curbuf->b_nwindows <= 1); - if (!need_hide || P_HID(curbuf)) { + if (!need_hide || buf_hide(curbuf)) { cleanup_T cs; /* Reset the error/interrupt/exception state here so that * aborting() returns FALSE when closing a window. */ enter_cleanup(&cs); - win_close(curwin, !need_hide && !P_HID(curbuf)); + win_close(curwin, !need_hide && !buf_hide(curbuf)); /* Restore the error/interrupt/exception state if not * discarded by a new aborting error, interrupt, or diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 8f585aef73..fbbc8248e8 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5230,12 +5230,12 @@ static void nv_gotofile(cmdarg_T *cap) if (ptr != NULL) { // do autowrite if necessary - if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf)) { + if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf)) { (void)autowrite(curbuf, false); } setpcmark(); (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST, - P_HID(curbuf) ? ECMD_HIDE : 0, curwin); + buf_hide(curbuf) ? ECMD_HIDE : 0, curwin); if (cap->nchar == 'F' && lnum >= 0) { curwin->w_cursor.lnum = lnum; check_cursor_lnum(); diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index b7fb40a7c1..e2e98f251e 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -454,9 +454,6 @@ EXTERN char_u *p_hf; // 'helpfile' EXTERN long p_hh; // 'helpheight' EXTERN char_u *p_hlg; // 'helplang' EXTERN int p_hid; // 'hidden' -// Use P_HID to check if a buffer is to be hidden when it is no longer -// visible in a window. -# define P_HID(buf) (buf_hide(buf)) EXTERN char_u *p_hl; // 'highlight' EXTERN int p_hls; // 'hlsearch' EXTERN long p_hi; // 'history' diff --git a/src/nvim/search.c b/src/nvim/search.c index 5d41ed9c2a..1943e2ca43 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1380,13 +1380,15 @@ int searchc(cmdarg_T *cap, int t_cmd) lastc_bytelen += (*mb_char2bytes)(cap->ncharC2, lastc_bytes + lastc_bytelen); } } - } else { /* repeat previous search */ - if (*lastc == NUL) + } else { // repeat previous search + if (*lastc == NUL && lastc_bytelen == 1) { return FAIL; - if (dir) /* repeat in opposite direction */ + } + if (dir) { // repeat in opposite direction dir = -lastcdir; - else + } else { dir = lastcdir; + } t_cmd = last_t_cmd; c = *lastc; /* For multi-byte re-use last lastc_bytes[] and lastc_bytelen. */ diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index aa5d534530..211ee974fb 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -23,7 +23,6 @@ SCRIPTS_DEFAULT = \ test49.out \ test52.out \ test64.out \ - test73.out \ ifneq ($(OS),Windows_NT) SCRIPTS_DEFAULTS := $(SCRIPTS_DEFAULT) \ @@ -42,17 +41,21 @@ NEW_TESTS ?= \ test_changedtick.res \ test_charsearch.res \ test_cindent.res \ + test_close_count.res \ test_cmdline.res \ test_command_count.res \ test_cscope.res \ test_curswant.res \ test_digraph.res \ test_edit.res \ + test_erasebackword.res \ test_exists.res \ test_diffmode.res \ test_farsi.res \ test_file_size.res \ test_filter_map.res \ + test_find_complete.res \ + test_fixeol.res \ test_findfile.res \ test_fnameescape.res \ test_fold.res \ @@ -72,13 +75,13 @@ NEW_TESTS ?= \ test_langmap.res \ test_let.res \ test_lineending.res \ + test_listdict.res \ + test_listchars.res \ test_makeencoding.res \ test_marks.res \ test_match.res \ test_matchadd_conceal.res \ - test_matchadd_conceal_utf8.res \ test_mksession.res \ - test_mksession_utf8.res \ test_nested_function.res \ test_normal.res \ test_number.res \ @@ -94,7 +97,6 @@ NEW_TESTS ?= \ test_spell.res \ test_stat.res \ test_startup.res \ - test_startup_utf8.res \ test_substitute.res \ test_syntax.res \ test_system.res \ @@ -109,6 +111,8 @@ NEW_TESTS ?= \ test_winbuf_close.res \ test_window_id.res \ test_writefile.res \ + test_alot_latin.res \ + test_alot_utf8.res \ test_alot.res SCRIPTS_GUI := test16.out diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 2d2dc8fbf8..6a7b44a76f 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -95,6 +95,10 @@ func RunTheTest(test) " buffers. %bwipe! + " The test may change the current directory. Save and restore the + " directory after executing the test. + let save_cwd = getcwd() + if exists("*SetUp") try call SetUp() @@ -149,6 +153,8 @@ func RunTheTest(test) break endif endwhile + + exe 'cd ' . save_cwd endfunc func AfterTheTest() diff --git a/src/nvim/testdir/sautest/autoload/footest.vim b/src/nvim/testdir/sautest/autoload/footest.vim index f467bc376d..1e78963a10 100644 --- a/src/nvim/testdir/sautest/autoload/footest.vim +++ b/src/nvim/testdir/sautest/autoload/footest.vim @@ -1,4 +1,4 @@ -" Autoload script used by test55 and test60 +" Autoload script used by test_listdict.vim, test_exists.vim and test_let.vim let footest#x = 1 func footest#F() return 0 diff --git a/src/nvim/testdir/test73.in b/src/nvim/testdir/test73.in deleted file mode 100644 index 9d50f7a789..0000000000 --- a/src/nvim/testdir/test73.in +++ /dev/null @@ -1,168 +0,0 @@ -Tests for find completion. - -STARTTEST -:set wildmode=full -:" Do all test in a separate window to avoid E211 when we recursively -:" delete the Xfind directory during cleanup -:" -:" This will cause a few errors, do it silently. -:set visualbell -:" -:" On windows a stale "Xfind" directory may exist, remove it so that -:" we start from a clean state. -:call delete("Xfind", "rf") -:new -:let cwd=getcwd() -:let test_out = cwd . '/test.out' -:call mkdir('Xfind') -:cd Xfind -:set path= -:find -:exec "w! " . test_out -:close -:new -:set path=. -:find -:exec "w >>" . test_out -:close -:new -:set path=.,, -:find -:exec "w >>" . test_out -:close -:new -:set path=./** -:find -:exec "w >>" . test_out -:close -:new -:" We shouldn't find any file at this point, test.out must be empty. -:call mkdir('in') -:cd in -:call mkdir('path') -:exec "cd " . cwd -:e Xfind/file.txt -SHoly Grail:w -:e Xfind/in/file.txt -SJimmy Hoffa:w -:e Xfind/in/stuff.txt -SAnother Holy Grail:w -:e Xfind/in/path/file.txt -SE.T.:w -:set path=Xfind/** -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:" Rerun the previous three find completions, using fullpath in 'path' -:exec "set path=" . cwd . "/Xfind/**" -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:" Same steps again, using relative and fullpath items that point to the same -:" recursive location. -:" This is to test that there are no duplicates in the completion list. -:exec "set path+=Xfind/**" -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:find file -:exec "w >>" . test_out -:find file -:" Test find completion for directory of current buffer, which at this point -:" is Xfind/in/file.txt. -:set path=. -:find st -:exec "w >>" . test_out -:" Test find completion for empty path item ",," which is the current directory -:cd Xfind -:set path=,, -:find f -:exec "w >>" . test_out -:" Test shortening of -:" -:" foo/x/bar/voyager.txt -:" foo/y/bar/voyager.txt -:" -:" When current directory is above foo/ they should be shortened to (in order -:" of appearance): -:" -:" x/bar/voyager.txt -:" y/bar/voyager.txt -:call mkdir('foo') -:cd foo -:call mkdir('x') -:call mkdir('y') -:cd x -:call mkdir('bar') -:cd .. -:cd y -:call mkdir('bar') -:cd .. -:cd .. -:" We should now be in the Xfind directory -:e foo/x/bar/voyager.txt -SVoyager 1:w -:e foo/y/bar/voyager.txt -SVoyager 2:w -:exec "set path=" . cwd . "/Xfind/**" -:find voyager -:exec "w >>" . test_out -:find voyager -:exec "w >>" . test_out -:" -:" When current directory is .../foo/y/bar they should be shortened to (in -:" order of appearance): -:" -:" ./voyager.txt -:" x/bar/voyager.txt -:cd foo -:cd y -:cd bar -:find voyager -:exec "w >> " . test_out -:find voyager -:exec "w >> " . test_out -:" Check the opposite too: -:cd .. -:cd .. -:cd x -:cd bar -:find voyager -:exec "w >> " . test_out -:find voyager -:exec "w >> " . test_out -:" Check for correct handling of shorten_fname()'s behavior on windows -:exec "cd " . cwd . "/Xfind/in" -:find file -:exec "w >>" . test_out -:" Test for relative to current buffer 'path' item -:exec "cd " . cwd . "/Xfind/" -:set path=./path -:" Open the file where Jimmy Hoffa is found -:e in/file.txt -:" Find the file containing 'E.T.' in the Xfind/in/path directory -:find file -:exec "w >>" . test_out -:" -:" Test that completion works when path=.,, -:" -:set path=.,, -:" Open Jimmy Hoffa file -:e in/file.txt -:exec "w >>" . test_out -:" Search for the file containing Holy Grail in same directory as in/path.txt -:find stu -:exec "w >>" . test_out -:q -:exec "cd " . cwd -:call delete("Xfind", "rf") -:qa! -ENDTEST - diff --git a/src/nvim/testdir/test73.ok b/src/nvim/testdir/test73.ok deleted file mode 100644 index 90efab756f..0000000000 --- a/src/nvim/testdir/test73.ok +++ /dev/null @@ -1,21 +0,0 @@ -Holy Grail -Jimmy Hoffa -E.T. -Holy Grail -Jimmy Hoffa -E.T. -Holy Grail -Jimmy Hoffa -E.T. -Another Holy Grail -Holy Grail -Voyager 1 -Voyager 2 -Voyager 2 -Voyager 1 -Voyager 1 -Voyager 2 -Jimmy Hoffa -E.T. -Jimmy Hoffa -Another Holy Grail diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 735c4bb691..9bf6df3251 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -7,7 +7,6 @@ source test_cursor_func.vim source test_ex_undo.vim source test_execute_func.vim source test_expr.vim -source test_expr_utf8.vim source test_feedkeys.vim source test_filter_cmd.vim source test_filter_map.vim @@ -28,6 +27,7 @@ source test_popup.vim source test_recover.vim source test_regexp_utf8.vim source test_source_utf8.vim +source test_sha256.vim source test_statusline.vim source test_syn_attr.vim source test_tabline.vim diff --git a/src/nvim/testdir/test_alot_latin.vim b/src/nvim/testdir/test_alot_latin.vim new file mode 100644 index 0000000000..ebb3bde4ce --- /dev/null +++ b/src/nvim/testdir/test_alot_latin.vim @@ -0,0 +1,10 @@ +" A series of tests that can run in one Vim invocation. +" This makes testing go faster, since Vim doesn't need to restart. + +" These tests use latin1 'encoding'. Setting 'encoding' is in the individual +" files, so that they can be run by themselves. + +" Nvim does not allow setting 'encoding', so skip this test group. +finish + +source test_regexp_latin.vim diff --git a/src/nvim/testdir/test_alot_utf8.vim b/src/nvim/testdir/test_alot_utf8.vim new file mode 100644 index 0000000000..648d806a94 --- /dev/null +++ b/src/nvim/testdir/test_alot_utf8.vim @@ -0,0 +1,17 @@ +" A series of tests that can run in one Vim invocation. +" This makes testing go faster, since Vim doesn't need to restart. + +" These tests use utf8 'encoding'. Setting 'encoding' is already done in +" runtest.vim. Checking for the multi_byte feature is in the individual +" files, so that they can be run by themselves. + +source test_charsearch_utf8.vim +source test_expr_utf8.vim +source test_listlbr_utf8.vim +source test_matchadd_conceal_utf8.vim +source test_mksession_utf8.vim +source test_regexp_utf8.vim +source test_source_utf8.vim +source test_startup_utf8.vim +source test_utf8.vim +source test_utf8_comparisons.vim diff --git a/src/nvim/testdir/test_charsearch_utf8.vim b/src/nvim/testdir/test_charsearch_utf8.vim new file mode 100644 index 0000000000..ade7dd408c --- /dev/null +++ b/src/nvim/testdir/test_charsearch_utf8.vim @@ -0,0 +1,22 @@ +" Tests for related f{char} and t{char} using utf-8. +if !has('multi_byte') + finish +endif + +" Test for t,f,F,T movement commands +function! Test_search_cmds() + new! + call setline(1, "・最åˆã‹ã‚‰æœ€å¾Œã¾ã§æœ€å¼·ã®Vimã¯æœ€é«˜") + 1 + normal! f最 + call assert_equal([0, 1, 4, 0], getpos('.')) + normal! ; + call assert_equal([0, 1, 16, 0], getpos('.')) + normal! 2; + call assert_equal([0, 1, 43, 0], getpos('.')) + normal! , + call assert_equal([0, 1, 28, 0], getpos('.')) + bw! +endfunction + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_close_count.vim b/src/nvim/testdir/test_close_count.vim new file mode 100644 index 0000000000..1f9adba32d --- /dev/null +++ b/src/nvim/testdir/test_close_count.vim @@ -0,0 +1,174 @@ + +" Tests for :[count]close! command +func Test_close_count() + enew! | only + + let wids = [win_getid()] + for i in range(5) + new + call add(wids, win_getid()) + endfor + + 4wincmd w + close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) + + 1close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) + + $close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1]], ids) + + 1wincmd w + 2close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[1]], ids) + + 1wincmd w + new + call add(wids, win_getid()) + new + call add(wids, win_getid()) + 2wincmd w + -1close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[6], wids[4], wids[1]], ids) + + 2wincmd w + +1close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[6], wids[4]], ids) + + only! +endfunc + +" Tests for :[count]hide command +func Test_hide_count() + enew! | only + + let wids = [win_getid()] + for i in range(5) + new + call add(wids, win_getid()) + endfor + + 4wincmd w + .hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) + + 1hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) + + $hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1]], ids) + + 1wincmd w + 2hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[1]], ids) + + 1wincmd w + new + call add(wids, win_getid()) + new + call add(wids, win_getid()) + 3wincmd w + -hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[7], wids[4], wids[1]], ids) + + 2wincmd w + +hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[7], wids[4]], ids) + + only! +endfunc + +" Tests for :[count]close! command with 'hidden' +func Test_hidden_close_count() + enew! | only + + let wids = [win_getid()] + for i in range(5) + new + call add(wids, win_getid()) + endfor + + set hidden + + $ hide + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[4], wids[3], wids[2], wids[1]], ids) + + $-1 close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[4], wids[3], wids[1]], ids) + + 1wincmd w + .+close! + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[3], wids[1]], ids) + + set nohidden + only! +endfunc + +" Tests for 'CTRL-W c' command to close windows. +func Test_winclose_command() + enew! | only + + let wids = [win_getid()] + for i in range(5) + new + call add(wids, win_getid()) + endfor + + set hidden + + 4wincmd w + exe "normal \<C-W>c" + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) + + exe "normal 1\<C-W>c" + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) + + exe "normal 9\<C-W>c" + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[3], wids[1]], ids) + + 1wincmd w + exe "normal 2\<C-W>c" + let ids = [] + windo call add(ids, win_getid()) + call assert_equal([wids[4], wids[1]], ids) + + set nohidden + only! +endfunc diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 0c54becde8..8f815478c2 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -216,14 +216,16 @@ endfunc func! Test_edit_08() throw 'skipped: moved to test/functional/legacy/edit_spec.lua' " reset insertmode from i_ctrl-r_= + let g:bufnr = bufnr('%') new call setline(1, ['abc']) call cursor(1, 4) - call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(1,'&im', 0)\<cr>",'tnix') + call feedkeys(":set im\<cr>ZZZ\<c-r>=setbufvar(g:bufnr,'&im', 0)\<cr>",'tnix') call assert_equal(['abZZZc'], getline(1,'$')) call assert_equal([0, 1, 1, 0], getpos('.')) call assert_false(0, '&im') bw! + unlet g:bufnr endfunc func! Test_edit_09() @@ -1308,3 +1310,16 @@ func! Test_edit_rightleft() set norightleft bw! endfunc + +func Test_edit_quit() + edit foo.txt + split + new + call setline(1, 'hello') + 3wincmd w + redraw! + call assert_fails('1q', 'E37:') + bwipe! foo.txt + only +endfunc + diff --git a/src/nvim/testdir/test_erasebackword.vim b/src/nvim/testdir/test_erasebackword.vim new file mode 100644 index 0000000000..098d6edfcb --- /dev/null +++ b/src/nvim/testdir/test_erasebackword.vim @@ -0,0 +1,25 @@ + +func Test_erasebackword() + if !has('multi_byte') + return + endif + + set encoding=utf-8 + enew + + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>" + call assert_equal(' wwwã“ã‚“ã«ã¡ã‚世界ワールド', getline('.')) + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>\<C-W>" + call assert_equal(' wwwã“ã‚“ã«ã¡ã‚世界', getline('.')) + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>\<C-W>\<C-W>" + call assert_equal(' wwwã“ã‚“ã«ã¡ã‚', getline('.')) + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>\<C-W>\<C-W>\<C-W>" + call assert_equal(' www', getline('.')) + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>\<C-W>\<C-W>\<C-W>\<C-W>" + call assert_equal(' ', getline('.')) + exe "normal o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim \<C-W>\<C-W>\<C-W>\<C-W>\<C-W>\<C-W>" + call assert_equal('', getline('.')) + + enew! + set encoding& +endfunc diff --git a/src/nvim/testdir/test_expr_utf8.vim b/src/nvim/testdir/test_expr_utf8.vim index 9ea6d8872b..1737a9f745 100644 --- a/src/nvim/testdir/test_expr_utf8.vim +++ b/src/nvim/testdir/test_expr_utf8.vim @@ -3,7 +3,7 @@ if !has('multi_byte') finish endif -func Test_strgetchar_utf8() +func Test_strgetchar() call assert_equal(char2nr('á'), strgetchar('áxb', 0)) call assert_equal(char2nr('x'), strgetchar('áxb', 1)) @@ -16,7 +16,7 @@ func Test_strgetchar_utf8() call assert_equal(char2nr('ã„'), strgetchar('ã‚aã„', 2)) endfunc -func Test_strcharpart_utf8() +func Test_strcharpart() call assert_equal('áxb', strcharpart('áxb', 0)) call assert_equal('á', strcharpart('áxb', 0, 1)) call assert_equal('x', strcharpart('áxb', 1, 1)) diff --git a/src/nvim/testdir/test_find_complete.vim b/src/nvim/testdir/test_find_complete.vim new file mode 100644 index 0000000000..4732109ed0 --- /dev/null +++ b/src/nvim/testdir/test_find_complete.vim @@ -0,0 +1,157 @@ +" Tests for the 'find' command completion. + +" Do all the tests in a separate window to avoid E211 when we recursively +" delete the Xfind directory during cleanup +func Test_find_complete() + set belloff=all + + " On windows a stale "Xfind" directory may exist, remove it so that + " we start from a clean state. + call delete("Xfind", "rf") + let cwd = getcwd() + let test_out = cwd . '/test.out' + call mkdir('Xfind') + cd Xfind + + new + set path= + call assert_fails('call feedkeys(":find\t\n", "xt")', 'E345:') + close + + new + set path=. + call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:') + close + + new + set path=.,, + call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:') + close + + new + set path=./** + call assert_fails('call feedkeys(":find\t\n", "xt")', 'E32:') + close + + " We shouldn't find any file till this point + + call mkdir('in/path', 'p') + exe 'cd ' . cwd + call writefile(['Holy Grail'], 'Xfind/file.txt') + call writefile(['Jimmy Hoffa'], 'Xfind/in/file.txt') + call writefile(['Another Holy Grail'], 'Xfind/in/stuff.txt') + call writefile(['E.T.'], 'Xfind/in/path/file.txt') + + new + set path=Xfind/** + call feedkeys(":find file\t\n", "xt") + call assert_equal('Holy Grail', getline(1)) + call feedkeys(":find file\t\t\n", "xt") + call assert_equal('Jimmy Hoffa', getline(1)) + call feedkeys(":find file\t\t\t\n", "xt") + call assert_equal('E.T.', getline(1)) + + " Rerun the previous three find completions, using fullpath in 'path' + exec "set path=" . cwd . "/Xfind/**" + + call feedkeys(":find file\t\n", "xt") + call assert_equal('Holy Grail', getline(1)) + call feedkeys(":find file\t\t\n", "xt") + call assert_equal('Jimmy Hoffa', getline(1)) + call feedkeys(":find file\t\t\t\n", "xt") + call assert_equal('E.T.', getline(1)) + + " Same steps again, using relative and fullpath items that point to the same + " recursive location. + " This is to test that there are no duplicates in the completion list. + set path+=Xfind/** + call feedkeys(":find file\t\n", "xt") + call assert_equal('Holy Grail', getline(1)) + call feedkeys(":find file\t\t\n", "xt") + call assert_equal('Jimmy Hoffa', getline(1)) + call feedkeys(":find file\t\t\t\n", "xt") + call assert_equal('E.T.', getline(1)) + call feedkeys(":find file\t\t\n", "xt") + + " Test find completion for directory of current buffer, which at this point + " is Xfind/in/file.txt. + set path=. + call feedkeys(":find st\t\n", "xt") + call assert_equal('Another Holy Grail', getline(1)) + + " Test find completion for empty path item ",," which is the current + " directory + cd Xfind + set path=,, + call feedkeys(":find f\t\n", "xt") + call assert_equal('Holy Grail', getline(1)) + + " Test shortening of + " + " foo/x/bar/voyager.txt + " foo/y/bar/voyager.txt + " + " When current directory is above foo/ they should be shortened to (in order + " of appearance): + " + " x/bar/voyager.txt + " y/bar/voyager.txt + call mkdir('foo/x/bar', 'p') + call mkdir('foo/y/bar', 'p') + call writefile(['Voyager 1'], 'foo/x/bar/voyager.txt') + call writefile(['Voyager 2'], 'foo/y/bar/voyager.txt') + + exec "set path=" . cwd . "/Xfind/**" + call feedkeys(":find voyager\t\n", "xt") + call assert_equal('Voyager 1', getline(1)) + call feedkeys(":find voyager\t\t\n", "xt") + call assert_equal('Voyager 2', getline(1)) + + " + " When current directory is .../foo/y/bar they should be shortened to (in + " order of appearance): + " + " ./voyager.txt + " x/bar/voyager.txt + cd foo/y/bar + call feedkeys(":find voyager\t\n", "xt") + call assert_equal('Voyager 2', getline(1)) + call feedkeys(":find voyager\t\t\n", "xt") + call assert_equal('Voyager 1', getline(1)) + + " Check the opposite too: + cd ../../x/bar + call feedkeys(":find voyager\t\n", "xt") + call assert_equal('Voyager 1', getline(1)) + call feedkeys(":find voyager\t\t\n", "xt") + call assert_equal('Voyager 2', getline(1)) + + " Check for correct handling of shorten_fname()'s behavior on windows + exec "cd " . cwd . "/Xfind/in" + call feedkeys(":find file\t\n", "xt") + call assert_equal('Jimmy Hoffa', getline(1)) + + " Test for relative to current buffer 'path' item + exec "cd " . cwd . "/Xfind/" + set path=./path + " Open the file where Jimmy Hoffa is found + e in/file.txt + " Find the file containing 'E.T.' in the Xfind/in/path directory + call feedkeys(":find file\t\n", "xt") + call assert_equal('E.T.', getline(1)) + + " Test that completion works when path=.,, + set path=.,, + " Open Jimmy Hoffa file + e in/file.txt + call assert_equal('Jimmy Hoffa', getline(1)) + + " Search for the file containing Holy Grail in same directory as in/path.txt + call feedkeys(":find stu\t\n", "xt") + call assert_equal('Another Holy Grail', getline(1)) + + enew | only + exe 'cd ' . cwd + call delete('Xfind', 'rf') + set path& +endfunc diff --git a/src/nvim/testdir/test_fixeol.vim b/src/nvim/testdir/test_fixeol.vim new file mode 100644 index 0000000000..32cb059e26 --- /dev/null +++ b/src/nvim/testdir/test_fixeol.vim @@ -0,0 +1,48 @@ +" Tests for 'fixeol' and 'eol' +func Test_fixeol() + " first write two test files – with and without trailing EOL + " use Unix fileformat for consistency + set ff=unix + enew! + call setline('.', 'with eol') + w! XXEol + enew! + set noeol nofixeol + call setline('.', 'without eol') + w! XXNoEol + set eol fixeol + bwipe XXEol XXNoEol + + " try editing files with 'fixeol' disabled + e! XXEol + normal ostays eol + set nofixeol + w! XXTestEol + e! XXNoEol + normal ostays without + set nofixeol + w! XXTestNoEol + bwipe! XXEol XXNoEol XXTestEol XXTestNoEol + set fixeol + + " Append "END" to each file so that we can see what the last written char + " was. + normal ggdGaEND + w >>XXEol + w >>XXNoEol + w >>XXTestEol + w >>XXTestNoEol + + call assert_equal(['with eol', 'END'], readfile('XXEol')) + call assert_equal(['without eolEND'], readfile('XXNoEol')) + call assert_equal(['with eol', 'stays eol', 'END'], readfile('XXTestEol')) + call assert_equal(['without eol', 'stays withoutEND'], + \ readfile('XXTestNoEol')) + + call delete('XXEol') + call delete('XXNoEol') + call delete('XXTestEol') + call delete('XXTestNoEol') + set ff& fixeol& eol& + enew! +endfunc diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim index 46c54e8614..7c6d38d7ec 100644 --- a/src/nvim/testdir/test_fold.vim +++ b/src/nvim/testdir/test_fold.vim @@ -360,3 +360,24 @@ func! Test_move_folds_around_indent() call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)')) bw! endfunc + +" test for patch 7.3.637 +" Cannot catch the error caused by a foldopen when there is no fold. +func Test_foldopen_exception() + enew! + let a = 'No error caught' + try + foldopen + catch + let a = matchstr(v:exception,'^[^ ]*') + endtry + call assert_equal('Vim(foldopen):E490:', a) + + let a = 'No error caught' + try + foobar + catch + let a = matchstr(v:exception,'^[^ ]*') + endtry + call assert_match('E492:', a) +endfunc diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index bdad26a8c7..8707438ede 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -2,6 +2,11 @@ " Test for insert expansion func Test_ins_complete() edit test_ins_complete.vim + " The files in the current directory interferes with the files + " used by this test. So use a separate directory for the test. + call mkdir('Xdir') + cd Xdir + set ff=unix call writefile(["test11\t36Gepeto\t/Tag/", \ "asd\ttest11file\t36G", @@ -89,4 +94,6 @@ func Test_ins_complete() call delete('Xtest11.two') call delete('Xtestdata') set cpt& cot& def& tags& tagbsearch& hidden& + cd .. + call delete('Xdir', 'rf') endfunc diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim new file mode 100644 index 0000000000..57ea7ca5a9 --- /dev/null +++ b/src/nvim/testdir/test_listchars.vim @@ -0,0 +1,63 @@ +" Tests for 'listchars' display with 'list' and :list + +source view_util.vim + +func Test_listchars() + enew! + set ff=unix + set list + + set listchars+=tab:>-,space:.,trail:< + call append(0, [ + \ ' aa ', + \ ' bb ', + \ ' cccc ', + \ 'dd ee ', + \ ' ' + \ ]) + let expected = [ + \ '>-------aa>-----$', + \ '..bb>---<<$', + \ '...cccc><$', + \ 'dd........ee<<>-$', + \ '<$' + \ ] + redraw! + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + set listchars-=trail:< + let expected = [ + \ '>-------aa>-----$', + \ '..bb>---..$', + \ '...cccc>.$', + \ 'dd........ee..>-$', + \ '.$' + \ ] + redraw! + for i in range(1, 5) + call cursor(i, 1) + call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$'))) + endfor + + set listchars+=trail:< + set nolist + normal ggdG + call append(0, [ + \ ' fff ', + \ ' gg ', + \ ' h ', + \ 'iii ', + \ ]) + let l = split(execute("%list"), "\n") + call assert_equal([ + \ '..fff>--<<$', + \ '>-------gg>-----$', + \ '.....h>-$', + \ 'iii<<<<><<$', '$'], l) + + enew! + set listchars& ff& +endfunc diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim new file mode 100644 index 0000000000..023332c90a --- /dev/null +++ b/src/nvim/testdir/test_listdict.vim @@ -0,0 +1,603 @@ +" Tests for the List and Dict types + +func TearDown() + " Run garbage collection after every test + call test_garbagecollect_now() +endfunc + +" Tests for List type + +" List creation +func Test_list_create() + " Creating List directly with different types + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + call assert_equal("[1, 'as''d', [1, 2, function('strlen')], {'a': 1}]", string(l)) + call assert_equal({'a' : 1}, l[-1]) + call assert_equal(1, l[-4]) + let x = 10 + try + let x = l[-5] + catch + call assert_match('E684:', v:exception) + endtry + call assert_equal(10, x) +endfunc + +" List slices +func Test_list_slice() + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + call assert_equal([1, 'as''d', [1, 2, function('strlen')], {'a': 1}], l[:]) + call assert_equal(['as''d', [1, 2, function('strlen')], {'a': 1}], l[1:]) + call assert_equal([1, 'as''d', [1, 2, function('strlen')]], l[:-2]) + call assert_equal([1, 'as''d', [1, 2, function('strlen')], {'a': 1}], l[0:8]) + call assert_equal([], l[8:-1]) +endfunc + +" List identity +func Test_list_identity() + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + let ll = l + let lx = copy(l) + call assert_true(l == ll) + call assert_false(l isnot ll) + call assert_true(l is ll) + call assert_true(l == lx) + call assert_false(l is lx) + call assert_true(l isnot lx) +endfunc + +" removing items with :unlet +func Test_list_unlet() + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + unlet l[2] + call assert_equal([1, 'as''d', {'a': 1}], l) + let l = range(8) + unlet l[:3] + unlet l[1:] + call assert_equal([4], l) + + " removing items out of range: silently skip items that don't exist + let l = [0, 1, 2, 3] + call assert_fails('unlet l[2:1]', 'E684') + let l = [0, 1, 2, 3] + unlet l[2:2] + call assert_equal([0, 1, 3], l) + let l = [0, 1, 2, 3] + unlet l[2:3] + call assert_equal([0, 1], l) + let l = [0, 1, 2, 3] + unlet l[2:4] + call assert_equal([0, 1], l) + let l = [0, 1, 2, 3] + unlet l[2:5] + call assert_equal([0, 1], l) + let l = [0, 1, 2, 3] + call assert_fails('unlet l[-1:2]', 'E684') + let l = [0, 1, 2, 3] + unlet l[-2:2] + call assert_equal([0, 1, 3], l) + let l = [0, 1, 2, 3] + unlet l[-3:2] + call assert_equal([0, 3], l) + let l = [0, 1, 2, 3] + unlet l[-4:2] + call assert_equal([3], l) + let l = [0, 1, 2, 3] + unlet l[-5:2] + call assert_equal([3], l) + let l = [0, 1, 2, 3] + unlet l[-6:2] + call assert_equal([3], l) +endfunc + +" assignment to a list +func Test_list_assign() + let l = [0, 1, 2, 3] + let [va, vb] = l[2:3] + call assert_equal([2, 3], [va, vb]) + call assert_fails('let [va, vb] = l', 'E687') + call assert_fails('let [va, vb] = l[1:1]', 'E688') +endfunc + +" test for range assign +func Test_list_range_assign() + let l = [0] + let l[:] = [1, 2] + call assert_equal([1, 2], l) +endfunc + +" Tests for Dictionary type + +func Test_dict() + " Creating Dictionary directly with different types + let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} + call assert_equal("{'1': 'asd', 'b': [1, 2, function('strlen')], '-1': {'a': 1}}", string(d)) + call assert_equal('asd', d.1) + call assert_equal(['-1', '1', 'b'], sort(keys(d))) + call assert_equal(['asd', [1, 2, function('strlen')], {'a': 1}], values(d)) + let v = [] + for [key, val] in items(d) + call extend(v, [key, val]) + unlet key val + endfor + call assert_equal(['1','asd','b',[1, 2, function('strlen')],'-1',{'a': 1}], v) + + call extend(d, {3:33, 1:99}) + call extend(d, {'b':'bbb', 'c':'ccc'}, "keep") + call assert_fails("call extend(d, {3:333,4:444}, 'error')", 'E737') + call assert_equal({'c': 'ccc', '1': 99, 'b': [1, 2, function('strlen')], '3': 33, '-1': {'a': 1}}, d) + call filter(d, 'v:key =~ ''[ac391]''') + call assert_equal({'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}}, d) +endfunc + +" Dictionary identity +func Test_dict_identity() + let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} + let dd = d + let dx = copy(d) + call assert_true(d == dd) + call assert_false(d isnot dd) + call assert_true(d is dd) + call assert_true(d == dx) + call assert_false(d is dx) + call assert_true(d isnot dx) +endfunc + +" removing items with :unlet +func Test_dict_unlet() + let d = {'b':'bbb', '1': 99, '3': 33, '-1': {'a': 1}} + unlet d.b + unlet d[-1] + call assert_equal({'1': 99, '3': 33}, d) +endfunc + +" manipulating a big Dictionary (hashtable.c has a border of 1000 entries) +func Test_dict_big() + let d = {} + for i in range(1500) + let d[i] = 3000 - i + endfor + call assert_equal([3000, 2900, 2001, 1600, 1501], [d[0], d[100], d[999], d[1400], d[1499]]) + let str = '' + try + let n = d[1500] + catch + let str=substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') + endtry + call assert_equal('Vim(let):E716: 1500', str) + + " lookup each items + for i in range(1500) + call assert_equal(3000 - i, d[i]) + endfor + let i += 1 + + " delete even items + while i >= 2 + let i -= 2 + unlet d[i] + endwhile + call assert_equal('NONE', get(d, 1500 - 100, 'NONE')) + call assert_equal(2999, d[1]) + + " delete odd items, checking value, one intentionally wrong + let d[33] = 999 + let i = 1 + while i < 1500 + if i != 33 + call assert_equal(3000 - i, d[i]) + else + call assert_equal(999, d[i]) + endif + unlet d[i] + let i += 2 + endwhile + call assert_equal({}, d) + unlet d +endfunc + +" Dictionary function +func Test_dict_func() + let d = {} + func d.func(a) dict + return a:a . len(self.data) + endfunc + let d.data = [1,2,3] + call assert_equal('len: 3', d.func('len: ')) + let x = d.func('again: ') + call assert_equal('again: 3', x) + let Fn = d.func + call assert_equal('xxx3', Fn('xxx')) +endfunc + +" Function in script-local List or Dict +func Test_script_local_dict_func() + let g:dict = {} + function g:dict.func() dict + return 'g:dict.func' . self.foo[1] . self.foo[0]('asdf') + endfunc + let g:dict.foo = ['-', 2, 3] + call insert(g:dict.foo, function('strlen')) + call assert_equal('g:dict.func-4', g:dict.func()) + unlet g:dict +endfunc + +" Nasty: remove func from Dict that's being called (works) +func Test_dict_func_remove_in_use() + let d = {1:1} + func d.func(a) + return "a:" . a:a + endfunc + let expected = 'a:' . string(get(d, 'func')) + call assert_equal(expected, d.func(string(remove(d, 'func')))) +endfunc + +" Nasty: deepcopy() dict that refers to itself (fails when noref used) +func Test_dict_deepcopy() + let d = {1:1, 2:2} + let l = [4, d, 6] + let d[3] = l + let dc = deepcopy(d) + call assert_fails('call deepcopy(d, 1)', 'E698') + let l2 = [0, l, l, 3] + let l[1] = l2 + let l3 = deepcopy(l2) + call assert_true(l3[1] is l3[2]) +endfunc + +" Locked variables +func Test_list_locked_var() + let expected = [ + \ [['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1000-000', 'ppppppF'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1100-100', 'ppFppFF'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1110-110', 'pFFpFFF'], + \ ['0010-010', 'pFppFpp'], + \ ['0000-000', 'ppppppp']], + \ [['1111-111', 'FFFFFFF'], + \ ['0011-011', 'FFpFFpp'], + \ ['0000-000', 'ppppppp']] + \ ] + for depth in range(5) + for u in range(3) + unlet! l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") + call assert_equal(expected[depth][u][0], ps) + let ps = '' + try + let l[1][1][0] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1][1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2]['6'][7] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2][6] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + call assert_equal(expected[depth][u][1], ps) + endfor + endfor +endfunc + +" Unletting locked variables +func Test_list_locked_var_unlet() + let expected = [ + \ [['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1000-000', 'ppFppFp'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1100-100', 'pFFpFFp'], + \ ['0000-000', 'ppppppp'], + \ ['0000-000', 'ppppppp']], + \ [['1110-110', 'FFFFFFp'], + \ ['0010-010', 'FppFppp'], + \ ['0000-000', 'ppppppp']], + \ [['1111-111', 'FFFFFFp'], + \ ['0011-011', 'FppFppp'], + \ ['0000-000', 'ppppppp']] + \ ] + + for depth in range(5) + for u in range(3) + unlet! l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") + call assert_equal(expected[depth][u][0], ps) + let ps = '' + try + unlet l[2]['6'][7] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2][6] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1][0] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l + let ps .= 'p' + catch + let ps .= 'F' + endtry + call assert_equal(expected[depth][u][1], ps) + endfor + endfor +endfunc + +" Locked variables and :unlet or list / dict functions + +" No :unlet after lock on dict: +func Test_dict_lock_unlet() + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + call assert_fails('unlet d.a', 'E741') +endfunc + +" unlet after lock on dict item +func Test_dict_item_lock_unlet() + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + unlet d.a + call assert_equal({'b' : 100}, d) +endfunc + +" filter() after lock on dict item +func Test_dict_lock_filter() + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + call filter(d, 'v:key != "a"') + call assert_equal({'b' : 100}, d) +endfunc + +" map() after lock on dict +func Test_dict_lock_map() + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + call map(d, 'v:val + 200') + call assert_equal({'a' : 299, 'b' : 300}, d) +endfunc + +" No extend() after lock on dict item +func Test_dict_lock_extend() + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + call assert_fails("call extend(d, {'a' : 123})", 'E741') + call assert_equal({'a': 99, 'b': 100}, d) +endfunc + +" No remove() of write-protected scope-level variable +func! Tfunc(this_is_a_long_parameter_name) + call assert_fails("call remove(a:, 'this_is_a_long_parameter_name')", 'E795') +endfun +func Test_dict_scope_var_remove() + call Tfunc('testval') +endfunc + +" No extend() of write-protected scope-level variable +func! Tfunc(this_is_a_long_parameter_name) + call assert_fails("call extend(a:, {'this_is_a_long_parameter_name': 1234})", 'E742') +endfunc +func Test_dict_scope_var_extend() + call Tfunc('testval') +endfunc + +" No :unlet of variable in locked scope +func Test_lock_var_unlet() + let b:testvar = 123 + lockvar 1 b: + call assert_fails('unlet b:testvar', 'E741:') + unlockvar 1 b: + unlet! b:testvar +endfunc + +" No :let += of locked list variable +func Test_let_lock_list() + let l = ['a', 'b', 3] + lockvar 1 l + call assert_fails("let l += ['x']", 'E741:') + call assert_equal(['a', 'b', 3], l) + + unlet l + let l = [1, 2, 3, 4] + lockvar! l + call assert_equal([1, 2, 3, 4], l) + unlockvar l[1] + call assert_fails('unlet l[0:1]', 'E741:') + call assert_equal([1, 2, 3, 4], l) + call assert_fails('unlet l[1:2]', 'E741:') + call assert_equal([1, 2, 3, 4], l) + unlockvar l[1] + call assert_fails('let l[0:1] = [0, 1]', 'E741:') + call assert_equal([1, 2, 3, 4], l) + call assert_fails('let l[1:2] = [0, 1]', 'E741:') + call assert_equal([1, 2, 3, 4], l) + unlet l +endfunc + +" lockvar/islocked() triggering script autoloading +func Test_lockvar_script_autoload() + let old_rtp = &rtp + set rtp+=./sautest + lockvar g:footest#x + unlockvar g:footest#x + call assert_equal(-1, islocked('g:footest#x')) + call assert_equal(0, exists('g:footest#x')) + call assert_equal(1, g:footest#x) + let &rtp = old_rtp +endfunc + +" a:000 function argument test +func s:arg_list_test(...) + call assert_fails('let a:000 = [1, 2]', 'E46:') + call assert_fails('let a:000[0] = 9', 'E742:') + call assert_fails('let a:000[2] = [9, 10]', 'E742:') + call assert_fails('let a:000[3] = {9 : 10}', 'E742:') + + " now the tests that should pass + let a:000[2][1] = 9 + call extend(a:000[2], [5, 6]) + let a:000[3][5] = 8 + let a:000[3]['a'] = 12 + call assert_equal([1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}], a:000) +endfunc + +func Test_func_arg_list() + call s:arg_list_test(1, 2, [3, 4], {5: 6}) +endfunc + +" Tests for reverse(), sort(), uniq() +func Test_reverse_sort_uniq() + let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] + call assert_equal(['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5], uniq(copy(l))) + call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(l)) + call assert_equal([1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'], reverse(reverse(l))) + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(l)) + call assert_equal([[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'], reverse(sort(l))) + call assert_equal(['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]], sort(reverse(sort(l)))) + call assert_equal(['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]], uniq(sort(l))) + + let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] + call assert_equal([-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255], sort(copy(l), 'n')) + + let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 1)) + call assert_equal(['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l), 'i')) + call assert_equal(['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}], sort(copy(l))) +endfunc + +" splitting a string to a List +func Test_str_split() + call assert_equal(['aa', 'bb'], split(' aa bb ')) + call assert_equal(['aa', 'bb'], split(' aa bb ', '\W\+', 0)) + call assert_equal(['', 'aa', 'bb', ''], split(' aa bb ', '\W\+', 1)) + call assert_equal(['', '', 'aa', '', 'bb', '', ''], split(' aa bb ', '\W', 1)) + call assert_equal(['aa', '', 'bb'], split(':aa::bb:', ':', 0)) + call assert_equal(['', 'aa', '', 'bb', ''], split(':aa::bb:', ':', 1)) + call assert_equal(['aa', '', 'bb', 'cc', ''], split('aa,,bb, cc,', ',\s*', 1)) + call assert_equal(['a', 'b', 'c'], split('abc', '\zs')) + call assert_equal(['', 'a', '', 'b', '', 'c', ''], split('abc', '\zs', 1)) +endfunc + +" compare recursively linked list and dict +func Test_listdict_compare() + let l = [1, 2, 3, 4] + let d = {'1': 1, '2': l, '3': 3} + let l[1] = d + call assert_true(l == l) + call assert_true(d == d) + call assert_false(l != deepcopy(l)) + call assert_false(d != deepcopy(d)) +endfunc + + " compare complex recursively linked list and dict +func Test_listdict_compare_complex() + let l = [] + call add(l, l) + let dict4 = {"l": l} + call add(dict4.l, dict4) + let lcopy = deepcopy(l) + let dict4copy = deepcopy(dict4) + call assert_true(l == lcopy) + call assert_true(dict4 == dict4copy) +endfunc + +func Test_listdict_extend() + " Pass the same List to extend() + let l = [1, 2, 3, 4, 5] + call extend(l, l) + call assert_equal([1, 2, 3, 4, 5, 1, 2, 3, 4, 5], l) + + " Pass the same Dict to extend() + let d = { 'a': {'b': 'B'}} + call extend(d, d) + call assert_equal({'a': {'b': 'B'}}, d) + + " Pass the same Dict to extend() with "error" + call assert_fails("call extend(d, d, 'error')", 'E737:') + call assert_equal({'a': {'b': 'B'}}, d) +endfunc diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim index 7856ee82ab..d28dbc444c 100644 --- a/src/nvim/testdir/test_listlbr.vim +++ b/src/nvim/testdir/test_listlbr.vim @@ -1,5 +1,8 @@ " Test for linebreak and list option (non-utf8) +" Nvim does not allow setting 'encoding', so skip this test. +finish + set encoding=latin1 scriptencoding latin1 diff --git a/src/nvim/testdir/test_mksession_utf8.vim b/src/nvim/testdir/test_mksession_utf8.vim index c05a1d3b6d..8ffbba2a1c 100644 --- a/src/nvim/testdir/test_mksession_utf8.vim +++ b/src/nvim/testdir/test_mksession_utf8.vim @@ -99,6 +99,7 @@ func Test_mksession_utf8() call delete('test_mks.out') call delete(tmpfile) let &wrap = wrap_save + set sessionoptions& splitbelow& fileencoding& endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index c7c0dc164c..1d15c7f83d 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -2337,3 +2337,45 @@ func! Test_normal54_Ctrl_bsl() " clean up bw! endfunc + +" Test for the gr (virtual replace) command +" Test for the bug fixed by 7.4.387 +func Test_gr_command() + enew! + let save_cpo = &cpo + call append(0, ['First line', 'Second line', 'Third line']) + exe "normal i\<C-G>u" + call cursor(2, 1) + set cpo-=X + normal 4gro + call assert_equal('oooond line', getline(2)) + undo + set cpo+=X + normal 4gro + call assert_equal('ooooecond line', getline(2)) + let &cpo = save_cpo + enew! +endfunc + +" When splitting a window the changelist position is wrong. +" Test the changelist position after splitting a window. +" Test for the bug fixed by 7.4.386 +func Test_changelist() + let save_ul = &ul + enew! + call append('$', ['1', '2']) + exe "normal i\<C-G>u" + exe "normal Gkylpa\<C-G>u" + set ul=100 + exe "normal Gylpa\<C-G>u" + set ul=100 + normal gg + vsplit + normal g; + call assert_equal([3, 2], [line('.'), col('.')]) + normal g; + call assert_equal([2, 2], [line('.'), col('.')]) + call assert_fails('normal g;', 'E662:') + %bwipe! + let &ul = save_ul +endfunc diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 7f818dd40d..f5bdd717dd 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -590,7 +590,8 @@ func Test_popup_and_preview_autocommand() call setline(2, ' os.') $ call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<enter>\<esc>", 'tx') - call assert_equal(["import os", " os.EX_IOERR", ''], getline(1,'$')) + call assert_equal("import os", getline(1)) + call assert_match(' os.\(EX_IOERR\|O_CREAT\)$', getline(2)) call assert_equal(1, winnr('$')) " previewwindow option is not set call assert_equal(0, &previewwindow) diff --git a/src/nvim/testdir/test_regexp_latin.vim b/src/nvim/testdir/test_regexp_latin.vim new file mode 100644 index 0000000000..8528412806 --- /dev/null +++ b/src/nvim/testdir/test_regexp_latin.vim @@ -0,0 +1,32 @@ +" Tests for regexp in latin1 encoding +set encoding=latin1 +scriptencoding latin1 + +func s:equivalence_test() + let str = "AÀÁÂÃÄÅ B C D EÈÉÊË F G H IÌÍÎÏ J K L M NÑ OÒÓÔÕÖØ P Q R S T UÙÚÛÜ V W X YÝ Z aàáâãäå b c d eèéêë f g h iìíîï j k l m nñ oòóôõöø p q r s t uùúûü v w x yýÿ z" + let groups = split(str) + for group1 in groups + for c in split(group1, '\zs') + " next statement confirms that equivalence class matches every + " character in group + call assert_match('^[[=' . c . '=]]*$', group1) + for group2 in groups + if group2 != group1 + " next statement converts that equivalence class doesn't match + " a character in any other group + call assert_equal(-1, match(group2, '[[=' . c . '=]]')) + endif + endfor + endfor + endfor +endfunc + +func Test_equivalence_re1() + set re=1 + call s:equivalence_test() +endfunc + +func Test_equivalence_re2() + set re=2 + call s:equivalence_test() +endfunc diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 9456f9c438..5da9397be5 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -438,3 +438,18 @@ func Test_search_regexp() set undolevels& enew! endfunc + +" Test for search('multi-byte char', 'bce') +func Test_search_multibyte() + if !has('multi_byte') + return + endif + let save_enc = &encoding + set encoding=utf8 + enew! + call append('$', 'A') + call cursor(2, 1) + call assert_equal(2, search('A', 'bce', line('.'))) + enew! + let &encoding = save_enc +endfunc diff --git a/src/nvim/testdir/test_sha256.vim b/src/nvim/testdir/test_sha256.vim new file mode 100644 index 0000000000..dd4707977e --- /dev/null +++ b/src/nvim/testdir/test_sha256.vim @@ -0,0 +1,22 @@ +" Tests for the sha256() function. + +if !has('cryptv') || !exists('*sha256') + finish +endif + +function Test_sha256() + " test for empty string: + call assert_equal(sha256(""), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') + + "'test for 1 char: + call assert_equal(sha256("a"), 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb') + " + "test for 3 chars: + call assert_equal(sha256("abc"), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad') + + " test for contains meta char: + call assert_equal(sha256("foo\nbar"), '807eff6267f3f926a21d234f7b0cf867a86f47e07a532f15e8cc39ed110ca776') + + " test for contains non-ascii char: + call assert_equal(sha256("\xde\xad\xbe\xef"), '5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953') +endfunction diff --git a/src/nvim/testdir/test_textformat.vim b/src/nvim/testdir/test_textformat.vim new file mode 100644 index 0000000000..999566c6ac --- /dev/null +++ b/src/nvim/testdir/test_textformat.vim @@ -0,0 +1,168 @@ +" Tests for the various 'formatoptions' settings +func Test_text_format() + enew! + + setl noai tw=2 fo=t + call append('$', [ + \ '{', + \ ' ', + \ '', + \ '}']) + exe "normal /^{/+1\n0" + normal gRa b + let lnum = line('.') + call assert_equal([ + \ 'a', + \ 'b'], getline(lnum - 1, lnum)) + + normal ggdG + setl ai tw=2 fo=tw + call append('$', [ + \ '{', + \ 'a b ', + \ '', + \ 'a ', + \ '}']) + exe "normal /^{/+1\n0" + normal gqgqjjllab + let lnum = line('.') + call assert_equal([ + \ 'a ', + \ 'b ', + \ '', + \ 'a ', + \ 'b'], getline(lnum - 4, lnum)) + + normal ggdG + setl tw=3 fo=t + call append('$', [ + \ '{', + \ "a \<C-A>", + \ '}']) + exe "normal /^{/+1\n0" + exe "normal gqgqo\na \<C-V>\<C-A>" + let lnum = line('.') + call assert_equal([ + \ 'a', + \ "\<C-A>", + \ '', + \ 'a', + \ "\<C-A>"], getline(lnum - 4, lnum)) + + normal ggdG + setl tw=2 fo=tcq1 comments=:# + call append('$', [ + \ '{', + \ 'a b', + \ '#a b', + \ '}']) + exe "normal /^{/+1\n0" + exe "normal gqgqjgqgqo\na b\n#a b" + let lnum = line('.') + call assert_equal([ + \ 'a b', + \ '#a b', + \ '', + \ 'a b', + \ '#a b'], getline(lnum - 4, lnum)) + + normal ggdG + setl tw=5 fo=tcn comments=:# + call append('$', [ + \ '{', + \ ' 1 a', + \ '# 1 a', + \ '}']) + exe "normal /^{/+1\n0" + exe "normal A b\<Esc>jA b" + let lnum = line('.') + call assert_equal([ + \ ' 1 a', + \ ' b', + \ '# 1 a', + \ '# b'], getline(lnum - 3, lnum)) + + normal ggdG + setl tw=5 fo=t2a si + call append('$', [ + \ '{', + \ '', + \ ' x a', + \ ' b', + \ ' c', + \ '', + \ '}']) + exe "normal /^{/+3\n0" + exe "normal i \<Esc>A_" + let lnum = line('.') + call assert_equal([ + \ '', + \ ' x a', + \ ' b_', + \ ' c', + \ ''], getline(lnum - 2, lnum + 2)) + + normal ggdG + setl tw=5 fo=qn comments=:# + call append('$', [ + \ '{', + \ '# 1 a b', + \ '}']) + exe "normal /^{/+1\n5|" + normal gwap + call assert_equal(5, col('.')) + let lnum = line('.') + call assert_equal([ + \ '# 1 a', + \ '# b'], getline(lnum, lnum + 1)) + + normal ggdG + setl tw=5 fo=q2 comments=:# + call append('$', [ + \ '{', + \ '# x', + \ '# a b', + \ '}']) + exe "normal /^{/+1\n0" + normal gwap + let lnum = line('.') + call assert_equal([ + \ '# x a', + \ '# b'], getline(lnum, lnum + 1)) + + normal ggdG + setl tw& fo=a + call append('$', [ + \ '{', + \ ' 1aa', + \ ' 2bb', + \ '}']) + exe "normal /^{/+2\n0" + normal I^^ + call assert_equal('{ 1aa ^^2bb }', getline('.')) + + normal ggdG + setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/ + call append('$', [ + \ '/* abc def ghi jkl ', + \ ' * mno pqr stu', + \ ' */']) + exe "normal /mno pqr/\n" + normal A vwx yz + let lnum = line('.') + call assert_equal([ + \ ' * mno pqr stu ', + \ ' * vwx yz', + \ ' */'], getline(lnum - 1, lnum + 1)) + + normal ggdG + setl tw=12 fo=tqnc comments=:# + call setline('.', '# 1 xxxxx') + normal A foobar + call assert_equal([ + \ '# 1 xxxxx', + \ '# foobar'], getline(1, 2)) + + setl ai& tw& fo& si& comments& + enew! +endfunc diff --git a/src/nvim/testdir/test_utf8_comparisons.vim b/src/nvim/testdir/test_utf8_comparisons.vim new file mode 100644 index 0000000000..576e86142f --- /dev/null +++ b/src/nvim/testdir/test_utf8_comparisons.vim @@ -0,0 +1,95 @@ +" Tests for case-insensitive UTF-8 comparisons (utf_strnicmp() in mbyte.c) +" Also test "g~ap". + +if !has("multi_byte") + finish +endif + +function! Ch(a, op, b, expected) + call assert_equal(eval(printf('"%s" %s "%s"', a:a, a:op, a:b)), a:expected, + \ printf('"%s" %s "%s" should return %d', a:a, a:op, a:b, a:expected)) +endfunction + +function! Chk(a, b, result) + if a:result == 0 + call Ch(a:a, '==?', a:b, 1) + call Ch(a:a, '!=?', a:b, 0) + call Ch(a:a, '<=?', a:b, 1) + call Ch(a:a, '>=?', a:b, 1) + call Ch(a:a, '<?', a:b, 0) + call Ch(a:a, '>?', a:b, 0) + elseif a:result > 0 + call Ch(a:a, '==?', a:b, 0) + call Ch(a:a, '!=?', a:b, 1) + call Ch(a:a, '<=?', a:b, 0) + call Ch(a:a, '>=?', a:b, 1) + call Ch(a:a, '<?', a:b, 0) + call Ch(a:a, '>?', a:b, 1) + else + call Ch(a:a, '==?', a:b, 0) + call Ch(a:a, '!=?', a:b, 1) + call Ch(a:a, '<=?', a:b, 1) + call Ch(a:a, '>=?', a:b, 0) + call Ch(a:a, '<?', a:b, 1) + call Ch(a:a, '>?', a:b, 0) + endif +endfunction + +function! Check(a, b, result) + call Chk(a:a, a:b, a:result) + call Chk(a:b, a:a, -a:result) +endfunction + +function! LT(a, b) + call Check(a:a, a:b, -1) +endfunction + +function! GT(a, b) + call Check(a:a, a:b, 1) +endfunction + +function! EQ(a, b) + call Check(a:a, a:b, 0) +endfunction + +function Test_comparisons() + call EQ('', '') + call LT('', 'a') + call EQ('abc', 'abc') + call EQ('Abc', 'abC') + call LT('ab', 'abc') + call LT('AB', 'abc') + call LT('ab', 'aBc') + call EQ('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xb9\xd0\xa6\xd0\xa3\xd0\xba\xd0\x95\xd0\xbd') + call LT('\xd0\xb9\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd', '\xd0\xaf\xd1\x86\xd1\x83\xd0\xba\xd0\xb5\xd0\xbd') + call EQ('\xe2\x84\xaa', 'k') + call LT('\xe2\x84\xaa', 'kkkkkk') + call EQ('\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa', 'kkk') + call LT('kk', '\xe2\x84\xaa\xe2\x84\xaa\xe2\x84\xaa') + call EQ('\xe2\x84\xaa\xe2\x84\xa6k\xe2\x84\xaak\xcf\x89', 'k\xcf\x89\xe2\x84\xaakk\xe2\x84\xa6') + call EQ('Abc\x80', 'AbC\x80') + call LT('Abc\x80', 'AbC\x81') + call LT('Abc', 'AbC\x80') + call LT('abc\x80DEF', 'abc\x80def') " case folding stops at the first bad character + call LT('\xc3XYZ', '\xc3xyz') + call EQ('\xef\xbc\xba', '\xef\xbd\x9a') " FF3A (upper), FF5A (lower) + call GT('\xef\xbc\xba', '\xef\xbc\xff') " first string is ok and equals \xef\xbd\x9a after folding, second string is illegal and was left unchanged, then the strings were bytewise compared + call LT('\xc3', '\xc3\x83') + call EQ('\xc3\xa3xYz', '\xc3\x83XyZ') + for n in range(0x60, 0xFF) + call LT(printf('xYz\x%.2X', n-1), printf('XyZ\x%.2X', n)) + endfor + for n in range(0x80, 0xBF) + call EQ(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n)) + endfor + for n in range(0xC0, 0xFF) + call LT(printf('xYz\xc2\x%.2XUvW', n), printf('XyZ\xc2\x%.2XuVw', n)) + endfor +endfunction + +" test that g~ap changes one paragraph only. +function Test_gap() + new + call feedkeys("iabcd\n\ndefggg0g~ap", "tx") + call assert_equal(["ABCD", "", "defg"], getline(1,3)) +endfunction diff --git a/src/nvim/window.c b/src/nvim/window.c index 8d7e20bb73..b4ef901d94 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2858,7 +2858,7 @@ close_others ( if (bufIsChanged(wp->w_buffer)) continue; } - win_close(wp, !P_HID(wp->w_buffer) && !bufIsChanged(wp->w_buffer)); + win_close(wp, !buf_hide(wp->w_buffer) && !bufIsChanged(wp->w_buffer)); } if (message && !ONE_WINDOW) |