aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/buffer.c55
-rw-r--r--src/nvim/ex_cmds.c23
-rw-r--r--src/nvim/ex_cmds2.c14
-rw-r--r--src/nvim/ex_docmd.c53
-rw-r--r--src/nvim/normal.c4
-rw-r--r--src/nvim/option_defs.h3
-rw-r--r--src/nvim/search.c10
-rw-r--r--src/nvim/testdir/Makefile12
-rw-r--r--src/nvim/testdir/runtest.vim6
-rw-r--r--src/nvim/testdir/sautest/autoload/footest.vim2
-rw-r--r--src/nvim/testdir/test73.in168
-rw-r--r--src/nvim/testdir/test73.ok21
-rw-r--r--src/nvim/testdir/test_alot.vim2
-rw-r--r--src/nvim/testdir/test_alot_latin.vim10
-rw-r--r--src/nvim/testdir/test_alot_utf8.vim17
-rw-r--r--src/nvim/testdir/test_charsearch_utf8.vim22
-rw-r--r--src/nvim/testdir/test_close_count.vim174
-rw-r--r--src/nvim/testdir/test_edit.vim17
-rw-r--r--src/nvim/testdir/test_erasebackword.vim25
-rw-r--r--src/nvim/testdir/test_expr_utf8.vim4
-rw-r--r--src/nvim/testdir/test_find_complete.vim157
-rw-r--r--src/nvim/testdir/test_fixeol.vim48
-rw-r--r--src/nvim/testdir/test_fold.vim21
-rw-r--r--src/nvim/testdir/test_ins_complete.vim7
-rw-r--r--src/nvim/testdir/test_listchars.vim63
-rw-r--r--src/nvim/testdir/test_listdict.vim603
-rw-r--r--src/nvim/testdir/test_listlbr.vim3
-rw-r--r--src/nvim/testdir/test_mksession_utf8.vim1
-rw-r--r--src/nvim/testdir/test_normal.vim42
-rw-r--r--src/nvim/testdir/test_popup.vim3
-rw-r--r--src/nvim/testdir/test_regexp_latin.vim32
-rw-r--r--src/nvim/testdir/test_search.vim15
-rw-r--r--src/nvim/testdir/test_sha256.vim22
-rw-r--r--src/nvim/testdir/test_textformat.vim168
-rw-r--r--src/nvim/testdir/test_utf8_comparisons.vim95
-rw-r--r--src/nvim/window.c2
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)