diff options
author | James McCoy <jamessan@jamessan.com> | 2018-03-28 21:52:06 -0400 |
---|---|---|
committer | James McCoy <jamessan@jamessan.com> | 2018-03-28 21:54:39 -0400 |
commit | 79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1 (patch) | |
tree | 4e0589d75801f3ff6a9678f84f5009102766661e /src/nvim/testdir | |
parent | 4403864da3c48412595d439f36458d1e6ccfc49f (diff) | |
parent | 3f3de9b1a95d273463a87516365510dbffcaf3d2 (diff) | |
download | rneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.tar.gz rneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.tar.bz2 rneovim-79f9c2d9c650ceab27cdc6707fd6d7fa1de29fc1.zip |
Merge branch 'master' into yagebu/option-fixes
Diffstat (limited to 'src/nvim/testdir')
108 files changed, 13562 insertions, 836 deletions
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 7e55fffa06..a31e1843fc 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -2,68 +2,106 @@ # Makefile to run all tests for Vim # -NVIM_PRG ?= ../../../build/bin/nvim -SCRIPTSOURCE := ../../../runtime +ifeq ($(OS),Windows_NT) + NVIM_PRG ?= ../../../build/bin/nvim.exe +else + NVIM_PRG ?= ../../../build/bin/nvim +endif +ROOT := ../../.. export SHELL := sh export NVIM_PRG := $(NVIM_PRG) +export TMPDIR := $(abspath ../../../Xtest-tmpdir) -SCRIPTS ?= \ - test13.out \ +SCRIPTS_DEFAULT = \ test14.out \ - test17.out \ test24.out \ - test32.out \ test37.out \ test40.out \ test42.out \ test48.out \ test49.out \ test52.out \ - test53.out \ test64.out \ - test73.out \ - test79.out \ + +ifneq ($(OS),Windows_NT) + SCRIPTS_DEFAULTS := $(SCRIPTS_DEFAULT) \ + test17.out \ + +endif + +SCRIPTS ?= $(SCRIPTS_DEFAULT) # Tests using runtest.vim. # Keep test_alot*.res as the last one, sort the others. NEW_TESTS ?= \ + test_arabic.res \ test_autocmd.res \ test_bufwintabinfo.res \ + 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 \ + test_ga.res \ test_glob2regpat.res \ test_gf.res \ test_gn.res \ test_hardcopy.res \ test_help_tagjump.res \ + test_hide.res \ test_history.res \ test_hlsearch.res \ test_increment.res \ test_increment_dbcs.res \ + test_ins_complete.res \ test_lambda.res \ 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_nested_function.res \ test_normal.res \ + test_number.res \ + test_options.res \ + test_profile.res \ + test_put.res \ test_quickfix.res \ + test_recover.res \ + test_retab.res \ + test_scrollbind.res \ test_search.res \ test_signs.res \ test_smartindent.res \ + test_spell.res \ test_stat.res \ + test_startup.res \ test_substitute.res \ test_syntax.res \ + test_system.res \ + test_tab.res \ test_tabpage.res \ test_textobjects.res \ test_timers.res \ @@ -71,8 +109,11 @@ NEW_TESTS ?= \ test_usercommands.res \ test_vimscript.res \ test_visual.res \ + 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 @@ -93,7 +134,7 @@ ifdef USE_VALGRIND $(VALGRIND_TOOL) \ --suppressions=../../.valgrind.supp \ --error-exitcode=123 \ - --log-file=valgrind.\%p.$* \ + --log-file=valgrind-\%p.$* \ $(VGDB) \ --trace-children=yes else @@ -111,7 +152,8 @@ nongui: nolog $(SCRIPTS) newtests report gui: nolog $(SCRIPTS) $(SCRIPTS_GUI) newtests report .gdbinit: - echo 'set $$_exitcode = -1\nrun\nif $$_exitcode != -1\n quit\nend' > .gdbinit + @echo "[OLDTEST-PREP] Setting up .gdbinit" + @echo 'set $$_exitcode = -1\nrun\nif $$_exitcode != -1\n quit\nend' > .gdbinit report: @echo @@ -130,7 +172,7 @@ $(SCRIPTS) $(SCRIPTS_GUI): $(NVIM_PRG) test1.out RM_ON_RUN := test.out X* viminfo RM_ON_START := test.ok -RUN_VIM := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --noplugin -s dotest.in +RUN_VIM := $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in clean: -rm -rf *.out \ @@ -138,6 +180,7 @@ clean: *.res \ *.rej \ *.orig \ + *.tlog \ test.log \ messages \ $(RM_ON_RUN) \ @@ -146,60 +189,36 @@ clean: .*.swp \ .*.swo \ .gdbinit \ + $(TMPDIR) \ del test1.out: .gdbinit test1.in - -rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize - $(RUN_VIM) $*.in - @/bin/sh -c "if test -e wrongtermsize; then \ - echo; \ - echo test1 FAILED - terminal size must be 80x24 or larger; \ - echo; exit 1; \ - elif diff test.out $*.ok; then \ - mv -f test.out $*.out; \ - else \ - echo; \ - echo test1 FAILED - Something basic is wrong; \ - echo; \ - exit 1; \ - fi" - -rm -rf X* viminfo + @echo "[OLDTEST-PREP] Running test1" + @rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize + @mkdir -p $(TMPDIR) + @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIM) $*.in + @rm -f wrongtermsize + @rm -rf X* viminfo %.out: %.in .gdbinit - -rm -rf $*.failed test.ok $(RM_ON_RUN) - cp $*.ok test.ok - # Sleep a moment to avoid that the xterm title is messed up. - # 200 msec is sufficient, but only modern sleep supports a fraction of - # a second, fall back to a second if it fails. - @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1" - $(RUN_VIM) $*.in - - # Check if the test.out file matches test.ok. - @/bin/sh -c "if test -f test.out; then \ - if diff -u test.out $*.ok; then \ - mv -f test.out $*.out; \ - else \ - echo $* FAILED >> test.log; \ - mv -f test.out $*.failed; \ - fi; \ - else \ - echo $* NO OUTPUT >>test.log; \ - fi" - @/bin/sh -c "if test -f valgrind; then \ - mv -f valgrind valgrind.$*; \ - fi" - -rm -rf X* test.ok viminfo + @echo "[OLDESTTEST] Running" $* + @rm -rf $*.failed test.ok $(RM_ON_RUN) + @mkdir -p $(TMPDIR) + @cp $*.ok test.ok + @/bin/sh runnvim.sh --oldesttest $(ROOT) $(NVIM_PRG) $* $(RUN_VIM) $*.in + @rm -rf X* test.ok viminfo test49.out: test49.vim nolog: - -rm -f test.log messages + @echo "[OLDTEST-PREP] Removing test.log and messages" + @rm -f test.log messages # New style of tests uses Vim script with assert calls. These are easier # to write and a lot easier to read and debug. # Limitation: Only works with the +eval feature. -RUN_VIMTEST = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(VALGRIND) $(NVIM_PRG) -u unix.vim -U NONE --noplugin +RUN_VIMTEST = $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE --headless --noplugin newtests: newtestssilent @/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \ @@ -209,4 +228,6 @@ newtests: newtestssilent newtestssilent: $(NEW_TESTS) %.res: %.vim .gdbinit - $(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim + @echo "[OLDTEST] Running" $* + @mkdir -p $(TMPDIR) + @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh new file mode 100755 index 0000000000..43556f3ad3 --- /dev/null +++ b/src/nvim/testdir/runnvim.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +main() {( + local separator="================================================================================" + local oldesttest= + if test "$1" = "--oldesttest" ; then + shift + oldesttest=1 + fi + local root="$1" ; shift + local nvim_prg="$1" ; shift + local test_name="$1" ; shift + + local tlog="$test_name.tlog" + + export NVIM_TEST_ARGC=$# + local arg + local i=0 + for arg ; do + eval "export NVIM_TEST_ARG$i=\"\$arg\"" + i=$(( i+1 )) + done + + export CI_DIR="$root/ci" + export BUILD_DIR="$(dirname "$nvim_prg")/.." + export FAILED=0 + + . "$CI_DIR/common/suite.sh" + . "$CI_DIR/common/test.sh" + + export VIMRUNTIME="$root/runtime" + if ! "$nvim_prg" \ + -u NONE -i NONE \ + --headless \ + --cmd 'set shortmess+=I noswapfile noundofile nomore' \ + -S runnvim.vim \ + "$tlog" > "out-$tlog" 2> "err-$tlog" + then + fail "$test_name" F "Nvim exited with non-zero code" + fi + echo "Stdout of :terminal runner" >> "$tlog" + echo "$separator" >> "$tlog" + cat "out-$tlog" >> "$tlog" + echo "$separator" >> "$tlog" + echo "Stderr of :terminal runner" >> "$tlog" + echo "$separator" >> "$tlog" + cat "err-$tlog" >> "$tlog" + echo "$separator" >> "$tlog" + if test "$oldesttest" = 1 ; then + if ! diff -q test.out "$test_name.ok" > /dev/null 2>&1 ; then + if test -f test.out ; then + fail "$test_name" F "Oldest test .out file differs from .ok file" + echo "Diff between test.out and $test_name.ok" >> "$tlog" + echo "$separator" >> "$tlog" + diff -a test.out "$test_name.ok" >> "$tlog" + echo "$separator" >> "$tlog" + else + echo "No output in test.out" >> "$tlog" + fi + fi + fi + if test "$FAILED" = 1 ; then + travis_fold start "$NVIM_TEST_CURRENT_SUITE/$test_name" + fi + valgrind_check . + if test -n "$LOG_DIR" ; then + asan_check "$LOG_DIR" + fi + check_core_dumps + if test "$FAILED" = 1 ; then + cat "$tlog" + fi + rm -f "$tlog" + if test "$FAILED" = 1 ; then + travis_fold end "$NVIM_TEST_CURRENT_SUITE/$test_name" + fi + if test "$FAILED" = 1 ; then + echo "Test $test_name failed, see output above and summary for more details" >> test.log + fi +)} + +main "$@" diff --git a/src/nvim/testdir/runnvim.vim b/src/nvim/testdir/runnvim.vim new file mode 100644 index 0000000000..396a3a6477 --- /dev/null +++ b/src/nvim/testdir/runnvim.vim @@ -0,0 +1,55 @@ +let s:logger = {'d_events': []} +function s:logger.on_stdout(id, data, event) + call add(self.d_events, [a:event, a:data]) +endfunction +let s:logger.on_stderr = s:logger.on_stdout +function s:logger.on_exit(id, data, event) + call add(self.d_events, [a:event, ['']]) +endfunction + +function Main() + let argc = +$NVIM_TEST_ARGC + let args = [] + for i in range(argc) + call add(args, eval("$NVIM_TEST_ARG" . i)) + endfor + set lines=25 + set columns=80 + enew + let job = termopen(args, s:logger) + let results = jobwait([job], 5 * 60 * 1000) + " TODO(ZyX-I): Get colors + let screen = getline(1, '$') + bwipeout! + let stringified_events = map(s:logger.d_events, + \'v:val[0] . ": " . ' . + \'join(map(v:val[1], '. + \ '''substitute(v:val, '. + \ '"\\v\\C(\\p@!.|\\<)", '. + \ '"\\=printf(\"<%x>\", '. + \ 'char2nr(submatch(0)))", '. + \ '"")''), '. + \ '''\n'')') + call setline(1, [ + \ 'Job exited with code ' . results[0], + \ printf('Screen (%u lines)', len(screen)), + \ repeat('=', 80), + \] + screen + [ + \ repeat('=', 80), + \ printf('Events (%u lines):', len(stringified_events)), + \ repeat('=', 80), + \] + stringified_events + [ + \ repeat('=', 80), + \]) + write + if results[0] != 0 + if results[0] != -1 + call jobstop(job) + endif + cquit + else + qall + endif +endfunction + +call Main() diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index 117ba52eb6..7090be7726 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -4,7 +4,7 @@ " " To execute only specific test functions, add a second argument. It will be " matched against the names of the Test_ function. E.g.: -" ../vim -u NONE -S runtest.vim test_channel.vim open_delay +" ../vim -u NONE -S runtest.vim test_channel.vim open_delay " The output can be found in the "messages" file. " " The test script may contain anything, only functions that start with @@ -42,10 +42,11 @@ endif " Common with all tests on all systems. source setup.vim +" For consistency run all tests with 'nocompatible' set. " This also enables use of line continuation. -set viminfo+=nviminfo +set nocp viminfo+=nviminfo -" Use utf-8 or latin1 be default, instead of whatever the system default +" Use utf-8 or latin1 by default, instead of whatever the system default " happens to be. Individual tests can overrule this at the top of the file. if has('multi_byte') set encoding=utf-8 @@ -62,42 +63,84 @@ lang mess C " Always use forward slashes. set shellslash -" Make sure $HOME does not get read or written. -let $HOME = '/does/not/exist' - -" Prepare for calling garbagecollect_for_testing(). +" Prepare for calling test_garbagecollect_now(). let v:testing = 1 -" Align Nvim defaults to Vim. -set directory^=. -set backspace= -set nohidden smarttab noautoindent noautoread complete-=i noruler noshowcmd -set listchars=eol:$ -" Prevent Nvim log from writing to stderr. -let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' +" Support function: get the alloc ID by name. +function GetAllocId(name) + exe 'split ' . s:srcdir . '/alloc.h' + let top = search('typedef enum') + if top == 0 + call add(v:errors, 'typedef not found in alloc.h') + endif + let lnum = search('aid_' . a:name . ',') + if lnum == 0 + call add(v:errors, 'Alloc ID ' . a:name . ' not defined') + endif + close + return lnum - top - 1 +endfunc func RunTheTest(test) echo 'Executing ' . a:test + + " Avoid stopping at the "hit enter" prompt + set nomore + + " Avoid a three second wait when a message is about to be overwritten by the + " mode message. + set noshowmode + + " Some tests wipe out buffers. To be consistent, always wipe out all + " 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") - call SetUp() + try + call SetUp() + catch + call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif call add(s:messages, 'Executing ' . a:test) let s:done += 1 - try + + if a:test =~ 'Test_nocatch_' + " Function handles errors itself. This avoids skipping commands after the + " error. exe 'call ' . a:test - catch /^\cskipped/ - call add(s:messages, ' Skipped') - call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) - catch - call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) - endtry + else + try + exe 'call ' . a:test + catch /^\cskipped/ + call add(s:messages, ' Skipped') + call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) + catch + call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry + endif if exists("*TearDown") - call TearDown() + try + call TearDown() + catch + call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) + endtry endif - " Close any extra windows and make the current one not modified. + " Clear any autocommands + au! + + " Close any extra tab pages and windows and make the current one not modified. + while tabpagenr('$') > 1 + quit! + endwhile + while 1 let wincount = winnr('$') if wincount == 1 @@ -110,7 +153,8 @@ func RunTheTest(test) break endif endwhile - set nomodified + + exe 'cd ' . save_cwd endfunc func AfterTheTest() @@ -189,13 +233,20 @@ endif " Names of flaky tests. let s:flaky = [ - \ 'Test_with_partial_callback()', + \ 'Test_exit_callback_interval()', \ 'Test_oneshot()', + \ 'Test_out_cb()', + \ 'Test_paused()', + \ 'Test_quoteplus()', + \ 'Test_reltime()', + \ 'Test_terminal_composing_unicode()', + \ 'Test_terminal_redir_file()', + \ 'Test_terminal_tmap()', + \ 'Test_with_partial_callback()', \ 'Test_lambda_with_timer()', \ ] " Locate Test_ functions and execute them. -set nomore redir @q silent function /^Test_ redir END @@ -208,12 +259,30 @@ endif " Execute the tests in alphabetical order. for s:test in sort(s:tests) + " Silence, please! + set belloff=all + call RunTheTest(s:test) if len(v:errors) > 0 && index(s:flaky, s:test) >= 0 + call add(s:messages, 'Found errors in ' . s:test . ':') + call extend(s:messages, v:errors) call add(s:messages, 'Flaky test failed, running it again') + let first_run = v:errors + + " Flakiness is often caused by the system being very busy. Sleep a couple + " of seconds to have a higher chance of succeeding the second time. + sleep 2 + let v:errors = [] call RunTheTest(s:test) + if len(v:errors) > 0 + let second_run = v:errors + let v:errors = ['First run:'] + call extend(v:errors, first_run) + call add(v:errors, 'Second run:') + call extend(v:errors, second_run) + endif endif call 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/setup.vim b/src/nvim/testdir/setup.vim index 06f2199214..7d6dd0c7ce 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -1,8 +1,15 @@ " Common preparations for running tests. -set noruler -set noshowcmd -set belloff= +" Align Nvim defaults to Vim. +set sidescroll=0 +set directory^=. +set backspace= +set nohidden smarttab noautoindent noautoread complete-=i noruler noshowcmd +set listchars=eol:$ +set fillchars=vert:\|,fold:- +" Prevent Nvim log from writing to stderr. +let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' + " Make sure 'runtimepath' and 'packpath' does not include $HOME. set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim index 72cfea96c6..4925b04a82 100644 --- a/src/nvim/testdir/shared.vim +++ b/src/nvim/testdir/shared.vim @@ -1,5 +1,25 @@ " Functions shared by several tests. +" {Nvim} +" Filepath captured from output may be truncated, like this: +" /home/va...estdir/Xtest-tmpdir/nvimxbXN4i/10 +" Get last 2 segments, then combine with $TMPDIR. +func! Fix_truncated_tmpfile(fname) + " sanity check + if $TMPDIR ==# '' + throw '$TMPDIR is empty' + endif + let tmpdir_tail = fnamemodify(substitute($TMPDIR, '[\/]\+$', '', 'g'), ':t') + if tmpdir_tail ==# '' + throw 'empty tmpdir_tail' + endif + if a:fname !~# tmpdir_tail + throw printf('$TMPDIR (%s) not in fname: %s', tmpdir_tail, a:fname) + endif + let last2segments = matchstr(a:fname, '[\/][^\/]\+[\/][^\/]\+$') + return $TMPDIR.last2segments +endfunc + " Get the name of the Python executable. " Also keeps it in s:python. func PythonProg() diff --git a/src/nvim/testdir/test32.in b/src/nvim/testdir/test32.in deleted file mode 100644 index 76bd9be889..0000000000 --- a/src/nvim/testdir/test32.in +++ /dev/null @@ -1,60 +0,0 @@ -Test for insert expansion - -:se cpt=.,w -* add-expands (word from next line) from other window -* add-expands (current buffer first) -* Local expansion, ends in an empty line (unless it becomes a global expansion) -* starts Local and switches to global add-expansion -:se cpt=.,w,i -* i-add-expands and switches to local -* add-expands lines (it would end in an empty line if it didn't ignored it self) -:se cpt=kXtestfile -* checks k-expansion, and file expansion (use Xtest11 instead of test11, -* because TEST11.OUT may match first on DOS) -:se cpt=w -* checks make_cyclic in other window -:se cpt=u nohid -* checks unloaded buffer expansion -* checks adding mode abortion -:se cpt=t,d -* tag expansion, define add-expansion interrupted -* t-expansion - -STARTTEST -:se backspace="" -:se cpt=.,w ff=unix | $-2,$w!Xtestfile | set ff& -:se cot= -nO#include "Xtestfile" -ru -O - - -:se cpt=.,w,i -kOM - -:se cpt=kXtestfile -:w Xtest11.one -:w Xtest11.two -OIXA -:" use CTRL-X CTRL-F to complete Xtest11.one, remove it and then use -:" CTRL-X CTRL-F again to verify this doesn't cause trouble. -OXddk -:se cpt=w -OST -:se cpt=u nohid -oOEN -unl -:se cpt=t,d def=^\\k* tags=Xtestfile notagbsearch -O -a -:wq! test.out -ENDTEST - -start of testfile -run1 -run2 -end of testfile - -test11 36Gepeto /Tag/ -asd test11file 36G -Makefile to run diff --git a/src/nvim/testdir/test32.ok b/src/nvim/testdir/test32.ok deleted file mode 100644 index afc4463fac..0000000000 --- a/src/nvim/testdir/test32.ok +++ /dev/null @@ -1,15 +0,0 @@ -#include "Xtestfile" -run1 run3 -run3 run3 - -Makefile to run3 -Makefile to run3 -Makefile to run3 -Xtest11.two -STARTTEST -ENDTEST -unless -test11file 36Gepeto /Tag/ asd -asd -run1 run2 - diff --git a/src/nvim/testdir/test53.in b/src/nvim/testdir/test53.in deleted file mode 100644 index 20b5d019af..0000000000 --- a/src/nvim/testdir/test53.in +++ /dev/null @@ -1,74 +0,0 @@ -Tests for string and html text objects. vim: set ft=vim : - -Note that the end-of-line moves the cursor to the next test line. - -Also test match() and matchstr() - -STARTTEST -/^start:/ -da" -0va'a'rx -02f`da` -0fXdi" -03f'vi'ry -:set quoteescape=+*- -di` -$F"va"oha"i"rz -:" -/^<begin -jfXdit -0fXdit -fXdat -0fXdat -dit -:" -:put =matchstr(\"abcd\", \".\", 0, 2) " b -:put =matchstr(\"abcd\", \"..\", 0, 2) " bc -:put =matchstr(\"abcd\", \".\", 2, 0) " c (zero and negative -> first match) -:put =matchstr(\"abcd\", \".\", 0, -1) " a -:put =match(\"abcd\", \".\", 0, 5) " -1 -:put =match(\"abcd\", \".\", 0, -1) " 0 -:put =match('abc', '.', 0, 1) " 0 -:put =match('abc', '.', 0, 2) " 1 -:put =match('abc', '.', 0, 3) " 2 -:put =match('abc', '.', 0, 4) " -1 -:put =match('abc', '.', 1, 1) " 1 -:put =match('abc', '.', 2, 1) " 2 -:put =match('abc', '.', 3, 1) " -1 -:put =match('abc', '$', 0, 1) " 3 -:put =match('abc', '$', 0, 2) " -1 -:put =match('abc', '$', 1, 1) " 3 -:put =match('abc', '$', 2, 1) " 3 -:put =match('abc', '$', 3, 1) " 3 -:put =match('abc', '$', 4, 1) " -1 -:put =match('abc', '\zs', 0, 1) " 0 -:put =match('abc', '\zs', 0, 2) " 1 -:put =match('abc', '\zs', 0, 3) " 2 -:put =match('abc', '\zs', 0, 4) " 3 -:put =match('abc', '\zs', 0, 5) " -1 -:put =match('abc', '\zs', 1, 1) " 1 -:put =match('abc', '\zs', 2, 1) " 2 -:put =match('abc', '\zs', 3, 1) " 3 -:put =match('abc', '\zs', 4, 1) " -1 -:/^start:/,/^end:/wq! test.out -ENDTEST - -start: "wo\"rd\\" foo -'foo' 'bar' 'piep' -bla bla `quote` blah -out " in "noXno" -"'" 'blah' rep 'buh' -bla `s*`d-`+++`l**` b`la -voo "nah" sdf " asdf" sdf " sdf" sd - -<begin> --<b>asdf<i>Xasdf</i>asdf</b>- --<b>asdX<i>a<i />sdf</i>asdf</b>- --<b>asdf<i>Xasdf</i>asdf</b>- --<b>asdX<i>as<b />df</i>asdf</b>- --<b> -innertext object -</b> -</begin> -SEARCH: -end: diff --git a/src/nvim/testdir/test53.ok b/src/nvim/testdir/test53.ok deleted file mode 100644 index d57d86bbb0..0000000000 --- a/src/nvim/testdir/test53.ok +++ /dev/null @@ -1,45 +0,0 @@ -start: foo -xxxxxxxxxxxx'piep' -bla bla blah -out " in "" -"'" 'blah'yyyyy'buh' -bla `` b`la -voo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzsd - -<begin> --<b>asdf<i></i>asdf</b>- --<b></b>- --<b>asdfasdf</b>- --- --<b></b> -</begin> -b -bc -c -a --1 -0 -0 -1 -2 --1 -1 -2 --1 -3 --1 -3 -3 -3 --1 -0 -1 -2 -3 --1 -1 -2 -3 --1 -SEARCH: -end: 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/test79.in b/src/nvim/testdir/test79.in Binary files differdeleted file mode 100644 index afbf2083d2..0000000000 --- a/src/nvim/testdir/test79.in +++ /dev/null diff --git a/src/nvim/testdir/test79.ok b/src/nvim/testdir/test79.ok Binary files differdeleted file mode 100644 index d4e0ae8819..0000000000 --- a/src/nvim/testdir/test79.ok +++ /dev/null diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 1103778107..b4baf7a8d7 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -2,27 +2,33 @@ " This makes testing go faster, since Vim doesn't need to restart. source test_assign.vim +source test_changedtick.vim source test_cursor_func.vim -source test_execute_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 +source test_findfile.vim source test_float_func.vim source test_functions.vim +source test_ga.vim source test_goto.vim source test_jumps.vim +source test_fileformat.vim +source test_filetype.vim source test_lambda.vim source test_menu.vim source test_mapping.vim source test_messages.vim -source test_options.vim source test_partial.vim source test_popup.vim +source test_put.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 @@ -33,4 +39,5 @@ source test_taglist.vim source test_true_false.vim source test_unlet.vim source test_utf8.vim +source test_virtualedit.vim source test_window_cmd.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_arabic.vim b/src/nvim/testdir/test_arabic.vim new file mode 100644 index 0000000000..9a16833a4c --- /dev/null +++ b/src/nvim/testdir/test_arabic.vim @@ -0,0 +1,472 @@ +" Simplistic testing of Arabic mode. + +if !has('arabic') || !has('multi_byte') + finish +endif + +source view_util.vim + +" Return list of Unicode characters at line lnum. +" Combining characters are treated as a single item. +func s:get_chars(lnum) + call cursor(a:lnum, 1) + let chars = [] + let numchars = strchars(getline('.'), 1) + for i in range(1, numchars) + exe 'norm ' i . '|' + let c=execute('ascii') + let c=substitute(c, '\n\?<.\{-}Hex\s*', 'U+', 'g') + let c=substitute(c, ',\s*Octal\s*\d*', '', 'g') + call add(chars, c) + endfor + return chars +endfunc + +func Test_arabic_toggle() + set arabic + call assert_equal(1, &rightleft) + call assert_equal(1, &arabicshape) + call assert_equal('arabic', &keymap) + call assert_equal(1, &delcombine) + + set iminsert=1 imsearch=1 + set arabic& + call assert_equal(0, &rightleft) + call assert_equal(1, &arabicshape) + call assert_equal('arabic', &keymap) + call assert_equal(1, &delcombine) + call assert_equal(0, &iminsert) + call assert_equal(-1, &imsearch) + + set arabicshape& keymap= delcombine& +endfunc + +func Test_arabic_input() + new + set arabic + " Typing sghl in Arabic insert mode should show the + " Arabic word 'Salaam' i.e. 'peace', spelled: + " SEEN, LAM, ALEF, MEEM. + " See: https://www.mediawiki.org/wiki/VisualEditor/Typing/Right-to-left + call feedkeys('isghl!', 'tx') + call assert_match("^ *!\uFEE1\uFEFC\uFEB3$", ScreenLines(1, &columns)[0]) + call assert_equal([ + \ 'U+0633', + \ 'U+0644 U+0627', + \ 'U+0645', + \ 'U+21'], s:get_chars(1)) + + " Without shaping, it should give individual Arabic letters. + set noarabicshape + call assert_match("^ *!\u0645\u0627\u0644\u0633$", ScreenLines(1, &columns)[0]) + call assert_equal([ + \ 'U+0633', + \ 'U+0644', + \ 'U+0627', + \ 'U+0645', + \ 'U+21'], s:get_chars(1)) + + set arabic& arabicshape& + bwipe! +endfunc + +func Test_arabic_toggle_keymap() + new + set arabic + call feedkeys("i12\<C-^>12\<C-^>12", 'tx') + call assert_match("^ *٢١21٢١$", ScreenLines(1, &columns)[0]) + call assert_equal('١٢12١٢', getline('.')) + set arabic& + bwipe! +endfunc + +func Test_delcombine() + new + set arabic + call feedkeys("isghl\<BS>\<BS>", 'tx') + call assert_match("^ *\uFEDE\uFEB3$", ScreenLines(1, &columns)[0]) + call assert_equal(['U+0633', 'U+0644'], s:get_chars(1)) + + " Now the same with 'nodelcombine' + set nodelcombine + %d + call feedkeys("isghl\<BS>\<BS>", 'tx') + call assert_match("^ *\uFEB1$", ScreenLines(1, &columns)[0]) + call assert_equal(['U+0633'], s:get_chars(1)) + set arabic& + bwipe! +endfunc + +" Values from src/arabic.h (not all used yet) +let s:a_COMMA = "\u060C" +let s:a_SEMICOLON = "\u061B" +let s:a_QUESTION = "\u061F" +let s:a_HAMZA = "\u0621" +let s:a_ALEF_MADDA = "\u0622" +let s:a_ALEF_HAMZA_ABOVE = "\u0623" +let s:a_WAW_HAMZA = "\u0624" +let s:a_ALEF_HAMZA_BELOW = "\u0625" +let s:a_YEH_HAMZA = "\u0626" +let s:a_ALEF = "\u0627" +let s:a_BEH = "\u0628" +let s:a_TEH_MARBUTA = "\u0629" +let s:a_TEH = "\u062a" +let s:a_THEH = "\u062b" +let s:a_JEEM = "\u062c" +let s:a_HAH = "\u062d" +let s:a_KHAH = "\u062e" +let s:a_DAL = "\u062f" +let s:a_THAL = "\u0630" +let s:a_REH = "\u0631" +let s:a_ZAIN = "\u0632" +let s:a_SEEN = "\u0633" +let s:a_SHEEN = "\u0634" +let s:a_SAD = "\u0635" +let s:a_DAD = "\u0636" +let s:a_TAH = "\u0637" +let s:a_ZAH = "\u0638" +let s:a_AIN = "\u0639" +let s:a_GHAIN = "\u063a" +let s:a_TATWEEL = "\u0640" +let s:a_FEH = "\u0641" +let s:a_QAF = "\u0642" +let s:a_KAF = "\u0643" +let s:a_LAM = "\u0644" +let s:a_MEEM = "\u0645" +let s:a_NOON = "\u0646" +let s:a_HEH = "\u0647" +let s:a_WAW = "\u0648" +let s:a_ALEF_MAKSURA = "\u0649" +let s:a_YEH = "\u064a" + +let s:a_FATHATAN = "\u064b" +let s:a_DAMMATAN = "\u064c" +let s:a_KASRATAN = "\u064d" +let s:a_FATHA = "\u064e" +let s:a_DAMMA = "\u064f" +let s:a_KASRA = "\u0650" +let s:a_SHADDA = "\u0651" +let s:a_SUKUN = "\u0652" + +let s:a_MADDA_ABOVE = "\u0653" +let s:a_HAMZA_ABOVE = "\u0654" +let s:a_HAMZA_BELOW = "\u0655" + +let s:a_ZERO = "\u0660" +let s:a_ONE = "\u0661" +let s:a_TWO = "\u0662" +let s:a_THREE = "\u0663" +let s:a_FOUR = "\u0664" +let s:a_FIVE = "\u0665" +let s:a_SIX = "\u0666" +let s:a_SEVEN = "\u0667" +let s:a_EIGHT = "\u0668" +let s:a_NINE = "\u0669" +let s:a_PERCENT = "\u066a" +let s:a_DECIMAL = "\u066b" +let s:a_THOUSANDS = "\u066c" +let s:a_STAR = "\u066d" +let s:a_MINI_ALEF = "\u0670" + +let s:a_s_FATHATAN = "\ufe70" +let s:a_m_TATWEEL_FATHATAN = "\ufe71" +let s:a_s_DAMMATAN = "\ufe72" + +let s:a_s_KASRATAN = "\ufe74" + +let s:a_s_FATHA = "\ufe76" +let s:a_m_FATHA = "\ufe77" +let s:a_s_DAMMA = "\ufe78" +let s:a_m_DAMMA = "\ufe79" +let s:a_s_KASRA = "\ufe7a" +let s:a_m_KASRA = "\ufe7b" +let s:a_s_SHADDA = "\ufe7c" +let s:a_m_SHADDA = "\ufe7d" +let s:a_s_SUKUN = "\ufe7e" +let s:a_m_SUKUN = "\ufe7f" + +let s:a_s_HAMZA = "\ufe80" +let s:a_s_ALEF_MADDA = "\ufe81" +let s:a_f_ALEF_MADDA = "\ufe82" +let s:a_s_ALEF_HAMZA_ABOVE = "\ufe83" +let s:a_f_ALEF_HAMZA_ABOVE = "\ufe84" +let s:a_s_WAW_HAMZA = "\ufe85" +let s:a_f_WAW_HAMZA = "\ufe86" +let s:a_s_ALEF_HAMZA_BELOW = "\ufe87" +let s:a_f_ALEF_HAMZA_BELOW = "\ufe88" +let s:a_s_YEH_HAMZA = "\ufe89" +let s:a_f_YEH_HAMZA = "\ufe8a" +let s:a_i_YEH_HAMZA = "\ufe8b" +let s:a_m_YEH_HAMZA = "\ufe8c" +let s:a_s_ALEF = "\ufe8d" +let s:a_f_ALEF = "\ufe8e" +let s:a_s_BEH = "\ufe8f" +let s:a_f_BEH = "\ufe90" +let s:a_i_BEH = "\ufe91" +let s:a_m_BEH = "\ufe92" +let s:a_s_TEH_MARBUTA = "\ufe93" +let s:a_f_TEH_MARBUTA = "\ufe94" +let s:a_s_TEH = "\ufe95" +let s:a_f_TEH = "\ufe96" +let s:a_i_TEH = "\ufe97" +let s:a_m_TEH = "\ufe98" +let s:a_s_THEH = "\ufe99" +let s:a_f_THEH = "\ufe9a" +let s:a_i_THEH = "\ufe9b" +let s:a_m_THEH = "\ufe9c" +let s:a_s_JEEM = "\ufe9d" +let s:a_f_JEEM = "\ufe9e" +let s:a_i_JEEM = "\ufe9f" +let s:a_m_JEEM = "\ufea0" +let s:a_s_HAH = "\ufea1" +let s:a_f_HAH = "\ufea2" +let s:a_i_HAH = "\ufea3" +let s:a_m_HAH = "\ufea4" +let s:a_s_KHAH = "\ufea5" +let s:a_f_KHAH = "\ufea6" +let s:a_i_KHAH = "\ufea7" +let s:a_m_KHAH = "\ufea8" +let s:a_s_DAL = "\ufea9" +let s:a_f_DAL = "\ufeaa" +let s:a_s_THAL = "\ufeab" +let s:a_f_THAL = "\ufeac" +let s:a_s_REH = "\ufead" +let s:a_f_REH = "\ufeae" +let s:a_s_ZAIN = "\ufeaf" +let s:a_f_ZAIN = "\ufeb0" +let s:a_s_SEEN = "\ufeb1" +let s:a_f_SEEN = "\ufeb2" +let s:a_i_SEEN = "\ufeb3" +let s:a_m_SEEN = "\ufeb4" +let s:a_s_SHEEN = "\ufeb5" +let s:a_f_SHEEN = "\ufeb6" +let s:a_i_SHEEN = "\ufeb7" +let s:a_m_SHEEN = "\ufeb8" +let s:a_s_SAD = "\ufeb9" +let s:a_f_SAD = "\ufeba" +let s:a_i_SAD = "\ufebb" +let s:a_m_SAD = "\ufebc" +let s:a_s_DAD = "\ufebd" +let s:a_f_DAD = "\ufebe" +let s:a_i_DAD = "\ufebf" +let s:a_m_DAD = "\ufec0" +let s:a_s_TAH = "\ufec1" +let s:a_f_TAH = "\ufec2" +let s:a_i_TAH = "\ufec3" +let s:a_m_TAH = "\ufec4" +let s:a_s_ZAH = "\ufec5" +let s:a_f_ZAH = "\ufec6" +let s:a_i_ZAH = "\ufec7" +let s:a_m_ZAH = "\ufec8" +let s:a_s_AIN = "\ufec9" +let s:a_f_AIN = "\ufeca" +let s:a_i_AIN = "\ufecb" +let s:a_m_AIN = "\ufecc" +let s:a_s_GHAIN = "\ufecd" +let s:a_f_GHAIN = "\ufece" +let s:a_i_GHAIN = "\ufecf" +let s:a_m_GHAIN = "\ufed0" +let s:a_s_FEH = "\ufed1" +let s:a_f_FEH = "\ufed2" +let s:a_i_FEH = "\ufed3" +let s:a_m_FEH = "\ufed4" +let s:a_s_QAF = "\ufed5" +let s:a_f_QAF = "\ufed6" +let s:a_i_QAF = "\ufed7" +let s:a_m_QAF = "\ufed8" +let s:a_s_KAF = "\ufed9" +let s:a_f_KAF = "\ufeda" +let s:a_i_KAF = "\ufedb" +let s:a_m_KAF = "\ufedc" +let s:a_s_LAM = "\ufedd" +let s:a_f_LAM = "\ufede" +let s:a_i_LAM = "\ufedf" +let s:a_m_LAM = "\ufee0" +let s:a_s_MEEM = "\ufee1" +let s:a_f_MEEM = "\ufee2" +let s:a_i_MEEM = "\ufee3" +let s:a_m_MEEM = "\ufee4" +let s:a_s_NOON = "\ufee5" +let s:a_f_NOON = "\ufee6" +let s:a_i_NOON = "\ufee7" +let s:a_m_NOON = "\ufee8" +let s:a_s_HEH = "\ufee9" +let s:a_f_HEH = "\ufeea" +let s:a_i_HEH = "\ufeeb" +let s:a_m_HEH = "\ufeec" +let s:a_s_WAW = "\ufeed" +let s:a_f_WAW = "\ufeee" +let s:a_s_ALEF_MAKSURA = "\ufeef" +let s:a_f_ALEF_MAKSURA = "\ufef0" +let s:a_s_YEH = "\ufef1" +let s:a_f_YEH = "\ufef2" +let s:a_i_YEH = "\ufef3" +let s:a_m_YEH = "\ufef4" +let s:a_s_LAM_ALEF_MADDA_ABOVE = "\ufef5" +let s:a_f_LAM_ALEF_MADDA_ABOVE = "\ufef6" +let s:a_s_LAM_ALEF_HAMZA_ABOVE = "\ufef7" +let s:a_f_LAM_ALEF_HAMZA_ABOVE = "\ufef8" +let s:a_s_LAM_ALEF_HAMZA_BELOW = "\ufef9" +let s:a_f_LAM_ALEF_HAMZA_BELOW = "\ufefa" +let s:a_s_LAM_ALEF = "\ufefb" +let s:a_f_LAM_ALEF = "\ufefc" + +let s:a_BYTE_ORDER_MARK = "\ufeff" + +func Test_shape_initial() + new + set arabicshape + + " Shaping arabic {testchar} non-arabic Tests chg_c_a2i(). + " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result + for pair in [[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_i_YEH_HAMZA], + \ [s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA], + \ [s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_s_ALEF_MADDA], + \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_ABOVE], + \ [s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_s_WAW_HAMZA], + \ [s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_BELOW], + \ [s:a_ALEF, s:a_s_GHAIN, s:a_s_ALEF], + \ [s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_s_TEH_MARBUTA], + \ [s:a_DAL, s:a_s_GHAIN, s:a_s_DAL], + \ [s:a_THAL, s:a_s_GHAIN, s:a_s_THAL], + \ [s:a_REH, s:a_s_GHAIN, s:a_s_REH], + \ [s:a_ZAIN, s:a_s_GHAIN, s:a_s_ZAIN], + \ [s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL], + \ [s:a_WAW, s:a_s_GHAIN, s:a_s_WAW], + \ [s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_s_ALEF_MAKSURA], + \ [s:a_BEH, s:a_f_GHAIN, s:a_i_BEH], + \ [s:a_TEH, s:a_f_GHAIN, s:a_i_TEH], + \ [s:a_THEH, s:a_f_GHAIN, s:a_i_THEH], + \ [s:a_JEEM, s:a_f_GHAIN, s:a_i_JEEM], + \ [s:a_HAH, s:a_f_GHAIN, s:a_i_HAH], + \ [s:a_KHAH, s:a_f_GHAIN, s:a_i_KHAH], + \ [s:a_SEEN, s:a_f_GHAIN, s:a_i_SEEN], + \ [s:a_SHEEN, s:a_f_GHAIN, s:a_i_SHEEN], + \ [s:a_SAD, s:a_f_GHAIN, s:a_i_SAD], + \ [s:a_DAD, s:a_f_GHAIN, s:a_i_DAD], + \ [s:a_TAH, s:a_f_GHAIN, s:a_i_TAH], + \ [s:a_ZAH, s:a_f_GHAIN, s:a_i_ZAH], + \ [s:a_AIN, s:a_f_GHAIN, s:a_i_AIN], + \ [s:a_GHAIN, s:a_f_GHAIN, s:a_i_GHAIN], + \ [s:a_FEH, s:a_f_GHAIN, s:a_i_FEH], + \ [s:a_QAF, s:a_f_GHAIN, s:a_i_QAF], + \ [s:a_KAF, s:a_f_GHAIN, s:a_i_KAF], + \ [s:a_LAM, s:a_f_GHAIN, s:a_i_LAM], + \ [s:a_MEEM, s:a_f_GHAIN, s:a_i_MEEM], + \ [s:a_NOON, s:a_f_GHAIN, s:a_i_NOON], + \ [s:a_HEH, s:a_f_GHAIN, s:a_i_HEH], + \ [s:a_YEH, s:a_f_GHAIN, s:a_i_YEH], + \ ] + call setline(1, s:a_GHAIN . pair[0] . ' ') + call assert_equal([pair[1] . pair[2] . ' '], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + +func Test_shape_isolated() + new + set arabicshape + + " Shaping non-arabic {testchar} non-arabic Tests chg_c_a2s(). + " pair[0] = testchar, pair[1] = current-result + for pair in [[s:a_HAMZA, s:a_s_HAMZA], + \ [s:a_ALEF_MADDA, s:a_s_ALEF_MADDA], + \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_ALEF_HAMZA_ABOVE], + \ [s:a_WAW_HAMZA, s:a_s_WAW_HAMZA], + \ [s:a_ALEF_HAMZA_BELOW, s:a_s_ALEF_HAMZA_BELOW], + \ [s:a_YEH_HAMZA, s:a_s_YEH_HAMZA], + \ [s:a_ALEF, s:a_s_ALEF], + \ [s:a_TEH_MARBUTA, s:a_s_TEH_MARBUTA], + \ [s:a_DAL, s:a_s_DAL], + \ [s:a_THAL, s:a_s_THAL], + \ [s:a_REH, s:a_s_REH], + \ [s:a_ZAIN, s:a_s_ZAIN], + \ [s:a_TATWEEL, s:a_TATWEEL], + \ [s:a_WAW, s:a_s_WAW], + \ [s:a_ALEF_MAKSURA, s:a_s_ALEF_MAKSURA], + \ [s:a_BEH, s:a_s_BEH], + \ [s:a_TEH, s:a_s_TEH], + \ [s:a_THEH, s:a_s_THEH], + \ [s:a_JEEM, s:a_s_JEEM], + \ [s:a_HAH, s:a_s_HAH], + \ [s:a_KHAH, s:a_s_KHAH], + \ [s:a_SEEN, s:a_s_SEEN], + \ [s:a_SHEEN, s:a_s_SHEEN], + \ [s:a_SAD, s:a_s_SAD], + \ [s:a_DAD, s:a_s_DAD], + \ [s:a_TAH, s:a_s_TAH], + \ [s:a_ZAH, s:a_s_ZAH], + \ [s:a_AIN, s:a_s_AIN], + \ [s:a_GHAIN, s:a_s_GHAIN], + \ [s:a_FEH, s:a_s_FEH], + \ [s:a_QAF, s:a_s_QAF], + \ [s:a_KAF, s:a_s_KAF], + \ [s:a_LAM, s:a_s_LAM], + \ [s:a_MEEM, s:a_s_MEEM], + \ [s:a_NOON, s:a_s_NOON], + \ [s:a_HEH, s:a_s_HEH], + \ [s:a_YEH, s:a_s_YEH], + \ ] + call setline(1, ' ' . pair[0] . ' ') + call assert_equal([' ' . pair[1] . ' '], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + +func Test_shape_medial() + new + set arabicshape + + " Shaping arabic {testchar} arabic Tests chg_c_a2m(). + " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result, + " pair[3] = previous-result + for pair in [[s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA, s:a_s_BEH], + \[s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_f_ALEF_MADDA, s:a_i_BEH], + \[s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_ABOVE, s:a_i_BEH], + \[s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_f_WAW_HAMZA, s:a_i_BEH], + \[s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_BELOW, s:a_i_BEH], + \[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_m_YEH_HAMZA, s:a_i_BEH], + \[s:a_ALEF, s:a_s_GHAIN, s:a_f_ALEF, s:a_i_BEH], + \[s:a_BEH, s:a_f_GHAIN, s:a_m_BEH, s:a_i_BEH], + \[s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_f_TEH_MARBUTA, s:a_i_BEH], + \[s:a_TEH, s:a_f_GHAIN, s:a_m_TEH, s:a_i_BEH], + \[s:a_THEH, s:a_f_GHAIN, s:a_m_THEH, s:a_i_BEH], + \[s:a_JEEM, s:a_f_GHAIN, s:a_m_JEEM, s:a_i_BEH], + \[s:a_HAH, s:a_f_GHAIN, s:a_m_HAH, s:a_i_BEH], + \[s:a_KHAH, s:a_f_GHAIN, s:a_m_KHAH, s:a_i_BEH], + \[s:a_DAL, s:a_s_GHAIN, s:a_f_DAL, s:a_i_BEH], + \[s:a_THAL, s:a_s_GHAIN, s:a_f_THAL, s:a_i_BEH], + \[s:a_REH, s:a_s_GHAIN, s:a_f_REH, s:a_i_BEH], + \[s:a_ZAIN, s:a_s_GHAIN, s:a_f_ZAIN, s:a_i_BEH], + \[s:a_SEEN, s:a_f_GHAIN, s:a_m_SEEN, s:a_i_BEH], + \[s:a_SHEEN, s:a_f_GHAIN, s:a_m_SHEEN, s:a_i_BEH], + \[s:a_SAD, s:a_f_GHAIN, s:a_m_SAD, s:a_i_BEH], + \[s:a_DAD, s:a_f_GHAIN, s:a_m_DAD, s:a_i_BEH], + \[s:a_TAH, s:a_f_GHAIN, s:a_m_TAH, s:a_i_BEH], + \[s:a_ZAH, s:a_f_GHAIN, s:a_m_ZAH, s:a_i_BEH], + \[s:a_AIN, s:a_f_GHAIN, s:a_m_AIN, s:a_i_BEH], + \[s:a_GHAIN, s:a_f_GHAIN, s:a_m_GHAIN, s:a_i_BEH], + \[s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL, s:a_i_BEH], + \[s:a_FEH, s:a_f_GHAIN, s:a_m_FEH, s:a_i_BEH], + \[s:a_QAF, s:a_f_GHAIN, s:a_m_QAF, s:a_i_BEH], + \[s:a_KAF, s:a_f_GHAIN, s:a_m_KAF, s:a_i_BEH], + \[s:a_LAM, s:a_f_GHAIN, s:a_m_LAM, s:a_i_BEH], + \[s:a_MEEM, s:a_f_GHAIN, s:a_m_MEEM, s:a_i_BEH], + \[s:a_NOON, s:a_f_GHAIN, s:a_m_NOON, s:a_i_BEH], + \[s:a_HEH, s:a_f_GHAIN, s:a_m_HEH, s:a_i_BEH], + \[s:a_WAW, s:a_s_GHAIN, s:a_f_WAW, s:a_i_BEH], + \[s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_f_ALEF_MAKSURA, s:a_i_BEH], + \[s:a_YEH, s:a_f_GHAIN, s:a_m_YEH, s:a_i_BEH], + \ ] + call setline(1, s:a_GHAIN . pair[0] . s:a_BEH) + call assert_equal([pair[1] . pair[2] . pair[3]], ScreenLines(1, 3)) + endfor + + set arabicshape& + bwipe! +endfunc + diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim new file mode 100644 index 0000000000..19d0cee47a --- /dev/null +++ b/src/nvim/testdir/test_arglist.vim @@ -0,0 +1,355 @@ +" Test argument list commands + +func Test_argidx() + args a b c + last + call assert_equal(2, argidx()) + %argdelete + call assert_equal(0, argidx()) + " doing it again doesn't result in an error + %argdelete + call assert_equal(0, argidx()) + call assert_fails('2argdelete', 'E16:') + + args a b c + call assert_equal(0, argidx()) + next + call assert_equal(1, argidx()) + next + call assert_equal(2, argidx()) + 1argdelete + call assert_equal(1, argidx()) + 1argdelete + call assert_equal(0, argidx()) + 1argdelete + call assert_equal(0, argidx()) +endfunc + +func Test_argadd() + %argdelete + argadd a b c + call assert_equal(0, argidx()) + + %argdelete + argadd a + call assert_equal(0, argidx()) + argadd b c d + call assert_equal(0, argidx()) + + call Init_abc() + argadd x + call Assert_argc(['a', 'b', 'x', 'c']) + call assert_equal(1, argidx()) + + call Init_abc() + 0argadd x + call Assert_argc(['x', 'a', 'b', 'c']) + call assert_equal(2, argidx()) + + call Init_abc() + 1argadd x + call Assert_argc(['a', 'x', 'b', 'c']) + call assert_equal(2, argidx()) + + call Init_abc() + $argadd x + call Assert_argc(['a', 'b', 'c', 'x']) + call assert_equal(1, argidx()) + + call Init_abc() + $argadd x + +2argadd y + call Assert_argc(['a', 'b', 'c', 'x', 'y']) + call assert_equal(1, argidx()) + + %argd + edit d + arga + call assert_equal(1, len(argv())) + call assert_equal('d', get(argv(), 0, '')) + + %argd + edit some\ file + arga + call assert_equal(1, len(argv())) + call assert_equal('some file', get(argv(), 0, '')) + + %argd + new + arga + call assert_equal(0, len(argv())) +endfunc + +func Init_abc() + args a b c + next +endfunc + +func Assert_argc(l) + call assert_equal(len(a:l), argc()) + let i = 0 + while i < len(a:l) && i < argc() + call assert_equal(a:l[i], argv(i)) + let i += 1 + endwhile +endfunc + +" Test for [count]argument and [count]argdelete commands +" Ported from the test_argument_count.in test script +func Test_argument() + " Clean the argument list + arga a | %argd + + let save_hidden = &hidden + set hidden + + let g:buffers = [] + augroup TEST + au BufEnter * call add(buffers, expand('%:t')) + augroup END + + argadd a b c d + $argu + $-argu + -argu + 1argu + +2argu + + augroup TEST + au! + augroup END + + call assert_equal(['d', 'c', 'b', 'a', 'c'], g:buffers) + + redir => result + ar + redir END + call assert_true(result =~# 'a b \[c] d') + + .argd + call assert_equal(['a', 'b', 'd'], argv()) + + -argd + call assert_equal(['a', 'd'], argv()) + + $argd + call assert_equal(['a'], argv()) + + 1arga c + 1arga b + $argu + $arga x + call assert_equal(['a', 'b', 'c', 'x'], argv()) + + 0arga y + call assert_equal(['y', 'a', 'b', 'c', 'x'], argv()) + + %argd + call assert_equal([], argv()) + + arga a b c d e f + 2,$-argd + call assert_equal(['a', 'f'], argv()) + + let &hidden = save_hidden + + " Setting argument list should fail when the current buffer has unsaved + " changes + %argd + enew! + set modified + call assert_fails('args x y z', 'E37:') + args! x y z + call assert_equal(['x', 'y', 'z'], argv()) + call assert_equal('x', expand('%:t')) + + last | enew | argu + call assert_equal('z', expand('%:t')) + + %argdelete + call assert_fails('argument', 'E163:') +endfunc + +" Test for 0argadd and 0argedit +" Ported from the test_argument_0count.in test script +func Test_zero_argadd() + " Clean the argument list + arga a | %argd + + arga a b c d + 2argu + 0arga added + call assert_equal(['added', 'a', 'b', 'c', 'd'], argv()) + + 2argu + arga third + call assert_equal(['added', 'a', 'third', 'b', 'c', 'd'], argv()) + + %argd + arga a b c d + 2argu + 0arge edited + call assert_equal(['edited', 'a', 'b', 'c', 'd'], argv()) + + 2argu + arga third + call assert_equal(['edited', 'a', 'third', 'b', 'c', 'd'], argv()) + + 2argu + argedit file\ with\ spaces another file + call assert_equal(['edited', 'a', 'file with spaces', 'another', 'file', 'third', 'b', 'c', 'd'], argv()) + call assert_equal('file with spaces', expand('%')) +endfunc + +func Reset_arglist() + args a | %argd +endfunc + +" Test for argc() +func Test_argc() + call Reset_arglist() + call assert_equal(0, argc()) + argadd a b + call assert_equal(2, argc()) +endfunc + +" Test for arglistid() +func Test_arglistid() + call Reset_arglist() + arga a b + call assert_equal(0, arglistid()) + split + arglocal + call assert_equal(1, arglistid()) + tabnew | tabfirst + call assert_equal(0, arglistid(2)) + call assert_equal(1, arglistid(1, 1)) + call assert_equal(0, arglistid(2, 1)) + call assert_equal(1, arglistid(1, 2)) + tabonly | only | enew! + argglobal + call assert_equal(0, arglistid()) +endfunc + +" Test for argv() +func Test_argv() + call Reset_arglist() + call assert_equal([], argv()) + call assert_equal("", argv(2)) + argadd a b c d + call assert_equal('c', argv(2)) +endfunc + +" Test for the :argedit command +func Test_argedit() + call Reset_arglist() + argedit a + call assert_equal(['a'], argv()) + call assert_equal('a', expand('%:t')) + argedit b + call assert_equal(['a', 'b'], argv()) + call assert_equal('b', expand('%:t')) + argedit a + call assert_equal(['a', 'b', 'a'], argv()) + call assert_equal('a', expand('%:t')) + " When file name case is ignored, an existing buffer with only case + " difference is re-used. + argedit C D + call assert_equal('C', expand('%:t')) + call assert_equal(['a', 'b', 'a', 'C', 'D'], argv()) + argedit c + if has('fname_case') + call assert_equal(['a', 'b', 'a', 'C', 'c', 'D'], argv()) + else + call assert_equal(['a', 'b', 'a', 'C', 'C', 'D'], argv()) + endif + 0argedit x + if has('fname_case') + call assert_equal(['x', 'a', 'b', 'a', 'C', 'c', 'D'], argv()) + else + call assert_equal(['x', 'a', 'b', 'a', 'C', 'C', 'D'], argv()) + endif + enew! | set modified + call assert_fails('argedit y', 'E37:') + argedit! y + if has('fname_case') + call assert_equal(['x', 'y', 'y', 'a', 'b', 'a', 'C', 'c', 'D'], argv()) + else + call assert_equal(['x', 'y', 'y', 'a', 'b', 'a', 'C', 'C', 'D'], argv()) + endif + %argd + bwipe! C + bwipe! D +endfunc + +" Test for the :argdelete command +func Test_argdelete() + call Reset_arglist() + args aa a aaa b bb + argdelete a* + call assert_equal(['b', 'bb'], argv()) + call assert_equal('aa', expand('%:t')) + last + argdelete % + call assert_equal(['b'], argv()) + call assert_fails('argdelete', 'E471:') + call assert_fails('1,100argdelete', 'E16:') + %argd +endfunc + +" Tests for the :next, :prev, :first, :last, :rewind commands +func Test_argpos() + call Reset_arglist() + args a b c d + last + call assert_equal(3, argidx()) + call assert_fails('next', 'E165:') + prev + call assert_equal(2, argidx()) + Next + call assert_equal(1, argidx()) + first + call assert_equal(0, argidx()) + call assert_fails('prev', 'E164:') + 3next + call assert_equal(3, argidx()) + rewind + call assert_equal(0, argidx()) + %argd +endfunc + +" Test for autocommand that redefines the argument list, when doing ":all". +func Test_arglist_autocmd() + autocmd BufReadPost Xxx2 next Xxx2 Xxx1 + call writefile(['test file Xxx1'], 'Xxx1') + call writefile(['test file Xxx2'], 'Xxx2') + call writefile(['test file Xxx3'], 'Xxx3') + + new + " redefine arglist; go to Xxx1 + next! Xxx1 Xxx2 Xxx3 + " open window for all args + all + call assert_equal('test file Xxx1', getline(1)) + wincmd w + wincmd w + call assert_equal('test file Xxx1', getline(1)) + " should now be in Xxx2 + rewind + call assert_equal('test file Xxx2', getline(1)) + + autocmd! BufReadPost Xxx2 + enew! | only + call delete('Xxx1') + call delete('Xxx2') + call delete('Xxx3') + argdelete Xxx* + bwipe! Xxx1 Xxx2 Xxx3 +endfunc + +func Test_arg_all_expand() + call writefile(['test file Xxx1'], 'Xx x') + next notexist Xx\ x runtest.vim + call assert_equal('notexist Xx\ x runtest.vim', expand('##')) + call delete('Xx x') +endfunc diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim new file mode 100644 index 0000000000..05d69631c4 --- /dev/null +++ b/src/nvim/testdir/test_autochdir.vim @@ -0,0 +1,19 @@ +" Test 'autochdir' behavior + +if !exists("+autochdir") + finish +endif + +func Test_set_filename() + let cwd = getcwd() + call test_autochdir() + set acd + new + w samples/Xtest + call assert_equal("Xtest", expand('%')) + call assert_equal("samples", substitute(getcwd(), '.*/\(\k*\)', '\1', '')) + bwipe! + set noacd + exe 'cd ' . cwd + call delete('samples/Xtest') +endfunc diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index c4110eba94..24651b75e1 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1,14 +1,13 @@ " Tests for autocommands -set belloff=all -function! s:cleanup_buffers() abort +func! s:cleanup_buffers() abort for bnr in range(1, bufnr('$')) if bufloaded(bnr) && bufnr('%') != bnr execute 'bd! ' . bnr endif endfor -endfunction +endfunc func Test_vim_did_enter() call assert_false(v:vim_did_enter) @@ -49,7 +48,7 @@ if has('timers') endfunc endif -function Test_bufunload() +func Test_bufunload() augroup test_bufunload_group autocmd! autocmd BufUnload * call add(s:li, "bufunload") @@ -80,7 +79,7 @@ function Test_bufunload() endfunc " SEGV occurs in older versions. (At least 7.4.2005 or older) -function Test_autocmd_bufunload_with_tabnext() +func Test_autocmd_bufunload_with_tabnext() tabedit tabfirst @@ -98,7 +97,7 @@ function Test_autocmd_bufunload_with_tabnext() quit endfunc -function Test_autocmd_bufwinleave_with_tabfirst() +func Test_autocmd_bufwinleave_with_tabfirst() tabedit augroup sample autocmd! @@ -110,7 +109,7 @@ function Test_autocmd_bufwinleave_with_tabfirst() endfunc " SEGV occurs in older versions. (At least 7.4.2321 or older) -function Test_autocmd_bufunload_avoiding_SEGV_01() +func Test_autocmd_bufunload_avoiding_SEGV_01() split aa.txt let lastbuf = bufnr('$') @@ -128,7 +127,7 @@ function Test_autocmd_bufunload_avoiding_SEGV_01() endfunc " SEGV occurs in older versions. (At least 7.4.2321 or older) -function Test_autocmd_bufunload_avoiding_SEGV_02() +func Test_autocmd_bufunload_avoiding_SEGV_02() setlocal buftype=nowrite let lastbuf = bufnr('$') @@ -342,7 +341,10 @@ func Test_BufEnter() call mkdir('Xdir') split Xdir call assert_equal('+++', g:val) - bwipe! + + " On MS-Windows we can't edit the directory, make sure we wipe the right + " buffer. + bwipe! Xdir call delete('Xdir', 'd') au! BufEnter @@ -350,41 +352,40 @@ endfunc " Closing a window might cause an endless loop " E814 for older Vims -function Test_autocmd_bufwipe_in_SessLoadPost() - if has('win32') - throw 'Skipped: test hangs on MS-Windows' - endif +func Test_autocmd_bufwipe_in_SessLoadPost() + edit Xtest tabnew + file Xsomething set noswapfile - let g:bufnr=bufnr('%') mksession! - let content=['set nocp noswapfile', + let content = ['set nocp noswapfile', \ 'let v:swapchoice="e"', \ 'augroup test_autocmd_sessionload', \ 'autocmd!', - \ 'autocmd SessionLoadPost * 4bw!|qall!', + \ 'autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"', \ 'augroup END', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', \ ] call writefile(content, 'Xvimrc') - let a=system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim') - call assert_match('E814', a) + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + call assert_match('E814', errors) - unlet! g:bufnr set swapfile - for file in ['Session.vim', 'Xvimrc'] + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] call delete(file) endfor endfunc " SEGV occurs in older versions. -function Test_autocmd_bufwipe_in_SessLoadPost2() - if has('win32') - throw 'Skipped: test hangs on MS-Windows' - endif +func Test_autocmd_bufwipe_in_SessLoadPost2() tabnew set noswapfile - let g:bufnr=bufnr('%') mksession! let content = ['set nocp noswapfile', @@ -399,22 +400,768 @@ function Test_autocmd_bufwipe_in_SessLoadPost2() \ ' exec ''bwipeout '' . b', \ ' endif', \ ' endfor', - \ 'redraw!', - \ 'echon "SessionLoadPost DONE"', - \ 'qall!', + \ ' echomsg "SessionLoadPost DONE"', \ 'endfunction', - \ 'au SessionLoadPost * call DeleteInactiveBufs()'] + \ 'au SessionLoadPost * call DeleteInactiveBufs()', + \ '', + \ 'func WriteErrors()', + \ ' call writefile([execute("messages")], "Xerrors")', + \ 'endfunc', + \ 'au VimLeave * call WriteErrors()', + \ ] call writefile(content, 'Xvimrc') - let a=system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim') - " this probably only matches on unix - if has("unix") - call assert_notmatch('Caught deadly signal SEGV', a) - endif - call assert_match('SessionLoadPost DONE', a) + call system(v:progpath. ' --headless -i NONE -u Xvimrc --noplugins -S Session.vim -c cq') + let errors = join(readfile('Xerrors')) + " This probably only ever matches on unix. + call assert_notmatch('Caught deadly signal SEGV', errors) + call assert_match('SessionLoadPost DONE', errors) - unlet! g:bufnr set swapfile - for file in ['Session.vim', 'Xvimrc'] + for file in ['Session.vim', 'Xvimrc', 'Xerrors'] call delete(file) endfor endfunc + +func Test_empty_doau() + doau \| +endfunc + +func s:AutoCommandOptionSet(match) + let item = remove(g:options, 0) + let expected = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3]) + let actual = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", a:match, v:option_old, v:option_new, v:option_type) + let g:opt = [expected, actual] + "call assert_equal(expected, actual) +endfunc + +func Test_OptionSet() + throw 'skipped: Nvim does not support test_override()' + if !has("eval") || !has("autocmd") || !exists("+autochdir") + return + endif + + call test_override('starting', 1) + set nocp + au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>")) + + " 1: Setting number option" + let g:options=[['number', 0, 1, 'global']] + set nu + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 2: Setting local number option" + let g:options=[['number', 1, 0, 'local']] + setlocal nonu + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 3: Setting global number option" + let g:options=[['number', 1, 0, 'global']] + setglobal nonu + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 4: Setting local autoindent option" + let g:options=[['autoindent', 0, 1, 'local']] + setlocal ai + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 5: Setting global autoindent option" + let g:options=[['autoindent', 0, 1, 'global']] + setglobal ai + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 6: Setting global autoindent option" + let g:options=[['autoindent', 1, 0, 'global']] + set ai! + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " Should not print anything, use :noa + " 7: don't trigger OptionSet" + let g:options=[['invalid', 1, 1, 'invalid']] + noa set nonu + call assert_equal([['invalid', 1, 1, 'invalid']], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 8: Setting several global list and number option" + let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']] + set list nu + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 9: don't trigger OptionSet" + let g:options=[['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']] + noa set nolist nonu + call assert_equal([['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 10: Setting global acd" + let g:options=[['autochdir', 0, 1, 'local']] + setlocal acd + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 11: Setting global autoread (also sets local value)" + let g:options=[['autoread', 0, 1, 'global']] + set ar + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 12: Setting local autoread" + let g:options=[['autoread', 1, 1, 'local']] + setlocal ar + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 13: Setting global autoread" + let g:options=[['autoread', 1, 0, 'global']] + setglobal invar + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 14: Setting option backspace through :let" + let g:options=[['backspace', '', 'eol,indent,start', 'global']] + let &bs="eol,indent,start" + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 15: Setting option backspace through setbufvar()" + let g:options=[['backup', 0, 1, 'local']] + " try twice, first time, shouldn't trigger because option name is invalid, + " second time, it should trigger + call assert_fails("call setbufvar(1, '&l:bk', 1)", "E355") + " should trigger, use correct option name + call setbufvar(1, '&backup', 1) + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 16: Setting number option using setwinvar" + let g:options=[['number', 0, 1, 'local']] + call setwinvar(0, '&number', 1) + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 17: Setting key option, shouldn't trigger" + let g:options=[['key', 'invalid', 'invalid1', 'invalid']] + setlocal key=blah + setlocal key= + call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 18: Setting string option" + let oldval = &tags + let g:options=[['tags', oldval, 'tagpath', 'global']] + set tags=tagpath + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " 1l: Resetting string option" + let g:options=[['tags', 'tagpath', oldval, 'global']] + set tags& + call assert_equal([], g:options) + call assert_equal(g:opt[0], g:opt[1]) + + " Cleanup + au! OptionSet + for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp'] + exe printf(":set %s&vi", opt) + endfor + call test_override('starting', 0) + delfunc! AutoCommandOptionSet +endfunc + +func Test_OptionSet_diffmode() + throw 'skipped: Nvim does not support test_override()' + call test_override('starting', 1) + " 18: Changing an option when enetering diff mode + new + au OptionSet diff :let &l:cul=v:option_new + + call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) + call assert_equal(0, &l:cul) + diffthis + call assert_equal(1, &l:cul) + + vnew + call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) + call assert_equal(0, &l:cul) + diffthis + call assert_equal(1, &l:cul) + + diffoff + call assert_equal(0, &l:cul) + call assert_equal(1, getwinvar(2, '&l:cul')) + bw! + + call assert_equal(1, &l:cul) + diffoff! + call assert_equal(0, &l:cul) + call assert_equal(0, getwinvar(1, '&l:cul')) + bw! + + " Cleanup + au! OptionSet + call test_override('starting', 0) +endfunc + +func Test_OptionSet_diffmode_close() + throw 'skipped: Nvim does not support test_override()' + call test_override('starting', 1) + " 19: Try to close the current window when entering diff mode + " should not segfault + new + au OptionSet diff close + + call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) + call assert_fails(':diffthis', 'E788') + call assert_equal(1, &diff) + vnew + call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) + call assert_fails(':diffthis', 'E788') + call assert_equal(1, &diff) + bw! + call assert_fails(':diffoff!', 'E788') + bw! + + " Cleanup + au! OptionSet + call test_override('starting', 0) + "delfunc! AutoCommandOptionSet +endfunc + +" Test for Bufleave autocommand that deletes the buffer we are about to edit. +func Test_BufleaveWithDelete() + new | edit Xfile1 + + augroup test_bufleavewithdelete + autocmd! + autocmd BufLeave Xfile1 bwipe Xfile2 + augroup END + + call assert_fails('edit Xfile2', 'E143:') + call assert_equal('Xfile1', bufname('%')) + + autocmd! test_bufleavewithdelete BufLeave Xfile1 + augroup! test_bufleavewithdelete + + new + bwipe! Xfile1 +endfunc + +" Test for autocommand that changes the buffer list, when doing ":ball". +func Test_Acmd_BufAll() + enew! + %bwipe! + call writefile(['Test file Xxx1'], 'Xxx1') + call writefile(['Test file Xxx2'], 'Xxx2') + call writefile(['Test file Xxx3'], 'Xxx3') + + " Add three files to the buffer list + split Xxx1 + close + split Xxx2 + close + split Xxx3 + close + + " Wipe the buffer when the buffer is opened + au BufReadPost Xxx2 bwipe + + call append(0, 'Test file Xxx4') + ball + + call assert_equal(2, winnr('$')) + call assert_equal('Xxx1', bufname(winbufnr(winnr('$')))) + wincmd t + + au! BufReadPost + %bwipe! + call delete('Xxx1') + call delete('Xxx2') + call delete('Xxx3') + enew! | only +endfunc + +" Test for autocommand that changes current buffer on BufEnter event. +" Check if modelines are interpreted for the correct buffer. +func Test_Acmd_BufEnter() + %bwipe! + call writefile(['start of test file Xxx1', + \ "\<Tab>this is a test", + \ 'end of test file Xxx1'], 'Xxx1') + call writefile(['start of test file Xxx2', + \ 'vim: set noai :', + \ "\<Tab>this is a test", + \ 'end of test file Xxx2'], 'Xxx2') + + au BufEnter Xxx2 brew + set ai modeline modelines=3 + edit Xxx1 + " edit Xxx2, autocmd will do :brew + edit Xxx2 + exe "normal G?this is a\<CR>" + " Append text with autoindent to this file + normal othis should be auto-indented + call assert_equal("\<Tab>this should be auto-indented", getline('.')) + call assert_equal(3, line('.')) + " Remove autocmd and edit Xxx2 again + au! BufEnter Xxx2 + buf! Xxx2 + exe "normal G?this is a\<CR>" + " append text without autoindent to Xxx + normal othis should be in column 1 + call assert_equal("this should be in column 1", getline('.')) + call assert_equal(4, line('.')) + + %bwipe! + call delete('Xxx1') + call delete('Xxx2') + set ai&vim modeline&vim modelines&vim +endfunc + +" Test for issue #57 +" do not move cursor on <c-o> when autoindent is set +func Test_ai_CTRL_O() + enew! + set ai + let save_fo = &fo + set fo+=r + exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>" + exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>" + call assert_equal(['# abc', 'def', 'def'], getline(2, 4)) + + set ai&vim + let &fo = save_fo + enew! +endfunc + +" Test for autocommand that deletes the current buffer on BufLeave event. +" Also test deleting the last buffer, should give a new, empty buffer. +func Test_BufLeave_Wipe() + throw 'skipped: TODO: ' + %bwipe! + let content = ['start of test file Xxx', + \ 'this is a test', + \ 'end of test file Xxx'] + call writefile(content, 'Xxx1') + call writefile(content, 'Xxx2') + + au BufLeave Xxx2 bwipe + edit Xxx1 + split Xxx2 + " delete buffer Xxx2, we should be back to Xxx1 + bwipe + call assert_equal('Xxx1', bufname('%')) + call assert_equal(1, winnr('$')) + + " Create an alternate buffer + %write! test.out + call assert_equal('test.out', bufname('#')) + " delete alternate buffer + bwipe test.out + call assert_equal('Xxx1', bufname('%')) + call assert_equal('', bufname('#')) + + au BufLeave Xxx1 bwipe + " delete current buffer, get an empty one + bwipe! + call assert_equal(1, line('$')) + call assert_equal('', bufname('%')) + let g:bufinfo = getbufinfo() + call assert_equal(1, len(g:bufinfo)) + + call delete('Xxx1') + call delete('Xxx2') + call delete('test.out') + %bwipe + au! BufLeave + + " check that bufinfo doesn't contain a pointer to freed memory + call test_garbagecollect_now() +endfunc + +func Test_QuitPre() + edit Xfoo + let winid = win_getid(winnr()) + split Xbar + au! QuitPre * let g:afile = expand('<afile>') + " Close the other window, <afile> should be correct. + exe win_id2win(winid) . 'q' + call assert_equal('Xfoo', g:afile) + + unlet g:afile + bwipe Xfoo + bwipe Xbar +endfunc + +func Test_Cmdline() + au! CmdlineEnter : let g:entered = expand('<afile>') + au! CmdlineLeave : let g:left = expand('<afile>') + let g:entered = 0 + let g:left = 0 + call feedkeys(":echo 'hello'\<CR>", 'xt') + call assert_equal(':', g:entered) + call assert_equal(':', g:left) + au! CmdlineEnter + au! CmdlineLeave + + au! CmdlineEnter / let g:entered = expand('<afile>') + au! CmdlineLeave / let g:left = expand('<afile>') + let g:entered = 0 + let g:left = 0 + new + call setline(1, 'hello') + call feedkeys("/hello\<CR>", 'xt') + call assert_equal('/', g:entered) + call assert_equal('/', g:left) + bwipe! + au! CmdlineEnter + au! CmdlineLeave +endfunc + +" Test for BufWritePre autocommand that deletes or unloads the buffer. +func Test_BufWritePre() + %bwipe + au BufWritePre Xxx1 bunload + au BufWritePre Xxx2 bwipe + + call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1') + call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2') + + edit Xtest + e! Xxx2 + bdel Xtest + e Xxx1 + " write it, will unload it and give an error msg + call assert_fails('w', 'E203') + call assert_equal('Xxx2', bufname('%')) + edit Xtest + e! Xxx2 + bwipe Xtest + " write it, will delete the buffer and give an error msg + call assert_fails('w', 'E203') + call assert_equal('Xxx1', bufname('%')) + au! BufWritePre + call delete('Xxx1') + call delete('Xxx2') +endfunc + +" Test for BufUnload autocommand that unloads all the other buffers +func Test_bufunload_all() + call writefile(['Test file Xxx1'], 'Xxx1')" + call writefile(['Test file Xxx2'], 'Xxx2')" + + let content = [ + \ "func UnloadAllBufs()", + \ " let i = 1", + \ " while i <= bufnr('$')", + \ " if i != bufnr('%') && bufloaded(i)", + \ " exe i . 'bunload'", + \ " endif", + \ " let i += 1", + \ " endwhile", + \ "endfunc", + \ "au BufUnload * call UnloadAllBufs()", + \ "au VimLeave * call writefile(['Test Finished'], 'Xout')", + \ "edit Xxx1", + \ "split Xxx2", + \ "q"] + call writefile(content, 'Xtest') + + call delete('Xout') + call system(v:progpath. ' -u NORC -i NONE -N -S Xtest') + call assert_true(filereadable('Xout')) + + call delete('Xxx1') + call delete('Xxx2') + call delete('Xtest') + call delete('Xout') +endfunc + +" Some tests for buffer-local autocommands +func Test_buflocal_autocmd() + let g:bname = '' + edit xx + au BufLeave <buffer> let g:bname = expand("%") + " here, autocommand for xx should trigger. + " but autocommand shall not apply to buffer named <buffer>. + edit somefile + call assert_equal('xx', g:bname) + let g:bname = '' + " here, autocommand shall be auto-deleted + bwipe xx + " autocmd should not trigger + edit xx + call assert_equal('', g:bname) + " autocmd should not trigger + edit somefile + call assert_equal('', g:bname) + enew + unlet g:bname +endfunc + +" Test for "*Cmd" autocommands +func Test_Cmd_Autocmds() + call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx') + + enew! + au BufReadCmd XtestA 0r Xxx|$del + edit XtestA " will read text of Xxd instead + call assert_equal('start of Xxx', getline(1)) + + au BufWriteCmd XtestA call append(line("$"), "write") + write " will append a line to the file + call assert_equal('write', getline('$')) + call assert_fails('read XtestA', 'E484') " should not read anything + call assert_equal('write', getline(4)) + + " now we have: + " 1 start of Xxx + " 2 abc2 + " 3 end of Xxx + " 4 write + + au FileReadCmd XtestB '[r Xxx + 2r XtestB " will read Xxx below line 2 instead + call assert_equal('start of Xxx', getline(3)) + + " now we have: + " 1 start of Xxx + " 2 abc2 + " 3 start of Xxx + " 4 abc2 + " 5 end of Xxx + " 6 end of Xxx + " 7 write + + au FileWriteCmd XtestC '[,']copy $ + normal 4GA1 + 4,5w XtestC " will copy lines 4 and 5 to the end + call assert_equal("\tabc21", getline(8)) + call assert_fails('r XtestC', 'E484') " should not read anything + call assert_equal("end of Xxx", getline(9)) + + " now we have: + " 1 start of Xxx + " 2 abc2 + " 3 start of Xxx + " 4 abc21 + " 5 end of Xxx + " 6 end of Xxx + " 7 write + " 8 abc21 + " 9 end of Xxx + + let g:lines = [] + au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']"))) + w >>XtestD " will add lines to 'lines' + call assert_equal(9, len(g:lines)) + call assert_fails('$r XtestD', 'E484') " should not read anything + call assert_equal(9, line('$')) + call assert_equal('end of Xxx', getline('$')) + + au BufReadCmd XtestE 0r Xxx|$del + sp XtestE " split window with test.out + call assert_equal('end of Xxx', getline(3)) + + let g:lines = [] + exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>" + au BufWriteCmd XtestE call extend(g:lines, getline(0, '$')) + wall " will write other window to 'lines' + call assert_equal(4, len(g:lines), g:lines) + call assert_equal("\tasdf", g:lines[2]) + + au! BufReadCmd + au! BufWriteCmd + au! FileReadCmd + au! FileWriteCmd + au! FileAppendCmd + %bwipe! + call delete('Xxx') + enew! +endfunc + +func SetChangeMarks(start, end) + exe a:start. 'mark [' + exe a:end. 'mark ]' +endfunc + +" Verify the effects of autocmds on '[ and '] +func Test_change_mark_in_autocmds() + edit! Xtest + call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn') + + call SetChangeMarks(2, 3) + write + call assert_equal([1, 4], [line("'["), line("']")]) + + call SetChangeMarks(2, 3) + au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")]) + write + au! BufWritePre + + if executable('cat') + write XtestFilter + write >> XtestFilter + + call SetChangeMarks(2, 3) + " Marks are set to the entire range of the write + au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")]) + " '[ is adjusted to just before the line that will receive the filtered + " data + au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")]) + " The filtered data is read into the buffer, and the source lines are + " still present, so the range is after the source lines + au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")]) + %!cat XtestFilter + " After the filtered data is read, the original lines are deleted + call assert_equal([1, 8], [line("'["), line("']")]) + au! FilterWritePre,FilterReadPre,FilterReadPost + undo + + call SetChangeMarks(1, 4) + au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")]) + au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")]) + au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")]) + 2,3!cat XtestFilter + call assert_equal([2, 9], [line("'["), line("']")]) + au! FilterWritePre,FilterReadPre,FilterReadPost + undo + + call delete('XtestFilter') + endif + + call SetChangeMarks(1, 4) + au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")]) + 2,3write Xtest2 + au! FileWritePre + + call SetChangeMarks(2, 3) + au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")]) + write >> Xtest2 + au! FileAppendPre + + call SetChangeMarks(1, 4) + au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")]) + 2,3write >> Xtest2 + au! FileAppendPre + + call SetChangeMarks(1, 1) + au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")]) + au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")]) + 3read Xtest2 + au! FileReadPre,FileReadPost + undo + + call SetChangeMarks(4, 4) + " When the line is 0, it's adjusted to 1 + au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) + au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")]) + 0read Xtest2 + au! FileReadPre,FileReadPost + undo + + call SetChangeMarks(4, 4) + " When the line is 0, it's adjusted to 1 + au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) + au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")]) + 1read Xtest2 + au! FileReadPre,FileReadPost + undo + + bwipe! + call delete('Xtest') + call delete('Xtest2') +endfunc + +func Test_Filter_noshelltemp() + if !executable('cat') + return + endif + + enew! + call setline(1, ['a', 'b', 'c', 'd']) + + let shelltemp = &shelltemp + set shelltemp + + let g:filter_au = 0 + au FilterWritePre * let g:filter_au += 1 + au FilterReadPre * let g:filter_au += 1 + au FilterReadPost * let g:filter_au += 1 + %!cat + call assert_equal(3, g:filter_au) + + if has('filterpipe') + set noshelltemp + + let g:filter_au = 0 + au FilterWritePre * let g:filter_au += 1 + au FilterReadPre * let g:filter_au += 1 + au FilterReadPost * let g:filter_au += 1 + %!cat + call assert_equal(0, g:filter_au) + endif + + au! FilterWritePre,FilterReadPre,FilterReadPost + let &shelltemp = shelltemp + bwipe! +endfunc + +func Test_TextYankPost() + enew! + call setline(1, ['foo']) + + let g:event = [] + au TextYankPost * let g:event = copy(v:event) + + call assert_equal({}, v:event) + call assert_fails('let v:event = {}', 'E46:') + call assert_fails('let v:event.mykey = 0', 'E742:') + + norm "ayiw + call assert_equal( + \{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v'}, + \g:event) + norm y_ + call assert_equal( + \{'regcontents': ['foo'], 'regname': '', 'operator': 'y', 'regtype': 'V'}, + \g:event) + call feedkeys("\<C-V>y", 'x') + call assert_equal( + \{'regcontents': ['f'], 'regname': '', 'operator': 'y', 'regtype': "\x161"}, + \g:event) + norm "xciwbar + call assert_equal( + \{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v'}, + \g:event) + norm "bdiw + call assert_equal( + \{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v'}, + \g:event) + + call assert_equal({}, v:event) + + au! TextYankPost + unlet g:event + bwipe! +endfunc + +func Test_nocatch_wipe_all_buffers() + " Real nasty autocommand: wipe all buffers on any event. + au * * bwipe * + call assert_fails('next x', 'E93') + bwipe + au! +endfunc + +func Test_nocatch_wipe_dummy_buffer() + " Nasty autocommand: wipe buffer on any event. + au * x bwipe + call assert_fails('lv½ /x', 'E480') + au! +endfunc diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim new file mode 100644 index 0000000000..7deffbe452 --- /dev/null +++ b/src/nvim/testdir/test_breakindent.vim @@ -0,0 +1,298 @@ +" Test for breakindent +" +" Note: if you get strange failures when adding new tests, it might be that +" while the test is run, the breakindent cacheing gets in its way. +" It helps to change the tabstop setting and force a redraw (e.g. see +" Test_breakindent08()) +if !exists('+breakindent') + finish +endif + +source view_util.vim + +let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" + +function s:screen_lines(lnum, width) abort + return ScreenLines([a:lnum, a:lnum + 2], a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 breakindent + put =s:input + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +function Test_breakindent01() + " simple breakindent test + call s:test_windows('setl briopt=min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrst", +\ " GHIJ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent02() + " simple breakindent test with showbreak set + call s:test_windows('setl briopt=min:0 sbr=>>') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " >>qr", +\ " >>EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent03() + " simple breakindent test with showbreak set and briopt including sbr + call s:test_windows('setl briopt=sbr,min:0 sbr=++') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ "++ qrst", +\ "++ GHIJ", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent04() + " breakindent set with min width 18 + call s:test_windows('setl sbr= briopt=min:18') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstuv", +\ " IJKLMN", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent05() + " breakindent set and shift by 2 + call s:test_windows('setl briopt=shift:2,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qr", +\ " EF", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent06() + " breakindent set and shift by -1 + call s:test_windows('setl briopt=shift:-1,min:0') + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ " abcd", +\ " qrstu", +\ " HIJKL", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent07() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "? m", +\ "? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent07a() + " breakindent set and shift by 1, Number set sbr=? and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ " ? m", +\ " ? x", +\ ] + call s:compare_lines(expect, lines) + " clean up + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent08() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ "# opq", +\ "# BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent08a() + " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr + call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " # opq", +\ " # BCD", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent09() + " breakindent set and shift by 1, Number and list set sbr=# + call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ^Iabcd", +\ " #op", +\ " #AB", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent10() + " breakindent set, Number set sbr=~ + call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + " make sure, cache is invalidated! + set ts=8 + redraw! + set ts=4 + redraw! + let lines=s:screen_lines(line('.'),10) + let expect=[ +\ " 2 ab", +\ "~ mn", +\ "~ yz", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set sbr= cpo-=n') +endfunction + +function Test_breakindent11() + " test strdisplaywidth() + call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + let text=getline(2) + let width = strlen(text[1:])+indent(2)+strlen(&sbr)*3 " text wraps 3 times + call assert_equal(width, strdisplaywidth(text)) + call s:close_windows('set sbr=') +endfunction + +function Test_breakindent12() + " test breakindent with long indent + let s:input="\t\t\t\t\t{" + call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') + let lines=s:screen_lines(2,16) + let expect=[ +\ " 2 >--->--->--->", +\ " ---{ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('set nuw=4 listchars=') +endfunction + +function Test_breakindent13() + let s:input="" + call s:test_windows('setl breakindent briopt=min:10 ts=8') + vert resize 20 + call setline(1, [" a\tb\tc\td\te", " z y x w v"]) + 1 + norm! fbgj"ayl + 2 + norm! fygj"byl + call assert_equal('d', @a) + call assert_equal('w', @b) + call s:close_windows() +endfunction + +function Test_breakindent14() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8') + vert resize 30 + norm! 3a1234567890 + norm! a abcde + exec "norm! 0\<C-V>tex" + let lines=s:screen_lines(line('.'),8) + let expect=[ +\ "e ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent15() + let s:input="" + call s:test_windows('setl breakindent briopt= ts=8 sw=8') + vert resize 30 + norm! 4a1234567890 + exe "normal! >>\<C-V>3f0x" + let lines=s:screen_lines(line('.'),20) + let expect=[ +\ " 1234567890 ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction + +function Test_breakindent16() + " Check that overlong lines are indented correctly. + let s:input="" + call s:test_windows('setl breakindent briopt=min:0 ts=4') + call setline(1, "\t".repeat("1234567890", 10)) + resize 6 + norm! 1gg$ + redraw! + let lines=s:screen_lines(1,10) + let expect=[ +\ " 789012", +\ " 345678", +\ " 901234", +\ ] + call s:compare_lines(expect, lines) + let lines=s:screen_lines(4,10) + let expect=[ +\ " 567890", +\ " 123456", +\ " 7890 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunction diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim index 5c916e2dd7..a592cd7b11 100644 --- a/src/nvim/testdir/test_bufwintabinfo.vim +++ b/src/nvim/testdir/test_bufwintabinfo.vim @@ -1,7 +1,6 @@ " Tests for the getbufinfo(), getwininfo() and gettabinfo() functions function Test_getbufwintabinfo() - 1,$bwipeout edit Xtestfile1 edit Xtestfile2 let buflist = getbufinfo() @@ -87,9 +86,17 @@ function Test_get_buf_options() endfunc function Test_get_win_options() + if has('folding') + set foldlevel=999 + endif + set list let opts = getwinvar(1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) + if has('folding') + call assert_equal(999, opts.foldlevel) + endif if has('signs') call assert_equal('auto', opts.signcolumn) endif @@ -97,7 +104,12 @@ function Test_get_win_options() let opts = gettabwinvar(1, 1, '&') call assert_equal(v:t_dict, type(opts)) call assert_equal(0, opts.linebreak) + call assert_equal(1, opts.list) if has('signs') call assert_equal('auto', opts.signcolumn) endif + set list& + if has('folding') + set foldlevel=0 + endif endfunc diff --git a/src/nvim/testdir/test_changedtick.vim b/src/nvim/testdir/test_changedtick.vim new file mode 100644 index 0000000000..3a91bb54aa --- /dev/null +++ b/src/nvim/testdir/test_changedtick.vim @@ -0,0 +1,57 @@ +" Tests for b:changedtick + +func Test_changedtick_increments() + new + " New buffer has an empty line, tick starts at 2. + let expected = 2 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + call setline(1, 'hello') + let expected += 1 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + undo + " Somehow undo counts as two changes. + let expected += 2 + call assert_equal(expected, b:changedtick) + call assert_equal(expected, b:['changedtick']) + bwipe! +endfunc + +func Test_changedtick_dict_entry() + let d = b: + call assert_equal(b:changedtick, d['changedtick']) +endfunc + +func Test_changedtick_bdel() + new + let bnr = bufnr('%') + let v = b:changedtick + bdel + " Delete counts as a change too. + call assert_equal(v + 1, getbufvar(bnr, 'changedtick')) +endfunc + +func Test_changedtick_islocked() + call assert_equal(0, islocked('b:changedtick')) + let d = b: + call assert_equal(0, islocked('d.changedtick')) +endfunc + +func Test_changedtick_fixed() + call assert_fails('let b:changedtick = 4', 'E46:') + call assert_fails('let b:["changedtick"] = 4', 'E46:') + + call assert_fails('lockvar b:changedtick', 'E940:') + call assert_fails('lockvar b:["changedtick"]', 'E46:') + call assert_fails('unlockvar b:changedtick', 'E940:') + call assert_fails('unlockvar b:["changedtick"]', 'E46:') + call assert_fails('unlet b:changedtick', 'E795:') + call assert_fails('unlet b:["changedtick"]', 'E46:') + + let d = b: + call assert_fails('lockvar d["changedtick"]', 'E46:') + call assert_fails('unlockvar d["changedtick"]', 'E46:') + call assert_fails('unlet d["changedtick"]', 'E46:') + +endfunc 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_cindent.vim b/src/nvim/testdir/test_cindent.vim new file mode 100644 index 0000000000..444c4c4109 --- /dev/null +++ b/src/nvim/testdir/test_cindent.vim @@ -0,0 +1,76 @@ +" Test for cinoptions and cindent +" +" TODO: rewrite test3.in into this new style test + +func Test_cino_hash() + " Test that curbuf->b_ind_hash_comment is correctly reset + new + setlocal cindent cinoptions=#1 + setlocal cinoptions= + call setline(1, ["#include <iostream>"]) + call cursor(1, 1) + norm! o#include + "call feedkeys("o#include\<esc>", 't') + call assert_equal(["#include <iostream>", "#include"], getline(1,2)) + bwipe! +endfunc + +func Test_cino_extern_c() + " Test for cino-E + + let without_ind = [ + \ '#ifdef __cplusplus', + \ 'extern "C" {', + \ '#endif', + \ 'int func_a(void);', + \ '#ifdef __cplusplus', + \ '}', + \ '#endif' + \ ] + + let with_ind = [ + \ '#ifdef __cplusplus', + \ 'extern "C" {', + \ '#endif', + \ "\tint func_a(void);", + \ '#ifdef __cplusplus', + \ '}', + \ '#endif' + \ ] + new + setlocal cindent cinoptions=E0 + call setline(1, without_ind) + call feedkeys("gg=G", 'tx') + call assert_equal(with_ind, getline(1, '$')) + + setlocal cinoptions=E-s + call setline(1, with_ind) + call feedkeys("gg=G", 'tx') + call assert_equal(without_ind, getline(1, '$')) + + setlocal cinoptions=Es + let tests = [ + \ ['recognized', ['extern "C" {'], "\t\t;"], + \ ['recognized', ['extern "C++" {'], "\t\t;"], + \ ['recognized', ['extern /* com */ "C"{'], "\t\t;"], + \ ['recognized', ['extern"C"{'], "\t\t;"], + \ ['recognized', ['extern "C"', '{'], "\t\t;"], + \ ['not recognized', ['extern {'], "\t;"], + \ ['not recognized', ['extern /*"C"*/{'], "\t;"], + \ ['not recognized', ['extern "C" //{'], ";"], + \ ['not recognized', ['extern "C" /*{*/'], ";"], + \ ] + + for pair in tests + let lines = pair[1] + call setline(1, lines) + call feedkeys(len(lines) . "Go;", 'tx') + call assert_equal(pair[2], getline(len(lines) + 1), 'Failed for "' . string(lines) . '"') + endfor + + + + bwipe! +endfunc + +" 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_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 0c9d1297d6..673246e1fb 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -1,8 +1,9 @@ " Tests for editing the command line. + func Test_complete_tab() call writefile(['testfile'], 'Xtestfile') - call feedkeys(":e Xtest\t\r", "tx") + call feedkeys(":e Xtestf\t\r", "tx") call assert_equal('testfile', getline(1)) call delete('Xtestfile') endfunc @@ -17,7 +18,7 @@ func Test_complete_wildmenu() call writefile(['testfile1'], 'Xtestfile1') call writefile(['testfile2'], 'Xtestfile2') set wildmenu - call feedkeys(":e Xtest\t\t\r", "tx") + call feedkeys(":e Xtestf\t\t\r", "tx") call assert_equal('testfile2', getline(1)) call delete('Xtestfile1') @@ -25,6 +26,88 @@ func Test_complete_wildmenu() set nowildmenu endfunc +func Test_map_completion() + if !has('cmdline_compl') + return + endif + call feedkeys(":map <unique> <si\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <unique> <silent>', getreg(':')) + call feedkeys(":map <script> <un\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <script> <unique>', getreg(':')) + call feedkeys(":map <expr> <sc\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <expr> <script>', getreg(':')) + call feedkeys(":map <buffer> <e\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <buffer> <expr>', getreg(':')) + call feedkeys(":map <nowait> <b\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <nowait> <buffer>', getreg(':')) + call feedkeys(":map <special> <no\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <special> <nowait>', getreg(':')) + call feedkeys(":map <silent> <sp\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"map <silent> <special>', getreg(':')) +endfunc + +func Test_match_completion() + if !has('cmdline_compl') + return + endif + hi Aardig ctermfg=green + call feedkeys(":match \<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"match Aardig', getreg(':')) + call feedkeys(":match \<S-Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"match none', getreg(':')) +endfunc + +func Test_highlight_completion() + if !has('cmdline_compl') + return + endif + hi Aardig ctermfg=green + call feedkeys(":hi \<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi Aardig', getreg(':')) + call feedkeys(":hi li\<S-Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi link', getreg(':')) + call feedkeys(":hi d\<S-Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi default', getreg(':')) + call feedkeys(":hi c\<S-Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"hi clear', getreg(':')) + + " A cleared group does not show up in completions. + hi Anders ctermfg=green + call assert_equal(['Aardig', 'Anders'], getcompletion('A', 'highlight')) + hi clear Aardig + call assert_equal(['Anders'], getcompletion('A', 'highlight')) + hi clear Anders + call assert_equal([], getcompletion('A', 'highlight')) +endfunc + +func Test_expr_completion() + if !has('cmdline_compl') + return + endif + for cmd in [ + \ 'let a = ', + \ 'if', + \ 'elseif', + \ 'while', + \ 'for', + \ 'echo', + \ 'echon', + \ 'execute', + \ 'echomsg', + \ 'echoerr', + \ 'call', + \ 'return', + \ 'cexpr', + \ 'caddexpr', + \ 'cgetexpr', + \ 'lexpr', + \ 'laddexpr', + \ 'lgetexpr'] + call feedkeys(":" . cmd . " getl\<Tab>\<Home>\"\<CR>", 'xt') + call assert_equal('"' . cmd . ' getline(', getreg(':')) + endfor +endfunc + func Test_getcompletion() if !has('cmdline_compl') return @@ -130,6 +213,11 @@ func Test_getcompletion() let l = getcompletion('dark', 'highlight') call assert_equal([], l) + let l = getcompletion('', 'messages') + call assert_true(index(l, 'clear') >= 0) + let l = getcompletion('not', 'messages') + call assert_equal([], l) + if has('cscope') let l = getcompletion('', 'cscope') let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show'] @@ -204,3 +292,129 @@ func Test_expand_star_star() bwipe! call delete('a', 'rf') endfunc + +func Test_paste_in_cmdline() + let @a = "def" + call feedkeys(":abc \<C-R>a ghi\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc def ghi', @:) + + new + call setline(1, 'asdf.x /tmp/some verylongword a;b-c*d ') + + call feedkeys(":aaa \<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa asdf bbb', @:) + + call feedkeys("ft:aaa \<C-R>\<C-F> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa /tmp/some bbb', @:) + + set incsearch + call feedkeys("fy:aaa veryl\<C-R>\<C-W> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa verylongword bbb', @:) + + call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx') + call assert_equal('"aaa a;b-c*d bbb', @:) + + call feedkeys(":\<C-\>etoupper(getline(1))\<CR>\<C-B>\"\<CR>", 'tx') + call assert_equal('"ASDF.X /TMP/SOME VERYLONGWORD A;B-C*D ', @:) + bwipe! +endfunc + +func Test_remove_char_in_cmdline() + call feedkeys(":abc def\<S-Left>\<Del>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ef', @:) + + call feedkeys(":abc def\<S-Left>\<BS>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abcdef', @:) + + call feedkeys(":abc def ghi\<S-Left>\<C-W>\<C-B>\"\<CR>", 'tx') + call assert_equal('"abc ghi', @:) + + call feedkeys(":abc def\<S-Left>\<C-U>\<C-B>\"\<CR>", 'tx') + call assert_equal('"def', @:) +endfunc + +func Test_illegal_address1() + new + 2;'( + 2;') + quit +endfunc + +func Test_illegal_address2() + call writefile(['c', 'x', ' x', '.', '1;y'], 'Xtest.vim') + new + source Xtest.vim + " Trigger calling validate_cursor() + diffsp Xtest.vim + quit! + bwipe! + call delete('Xtest.vim') +endfunc + +func Test_cmdline_complete_wildoptions() + help + call feedkeys(":tag /\<c-a>\<c-b>\"\<cr>", 'tx') + let a = join(sort(split(@:)),' ') + set wildoptions=tagfile + call feedkeys(":tag /\<c-a>\<c-b>\"\<cr>", 'tx') + let b = join(sort(split(@:)),' ') + call assert_equal(a, b) + bw! +endfunc + +" using a leading backslash here +set cpo+=C + +func Test_cmdline_search_range() + new + call setline(1, ['a', 'b', 'c', 'd']) + /d + 1,\/s/b/B/ + call assert_equal('B', getline(2)) + + /a + $ + \?,4s/c/C/ + call assert_equal('C', getline(3)) + + call setline(1, ['a', 'b', 'c', 'd']) + %s/c/c/ + 1,\&s/b/B/ + call assert_equal('B', getline(2)) + + bwipe! +endfunc + +" Tests for getcmdline(), getcmdpos() and getcmdtype() +func Check_cmdline(cmdtype) + call assert_equal('MyCmd a', getcmdline()) + call assert_equal(8, getcmdpos()) + call assert_equal(a:cmdtype, getcmdtype()) + return '' +endfunc + +func Test_getcmdtype() + call feedkeys(":MyCmd a\<C-R>=Check_cmdline(':')\<CR>\<Esc>", "xt") + + let cmdtype = '' + debuggreedy + call feedkeys(":debug echo 'test'\<CR>", "t") + call feedkeys("let cmdtype = \<C-R>=string(getcmdtype())\<CR>\<CR>", "t") + call feedkeys("cont\<CR>", "xt") + 0debuggreedy + call assert_equal('>', cmdtype) + + call feedkeys("/MyCmd a\<C-R>=Check_cmdline('/')\<CR>\<Esc>", "xt") + call feedkeys("?MyCmd a\<C-R>=Check_cmdline('?')\<CR>\<Esc>", "xt") + + call feedkeys(":call input('Answer?')\<CR>", "t") + call feedkeys("MyCmd a\<C-R>=Check_cmdline('@')\<CR>\<C-C>", "xt") + + call feedkeys(":insert\<CR>MyCmd a\<C-R>=Check_cmdline('-')\<CR>\<Esc>", "xt") + + cnoremap <expr> <F6> Check_cmdline('=') + call feedkeys("a\<C-R>=MyCmd a\<F6>\<Esc>\<Esc>", "xt") + cunmap <F6> +endfunc + +set cpo& diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim index e438a8b077..2d793ed88f 100644 --- a/src/nvim/testdir/test_command_count.vim +++ b/src/nvim/testdir/test_command_count.vim @@ -1,6 +1,7 @@ " Test for user command counts. func Test_command_count_0() + let bufnr = bufnr('%') set hidden set noswapfile @@ -15,17 +16,17 @@ func Test_command_count_0() command! -range=% -addr=buffers RangeBuffersAll :let lines = [<line1>, <line2>] .,$RangeLoadedBuffers - call assert_equal([1, 1], lines) + call assert_equal([bufnr, bufnr], lines) %RangeLoadedBuffers - call assert_equal([1, 1], lines) + call assert_equal([bufnr, bufnr], lines) RangeLoadedBuffersAll - call assert_equal([1, 1], lines) + call assert_equal([bufnr, bufnr], lines) .,$RangeBuffers - call assert_equal([1, lastbuf], lines) + call assert_equal([bufnr, lastbuf], lines) %RangeBuffers - call assert_equal([1, lastbuf], lines) + call assert_equal([bufnr, lastbuf], lines) RangeBuffersAll - call assert_equal([1, lastbuf], lines) + call assert_equal([bufnr, lastbuf], lines) delcommand RangeLoadedBuffers delcommand RangeLoadedBuffersAll @@ -138,6 +139,7 @@ func Test_command_count_2() endfunc func Test_command_count_3() + let bufnr = bufnr('%') se nohidden e aaa let buf_aaa = bufnr('%') @@ -145,7 +147,7 @@ func Test_command_count_3() let buf_bbb = bufnr('%') e ccc let buf_ccc = bufnr('%') - buf 1 + exe bufnr . 'buf' call assert_equal([1, 1, 1], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) exe buf_bbb . "," . buf_ccc . "bdelete" call assert_equal([1, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)]) @@ -155,7 +157,7 @@ endfunc func Test_command_count_4() %argd - let bufnr = bufnr('$') + 1 + let bufnr = bufnr('$') arga aa bb cc dd ee ff 3argu let args = [] @@ -171,6 +173,8 @@ func Test_command_count_4() only! exe bufnr . 'buf' + bnext + let bufnr = bufnr('%') let buffers = [] .,$-bufdo call add(buffers, bufnr('%')) call assert_equal([bufnr, bufnr + 1, bufnr + 2, bufnr + 3, bufnr + 4], buffers) diff --git a/src/nvim/testdir/test_curswant.vim b/src/nvim/testdir/test_curswant.vim new file mode 100644 index 0000000000..e54cd4b280 --- /dev/null +++ b/src/nvim/testdir/test_curswant.vim @@ -0,0 +1,23 @@ +" Tests for curswant not changing when setting an option + +func Test_curswant() + new + call append(0, ['1234567890', '12345']) + + normal! ggf8j + call assert_equal(7, winsaveview().curswant) + let &tabstop=&tabstop + call assert_equal(4, winsaveview().curswant) + + normal! ggf8j + call assert_equal(7, winsaveview().curswant) + let &timeoutlen=&timeoutlen + call assert_equal(7, winsaveview().curswant) + + normal! ggf8j + call assert_equal(7, winsaveview().curswant) + let &ttimeoutlen=&ttimeoutlen + call assert_equal(7, winsaveview().curswant) + + enew! +endfunc diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim index 5de394de8e..d95b29759e 100644 --- a/src/nvim/testdir/test_diffmode.vim +++ b/src/nvim/testdir/test_diffmode.vim @@ -198,23 +198,366 @@ func Test_diffget_diffput() call assert_fails('diffget', 'E101:') windo diffoff - bwipe! - bwipe! - enew! + %bwipe! +endfunc + +func Test_dp_do_buffer() + e! one + let bn1=bufnr('%') + let l = range(60) + call setline(1, l) + diffthis + + new two + let l[10] = 'one' + let l[20] = 'two' + let l[30] = 'three' + let l[40] = 'four' + let l[50] = 'five' + call setline(1, l) + diffthis + + " dp and do with invalid buffer number. + 11 + call assert_fails('norm 99999dp', 'E102:') + call assert_fails('norm 99999do', 'E102:') + call assert_fails('diffput non_existing_buffer', 'E94:') + call assert_fails('diffget non_existing_buffer', 'E94:') + + " dp and do with valid buffer number. + call assert_equal('one', getline('.')) + exe 'norm ' . bn1 . 'do' + call assert_equal('10', getline('.')) + 21 + call assert_equal('two', getline('.')) + diffget one + call assert_equal('20', getline('.')) + + 31 + exe 'norm ' . bn1 . 'dp' + 41 + diffput one + wincmd w + 31 + call assert_equal('three', getline('.')) + 41 + call assert_equal('four', getline('.')) + + " dp and do with buffer number which is not in diff mode. + new not_in_diff_mode + let bn3=bufnr('%') + wincmd w + 51 + call assert_fails('exe "norm" . bn3 . "dp"', 'E103:') + call assert_fails('exe "norm" . bn3 . "do"', 'E103:') + call assert_fails('diffput not_in_diff_mode', 'E94:') + call assert_fails('diffget not_in_diff_mode', 'E94:') + + windo diffoff + %bwipe! endfunc func Test_diffoff() enew! call setline(1, ['Two', 'Three']) + redraw let normattr = screenattr(1, 1) diffthis botright vert new call setline(1, ['One', '', 'Two', 'Three']) diffthis redraw + call assert_notequal(normattr, screenattr(1, 1)) + diffoff! + redraw + call assert_equal(normattr, screenattr(1, 1)) + bwipe! + bwipe! +endfunc + +func Test_diffopt_icase() + set diffopt=icase,foldcolumn:0 + + e one + call setline(1, ['One', 'Two', 'Three', 'Four']) + redraw + let normattr = screenattr(1, 1) + diffthis + + botright vert new two + call setline(1, ['one', 'TWO', 'Three ', 'Four']) + diffthis + + redraw + call assert_equal(normattr, screenattr(1, 1)) + call assert_equal(normattr, screenattr(2, 1)) + call assert_notequal(normattr, screenattr(3, 1)) + call assert_equal(normattr, screenattr(4, 1)) + diffoff! + %bwipe! + set diffopt& +endfunc + +func Test_diffopt_iwhite() + set diffopt=iwhite,foldcolumn:0 + + e one + " Difference in trailing spaces should be ignored, + " but not other space differences. + call setline(1, ["One \t", 'Two', 'Three', 'Four']) + redraw + let normattr = screenattr(1, 1) + diffthis + + botright vert new two + call setline(1, ["One\t ", "Two\t ", 'Three', ' Four']) + diffthis + redraw call assert_equal(normattr, screenattr(1, 1)) + call assert_equal(normattr, screenattr(2, 1)) + call assert_equal(normattr, screenattr(3, 1)) + call assert_notequal(normattr, screenattr(4, 1)) + + diffoff! + %bwipe! + set diffopt& +endfunc + +func Test_diffopt_context() + enew! + call setline(1, ['1', '2', '3', '4', '5', '6', '7']) + diffthis + new + call setline(1, ['1', '2', '3', '4', '5x', '6', '7']) + diffthis + + set diffopt=context:2 + call assert_equal('+-- 2 lines: 1', foldtextresult(1)) + set diffopt=context:1 + call assert_equal('+-- 3 lines: 1', foldtextresult(1)) + + diffoff! + %bwipe! + set diffopt& +endfunc + +func Test_diffopt_horizontal() + set diffopt=horizontal + diffsplit + + call assert_equal(&columns, winwidth(1)) + call assert_equal(&columns, winwidth(2)) + call assert_equal(&lines, winheight(1) + winheight(2) + 3) + call assert_inrange(0, 1, winheight(1) - winheight(2)) + + set diffopt& + diffoff! + %bwipe +endfunc + +func Test_diffopt_vertical() + set diffopt=vertical + diffsplit + + call assert_equal(&lines - 2, winheight(1)) + call assert_equal(&lines - 2, winheight(2)) + call assert_equal(&columns, winwidth(1) + winwidth(2) + 1) + call assert_inrange(0, 1, winwidth(1) - winwidth(2)) + + set diffopt& + diffoff! + %bwipe +endfunc + +func Test_diffoff_hidden() + set diffopt=filler,foldcolumn:0 + e! one + call setline(1, ['Two', 'Three']) + redraw + let normattr = screenattr(1, 1) + diffthis + botright vert new two + call setline(1, ['One', 'Four']) + diffthis + redraw + call assert_notequal(normattr, screenattr(1, 1)) + set hidden + close + redraw + " diffing with hidden buffer two + call assert_notequal(normattr, screenattr(1, 1)) + diffoff + redraw + call assert_equal(normattr, screenattr(1, 1)) + diffthis + redraw + " still diffing with hidden buffer two + call assert_notequal(normattr, screenattr(1, 1)) + diffoff! + redraw + call assert_equal(normattr, screenattr(1, 1)) + diffthis + redraw + " no longer diffing with hidden buffer two + call assert_equal(normattr, screenattr(1, 1)) + + bwipe! + bwipe! + set hidden& diffopt& +endfunc + +func Test_setting_cursor() + new Xtest1 + put =range(1,90) + wq + new Xtest2 + put =range(1,100) + wq + + tabe Xtest2 + $ + diffsp Xtest1 + tabclose + + call delete('Xtest1') + call delete('Xtest2') +endfunc + +func Test_diff_move_to() + new + call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + diffthis + vnew + call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x']) + diffthis + norm ]c + call assert_equal(2, line('.')) + norm 3]c + call assert_equal(9, line('.')) + norm 10]c + call assert_equal(11, line('.')) + norm [c + call assert_equal(9, line('.')) + norm 2[c + call assert_equal(5, line('.')) + norm 10[c + call assert_equal(2, line('.')) + %bwipe! +endfunc + +func Test_diffexpr() + if !executable('diff') + return + endif + + func DiffExpr() + silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>' . v:fname_out + endfunc + set diffexpr=DiffExpr() + set diffopt=foldcolumn:0 + + enew! + call setline(1, ['one', 'two', 'three']) + redraw + let normattr = screenattr(1, 1) + diffthis + + botright vert new + call setline(1, ['one', 'two', 'three.']) + diffthis + + redraw + call assert_equal(normattr, screenattr(1, 1)) + call assert_equal(normattr, screenattr(2, 1)) + call assert_notequal(normattr, screenattr(3, 1)) + + diffoff! + %bwipe! + set diffexpr& diffopt& +endfunc + +func Test_diffpatch() + " The patch program on MS-Windows may fail or hang. + if !executable('patch') || !has('unix') + return + endif + new + insert +*************** +*** 1,3 **** + 1 +! 2 + 3 +--- 1,4 ---- + 1 +! 2x + 3 ++ 4 +. + saveas Xpatch + bwipe! + new + call assert_fails('diffpatch Xpatch', 'E816:') + + for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch'] + call setline(1, ['1', '2', '3']) + if name != 'Xpatch' + call rename('Xpatch', name) + endif + exe 'diffpatch ' . escape(name, '$') + call assert_equal(['1', '2x', '3', '4'], getline(1, '$')) + if name != 'Xpatch' + call rename(name, 'Xpatch') + endif + bwipe! + endfor + + call delete('Xpatch') + bwipe! +endfunc + +func Test_diff_too_many_buffers() + for i in range(1, 8) + exe "new Xtest" . i + diffthis + endfor + new Xtest9 + call assert_fails('diffthis', 'E96:') + %bwipe! +endfunc + +func Test_diff_nomodifiable() + new + call setline(1, [1, 2, 3, 4]) + setl nomodifiable + diffthis + vnew + call setline(1, ['1x', 2, 3, 3, 4]) + diffthis + call assert_fails('norm dp', 'E793:') + setl nomodifiable + call assert_fails('norm do', 'E21:') + %bwipe! +endfunc + +func Test_diff_lastline() + enew! + only! + call setline(1, ['This is a ', 'line with five ', 'rows']) + diffthis + botright vert new + call setline(1, ['This is', 'a line with ', 'four rows']) + diffthis + 1 + call feedkeys("Je a\<CR>", 'tx') + call feedkeys("Je a\<CR>", 'tx') + let w1lines = winline() + wincmd w + $ + let w2lines = winline() + call assert_equal(w2lines, w1lines) bwipe! bwipe! endfunc diff --git a/src/nvim/testdir/test_display.vim b/src/nvim/testdir/test_display.vim new file mode 100644 index 0000000000..0ed672d577 --- /dev/null +++ b/src/nvim/testdir/test_display.vim @@ -0,0 +1,71 @@ +" Test for displaying stuff + +" Nvim: `:set term` is not supported. +" if !has('gui_running') && has('unix') +" set term=ansi +" endif + +source view_util.vim + +func! Test_display_foldcolumn() + if !has("folding") + return + endif + new + vnew + vert resize 25 + call assert_equal(25, winwidth(winnr())) + set isprint=@ + + 1put='e more noise blah blah more stuff here' + + let expect = [ + \ "e more noise blah blah<82", + \ "> more stuff here " + \ ] + + call cursor(2, 1) + norm! zt + let lines=ScreenLines([1,2], winwidth(0)) + call assert_equal(expect, lines) + set fdc=2 + let lines=ScreenLines([1,2], winwidth(0)) + let expect = [ + \ " e more noise blah blah<", + \ " 82> more stuff here " + \ ] + call assert_equal(expect, lines) + + quit! + quit! +endfunc + +func! Test_display_foldtext_mbyte() + if !has("folding") || !has("multi_byte") + return + endif + call NewWindow(10, 40) + call append(0, range(1,20)) + exe "set foldmethod=manual foldtext=foldtext() fillchars=fold:\u2500,vert:\u2502 fdc=2" + call cursor(2, 1) + norm! zf13G + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 \u2502", + \ "+ +-- 12 lines: 2". repeat("\u2500", 23). "\u2502", + \ " 14 \u2502", + \ ] + call assert_equal(expect, lines) + + set fillchars=fold:-,vert:\| + let lines=ScreenLines([1,3], winwidth(0)+1) + let expect=[ + \ " 1 |", + \ "+ +-- 12 lines: 2". repeat("-", 23). "|", + \ " 14 |", + \ ] + call assert_equal(expect, lines) + + set foldtext& fillchars& foldmethod& fdc& + bw! +endfunc diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim new file mode 100644 index 0000000000..8f815478c2 --- /dev/null +++ b/src/nvim/testdir/test_edit.vim @@ -0,0 +1,1325 @@ +" Test for edit functions +" +if exists("+t_kD") + let &t_kD="[3;*~" +endif + +" Needed for testing basic rightleft: Test_edit_rightleft +source view_util.vim + +" Needs to come first until the bug in getchar() is +" fixed: https://groups.google.com/d/msg/vim_dev/fXL9yme4H4c/bOR-U6_bAQAJ +func! Test_edit_00b() + new + call setline(1, ['abc ']) + inoreabbr <buffer> h here some more + call cursor(1, 4) + " <c-l> expands the abbreviation and ends insertmode + call feedkeys(":set im\<cr> h\<c-l>:set noim\<cr>", 'tix') + call assert_equal(['abc here some more '], getline(1,'$')) + iunabbr <buffer> h + bw! +endfunc + +func! Test_edit_01() + " set for Travis CI? + " set nocp noesckeys + new + " 1) empty buffer + call assert_equal([''], getline(1,'$')) + " 2) delete in an empty line + call feedkeys("i\<del>\<esc>", 'tnix') + call assert_equal([''], getline(1,'$')) + %d + " 3) delete one character + call setline(1, 'a') + call feedkeys("i\<del>\<esc>", 'tnix') + call assert_equal([''], getline(1,'$')) + %d + " 4) delete a multibyte character + if has("multi_byte") + call setline(1, "\u0401") + call feedkeys("i\<del>\<esc>", 'tnix') + call assert_equal([''], getline(1,'$')) + %d + endif + " 5.1) delete linebreak with 'bs' option containing eol + let _bs=&bs + set bs=eol + call setline(1, ["abc def", "ghi jkl"]) + call cursor(1, 1) + call feedkeys("A\<del>\<esc>", 'tnix') + call assert_equal(['abc defghi jkl'], getline(1, 2)) + %d + " 5.2) delete linebreak with backspace option w/out eol + set bs= + call setline(1, ["abc def", "ghi jkl"]) + call cursor(1, 1) + call feedkeys("A\<del>\<esc>", 'tnix') + call assert_equal(["abc def", "ghi jkl"], getline(1, 2)) + let &bs=_bs + bw! +endfunc + +func! Test_edit_02() + " Change cursor position in InsertCharPre command + new + call setline(1, 'abc') + call cursor(1, 1) + fu! DoIt(...) + call cursor(1, 4) + if len(a:000) + let v:char=a:1 + endif + endfu + au InsertCharPre <buffer> :call DoIt('y') + call feedkeys("ix\<esc>", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + " Setting <Enter> in InsertCharPre + au! InsertCharPre <buffer> :call DoIt("\n") + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\<esc>", 'tnix') + call assert_equal(['abc', ''], getline(1, '$')) + %d + au! InsertCharPre + " Change cursor position in InsertEnter command + " 1) when setting v:char, keeps changed cursor position + au! InsertEnter <buffer> :call DoIt('y') + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\<esc>", 'tnix') + call assert_equal(['abxc'], getline(1, '$')) + " 2) when not setting v:char, restores changed cursor position + au! InsertEnter <buffer> :call DoIt() + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("ix\<esc>", 'tnix') + call assert_equal(['xabc'], getline(1, '$')) + au! InsertEnter + delfu DoIt + bw! +endfunc + +func! Test_edit_03() + " Change cursor after <c-o> command to end of line + new + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("i\<c-o>$y\<esc>", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + %d + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("i\<c-o>80|y\<esc>", 'tnix') + call assert_equal(['abcy'], getline(1, '$')) + %d + call setline(1, 'abc') + call feedkeys("Ad\<c-o>:s/$/efg/\<cr>hij", 'tnix') + call assert_equal(['hijabcdefg'], getline(1, '$')) + bw! +endfunc + +func! Test_edit_04() + " test for :stopinsert + new + call setline(1, 'abc') + call cursor(1, 1) + call feedkeys("i\<c-o>:stopinsert\<cr>$", 'tnix') + call feedkeys("aX\<esc>", 'tnix') + call assert_equal(['abcX'], getline(1, '$')) + %d + bw! +endfunc + +func! Test_edit_05() + " test for folds being opened + new + call setline(1, ['abcX', 'abcX', 'zzzZ']) + call cursor(1, 1) + set foldmethod=manual foldopen+=insert + " create fold for those two lines + norm! Vjzf + call feedkeys("$ay\<esc>", 'tnix') + call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$')) + %d + call setline(1, ['abcX', 'abcX', 'zzzZ']) + call cursor(1, 1) + set foldmethod=manual foldopen-=insert + " create fold for those two lines + norm! Vjzf + call feedkeys("$ay\<esc>", 'tnix') + call assert_equal(['abcXy', 'abcX', 'zzzZ'], getline(1, '$')) + %d + bw! +endfunc + +func! Test_edit_06() + " Test in diff mode + if !has("diff") || !executable("diff") + return + endif + new + call setline(1, ['abc', 'xxx', 'yyy']) + vnew + call setline(1, ['abc', 'zzz', 'xxx', 'yyy']) + wincmd p + diffthis + wincmd p + diffthis + wincmd p + call cursor(2, 1) + norm! zt + call feedkeys("Ozzz\<esc>", 'tnix') + call assert_equal(['abc', 'zzz', 'xxx', 'yyy'], getline(1,'$')) + bw! + bw! +endfunc + +func! Test_edit_07() + " 1) Test with completion <c-l> when popupmenu is visible + new + call setline(1, 'J') + + func! ListMonths() + call complete(col('.')-1, ['January', 'February', 'March', + \ 'April', 'May', 'June', 'July', 'August', 'September', + \ 'October', 'November', 'December']) + return '' + endfunc + inoremap <buffer> <F5> <C-R>=ListMonths()<CR> + + call feedkeys("A\<f5>\<c-p>". repeat("\<down>", 6)."\<c-l>\<down>\<c-l>\<cr>", 'tx') + call assert_equal(['July'], getline(1,'$')) + " 1) Test completion when InsertCharPre kicks in + %d + call setline(1, 'J') + fu! DoIt() + if v:char=='u' + let v:char='an' + endif + endfu + au InsertCharPre <buffer> :call DoIt() + call feedkeys("A\<f5>\<c-p>u\<cr>\<c-l>\<cr>", 'tx') + call assert_equal(["Jan\<c-l>",''], getline(1,'$')) + %d + call setline(1, 'J') + call feedkeys("A\<f5>\<c-p>u\<down>\<c-l>\<cr>", 'tx') + call assert_equal(["January"], getline(1,'$')) + + delfu ListMonths + delfu DoIt + iunmap <buffer> <f5> + bw! +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(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() + " test i_CTRL-\ combinations + new + call setline(1, ['abc', 'def', 'ghi']) + call cursor(1, 1) + " 1) CTRL-\ CTLR-N + call feedkeys(":set im\<cr>\<c-\>\<c-n>ccABC\<c-l>", 'txin') + call assert_equal(['ABC', 'def', 'ghi'], getline(1,'$')) + call setline(1, ['ABC', 'def', 'ghi']) + " 2) CTRL-\ CTLR-G + call feedkeys("j0\<c-\>\<c-g>ZZZ\<cr>\<c-l>", 'txin') + call assert_equal(['ABC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + call feedkeys("I\<c-\>\<c-g>YYY\<c-l>", 'txin') + call assert_equal(['ABC', 'ZZZ', 'YYYdef', 'ghi'], getline(1,'$')) + set noinsertmode + " 3) CTRL-\ CTRL-O + call setline(1, ['ABC', 'ZZZ', 'def', 'ghi']) + call cursor(1, 1) + call feedkeys("A\<c-o>ix", 'txin') + call assert_equal(['ABxC', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + call feedkeys("A\<c-\>\<c-o>ix", 'txin') + call assert_equal(['ABxCx', 'ZZZ', 'def', 'ghi'], getline(1,'$')) + " 4) CTRL-\ a (should be inserted literally, not special after <c-\> + call setline(1, ['ABC', 'ZZZ', 'def', 'ghi']) + call cursor(1, 1) + call feedkeys("A\<c-\>a", 'txin') + call assert_equal(["ABC\<c-\>a", 'ZZZ', 'def', 'ghi'], getline(1, '$')) + bw! +endfunc + +func! Test_edit_10() + " Test for starting selectmode + new + set selectmode=key keymodel=startsel + call setline(1, ['abc', 'def', 'ghi']) + call cursor(1, 4) + call feedkeys("A\<s-home>start\<esc>", 'txin') + call assert_equal(['startdef', 'ghi'], getline(1, '$')) + set selectmode= keymodel= + bw! +endfunc + +func! Test_edit_11() + " Test that indenting kicks in + new + set cindent + call setline(1, ['{', '', '']) + call cursor(2, 1) + call feedkeys("i\<c-f>int c;\<esc>", 'tnix') + call cursor(3, 1) + call feedkeys("i/* comment */", 'tnix') + call assert_equal(['{', "\<tab>int c;", "/* comment */"], getline(1, '$')) + " added changed cindentkeys slightly + set cindent cinkeys+=*/ + call setline(1, ['{', '', '']) + call cursor(2, 1) + call feedkeys("i\<c-f>int c;\<esc>", 'tnix') + call cursor(3, 1) + call feedkeys("i/* comment */", 'tnix') + call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */"], getline(1, '$')) + set cindent cinkeys+==end + call feedkeys("oend\<cr>\<esc>", 'tnix') + call assert_equal(['{', "\<tab>int c;", "\<tab>/* comment */", "\tend", ''], getline(1, '$')) + set cinkeys-==end + %d + " Use indentexpr instead of cindenting + func! Do_Indent() + if v:lnum == 3 + return 3*shiftwidth() + else + return 2*shiftwidth() + endif + endfunc + setl indentexpr=Do_Indent() indentkeys+=*/ + call setline(1, ['{', '', '']) + call cursor(2, 1) + call feedkeys("i\<c-f>int c;\<esc>", 'tnix') + call cursor(3, 1) + call feedkeys("i/* comment */", 'tnix') + call assert_equal(['{', "\<tab>\<tab>int c;", "\<tab>\<tab>\<tab>/* comment */"], getline(1, '$')) + set cinkeys&vim indentkeys&vim + set nocindent indentexpr= + delfu Do_Indent + bw! +endfunc + +func! Test_edit_12() + " Test changing indent in replace mode + new + call setline(1, ["\tabc", "\tdef"]) + call cursor(2, 4) + call feedkeys("R^\<c-d>", 'tnix') + call assert_equal(["\tabc", "def"], getline(1, '$')) + call assert_equal([0, 2, 2, 0], getpos('.')) + %d + call setline(1, ["\tabc", "\t\tdef"]) + call cursor(2, 2) + call feedkeys("R^\<c-d>", 'tnix') + call assert_equal(["\tabc", "def"], getline(1, '$')) + call assert_equal([0, 2, 1, 0], getpos('.')) + %d + call setline(1, ["\tabc", "\t\tdef"]) + call cursor(2, 2) + call feedkeys("R\<c-t>", 'tnix') + call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) + call assert_equal([0, 2, 2, 0], getpos('.')) + bw! + 10vnew + call setline(1, ["\tabc", "\t\tdef"]) + call cursor(2, 2) + call feedkeys("R\<c-t>", 'tnix') + call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) + call assert_equal([0, 2, 2, 0], getpos('.')) + %d + set sw=4 + call setline(1, ["\tabc", "\t\tdef"]) + call cursor(2, 2) + call feedkeys("R\<c-t>\<c-t>", 'tnix') + call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) + call assert_equal([0, 2, 2, 0], getpos('.')) + %d + call setline(1, ["\tabc", "\t\tdef"]) + call cursor(2, 2) + call feedkeys("R\<c-t>\<c-t>", 'tnix') + call assert_equal(["\tabc", "\t\t\tdef"], getline(1, '$')) + call assert_equal([0, 2, 2, 0], getpos('.')) + set et + set sw& et& + %d + call setline(1, ["\t/*"]) + set formatoptions=croql + call cursor(1, 3) + call feedkeys("A\<cr>\<cr>/", 'tnix') + call assert_equal(["\t/*", " *", " */"], getline(1, '$')) + set formatoptions& + bw! +endfunc + +func! Test_edit_13() + " Test smartindenting + if exists("+smartindent") + new + set smartindent autoindent + call setline(1, ["\tabc"]) + call feedkeys("A {\<cr>more\<cr>}\<esc>", 'tnix') + call assert_equal(["\tabc {", "\t\tmore", "\t}"], getline(1, '$')) + set smartindent& autoindent& + bw! + endif +endfunc + +func! Test_edit_CR() + " Test for <CR> in insert mode + " basically only in quickfix mode ist tested, the rest + " has been taken care of by other tests + if !has("quickfix") + return + endif + botright new + call writefile(range(1, 10), 'Xqflist.txt') + call setqflist([{'filename': 'Xqflist.txt', 'lnum': 2}]) + copen + set modifiable + call feedkeys("A\<cr>", 'tnix') + call assert_equal('Xqflist.txt', bufname('')) + call assert_equal(2, line('.')) + cclose + botright new + call setloclist(0, [{'filename': 'Xqflist.txt', 'lnum': 10}]) + lopen + set modifiable + call feedkeys("A\<cr>", 'tnix') + call assert_equal('Xqflist.txt', bufname('')) + call assert_equal(10, line('.')) + call feedkeys("A\<Enter>", 'tnix') + call feedkeys("A\<kEnter>", 'tnix') + call feedkeys("A\n", 'tnix') + call feedkeys("A\r", 'tnix') + call assert_equal(map(range(1, 10), 'string(v:val)') + ['', '', '', ''], getline(1, '$')) + bw! + lclose + call delete('Xqflist.txt') +endfunc + +func! Test_edit_CTRL_() + " disabled for Windows builds, why? + if !has("multi_byte") || !has("rightleft") || has("win32") + return + endif + let _encoding=&encoding + set encoding=utf-8 + " Test for CTRL-_ + new + call setline(1, ['abc']) + call cursor(1, 1) + call feedkeys("i\<c-_>xyz\<esc>", 'tnix') + call assert_equal(["\<C-_>xyzabc"], getline(1, '$')) + call assert_false(&revins) + set ari + call setline(1, ['abc']) + call cursor(1, 1) + call feedkeys("i\<c-_>xyz\<esc>", 'tnix') + call assert_equal(["æèñabc"], getline(1, '$')) + call assert_true(&revins) + call setline(1, ['abc']) + call cursor(1, 1) + call feedkeys("i\<c-_>xyz\<esc>", 'tnix') + call assert_equal(["xyzabc"], getline(1, '$')) + call assert_false(&revins) + set noari + let &encoding=_encoding + bw! +endfunc + +" needs to come first, to have the @. register empty +func! Test_edit_00a_CTRL_A() + " Test pressing CTRL-A + new + call setline(1, repeat([''], 5)) + call cursor(1, 1) + try + call feedkeys("A\<NUL>", 'tnix') + catch /^Vim\%((\a\+)\)\=:E29/ + call assert_true(1, 'E29 error caught') + endtry + call cursor(1, 1) + call feedkeys("Afoobar \<esc>", 'tnix') + call cursor(2, 1) + call feedkeys("A\<c-a>more\<esc>", 'tnix') + call cursor(3, 1) + call feedkeys("A\<NUL>and more\<esc>", 'tnix') + call assert_equal(['foobar ', 'foobar more', 'foobar morend more', '', ''], getline(1, '$')) + bw! +endfunc + +func! Test_edit_CTRL_EY() + " Ctrl-E/ Ctrl-Y in insert mode completion to scroll + 10new + call setline(1, range(1, 100)) + call cursor(30, 1) + norm! z. + call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix') + call assert_equal(30, winsaveview()['topline']) + call assert_equal([0, 30, 2, 0], getpos('.')) + call feedkeys("A\<c-x>\<c-e>\<c-e>\<c-e>\<c-e>\<c-e>", 'tnix') + call feedkeys("A\<c-x>".repeat("\<c-y>", 10), 'tnix') + call assert_equal(21, winsaveview()['topline']) + call assert_equal([0, 30, 2, 0], getpos('.')) + bw! +endfunc + +func! Test_edit_CTRL_G() + new + call setline(1, ['foobar', 'foobar', 'foobar']) + call cursor(2, 4) + call feedkeys("ioooooooo\<c-g>k\<c-r>.\<esc>", 'tnix') + call assert_equal(['foooooooooobar', 'foooooooooobar', 'foobar'], getline(1, '$')) + call assert_equal([0, 1, 11, 0], getpos('.')) + call feedkeys("i\<c-g>k\<esc>", 'tnix') + call assert_equal([0, 1, 10, 0], getpos('.')) + call cursor(2, 4) + call feedkeys("i\<c-g>jzzzz\<esc>", 'tnix') + call assert_equal(['foooooooooobar', 'foooooooooobar', 'foozzzzbar'], getline(1, '$')) + call assert_equal([0, 3, 7, 0], getpos('.')) + call feedkeys("i\<c-g>j\<esc>", 'tnix') + call assert_equal([0, 3, 6, 0], getpos('.')) + bw! +endfunc + +func! Test_edit_CTRL_I() + " Tab in completion mode + let path=expand("%:p:h") + new + call setline(1, [path."/", '']) + call feedkeys("Arunt\<c-x>\<c-f>\<tab>\<cr>\<esc>", 'tnix') + call assert_match('runtest\.vim', getline(1)) + %d + call writefile(['one', 'two', 'three'], 'Xinclude.txt') + let include='#include Xinclude.txt' + call setline(1, [include, '']) + call cursor(2, 1) + call feedkeys("A\<c-x>\<tab>\<cr>\<esc>", 'tnix') + call assert_equal([include, 'one', ''], getline(1, '$')) + call feedkeys("2ggC\<c-x>\<tab>\<down>\<cr>\<esc>", 'tnix') + call assert_equal([include, 'two', ''], getline(1, '$')) + call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<cr>\<esc>", 'tnix') + call assert_equal([include, 'three', ''], getline(1, '$')) + call feedkeys("2ggC\<c-x>\<tab>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') + call assert_equal([include, '', ''], getline(1, '$')) + call delete("Xinclude.txt") + bw! +endfunc + +func! Test_edit_CTRL_K() + " Test pressing CTRL-K (basically only dictionary completion and digraphs + " the rest is already covered + call writefile(['A', 'AA', 'AAA', 'AAAA'], 'Xdictionary.txt') + set dictionary=Xdictionary.txt + new + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<cr>\<esc>", 'tnix') + call assert_equal(['AA', ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<down>\<cr>\<esc>", 'tnix') + call assert_equal(['AAA'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<cr>\<esc>", 'tnix') + call assert_equal(['AAAA'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') + call assert_equal(['A'], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<down>\<down>\<down>\<down>\<cr>\<esc>", 'tnix') + call assert_equal(['AA'], getline(1, '$')) + + " press an unexecpted key after dictionary completion + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<c-]>\<cr>\<esc>", 'tnix') + call assert_equal(['AA', ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<c-s>\<cr>\<esc>", 'tnix') + call assert_equal(["AA\<c-s>", ''], getline(1, '$')) + %d + call setline(1, 'A') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-k>\<c-f>\<cr>\<esc>", 'tnix') + call assert_equal(["AA\<c-f>", ''], getline(1, '$')) + + set dictionary= + %d + call setline(1, 'A') + call cursor(1, 1) + let v:testing = 1 + try + call feedkeys("A\<c-x>\<c-k>\<esc>", 'tnix') + catch + " error sleeps 2 seconds, when v:testing is not set + let v:testing = 0 + endtry + call delete('Xdictionary.txt') + + if has("multi_byte") && !has("nvim") + call test_override("char_avail", 1) + set showcmd + %d + call feedkeys("A\<c-k>a:\<esc>", 'tnix') + call assert_equal(['ä'], getline(1, '$')) + call test_override("char_avail", 0) + set noshowcmd + endif + bw! +endfunc + +func! Test_edit_CTRL_L() + " Test Ctrl-X Ctrl-L (line completion) + new + set complete=. + call setline(1, ['one', 'two', 'three', '', '', '', '']) + call cursor(4, 1) + call feedkeys("A\<c-x>\<c-l>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-n>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-n>\<c-n>\<c-n>\<c-n>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-p>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'two', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 't', '', '', ''], getline(1, '$')) + call feedkeys("cct\<c-x>\<c-l>\<c-p>\<c-p>\<c-p>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', '', '', ''], getline(1, '$')) + set complete= + call cursor(5, 1) + call feedkeys("A\<c-x>\<c-l>\<c-p>\<c-n>\<esc>", 'tnix') + call assert_equal(['one', 'two', 'three', 'three', "\<c-l>\<c-p>\<c-n>", '', ''], getline(1, '$')) + set complete& + %d + if has("conceal") && has("syntax") && !has("nvim") + call setline(1, ['foo', 'bar', 'foobar']) + call test_override("char_avail", 1) + set conceallevel=2 concealcursor=n + syn on + syn match ErrorMsg "^bar" + call matchadd("Conceal", 'oo', 10, -1, {'conceal': 'X'}) + func! DoIt() + let g:change=1 + endfunc + au! TextChangedI <buffer> :call DoIt() + + call cursor(2, 1) + call assert_false(exists("g:change")) + call feedkeys("A \<esc>", 'tnix') + call assert_equal(['foo', 'bar ', 'foobar'], getline(1, '$')) + call assert_equal(1, g:change) + + call test_override("char_avail", 0) + call clearmatches() + syn off + au! TextChangedI + delfu DoIt + unlet! g:change + endif + bw! +endfunc + +func! Test_edit_CTRL_N() + " Check keyword completion + new + set complete=. + call setline(1, ['INFER', 'loWER', '', '', ]) + call cursor(3, 1) + call feedkeys("Ai\<c-n>\<cr>\<esc>", "tnix") + call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['INFER', 'loWER', 'i', 'LO', '', ''], getline(1, '$')) + %d + call setline(1, ['INFER', 'loWER', '', '', ]) + call cursor(3, 1) + set ignorecase infercase + call feedkeys("Ii\<c-n>\<cr>\<esc>", "tnix") + call feedkeys("ILO\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['INFER', 'loWER', 'infer', 'LOWER', '', ''], getline(1, '$')) + + set noignorecase noinfercase complete& + bw! +endfunc + +func! Test_edit_CTRL_O() + " Check for CTRL-O in insert mode + new + inoreabbr <buffer> h here some more + call setline(1, ['abc', 'def']) + call cursor(1, 1) + " Ctrl-O after an abbreviation + exe "norm A h\<c-o>:set nu\<cr> text" + call assert_equal(['abc here some more text', 'def'], getline(1, '$')) + call assert_true(&nu) + set nonu + iunabbr <buffer> h + " Ctrl-O at end of line with 've'=onemore + call cursor(1, 1) + call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix') + call assert_equal([0, 1, 23, 0], g:a) + call cursor(1, 1) + set ve=onemore + call feedkeys("A\<c-o>:let g:a=getpos('.')\<cr>\<esc>", 'tnix') + call assert_equal([0, 1, 24, 0], g:a) + set ve= + unlet! g:a + bw! +endfunc + +func! Test_edit_CTRL_R() + throw 'skipped: Nvim does not support test_override()' + " Insert Register + new + call test_override("ALL", 1) + set showcmd + call feedkeys("AFOOBAR eins zwei\<esc>", 'tnix') + call feedkeys("O\<c-r>.", 'tnix') + call feedkeys("O\<c-r>=10*500\<cr>\<esc>", 'tnix') + call feedkeys("O\<c-r>=getreg('=', 1)\<cr>\<esc>", 'tnix') + call assert_equal(["getreg('=', 1)", '5000', "FOOBAR eins zwei", "FOOBAR eins zwei"], getline(1, '$')) + call test_override("ALL", 0) + set noshowcmd + bw! +endfunc + +func! Test_edit_CTRL_S() + " Test pressing CTRL-S (basically only spellfile completion) + " the rest is already covered + new + if !has("spell") + call setline(1, 'vim') + call feedkeys("A\<c-x>ss\<cr>\<esc>", 'tnix') + call assert_equal(['vims', ''], getline(1, '$')) + bw! + return + endif + call setline(1, 'vim') + " spell option not yet set + try + call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix') + catch /^Vim\%((\a\+)\)\=:E756/ + call assert_true(1, 'error caught') + endtry + call assert_equal(['vim', ''], getline(1, '$')) + %d + setl spell spelllang=en + call setline(1, 'vim') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-s>\<cr>\<esc>", 'tnix') + call assert_equal(['Vim', ''], getline(1, '$')) + %d + call setline(1, 'vim') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-s>\<down>\<cr>\<esc>", 'tnix') + call assert_equal(['Aim'], getline(1, '$')) + %d + call setline(1, 'vim') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix') + call assert_equal(['vim', ''], getline(1, '$')) + %d + " empty buffer + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-s>\<c-p>\<cr>\<esc>", 'tnix') + call assert_equal(['', ''], getline(1, '$')) + setl nospell + bw! +endfunc + +func! Test_edit_CTRL_T() + " Check for CTRL-T and CTRL-X CTRL-T in insert mode + " 1) increase indent + new + call setline(1, "abc") + call cursor(1, 1) + call feedkeys("A\<c-t>xyz", 'tnix') + call assert_equal(["\<tab>abcxyz"], getline(1, '$')) + " 2) also when paste option is set + set paste + call setline(1, "abc") + call cursor(1, 1) + call feedkeys("A\<c-t>xyz", 'tnix') + call assert_equal(["\<tab>abcxyz"], getline(1, '$')) + set nopaste + " CTRL-X CTRL-T (thesaurus complete) + call writefile(['angry furious mad enraged'], 'Xthesaurus') + set thesaurus=Xthesaurus + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<cr>\<esc>", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['angry', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['furious', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['enraged', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + " Using <c-p> <c-n> when 'complete' is empty + set complete= + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['angry', ''], getline(1, '$')) + %d + call setline(1, 'mad') + call cursor(1, 1) + call feedkeys("A\<c-x>\<c-t>\<c-p>\<cr>\<esc>", 'tnix') + call assert_equal(['mad', ''], getline(1, '$')) + set complete& + + set thesaurus= + %d + call setline(1, 'mad') + call cursor(1, 1) + let v:testing = 1 + try + call feedkeys("A\<c-x>\<c-t>\<esc>", 'tnix') + catch + " error sleeps 2 seconds, when v:testing is not set + let v:testing = 0 + endtry + call assert_equal(['mad'], getline(1, '$')) + call delete('Xthesaurus') + bw! +endfunc + +func! Test_edit_CTRL_U() + " Test 'completefunc' + new + " -1, -2 and -3 are special return values + let g:special=0 + fun! CompleteMonths(findstart, base) + if a:findstart + " locate the start of the word + return g:special + else + " find months matching with "a:base" + let res = [] + for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") + if m =~ '^\c'.a:base + call add(res, {'word': m, 'abbr': m.' Month', 'icase': 0}) + endif + endfor + return {'words': res, 'refresh': 'always'} + endif + endfun + set completefunc=CompleteMonths + call setline(1, ['', '']) + call cursor(1, 1) + call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') + call assert_equal(['X', '', ''], getline(1, '$')) + %d + let g:special=-1 + call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') + call assert_equal(['XJan', ''], getline(1, '$')) + %d + let g:special=-2 + call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') + call assert_equal(['X', ''], getline(1, '$')) + %d + let g:special=-3 + call feedkeys("AX\<c-x>\<c-u>\<cr>\<esc>", 'tnix') + call assert_equal(['X', ''], getline(1, '$')) + %d + let g:special=0 + call feedkeys("AM\<c-x>\<c-u>\<cr>\<esc>", 'tnix') + call assert_equal(['Mar', ''], getline(1, '$')) + %d + call feedkeys("AM\<c-x>\<c-u>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['May', ''], getline(1, '$')) + %d + call feedkeys("AM\<c-x>\<c-u>\<c-n>\<c-n>\<cr>\<esc>", 'tnix') + call assert_equal(['M', ''], getline(1, '$')) + delfu CompleteMonths + %d + try + call feedkeys("A\<c-x>\<c-u>", 'tnix') + call assert_fails(1, 'unknown completion function') + catch /^Vim\%((\a\+)\)\=:E117/ + call assert_true(1, 'E117 error caught') + endtry + set completefunc= + bw! +endfunc + +func! Test_edit_CTRL_Z() + " Ctrl-Z when insertmode is not set inserts it literally + new + call setline(1, 'abc') + call feedkeys("A\<c-z>\<esc>", 'tnix') + call assert_equal(["abc\<c-z>"], getline(1,'$')) + bw! + " TODO: How to Test Ctrl-Z in insert mode, e.g. suspend? +endfunc + +func! Test_edit_DROP() + if !has("dnd") + return + endif + new + call setline(1, ['abc def ghi']) + call cursor(1, 1) + try + call feedkeys("i\<Drop>\<Esc>", 'tnix') + call assert_fails(1, 'Invalid register name') + catch /^Vim\%((\a\+)\)\=:E353/ + call assert_true(1, 'error caught') + endtry + bw! +endfunc + +func! Test_edit_CTRL_V() + throw 'skipped: Nvim does not support test_override()' + if has("ebcdic") + return + endif + new + call setline(1, ['abc']) + call cursor(2, 1) + " force some redraws + set showmode showcmd + "call test_override_char_avail(1) + call test_override('ALL', 1) + call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix') + call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$')) + + if has("rightleft") && exists("+rl") + set rl + call setline(1, ['abc']) + call cursor(2, 1) + call feedkeys("A\<c-v>\<c-n>\<c-v>\<c-l>\<c-v>\<c-b>\<esc>", 'tnix') + call assert_equal(["abc\x0e\x0c\x02"], getline(1, '$')) + set norl + endif + + call test_override('ALL', 0) + set noshowmode showcmd + bw! +endfunc + +func! Test_edit_F1() + " Pressing <f1> + new + call feedkeys(":set im\<cr>\<f1>\<c-l>", 'tnix') + set noinsertmode + call assert_equal('help', &buftype) + bw + bw +endfunc + +func! Test_edit_F21() + " Pressing <f21> + " sends a netbeans command + if has("netbeans_intg") + new + " I have no idea what this is supposed to do :) + call feedkeys("A\<F21>\<F1>\<esc>", 'tnix') + bw + endif +endfunc + +func! Test_edit_HOME_END() + " Test Home/End Keys + new + set foldopen+=hor + call setline(1, ['abc', 'def']) + call cursor(1, 1) + call feedkeys("AX\<Home>Y\<esc>", 'tnix') + call cursor(2, 1) + call feedkeys("iZ\<End>Y\<esc>", 'tnix') + call assert_equal(['YabcX', 'ZdefY'], getline(1, '$')) + + set foldopen-=hor + bw! +endfunc + +func! Test_edit_INS() + " Test for Pressing <Insert> + new + call setline(1, ['abc', 'def']) + call cursor(1, 1) + call feedkeys("i\<Insert>ZYX>", 'tnix') + call assert_equal(['ZYX>', 'def'], getline(1, '$')) + call setline(1, ['abc', 'def']) + call cursor(1, 1) + call feedkeys("i\<Insert>Z\<Insert>YX>", 'tnix') + call assert_equal(['ZYX>bc', 'def'], getline(1, '$')) + bw! +endfunc + +func! Test_edit_LEFT_RIGHT() + " Left, Shift-Left, Right, Shift-Right + new + call setline(1, ['abc def ghi', 'ABC DEF GHI', 'ZZZ YYY XXX']) + let _ww=&ww + set ww= + call cursor(2, 1) + call feedkeys("i\<left>\<esc>", 'tnix') + call assert_equal([0, 2, 1, 0], getpos('.')) + " Is this a bug, <s-left> does not respect whichwrap option + call feedkeys("i\<s-left>\<esc>", 'tnix') + call assert_equal([0, 1, 8, 0], getpos('.')) + call feedkeys("i". repeat("\<s-left>", 3). "\<esc>", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call feedkeys("i\<right>\<esc>", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call feedkeys("i\<right>\<right>\<esc>", 'tnix') + call assert_equal([0, 1, 2, 0], getpos('.')) + call feedkeys("A\<right>\<esc>", 'tnix') + call assert_equal([0, 1, 11, 0], getpos('.')) + call feedkeys("A\<s-right>\<esc>", 'tnix') + call assert_equal([0, 2, 1, 0], getpos('.')) + call feedkeys("i\<s-right>\<esc>", 'tnix') + call assert_equal([0, 2, 4, 0], getpos('.')) + call cursor(3, 11) + call feedkeys("A\<right>\<esc>", 'tnix') + call feedkeys("A\<s-right>\<esc>", 'tnix') + call assert_equal([0, 3, 11, 0], getpos('.')) + call cursor(2, 11) + " <S-Right> does not respect 'whichwrap' option + call feedkeys("A\<s-right>\<esc>", 'tnix') + call assert_equal([0, 3, 1, 0], getpos('.')) + " Check motion when 'whichwrap' contains cursor keys for insert mode + set ww+=[,] + call cursor(2, 1) + call feedkeys("i\<left>\<esc>", 'tnix') + call assert_equal([0, 1, 11, 0], getpos('.')) + call cursor(2, 11) + call feedkeys("A\<right>\<esc>", 'tnix') + call assert_equal([0, 3, 1, 0], getpos('.')) + call cursor(2, 11) + call feedkeys("A\<s-right>\<esc>", 'tnix') + call assert_equal([0, 3, 1, 0], getpos('.')) + let &ww = _ww + bw! +endfunc + +func! Test_edit_MOUSE() + " This is a simple test, since we not really using the mouse here + if !has("mouse") + return + endif + 10new + call setline(1, range(1, 100)) + call cursor(1, 1) + set mouse=a + call feedkeys("A\<ScrollWheelDown>\<esc>", 'tnix') + call assert_equal([0, 4, 1, 0], getpos('.')) + " This should move by one pageDown, but only moves + " by one line when the test is run... + call feedkeys("A\<S-ScrollWheelDown>\<esc>", 'tnix') + call assert_equal([0, 5, 1, 0], getpos('.')) + set nostartofline + call feedkeys("A\<C-ScrollWheelDown>\<esc>", 'tnix') + call assert_equal([0, 6, 1, 0], getpos('.')) + call feedkeys("A\<LeftMouse>\<esc>", 'tnix') + call assert_equal([0, 6, 1, 0], getpos('.')) + call feedkeys("A\<RightMouse>\<esc>", 'tnix') + call assert_equal([0, 6, 1, 0], getpos('.')) + call cursor(1, 100) + norm! zt + " this should move by a screen up, but when the test + " is run, it moves up to the top of the buffer... + call feedkeys("A\<ScrollWheelUp>\<esc>", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call cursor(1, 30) + norm! zt + call feedkeys("A\<S-ScrollWheelUp>\<esc>", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + call cursor(1, 30) + norm! zt + call feedkeys("A\<C-ScrollWheelUp>\<esc>", 'tnix') + call assert_equal([0, 1, 1, 0], getpos('.')) + %d + call setline(1, repeat(["12345678901234567890"], 100)) + call cursor(2, 1) + call feedkeys("A\<ScrollWheelRight>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\<ScrollWheelLeft>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\<S-ScrollWheelRight>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\<S-ScrollWheelLeft>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\<C-ScrollWheelRight>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + call feedkeys("A\<C-ScrollWheelLeft>\<esc>", 'tnix') + call assert_equal([0, 2, 20, 0], getpos('.')) + set mouse& startofline + bw! +endfunc + +func! Test_edit_PAGEUP_PAGEDOWN() + 10new + call setline(1, repeat(['abc def ghi'], 30)) + call cursor(1, 1) + call feedkeys("i\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 9, 1, 0], getpos('.')) + call feedkeys("i\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 17, 1, 0], getpos('.')) + call feedkeys("i\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 25, 1, 0], getpos('.')) + call feedkeys("i\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("i\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 29, 1, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 21, 1, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 13, 1, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 5, 1, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + " <S-Up> is the same as <PageUp> + " <S-Down> is the same as <PageDown> + call cursor(1, 1) + call feedkeys("i\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 9, 1, 0], getpos('.')) + call feedkeys("i\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 17, 1, 0], getpos('.')) + call feedkeys("i\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 25, 1, 0], getpos('.')) + call feedkeys("i\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("i\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 30, 1, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 29, 1, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 21, 1, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 13, 1, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 5, 1, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + set nostartofline + call cursor(30, 11) + norm! zt + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 29, 11, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 21, 11, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 13, 11, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call feedkeys("A\<PageUp>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call cursor(1, 1) + call feedkeys("A\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 9, 11, 0], getpos('.')) + call feedkeys("A\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 17, 11, 0], getpos('.')) + call feedkeys("A\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 25, 11, 0], getpos('.')) + call feedkeys("A\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + call feedkeys("A\<PageDown>\<esc>", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + " <S-Up> is the same as <PageUp> + " <S-Down> is the same as <PageDown> + call cursor(30, 11) + norm! zt + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 29, 11, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 21, 11, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 13, 11, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call feedkeys("A\<S-Up>\<esc>", 'tnix') + call assert_equal([0, 5, 11, 0], getpos('.')) + call cursor(1, 1) + call feedkeys("A\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 9, 11, 0], getpos('.')) + call feedkeys("A\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 17, 11, 0], getpos('.')) + call feedkeys("A\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 25, 11, 0], getpos('.')) + call feedkeys("A\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + call feedkeys("A\<S-Down>\<esc>", 'tnix') + call assert_equal([0, 30, 11, 0], getpos('.')) + bw! +endfunc + +func! Test_edit_forbidden() + new + " 1) edit in the sandbox is not allowed + call setline(1, 'a') + com! Sandbox :sandbox call feedkeys("i\<del>\<esc>", 'tnix') + call assert_fails(':Sandbox', 'E48:') + com! Sandbox :sandbox exe "norm! i\<del>" + call assert_fails(':Sandbox', 'E48:') + delcom Sandbox + call assert_equal(['a'], getline(1,'$')) + " 2) edit with textlock set + fu! DoIt() + call feedkeys("i\<del>\<esc>", 'tnix') + endfu + au InsertCharPre <buffer> :call DoIt() + try + call feedkeys("ix\<esc>", 'tnix') + call assert_fails(1, 'textlock') + catch /^Vim\%((\a\+)\)\=:E523/ " catch E523: not allowed here + endtry + " TODO: Might be a bug: should x really be inserted here + call assert_equal(['xa'], getline(1, '$')) + delfu DoIt + try + call feedkeys("ix\<esc>", 'tnix') + call assert_fails(1, 'unknown function') + catch /^Vim\%((\a\+)\)\=:E117/ " catch E117: unknown function + endtry + au! InsertCharPre + " 3) edit when completion is shown + fun! Complete(findstart, base) + if a:findstart + return col('.') + else + call feedkeys("i\<del>\<esc>", 'tnix') + return [] + endif + endfun + set completefunc=Complete + try + call feedkeys("i\<c-x>\<c-u>\<esc>", 'tnix') + call assert_fails(1, 'change in complete function') + catch /^Vim\%((\a\+)\)\=:E523/ " catch E523 + endtry + delfu Complete + set completefunc= + if has("rightleft") && exists("+fkmap") + " 4) 'R' when 'fkmap' and 'revins' is set. + set revins fkmap + try + normal Ri + call assert_fails(1, "R with 'fkmap' and 'ri' set") + catch + finally + set norevins nofkmap + endtry + endif + bw! +endfunc + +func! Test_edit_rightleft() + " Cursor in rightleft mode moves differently + if !exists("+rightleft") + return + endif + call NewWindow(10, 20) + call setline(1, ['abc', 'def', 'ghi']) + call cursor(1, 2) + set rightleft + " Screen looks as expected + let lines = ScreenLines([1, 4], winwidth(0)) + let expect = [ + \" cba", + \" fed", + \" ihg", + \" ~"] + call assert_equal(join(expect, "\n"), join(lines, "\n")) + " 2) right moves to the left + call feedkeys("i\<right>\<esc>x", 'txin') + call assert_equal(['bc', 'def', 'ghi'], getline(1,'$')) + call cursor(1, 2) + call feedkeys("i\<s-right>\<esc>", 'txin') + call cursor(1, 2) + call feedkeys("i\<c-right>\<esc>", 'txin') + " Screen looks as expected + let lines = ScreenLines([1, 4], winwidth(0)) + let expect = [ + \" cb", + \" fed", + \" ihg", + \" ~"] + call assert_equal(join(expect, "\n"), join(lines, "\n")) + " 2) left moves to the right + call setline(1, ['abc', 'def', 'ghi']) + call cursor(1, 2) + call feedkeys("i\<left>\<esc>x", 'txin') + call assert_equal(['ac', 'def', 'ghi'], getline(1,'$')) + call cursor(1, 2) + call feedkeys("i\<s-left>\<esc>", 'txin') + call cursor(1, 2) + call feedkeys("i\<c-left>\<esc>", 'txin') + " Screen looks as expected + let lines = ScreenLines([1, 4], winwidth(0)) + let expect = [ + \" ca", + \" fed", + \" ihg", + \" ~"] + call assert_equal(join(expect, "\n"), join(lines, "\n")) + 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_exists.vim b/src/nvim/testdir/test_exists.vim new file mode 100644 index 0000000000..fd34be83b0 --- /dev/null +++ b/src/nvim/testdir/test_exists.vim @@ -0,0 +1,321 @@ +" Tests for the exists() function +func Test_exists() + augroup myagroup + autocmd! BufEnter *.my echo "myfile edited" + autocmd! FuncUndefined UndefFun exec "fu UndefFun()\nendfu" + augroup END + set rtp+=./sautest + + " valid autocmd group + call assert_equal(1, exists('#myagroup')) + " valid autocmd group with garbage + call assert_equal(0, exists('#myagroup+b')) + " Valid autocmd group and event + call assert_equal(1, exists('#myagroup#BufEnter')) + " Valid autocmd group, event and pattern + call assert_equal(1, exists('#myagroup#BufEnter#*.my')) + " Valid autocmd event + call assert_equal(1, exists('#BufEnter')) + " Valid autocmd event and pattern + call assert_equal(1, exists('#BufEnter#*.my')) + " Non-existing autocmd group or event + call assert_equal(0, exists('#xyzagroup')) + " Non-existing autocmd group and valid autocmd event + call assert_equal(0, exists('#xyzagroup#BufEnter')) + " Valid autocmd group and event with no matching pattern + call assert_equal(0, exists('#myagroup#CmdwinEnter')) + " Valid autocmd group and non-existing autocmd event + call assert_equal(0, exists('#myagroup#xyzacmd')) + " Valid autocmd group and event and non-matching pattern + call assert_equal(0, exists('#myagroup#BufEnter#xyzpat')) + " Valid autocmd event and non-matching pattern + call assert_equal(0, exists('#BufEnter#xyzpat')) + " Empty autocmd group, event and pattern + call assert_equal(0, exists('###')) + " Empty autocmd group and event or empty event and pattern + call assert_equal(0, exists('##')) + " Valid autocmd event + call assert_equal(1, exists('##FileReadCmd')) + " Non-existing autocmd event + call assert_equal(0, exists('##MySpecialCmd')) + + " Existing and working option (long form) + call assert_equal(1, exists('&textwidth')) + " Existing and working option (short form) + call assert_equal(1, exists('&tw')) + " Existing and working option with garbage + call assert_equal(0, exists('&tw-')) + " Global option + call assert_equal(1, exists('&g:errorformat')) + " Local option + call assert_equal(1, exists('&l:errorformat')) + " Negative form of existing and working option (long form) + call assert_equal(0, exists('&nojoinspaces')) + " Negative form of existing and working option (short form) + call assert_equal(0, exists('&nojs')) + " Non-existing option + call assert_equal(0, exists('&myxyzoption')) + + " Existing and working option (long form) + call assert_equal(1, exists('+incsearch')) + " Existing and working option with garbage + call assert_equal(0, exists('+incsearch!1')) + " Existing and working option (short form) + call assert_equal(1, exists('+is')) + " Existing option that is hidden. + call assert_equal(0, exists('+autoprint')) + + " Existing environment variable + let $EDITOR_NAME = 'Vim Editor' + call assert_equal(1, exists('$EDITOR_NAME')) + " Non-existing environment variable + call assert_equal(0, exists('$NON_ENV_VAR')) + + " Valid internal function + call assert_equal(1, exists('*bufnr')) + " Valid internal function with () + call assert_equal(1, exists('*bufnr()')) + " Non-existing internal function + call assert_equal(0, exists('*myxyzfunc')) + " Valid internal function with garbage + call assert_equal(0, exists('*bufnr&6')) + " Valid user defined function + call assert_equal(1, exists('*Test_exists')) + " Non-existing user defined function + call assert_equal(0, exists('*MyxyzFunc')) + " Function that may be created by FuncUndefined event + call assert_equal(0, exists('*UndefFun')) + " Function that may be created by script autoloading + call assert_equal(0, exists('*footest#F')) + + " Valid internal command (full match) + call assert_equal(2, exists(':edit')) + " Valid internal command (full match) with garbage + call assert_equal(0, exists(':edit/a')) + " Valid internal command (partial match) + call assert_equal(1, exists(':q')) + " Non-existing internal command + call assert_equal(0, exists(':invalidcmd')) + + " User defined command (full match) + command! MyCmd :echo 'My command' + call assert_equal(2, exists(':MyCmd')) + " User defined command (partial match) + command! MyOtherCmd :echo 'Another command' + call assert_equal(3, exists(':My')) + + " Command modifier + call assert_equal(2, exists(':rightbelow')) + + " Non-existing user defined command (full match) + delcommand MyCmd + call assert_equal(0, exists(':MyCmd')) + + " Non-existing user defined command (partial match) + delcommand MyOtherCmd + call assert_equal(0, exists(':My')) + + " Valid local variable + let local_var = 1 + call assert_equal(1, exists('local_var')) + " Valid local variable with garbage + call assert_equal(0, exists('local_var%n')) + " Non-existing local variable + unlet local_var + call assert_equal(0, exists('local_var')) + + " Non-existing autoload variable that may be autoloaded + call assert_equal(0, exists('footest#x')) + + " Valid local list + let local_list = ["blue", "orange"] + call assert_equal(1, exists('local_list')) + " Valid local list item + call assert_equal(1, exists('local_list[1]')) + " Valid local list item with garbage + call assert_equal(0, exists('local_list[1]+5')) + " Invalid local list item + call assert_equal(0, exists('local_list[2]')) + " Non-existing local list + unlet local_list + call assert_equal(0, exists('local_list')) + " Valid local dictionary + let local_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('local_dict')) + " Non-existing local dictionary + unlet local_dict + call assert_equal(0, exists('local_dict')) + " Existing local curly-brace variable + let str = "local" + let curly_{str}_var = 1 + call assert_equal(1, exists('curly_{str}_var')) + " Non-existing local curly-brace variable + unlet curly_{str}_var + call assert_equal(0, exists('curly_{str}_var')) + + " Existing global variable + let g:global_var = 1 + call assert_equal(1, exists('g:global_var')) + " Existing global variable with garbage + call assert_equal(0, exists('g:global_var-n')) + " Non-existing global variable + unlet g:global_var + call assert_equal(0, exists('g:global_var')) + " Existing global list + let g:global_list = ["blue", "orange"] + call assert_equal(1, exists('g:global_list')) + " Non-existing global list + unlet g:global_list + call assert_equal(0, exists('g:global_list')) + " Existing global dictionary + let g:global_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('g:global_dict')) + " Non-existing global dictionary + unlet g:global_dict + call assert_equal(0, exists('g:global_dict')) + " Existing global curly-brace variable + let str = "global" + let g:curly_{str}_var = 1 + call assert_equal(1, exists('g:curly_{str}_var')) + " Non-existing global curly-brace variable + unlet g:curly_{str}_var + call assert_equal(0, exists('g:curly_{str}_var')) + + " Existing window variable + let w:window_var = 1 + call assert_equal(1, exists('w:window_var')) + " Non-existing window variable + unlet w:window_var + call assert_equal(0, exists('w:window_var')) + " Existing window list + let w:window_list = ["blue", "orange"] + call assert_equal(1, exists('w:window_list')) + " Non-existing window list + unlet w:window_list + call assert_equal(0, exists('w:window_list')) + " Existing window dictionary + let w:window_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('w:window_dict')) + " Non-existing window dictionary + unlet w:window_dict + call assert_equal(0, exists('w:window_dict')) + " Existing window curly-brace variable + let str = "window" + let w:curly_{str}_var = 1 + call assert_equal(1, exists('w:curly_{str}_var')) + " Non-existing window curly-brace variable + unlet w:curly_{str}_var + call assert_equal(0, exists('w:curly_{str}_var')) + + " Existing tab variable + let t:tab_var = 1 + call assert_equal(1, exists('t:tab_var')) + " Non-existing tab variable + unlet t:tab_var + call assert_equal(0, exists('t:tab_var')) + " Existing tab list + let t:tab_list = ["blue", "orange"] + call assert_equal(1, exists('t:tab_list')) + " Non-existing tab list + unlet t:tab_list + call assert_equal(0, exists('t:tab_list')) + " Existing tab dictionary + let t:tab_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('t:tab_dict')) + " Non-existing tab dictionary + unlet t:tab_dict + call assert_equal(0, exists('t:tab_dict')) + " Existing tab curly-brace variable + let str = "tab" + let t:curly_{str}_var = 1 + call assert_equal(1, exists('t:curly_{str}_var')) + " Non-existing tab curly-brace variable + unlet t:curly_{str}_var + call assert_equal(0, exists('t:curly_{str}_var')) + + " Existing buffer variable + let b:buffer_var = 1 + call assert_equal(1, exists('b:buffer_var')) + " Non-existing buffer variable + unlet b:buffer_var + call assert_equal(0, exists('b:buffer_var')) + " Existing buffer list + let b:buffer_list = ["blue", "orange"] + call assert_equal(1, exists('b:buffer_list')) + " Non-existing buffer list + unlet b:buffer_list + call assert_equal(0, exists('b:buffer_list')) + " Existing buffer dictionary + let b:buffer_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('b:buffer_dict')) + " Non-existing buffer dictionary + unlet b:buffer_dict + call assert_equal(0, exists('b:buffer_dict')) + " Existing buffer curly-brace variable + let str = "buffer" + let b:curly_{str}_var = 1 + call assert_equal(1, exists('b:curly_{str}_var')) + " Non-existing buffer curly-brace variable + unlet b:curly_{str}_var + call assert_equal(0, exists('b:curly_{str}_var')) + + " Existing Vim internal variable + call assert_equal(1, exists('v:version')) + " Non-existing Vim internal variable + call assert_equal(0, exists('v:non_exists_var')) + + " Existing script-local variable + let s:script_var = 1 + call assert_equal(1, exists('s:script_var')) + " Non-existing script-local variable + unlet s:script_var + call assert_equal(0, exists('s:script_var')) + " Existing script-local list + let s:script_list = ["blue", "orange"] + call assert_equal(1, exists('s:script_list')) + " Non-existing script-local list + unlet s:script_list + call assert_equal(0, exists('s:script_list')) + " Existing script-local dictionary + let s:script_dict = {"xcord":100, "ycord":2} + call assert_equal(1, exists('s:script_dict')) + " Non-existing script-local dictionary + unlet s:script_dict + call assert_equal(0, exists('s:script_dict')) + " Existing script curly-brace variable + let str = "script" + let s:curly_{str}_var = 1 + call assert_equal(1, exists('s:curly_{str}_var')) + " Non-existing script-local curly-brace variable + unlet s:curly_{str}_var + call assert_equal(0, exists('s:curly_{str}_var')) + + " Existing script-local function + function! s:my_script_func() + endfunction + + echo '*s:my_script_func: 1' + call assert_equal(1, exists('*s:my_script_func')) + + " Non-existing script-local function + delfunction s:my_script_func + + call assert_equal(0, exists('*s:my_script_func')) + unlet str + + call assert_equal(1, g:footest#x) + call assert_equal(0, footest#F()) + call assert_equal(0, UndefFun()) +endfunc + +" exists() test for Function arguments +func FuncArg_Tests(func_arg, ...) + call assert_equal(1, exists('a:func_arg')) + call assert_equal(0, exists('a:non_exists_arg')) + call assert_equal(1, exists('a:1')) + call assert_equal(0, exists('a:2')) +endfunc + +func Test_exists_funcarg() + call FuncArg_Tests("arg1", "arg2") +endfunc diff --git a/src/nvim/testdir/test_expr.vim b/src/nvim/testdir/test_expr.vim index 82c5d21bd0..ad967c528c 100644 --- a/src/nvim/testdir/test_expr.vim +++ b/src/nvim/testdir/test_expr.vim @@ -384,9 +384,10 @@ func Test_substitute_expr() \ {-> submatch(2) . submatch(3) . submatch(1)}, '')) func Recurse() - return substitute('yyy', 'y*', {-> g:val}, '') + return substitute('yyy', 'y\(.\)y', {-> submatch(1)}, '') endfunc - call assert_equal('--', substitute('xxx', 'x*', {-> '-' . Recurse() . '-'}, '')) + " recursive call works + call assert_equal('-y-x-', substitute('xxx', 'x\(.\)x', {-> '-' . Recurse() . '-' . submatch(1) . '-'}, '')) endfunc func Test_invalid_submatch() @@ -418,6 +419,9 @@ func Test_function_with_funcref() let s:fref = function(s:f) call assert_equal(v:t_string, s:fref('x')) call assert_fails("call function('s:f')", 'E700:') + + call assert_fails("call function('foo()')", 'E475:') + call assert_fails("call function('foo()')", 'foo()') endfunc func Test_funcref() @@ -435,3 +439,8 @@ func Test_funcref() call assert_equal(2, OneByRef()) call assert_fails('echo funcref("{")', 'E475:') endfunc + +func Test_empty_concatenate() + call assert_equal('b', 'a'[4:0] . 'b') + call assert_equal('b', 'b' . 'a'[4:0]) +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_farsi.vim b/src/nvim/testdir/test_farsi.vim index e094191599..9ff2653af4 100644 --- a/src/nvim/testdir/test_farsi.vim +++ b/src/nvim/testdir/test_farsi.vim @@ -1,4 +1,5 @@ " Simplistic testing of Farsi mode. +" Note: must be edited with latin1 encoding. if !has('farsi') || has('nvim') " Not supported in Nvim. #6192 finish @@ -82,3 +83,51 @@ func Test_farsi_map() set noaltkeymap bwipe! endfunc + +func Test_input_farsi() + new + setlocal rightleft fkmap + " numbers switch input direction + call feedkeys("aabc0123456789.+-^%#=xyz\<Esc>", 'tx') + call assert_equal("\x8cν\x93", getline('.')) + + " all non-number special chars with spaces + call feedkeys("oB E F H I K L M O P Q R T U W Y ` ! @ # $ % ^ & * () - _ = + \\ | : \" . / < > ? \<Esc>", 'tx') + call assert_equal(" []蠨頽", getline('.')) + + " all non-number special chars without spaces + call feedkeys("oBEFHIKLMOPQRTUWY`!@#$%^&*()-_=+\\|:\"./<>?\<Esc>",'tx') + call assert_equal("[]訩齫꺻", getline('.')) + + " all letter chars with spaces + call feedkeys("oa A b c C d D e f g G h i j J k l m n N o p q r s S t u v V w x X y z Z ; \ , [ ] \<Esc>", 'tx') + call assert_equal("Ѡ̠ΠϠƠàܠŠޠݠĠˠˠʠɠӠ٠Рؠ֠͠͠ҠԠԠנՠڠߠǠȠ", getline('.')) + + " all letter chars without spaces + call feedkeys("oaAbcCdDefgGhijJklmnNopqrsStuvVwxXyzZ;\,[]\<Esc>", 'tx') + call assert_equal("\x8c\x9f\x86\x83\x9d\x85\x80\x9c\x9b\x84\x8a\x89\x8e\x96\x8b\x95\x90\x8d\x93\x97\x87\x88", getline('.')) + + bwipe! +endfunc + +func Test_command_line_farsi() + set allowrevins altkeymap + + " letter characters with spaces + call feedkeys(":\"\<C-_>a A b c C d D e f g G h i j J k l m n N o p q r s S t u v V w x X y z Z ; \\ , [ ]\<CR>", 'tx') + call assert_equal("\"\x88ǠߠڠՠՠנԠԠҠ֠͠͠ؠР٠ӠɠʠˠˠĠݠޠŠܠàƠϠΠ̠", getreg(':')) + + " letter characters without spaces + call feedkeys(":\"\<C-_>aAbcCdDefgGhijJklmnNopqrsStuvVwxXyzZ;\\,[]\<CR>", 'tx') + call assert_equal("\"\x88\x87\x93\x8d\x90\x95\x8b\x96\x8e\x89\x8a\x84\x9b\x9c\x80\x85\x9d\x83\x86\x9f\x8c", getreg(':')) + + " other characters with spaces + call feedkeys(":\"\<C-_>0 1 2 3 4 5 6 7 8 9 ` . ! \" $ % ^ & / () = \\ ? + - _ * : # ~ @ < > { } | B E F H I K L M O P Q R T U W Y\<CR>", 'tx') + call assert_equal("\"][ }{~頭렽", getreg(':')) + + " other characters without spaces + call feedkeys(":\"\<C-_>0123456789`.!\"$%^&/()=\\?+-_*:#~@<>{}|BEFHIKLMOPQRTUWY\<CR>", 'tx') + call assert_equal("\"][}{~魫뽩", getreg(':')) + + set noallowrevins noaltkeymap +endfunc diff --git a/src/nvim/testdir/test_file_size.vim b/src/nvim/testdir/test_file_size.vim new file mode 100644 index 0000000000..3e78a7b23c --- /dev/null +++ b/src/nvim/testdir/test_file_size.vim @@ -0,0 +1,58 @@ +" Inserts 2 million lines with consecutive integers starting from 1 +" (essentially, the output of GNU's seq 1 2000000), writes them to Xtest +" and writes its cksum to test.out. +" +" We need 2 million lines to trigger a call to mf_hash_grow(). If it would mess +" up the lines the checksum would differ. +" +" cksum is part of POSIX and so should be available on most Unixes. +" If it isn't available then the test will be skipped. +func Test_File_Size() + if !executable('cksum') + return + endif + + new + set fileformat=unix undolevels=-1 + for i in range(1, 2000000, 100) + call append(i, range(i, i + 99)) + endfor + + 1delete + w! Xtest + let res = systemlist('cksum Xtest')[0] + let res = substitute(res, "\r", "", "") + call assert_equal('3678979763 14888896 Xtest', res) + + enew! + call delete('Xtest') + set fileformat& undolevels& +endfunc + +" Test for writing and reading a file of over 100 Kbyte +func Test_File_Read_Write() + enew! + + " Create a file with the following contents + " 1 line: "This is the start" + " 3001 lines: "This is the leader" + " 1 line: "This is the middle" + " 3001 lines: "This is the trailer" + " 1 line: "This is the end" + call append(0, "This is the start") + call append(1, repeat(["This is the leader"], 3001)) + call append(3002, "This is the middle") + call append(3003, repeat(["This is the trailer"], 3001)) + call append(6004, "This is the end") + + write! Xtest + enew! + edit! Xtest + + call assert_equal("This is the start", getline(1)) + call assert_equal("This is the middle", getline(3003)) + call assert_equal("This is the end", getline(6005)) + + enew! + call delete("Xtest") +endfunc diff --git a/src/nvim/testdir/test_fileformat.vim b/src/nvim/testdir/test_fileformat.vim new file mode 100644 index 0000000000..8dc25f62b1 --- /dev/null +++ b/src/nvim/testdir/test_fileformat.vim @@ -0,0 +1,33 @@ +" Test behavior of fileformat after bwipeout of last buffer + +func Test_fileformat_after_bw() + bwipeout + set fileformat& + if &fileformat == 'dos' + let test_fileformats = 'unix' + elseif &fileformat == 'unix' + let test_fileformats = 'mac' + else " must be mac + let test_fileformats = 'dos' + endif + exec 'set fileformats='.test_fileformats + bwipeout! + call assert_equal(test_fileformats, &fileformat) + set fileformats& +endfunc + +func Test_fileformat_autocommand() + let filecnt = ["", "foobar\<CR>", "eins\<CR>", "\<CR>", "zwei\<CR>", "drei", "vier", "fünf", ""] + let ffs = &ffs + call writefile(filecnt, 'Xfile', 'b') + au BufReadPre Xfile set ffs=dos ff=dos + new Xfile + call assert_equal('dos', &l:ff) + call assert_equal('dos', &ffs) + + " cleanup + call delete('Xfile') + let &ffs = ffs + au! BufReadPre Xfile + bw! +endfunc diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim new file mode 100644 index 0000000000..43dc383f3d --- /dev/null +++ b/src/nvim/testdir/test_filetype.vim @@ -0,0 +1,557 @@ +" Test :setfiletype + +func Test_detection() + filetype on + augroup filetypedetect + au BufNewFile,BufRead * call assert_equal(1, did_filetype()) + augroup END + new something.vim + call assert_equal('vim', &filetype) + + bwipe! + filetype off +endfunc + +func Test_conf_type() + filetype on + call writefile(['# some comment', 'must be conf'], 'Xfile') + augroup filetypedetect + au BufNewFile,BufRead * call assert_equal(0, did_filetype()) + augroup END + split Xfile + call assert_equal('conf', &filetype) + + bwipe! + call delete('Xfile') + filetype off +endfunc + +func Test_other_type() + filetype on + augroup filetypedetect + au BufNewFile,BufRead * call assert_equal(0, did_filetype()) + au BufNewFile,BufRead Xfile setf testfile + au BufNewFile,BufRead * call assert_equal(1, did_filetype()) + augroup END + call writefile(['# some comment', 'must be conf'], 'Xfile') + split Xfile + call assert_equal('testfile', &filetype) + + bwipe! + call delete('Xfile') + filetype off +endfunc + +" Filetypes detected just from matching the file name. +let s:filename_checks = { + \ 'a2ps': ['/etc/a2ps.cfg', '/etc/a2ps/file.cfg', 'a2psrc', '.a2psrc'], + \ 'a65': ['file.a65'], + \ 'abap': ['file.abap'], + \ 'abc': ['file.abc'], + \ 'abel': ['file.abl'], + \ 'acedb': ['file.wrm'], + \ 'ada': ['file.adb', 'file.ads', 'file.ada', 'file.gpr'], + \ 'ahdl': ['file.tdf'], + \ 'alsaconf': ['.asoundrc', '/usr/share/alsa/alsa.conf', '/etc/asound.conf'], + \ 'aml': ['file.aml'], + \ 'ampl': ['file.run'], + \ 'ant': ['build.xml'], + \ 'apache': ['.htaccess', '/etc/httpd/file.conf'], + \ 'applescript': ['file.scpt'], + \ 'aptconf': ['apt.conf', '/.aptitude/config'], + \ 'arch': ['.arch-inventory'], + \ 'arduino': ['file.ino', 'file.pde'], + \ 'art': ['file.art'], + \ 'asciidoc': ['file.asciidoc', 'file.adoc'], + \ 'asn': ['file.asn', 'file.asn1'], + \ 'atlas': ['file.atl', 'file.as'], + \ 'autohotkey': ['file.ahk'], + \ 'autoit': ['file.au3'], + \ 'automake': ['GNUmakefile.am'], + \ 'ave': ['file.ave'], + \ 'awk': ['file.awk'], + \ 'b': ['file.mch', 'file.ref', 'file.imp'], + \ 'bc': ['file.bc'], + \ 'bdf': ['file.bdf'], + \ 'bib': ['file.bib'], + \ 'bindzone': ['named.root'], + \ 'blank': ['file.bl'], + \ 'bst': ['file.bst'], + \ 'bzr': ['bzr_log.any'], + \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c'], + \ 'cabal': ['file.cabal'], + \ 'calendar': ['calendar'], + \ 'catalog': ['catalog'], + \ 'cdl': ['file.cdl'], + \ 'cdrdaoconf': ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao'], + \ 'cdrtoc': ['file.toc'], + \ 'cf': ['file.cfm', 'file.cfi', 'file.cfc'], + \ 'cfengine': ['cfengine.conf'], + \ 'cfg': ['file.cfg', 'file.hgrc', 'filehgrc'], + \ 'ch': ['file.chf'], + \ 'chaiscript': ['file.chai'], + \ 'chaskell': ['file.chs'], + \ 'chill': ['file..ch'], + \ 'chordpro': ['file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'], + \ 'cl': ['file.eni'], + \ 'clean': ['file.dcl', 'file.icl'], + \ 'clojure': ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'], + \ 'cmake': ['CMakeLists.txt', 'file.cmake', 'file.cmake.in'], + \ 'cmusrc': ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme'], + \ 'cobol': ['file.cbl', 'file.cob', 'file.lib'], + \ 'coco': ['file.atg'], + \ 'conaryrecipe': ['file.recipe'], + \ 'conf': ['auto.master'], + \ 'config': ['configure.in', 'configure.ac'], + \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi'], + \ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'], + \ 'crm': ['file.crm'], + \ 'cs': ['file.cs'], + \ 'csc': ['file.csc'], + \ 'csdl': ['file.csdl'], + \ 'csp': ['file.csp', 'file.fdr'], + \ 'css': ['file.css'], + \ 'cterm': ['file.con'], + \ 'cucumber': ['file.feature'], + \ 'cuda': ['file.cu'], + \ 'cupl': ['file.pld'], + \ 'cuplsim': ['file.si'], + \ 'cvs': ['cvs123'], + \ 'cvsrc': ['.cvsrc'], + \ 'cynpp': ['file.cyn'], + \ 'datascript': ['file.ds'], + \ 'dcd': ['file.dcd'], + \ 'debcontrol': ['/debian/control'], + \ 'debsources': ['/etc/apt/sources.list', '/etc/apt/sources.list.d/file.list'], + \ 'def': ['file.def'], + \ 'denyhosts': ['denyhosts.conf'], + \ 'desc': ['file.desc'], + \ 'desktop': ['file.desktop', '.directory'], + \ 'dictconf': ['dict.conf', '.dictrc'], + \ 'dictdconf': ['dictd.conf'], + \ 'diff': ['file.diff', 'file.rej'], + \ 'dircolors': ['.dir_colors', '.dircolors', '/etc/DIR_COLORS'], + \ 'dnsmasq': ['/etc/dnsmasq.conf'], + \ 'dockerfile': ['Dockerfile', 'file.Dockerfile'], + \ 'dosbatch': ['file.bat', 'file.sys'], + \ 'dosini': ['.editorconfig', '/etc/yum.conf', 'file.ini'], + \ 'dot': ['file.dot'], + \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe'], + \ 'dsl': ['file.dsl'], + \ 'dtd': ['file.dtd'], + \ 'dts': ['file.dts', 'file.dtsi'], + \ 'dylan': ['file.dylan'], + \ 'dylanintr': ['file.intr'], + \ 'dylanlid': ['file.lid'], + \ 'ecd': ['file.ecd'], + \ 'edif': ['file.edf', 'file.edif', 'file.edo'], + \ 'elinks': ['/etc/elinks.conf', '/.elinks/elinks.conf'], + \ 'elmfilt': ['filter-rules'], + \ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'], + \ 'eruby': ['file.erb', 'file.rhtml'], + \ 'esmtprc': ['anyesmtprc'], + \ 'esqlc': ['file.ec', 'file.EC'], + \ 'esterel': ['file.strl'], + \ 'eterm': ['anyEterm/file.cfg'], + \ 'exim': ['exim.conf'], + \ 'expect': ['file.exp'], + \ 'exports': ['exports'], + \ 'factor': ['file.factor'], + \ 'falcon': ['file.fal'], + \ 'fan': ['file.fan', 'file.fwt'], + \ 'fetchmail': ['.fetchmailrc'], + \ 'fgl': ['file.4gl', 'file.4gh', 'file.m4gl'], + \ 'focexec': ['file.fex', 'file.focexec'], + \ 'forth': ['file.fs', 'file.ft'], + \ 'fortran': ['file.f', 'file.for', 'file.fortran', 'file.fpp', 'file.ftn', 'file.f77', 'file.f90', 'file.f95', 'file.f03', 'file.f08'], + \ 'framescript': ['file.fsl'], + \ 'freebasic': ['file.fb', 'file.bi'], + \ 'fstab': ['fstab', 'mtab'], + \ 'gdb': ['.gdbinit'], + \ 'gdmo': ['file.mo', 'file.gdmo'], + \ 'gedcom': ['file.ged', 'lltxxxxx.txt'], + \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'], + \ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config'], + \ 'gitolite': ['gitolite.conf'], + \ 'gitrebase': ['git-rebase-todo'], + \ 'gitsendemail': ['.gitsendemail.msg.xxxxxx'], + \ 'gkrellmrc': ['gkrellmrc', 'gkrellmrc_x'], + \ 'gnash': ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], + \ 'gnuplot': ['file.gpi'], + \ 'go': ['file.go'], + \ 'gp': ['file.gp', '.gprc'], + \ 'gpg': ['/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel'], + \ 'grads': ['file.gs'], + \ 'gretl': ['file.gretl'], + \ 'groovy': ['file.gradle', 'file.groovy'], + \ 'group': ['any/etc/group', 'any/etc/group-', 'any/etc/group.edit', 'any/etc/gshadow', 'any/etc/gshadow-', 'any/etc/gshadow.edit', 'any/var/backups/group.bak', 'any/var/backups/gshadow.bak'], + \ 'grub': ['/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf'], + \ 'gsp': ['file.gsp'], + \ 'gtkrc': ['.gtkrc', 'gtkrc'], + \ 'haml': ['file.haml'], + \ 'hamster': ['file.hsc', 'file.hsm'], + \ 'haskell': ['file.hs', 'file.hs-boot'], + \ 'haste': ['file.ht'], + \ 'hastepreproc': ['file.htpp'], + \ 'hb': ['file.hb'], + \ 'hercules': ['file.vc', 'file.ev', 'file.sum', 'file.errsum'], + \ 'hex': ['file.hex', 'file.h32'], + \ 'hgcommit': ['hg-editor-file.txt'], + \ 'hog': ['file.hog', 'snort.conf', 'vision.conf'], + \ 'hostconf': ['/etc/host.conf'], + \ 'hostsaccess': ['/etc/hosts.allow', '/etc/hosts.deny'], + \ 'htmlcheetah': ['file.tmpl'], + \ 'htmlm4': ['file.html.m4'], + \ 'httest': ['file.htt', 'file.htb'], + \ 'ibasic': ['file.iba', 'file.ibi'], + \ 'icemenu': ['/.icewm/menu'], + \ 'icon': ['file.icn'], + \ 'indent': ['.indent.pro', 'indentrc'], + \ 'inform': ['file.inf', 'file.INF'], + \ 'initng': ['/etc/initng/any/file.i', 'file.ii'], + \ 'inittab': ['inittab'], + \ 'ipfilter': ['ipf.conf', 'ipf6.conf', 'ipf.rules'], + \ 'iss': ['file.iss'], + \ 'ist': ['file.ist', 'file.mst'], + \ 'j': ['file.ijs'], + \ 'jal': ['file.jal', 'file.JAL'], + \ 'jam': ['file.jpl', 'file.jpr'], + \ 'java': ['file.java', 'file.jav'], + \ 'javacc': ['file.jj', 'file.jjt'], + \ 'javascript': ['file.js', 'file.javascript', 'file.es', 'file.jsx', 'file.mjs'], + \ 'jess': ['file.clp'], + \ 'jgraph': ['file.jgr'], + \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], + \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx'], + \ 'json': ['file.json', 'file.jsonp', 'file.webmanifest'], + \ 'jsp': ['file.jsp'], + \ 'kconfig': ['Kconfig', 'Kconfig.debug'], + \ 'kivy': ['file.kv'], + \ 'kix': ['file.kix'], + \ 'kscript': ['file.ks'], + \ 'kwt': ['file.k'], + \ 'lace': ['file.ace', 'file.ACE'], + \ 'latte': ['file.latte', 'file.lte'], + \ 'ld': ['file.ld'], + \ 'ldif': ['file.ldif'], + \ 'less': ['file.less'], + \ 'lex': ['file.lex', 'file.l', 'file.lxx', 'file.l++'], + \ 'lftp': ['lftp.conf', '.lftprc', 'anylftp/rc'], + \ 'lhaskell': ['file.lhs'], + \ 'libao': ['/etc/libao.conf', '/.libao'], + \ 'lifelines': ['file.ll'], + \ 'lilo': ['lilo.conf'], + \ 'limits': ['/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf'], + \ 'liquid': ['file.liquid'], + \ 'lisp': ['sbclrc', '.sbclrc'], + \ 'lite': ['file.lite', 'file.lt'], + \ 'litestep': ['/LiteStep/any/file.rc'], + \ 'loginaccess': ['/etc/login.access'], + \ 'logindefs': ['/etc/login.defs'], + \ 'logtalk': ['file.lgt'], + \ 'lotos': ['file.lot', 'file.lotos'], + \ 'lout': ['file.lou', 'file.lout'], + \ 'lprolog': ['file.sig'], + \ 'lsl': ['file.lsl'], + \ 'lss': ['file.lss'], + \ 'lua': ['file.lua', 'file.rockspec', 'file.nse'], + \ 'lynx': ['lynx.cfg'], + \ 'm4': ['file.at'], + \ 'mail': ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml'], + \ 'mailaliases': ['/etc/mail/aliases', '/etc/aliases'], + \ 'mailcap': ['.mailcap', 'mailcap'], + \ 'make': ['file.mk', 'file.mak', 'file.dsp'], + \ 'mallard': ['file.page'], + \ 'manconf': ['/etc/man.conf', 'man.config'], + \ 'map': ['file.map'], + \ 'maple': ['file.mv', 'file.mpl', 'file.mws'], + \ 'markdown': ['file.markdown', 'file.mdown', 'file.mkd', 'file.mkdn', 'file.mdwn', 'file.md'], + \ 'mason': ['file.mason', 'file.mhtml', 'file.comp'], + \ 'master': ['file.mas', 'file.master'], + \ 'mel': ['file.mel'], + \ 'messages': ['/log/auth', '/log/cron', '/log/daemon', '/log/debug', '/log/kern', '/log/lpr', '/log/mail', '/log/messages', '/log/news/news', '/log/syslog', '/log/user', + \ '/log/auth.log', '/log/cron.log', '/log/daemon.log', '/log/debug.log', '/log/kern.log', '/log/lpr.log', '/log/mail.log', '/log/messages.log', '/log/news/news.log', '/log/syslog.log', '/log/user.log', + \ '/log/auth.err', '/log/cron.err', '/log/daemon.err', '/log/debug.err', '/log/kern.err', '/log/lpr.err', '/log/mail.err', '/log/messages.err', '/log/news/news.err', '/log/syslog.err', '/log/user.err', + \ '/log/auth.info', '/log/cron.info', '/log/daemon.info', '/log/debug.info', '/log/kern.info', '/log/lpr.info', '/log/mail.info', '/log/messages.info', '/log/news/news.info', '/log/syslog.info', '/log/user.info', + \ '/log/auth.warn', '/log/cron.warn', '/log/daemon.warn', '/log/debug.warn', '/log/kern.warn', '/log/lpr.warn', '/log/mail.warn', '/log/messages.warn', '/log/news/news.warn', '/log/syslog.warn', '/log/user.warn', + \ '/log/auth.crit', '/log/cron.crit', '/log/daemon.crit', '/log/debug.crit', '/log/kern.crit', '/log/lpr.crit', '/log/mail.crit', '/log/messages.crit', '/log/news/news.crit', '/log/syslog.crit', '/log/user.crit', + \ '/log/auth.notice', '/log/cron.notice', '/log/daemon.notice', '/log/debug.notice', '/log/kern.notice', '/log/lpr.notice', '/log/mail.notice', '/log/messages.notice', '/log/news/news.notice', '/log/syslog.notice', '/log/user.notice'], + \ 'mf': ['file.mf'], + \ 'mgl': ['file.mgl'], + \ 'mgp': ['file.mgp'], + \ 'mib': ['file.mib', 'file.my'], + \ 'mix': ['file.mix', 'file.mixal'], + \ 'mma': ['file.nb'], + \ 'mmp': ['file.mmp'], + \ 'modconf': ['/etc/modules.conf', '/etc/modules', '/etc/conf.modules'], + \ 'modula2': ['file.m2', 'file.mi'], + \ 'monk': ['file.isc', 'file.monk', 'file.ssc', 'file.tsc'], + \ 'moo': ['file.moo'], + \ 'mp': ['file.mp'], + \ 'mplayerconf': ['mplayer.conf', '/.mplayer/config'], + \ 'mrxvtrc': ['mrxvtrc', '.mrxvtrc'], + \ 'msidl': ['file.odl', 'file.mof'], + \ 'msql': ['file.msql'], + \ 'mupad': ['file.mu'], + \ 'mush': ['file.mush'], + \ 'muttrc': ['Muttngrc', 'Muttrc'], + \ 'mysql': ['file.mysql'], + \ 'n1ql': ['file.n1ql', 'file.nql'], + \ 'named': ['namedfile.conf', 'rndcfile.conf'], + \ 'nanorc': ['/etc/nanorc', 'file.nanorc'], + \ 'ncf': ['file.ncf'], + \ 'netrc': ['.netrc'], + \ 'ninja': ['file.ninja'], + \ 'nqc': ['file.nqc'], + \ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom'], + \ 'nsis': ['file.nsi', 'file.nsh'], + \ 'obj': ['file.obj'], + \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit'], + \ 'occam': ['file.occ'], + \ 'omnimark': ['file.xom', 'file.xin'], + \ 'openroad': ['file.or'], + \ 'ora': ['file.ora'], + \ 'pamconf': ['/etc/pam.conf'], + \ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'], + \ 'pascal': ['file.pas', 'file.dpr'], + \ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak'], + \ 'pccts': ['file.g'], + \ 'pdf': ['file.pdf'], + \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'], + \ 'perl6': ['file.p6', 'file.pm6', 'file.pl6'], + \ 'pf': ['pf.conf'], + \ 'pfmain': ['main.cf'], + \ 'php': ['file.php', 'file.php9', 'file.phtml', 'file.ctp'], + \ 'pike': ['file.pike', 'file.lpc', 'file.ulpc', 'file.pmod'], + \ 'pilrc': ['file.rcp'], + \ 'pine': ['.pinerc', 'pinerc', '.pinercex', 'pinercex'], + \ 'pinfo': ['/etc/pinforc', '/.pinforc'], + \ 'pli': ['file.pli', 'file.pl1'], + \ 'plm': ['file.plm', 'file.p36', 'file.pac'], + \ 'plp': ['file.plp'], + \ 'plsql': ['file.pls', 'file.plsql'], + \ 'po': ['file.po', 'file.pot'], + \ 'pod': ['file.pod'], + \ 'pod6': ['file.pod6'], + \ 'postscr': ['file.ps', 'file.pfa', 'file.afm', 'file.eps', 'file.epsf', 'file.epsi', 'file.ai'], + \ 'pov': ['file.pov'], + \ 'povini': ['.povrayrc'], + \ 'ppd': ['file.ppd'], + \ 'ppwiz': ['file.it', 'file.ih'], + \ 'privoxy': ['file.action'], + \ 'proc': ['file.pc'], + \ 'procmail': ['.procmail', '.procmailrc'], + \ 'prolog': ['file.pdb'], + \ 'promela': ['file.pml'], + \ 'proto': ['file.proto'], + \ 'protocols': ['/etc/protocols'], + \ 'psf': ['file.psf'], + \ 'pyrex': ['file.pyx', 'file.pxd'], + \ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl'], + \ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg'], + \ 'radiance': ['file.rad', 'file.mat'], + \ 'ratpoison': ['.ratpoisonrc', 'ratpoisonrc'], + \ 'rc': ['file.rc', 'file.rch'], + \ 'rcs': ['file,v'], + \ 'readline': ['.inputrc', 'inputrc'], + \ 'remind': ['.reminders', 'file.remind', 'file.rem'], + \ 'resolv': ['resolv.conf'], + \ 'reva': ['file.frt'], + \ 'rexx': ['file.rex', 'file.orx', 'file.rxo', 'file.rxj', 'file.jrexx', 'file.rexxj', 'file.rexx', 'file.testGroup', 'file.testUnit'], + \ 'rib': ['file.rib'], + \ 'rnc': ['file.rnc'], + \ 'rng': ['file.rng'], + \ 'robots': ['robots.txt'], + \ 'rpcgen': ['file.x'], + \ 'rpl': ['file.rpl'], + \ 'rst': ['file.rst'], + \ 'rtf': ['file.rtf'], + \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake'], + \ 'rust': ['file.rs'], + \ 'samba': ['smb.conf'], + \ 'sas': ['file.sas'], + \ 'sass': ['file.sass'], + \ 'sather': ['file.sa'], + \ 'sbt': ['file.sbt'], + \ 'scala': ['file.scala'], + \ 'scheme': ['file.scm', 'file.ss', 'file.rkt'], + \ 'scilab': ['file.sci', 'file.sce'], + \ 'screen': ['.screenrc', 'screenrc'], + \ 'scss': ['file.scss'], + \ 'sd': ['file.sd'], + \ 'sdc': ['file.sdc'], + \ 'sdl': ['file.sdl', 'file.pr'], + \ 'sed': ['file.sed'], + \ 'sensors': ['/etc/sensors.conf', '/etc/sensors3.conf'], + \ 'services': ['/etc/services'], + \ 'setserial': ['/etc/serial.conf'], + \ 'sh': ['/etc/udev/cdsymlinks.conf'], + \ 'sieve': ['file.siv'], + \ 'simula': ['file.sim'], + \ 'sinda': ['file.sin', 'file.s85'], + \ 'sisu': ['file.sst', 'file.ssm', 'file.ssi', 'file.-sst', 'file._sst', 'file.sst.meta', 'file.-sst.meta', 'file._sst.meta'], + \ 'skill': ['file.il', 'file.ils', 'file.cdf'], + \ 'slang': ['file.sl'], + \ 'slice': ['file.ice'], + \ 'slpconf': ['/etc/slp.conf'], + \ 'slpreg': ['/etc/slp.reg'], + \ 'slpspi': ['/etc/slp.spi'], + \ 'slrnrc': ['.slrnrc'], + \ 'slrnsc': ['file.score'], + \ 'sm': ['sendmail.cf'], + \ 'smarty': ['file.tpl'], + \ 'smcl': ['file.hlp', 'file.ihlp', 'file.smcl'], + \ 'smith': ['file.smt', 'file.smith'], + \ 'sml': ['file.sml'], + \ 'snobol4': ['file.sno', 'file.spt'], + \ 'spec': ['file.spec'], + \ 'spice': ['file.sp', 'file.spice'], + \ 'spup': ['file.speedup', 'file.spdata', 'file.spd'], + \ 'spyce': ['file.spy', 'file.spi'], + \ 'sql': ['file.tyb', 'file.typ', 'file.tyc', 'file.pkb', 'file.pks'], + \ 'sqlj': ['file.sqlj'], + \ 'sqr': ['file.sqr', 'file.sqi'], + \ 'squid': ['squid.conf'], + \ 'srec': ['file.s19', 'file.s28', 'file.s37', 'file.mot', 'file.srec'], + \ 'sshconfig': ['ssh_config', '/.ssh/config'], + \ 'sshdconfig': ['sshd_config'], + \ 'st': ['file.st'], + \ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'], + \ 'stp': ['file.stp'], + \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp'], + \ 'svg': ['file.svg'], + \ 'svn': ['svn-commitfile.tmp'], + \ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf'], + \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.mount', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer'], + \ 'systemverilog': ['file.sv', 'file.svh'], + \ 'tags': ['tags'], + \ 'tak': ['file.tak'], + \ 'taskdata': ['pending.data', 'completed.data', 'undo.data'], + \ 'taskedit': ['file.task'], + \ 'tcl': ['file.tcl', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl'], + \ 'teraterm': ['file.ttl'], + \ 'terminfo': ['file.ti'], + \ 'tex': ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl'], + \ 'texinfo': ['file.texinfo', 'file.texi', 'file.txi'], + \ 'texmf': ['texmf.cnf'], + \ 'text': ['file.text', 'README'], + \ 'tf': ['file.tf', '.tfrc', 'tfrc'], + \ 'tidy': ['.tidyrc', 'tidyrc'], + \ 'tilde': ['file.t.html'], + \ 'tli': ['file.tli'], + \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf'], + \ 'tpp': ['file.tpp'], + \ 'treetop': ['file.treetop'], + \ 'trustees': ['trustees.conf'], + \ 'tsalt': ['file.slt'], + \ 'tsscl': ['file.tsscl'], + \ 'tssgm': ['file.tssgm'], + \ 'tssop': ['file.tssop'], + \ 'twig': ['file.twig'], + \ 'uc': ['file.uc'], + \ 'udevconf': ['/etc/udev/udev.conf'], + \ 'udevperm': ['/etc/udev/permissions.d/file.permissions'], + \ 'uil': ['file.uit', 'file.uil'], + \ 'updatedb': ['/etc/updatedb.conf'], + \ 'upstart': ['/usr/share/upstart/file.conf', '/usr/share/upstart/file.override', '/etc/init/file.conf', '/etc/init/file.override', '/.init/file.conf', '/.init/file.override', '/.config/upstart/file.conf', '/.config/upstart/file.override'], + \ 'upstreamdat': ['upstream.dat', 'UPSTREAM.DAT', 'upstream.file.dat', 'UPSTREAM.FILE.DAT', 'file.upstream.dat', 'FILE.UPSTREAM.DAT'], + \ 'upstreaminstalllog': ['upstreaminstall.log', 'UPSTREAMINSTALL.LOG', 'upstreaminstall.file.log', 'UPSTREAMINSTALL.FILE.LOG', 'file.upstreaminstall.log', 'FILE.UPSTREAMINSTALL.LOG'], + \ 'upstreamlog': ['fdrupstream.log', 'upstream.log', 'UPSTREAM.LOG', 'upstream.file.log', 'UPSTREAM.FILE.LOG', 'file.upstream.log', 'FILE.UPSTREAM.LOG', 'UPSTREAM-file.log', 'UPSTREAM-FILE.LOG'], + \ 'usserverlog': ['usserver.log', 'USSERVER.LOG', 'usserver.file.log', 'USSERVER.FILE.LOG', 'file.usserver.log', 'FILE.USSERVER.LOG'], + \ 'usw2kagtlog': ['usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'], + \ 'vb': ['file.sba', 'file.vb', 'file.vbs', 'file.dsm', 'file.ctl'], + \ 'vera': ['file.vr', 'file.vri', 'file.vrh'], + \ 'verilog': ['file.v'], + \ 'verilogams': ['file.va', 'file.vams'], + \ 'vgrindefs': ['vgrindefs'], + \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst'], + \ 'vim': ['file.vim', 'file.vba', '.exrc', '_exrc'], + \ 'viminfo': ['.viminfo', '_viminfo'], + \ 'vmasm': ['file.mar'], + \ 'voscm': ['file.cm'], + \ 'vrml': ['file.wrl'], + \ 'vroom': ['file.vroom'], + \ 'webmacro': ['file.wm'], + \ 'wget': ['.wgetrc', 'wgetrc'], + \ 'winbatch': ['file.wbt'], + \ 'wml': ['file.wml'], + \ 'wsml': ['file.wsml'], + \ 'wvdial': ['wvdial.conf', '.wvdialrc'], + \ 'xdefaults': ['.Xdefaults', '.Xpdefaults', '.Xresources', 'xdm-config', 'file.ad'], + \ 'xhtml': ['file.xhtml', 'file.xht'], + \ 'xinetd': ['/etc/xinetd.conf'], + \ 'xmath': ['file.msc', 'file.msf'], + \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.ts', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul'], + \ 'xmodmap': ['anyXmodmap'], + \ 'xf86conf': ['xorg.conf', 'xorg.conf-4'], + \ 'xpm2': ['file.xpm2'], + \ 'xquery': ['file.xq', 'file.xql', 'file.xqm', 'file.xquery', 'file.xqy'], + \ 'xs': ['file.xs'], + \ 'xsd': ['file.xsd'], + \ 'xslt': ['file.xsl', 'file.xslt'], + \ 'yacc': ['file.yy', 'file.yxx', 'file.y++'], + \ 'yaml': ['file.yaml', 'file.yml'], + \ 'z8a': ['file.z8a'], + \ 'zimbu': ['file.zu'], + \ 'zimbutempl': ['file.zut'], + \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh'], + \ + \ 'aap': ['file.aap'], + \ 'help': [$VIMRUNTIME . '/doc/help.txt'], + \ 'xpm': ['file.xpm'], + \ } + +let s:filename_case_checks = { + \ 'modula2': ['file.DEF', 'file.MOD'], + \ } + +func CheckItems(checks) + for [ft, names] in items(a:checks) + for i in range(0, len(names) - 1) + new + try + exe 'edit ' . names[i] + catch + call assert_report('cannot edit "' . names[i] . '": ' . v:errmsg) + endtry + call assert_equal(ft, &filetype, 'with file name: ' . names[i]) + bwipe! + endfor + endfor +endfunc + +func Test_filetype_detection() + filetype on + call CheckItems(s:filename_checks) + if has('fname_case') + call CheckItems(s:filename_case_checks) + endif + filetype off +endfunc + +" Filetypes detected from the file contents by scripts.vim +let s:script_checks = { + \ 'virata': [['% Virata'], + \ ['', '% Virata'], + \ ['', '', '% Virata'], + \ ['', '', '', '% Virata'], + \ ['', '', '', '', '% Virata']], + \ 'strace': [['execve("/usr/bin/pstree", ["pstree"], 0x7ff0 /* 63 vars */) = 0'], + \ ['15:17:47 execve("/usr/bin/pstree", ["pstree"], ... "_=/usr/bin/strace"]) = 0'], + \ ['__libc_start_main and something']], + \ } + +func Test_script_detection() + filetype on + for [ft, files] in items(s:script_checks) + for file in files + call writefile(file, 'Xtest') + split Xtest + call assert_equal(ft, &filetype, 'for text: ' . string(file)) + bwipe! + endfor + endfor + call delete('Xtest') + filetype off +endfunc + 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_findfile.vim b/src/nvim/testdir/test_findfile.vim new file mode 100644 index 0000000000..d9a89801ea --- /dev/null +++ b/src/nvim/testdir/test_findfile.vim @@ -0,0 +1,25 @@ +" Test for findfile() +" +func Test_findfile() + new + let cwd=getcwd() + cd .. + + " Tests may be run from a shadow directory, so an extra cd needs to be done to + " get above src/ + if fnamemodify(getcwd(), ':t') != 'src' + cd ../.. + else + cd .. + endif + set ssl + + call assert_equal('src/nvim/testdir/test_findfile.vim', findfile('test_findfile.vim','src/nvim/test*')) + exe "cd" cwd + cd .. + call assert_equal('testdir/test_findfile.vim', findfile('test_findfile.vim','test*')) + call assert_equal('testdir/test_findfile.vim', findfile('test_findfile.vim','testdir')) + + exe "cd" cwd + q! +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_functions.vim b/src/nvim/testdir/test_functions.vim index 237a2dc820..398e9ab331 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -191,4 +191,165 @@ func Test_toupper() call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ")) endfunc +" Tests for the mode() function +let current_modes = '' +func! Save_mode() + let g:current_modes = mode(0) . '-' . mode(1) + return '' +endfunc + +func! Test_mode() + new + call append(0, ["Blue Ball Black", "Brown Band Bowl", ""]) + + inoremap <F2> <C-R>=Save_mode()<CR> + + normal! 3G + exe "normal i\<F2>\<Esc>" + call assert_equal('i-i', g:current_modes) + " i_CTRL-P: Multiple matches + exe "normal i\<C-G>uBa\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-P: Single match + exe "normal iBro\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X + exe "normal iBa\<C-X>\<F2>\<Esc>u" + call assert_equal('i-ix', g:current_modes) + " i_CTRL-X CTRL-P: Multiple matches + exe "normal iBa\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-P: Single match + exe "normal iBro\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-P + CTRL-P: Single match + exe "normal iBro\<C-X>\<C-P>\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-L: Multiple matches + exe "normal i\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-L: Single match + exe "normal iBlu\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-P: No match + exe "normal iCom\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-P: No match + exe "normal iCom\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + " i_CTRL-X CTRL-L: No match + exe "normal iabc\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('i-ic', g:current_modes) + + " R_CTRL-P: Multiple matches + exe "normal RBa\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-P: Single match + exe "normal RBro\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X + exe "normal RBa\<C-X>\<F2>\<Esc>u" + call assert_equal('R-Rx', g:current_modes) + " R_CTRL-X CTRL-P: Multiple matches + exe "normal RBa\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-P: Single match + exe "normal RBro\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-P + CTRL-P: Single match + exe "normal RBro\<C-X>\<C-P>\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-L: Multiple matches + exe "normal R\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-L: Single match + exe "normal RBlu\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-P: No match + exe "normal RCom\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-P: No match + exe "normal RCom\<C-X>\<C-P>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + " R_CTRL-X CTRL-L: No match + exe "normal Rabc\<C-X>\<C-L>\<F2>\<Esc>u" + call assert_equal('R-Rc', g:current_modes) + + call assert_equal('n', mode(0)) + call assert_equal('n', mode(1)) + + " How to test operator-pending mode? + + call feedkeys("v", 'xt') + call assert_equal('v', mode()) + call assert_equal('v', mode(1)) + call feedkeys("\<Esc>V", 'xt') + call assert_equal('V', mode()) + call assert_equal('V', mode(1)) + call feedkeys("\<Esc>\<C-V>", 'xt') + call assert_equal("\<C-V>", mode()) + call assert_equal("\<C-V>", mode(1)) + call feedkeys("\<Esc>", 'xt') + + call feedkeys("gh", 'xt') + call assert_equal('s', mode()) + call assert_equal('s', mode(1)) + call feedkeys("\<Esc>gH", 'xt') + call assert_equal('S', mode()) + call assert_equal('S', mode(1)) + call feedkeys("\<Esc>g\<C-H>", 'xt') + call assert_equal("\<C-S>", mode()) + call assert_equal("\<C-S>", mode(1)) + call feedkeys("\<Esc>", 'xt') + + call feedkeys(":echo \<C-R>=Save_mode()\<C-U>\<CR>", 'xt') + call assert_equal('c-c', g:current_modes) + call feedkeys("gQecho \<C-R>=Save_mode()\<CR>\<CR>vi\<CR>", 'xt') + call assert_equal('c-cv', g:current_modes) + " How to test Ex mode? + + bwipe! + iunmap <F2> +endfunc + +func Test_getbufvar() + let bnr = bufnr('%') + let b:var_num = '1234' + let def_num = '5678' + call assert_equal('1234', getbufvar(bnr, 'var_num')) + call assert_equal('1234', getbufvar(bnr, 'var_num', def_num)) + + let bd = getbufvar(bnr, '') + call assert_equal('1234', bd['var_num']) + call assert_true(exists("bd['changedtick']")) + call assert_equal(2, len(bd)) + + let bd2 = getbufvar(bnr, '', def_num) + call assert_equal(bd, bd2) + + unlet b:var_num + call assert_equal(def_num, getbufvar(bnr, 'var_num', def_num)) + call assert_equal('', getbufvar(bnr, 'var_num')) + let bd = getbufvar(bnr, '') + call assert_equal(1, len(bd)) + let bd = getbufvar(bnr, '',def_num) + call assert_equal(1, len(bd)) + + call assert_equal('', getbufvar(9999, '')) + call assert_equal(def_num, getbufvar(9999, '', def_num)) + unlet def_num + + call assert_equal(0, getbufvar(bnr, '&autoindent')) + call assert_equal(0, getbufvar(bnr, '&autoindent', 1)) + + " Open new window with forced option values + set fileformats=unix,dos + new ++ff=dos ++bin ++enc=iso-8859-2 + call assert_equal('dos', getbufvar(bufnr('%'), '&fileformat')) + call assert_equal(1, getbufvar(bufnr('%'), '&bin')) + call assert_equal('iso-8859-2', getbufvar(bufnr('%'), '&fenc')) + close + + set fileformats& +endfunc diff --git a/src/nvim/testdir/test_ga.vim b/src/nvim/testdir/test_ga.vim new file mode 100644 index 0000000000..f9357ddc87 --- /dev/null +++ b/src/nvim/testdir/test_ga.vim @@ -0,0 +1,37 @@ +" Test ga normal command, and :ascii Ex command. +func Do_ga(c) + call setline(1, a:c) + let l:a = execute("norm 1goga") + let l:b = execute("ascii") + call assert_equal(l:a, l:b) + return l:a +endfunc + +func Test_ga_command() + new + set display=uhex + call assert_equal("\nNUL", Do_ga('')) + call assert_equal("\n<<01>> 1, Hex 01, Octal 001", Do_ga("\x01")) + call assert_equal("\n<<09>> 9, Hex 09, Octal 011", Do_ga("\t")) + + set display= + call assert_equal("\nNUL", Do_ga('')) + call assert_equal("\n<^A> 1, Hex 01, Octal 001", Do_ga("\x01")) + call assert_equal("\n<^I> 9, Hex 09, Octal 011", Do_ga("\t")) + + call assert_equal("\n<e> 101, Hex 65, Octal 145", Do_ga('e')) + + if !has('multi_byte') + return + endif + + " Test a few multi-bytes characters. + call assert_equal("\n<é> 233, Hex 00e9, Octal 351", Do_ga('é')) + call assert_equal("\n<ẻ> 7867, Hex 1ebb, Octal 17273", Do_ga('ẻ')) + + " Test with combining characters. + call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401", Do_ga("e\u0301")) + call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401 < ̱> 817, Hex 0331, Octal 1461", Do_ga("e\u0301\u0331")) + call assert_equal("\n<e> 101, Hex 65, Octal 145 < ́> 769, Hex 0301, Octal 1401 < ̱> 817, Hex 0331, Octal 1461 < ̸> 824, Hex 0338, Octal 1470", Do_ga("e\u0301\u0331\u0338")) + bwipe! +endfunc diff --git a/src/nvim/testdir/test_goto.vim b/src/nvim/testdir/test_goto.vim index b6ac5720c3..2573401707 100644 --- a/src/nvim/testdir/test_goto.vim +++ b/src/nvim/testdir/test_goto.vim @@ -1,22 +1,277 @@ " Test commands that jump somewhere. -func Test_geeDEE() +" Create a new buffer using "lines" and place the cursor on the word after the +" first occurrence of return and invoke "cmd". The cursor should now be +" positioned at the given line and col. +func XTest_goto_decl(cmd, lines, line, col) new - call setline(1, ["Filename x;", "", "int Filename", "int func() {", "Filename y;"]) - /y;/ - normal gD - call assert_equal(1, line('.')) + call setline(1, a:lines) + /return/ + normal! W + execute 'norm! ' . a:cmd + call assert_equal(a:line, line('.')) + call assert_equal(a:col, col('.')) quit! endfunc -func Test_gee_dee() - new - call setline(1, ["int x;", "", "int func(int x)", "{", " return x;", "}"]) - /return/ - normal $hgd - call assert_equal(3, line('.')) - call assert_equal(14, col('.')) - quit! +func Test_gD() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 5) +endfunc + +func Test_gD_too() + let lines = [ + \ 'Filename x;', + \ '', + \ 'int Filename', + \ 'int func() {', + \ ' Filename x;', + \ ' return x;', + \ ] + call XTest_goto_decl('gD', lines, 1, 10) +endfunc + +func Test_gD_comment() + let lines = [ + \ '/* int x; */', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_inline_comment() + let lines = [ + \ 'int y /* , x */;', + \ 'int x;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string() + let lines = [ + \ 'char *s[] = "x";', + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gD_string_same_line() + let lines = [ + \ 'char *s[] = "x", int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 1, 22) +endfunc + +func Test_gD_char() + let lines = [ + \ "char c = 'x';", + \ 'int x = 1;', + \ '', + \ 'int func(void)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gD', lines, 2, 5) +endfunc + +func Test_gd() + let lines = [ + \ 'int x;', + \ '', + \ 'int func(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 14) +endfunc + +func Test_gd_not_local() + let lines = [ + \ 'int func1(void)', + \ '{', + \ ' return x;', + \ '}', + \ '', + \ 'int func2(int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_kr_style() + let lines = [ + \ 'int func(x)', + \ ' int x;', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 2, 7) +endfunc + +func Test_gd_missing_braces() + let lines = [ + \ 'def func1(a)', + \ ' a + 1', + \ 'end', + \ '', + \ 'a = 1', + \ '', + \ 'def func2()', + \ ' return a', + \ 'end', + \ ] + call XTest_goto_decl('gd', lines, 1, 11) +endfunc + +func Test_gd_comment() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* int x; */', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_comment_in_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s ="//"; int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 22) +endfunc + +func Test_gd_string_in_comment() + set comments= + let lines = [ + \ 'int func(void)', + \ '{', + \ ' /* " */ int x;', + \ ' int x;', + \ ' return x;', + \ '}', + \] + call XTest_goto_decl('gd', lines, 3, 15) + set comments& +endfunc + +func Test_gd_inline_comment() + let lines = [ + \ 'int func(/* x is an int */ int x)', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 32) +endfunc + +func Test_gd_inline_comment_only() + let lines = [ + \ 'int func(void) /* one lonely x */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 3, 10) +endfunc + +func Test_gd_inline_comment_body() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' int y /* , x */;', + \ '', + \ ' for (/* int x = 0 */; y < 2; y++);', + \ '', + \ ' int x = 0;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 7, 7) +endfunc + +func Test_gd_trailing_multiline_comment() + let lines = [ + \ 'int func(int x) /* x is an int */', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_trailing_comment() + let lines = [ + \ 'int func(int x) // x is an int', + \ '{', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 1, 14) +endfunc + +func Test_gd_string() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ ' int x = 1;', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 4, 7) +endfunc + +func Test_gd_string_only() + let lines = [ + \ 'int func(void)', + \ '{', + \ ' char *s = "x";', + \ '', + \ ' return x;', + \ '}', + \ ] + call XTest_goto_decl('gd', lines, 5, 10) endfunc " Check that setting 'cursorline' does not change curswant diff --git a/src/nvim/testdir/test_hardcopy.vim b/src/nvim/testdir/test_hardcopy.vim index ea9790d134..7aea704e86 100644 --- a/src/nvim/testdir/test_hardcopy.vim +++ b/src/nvim/testdir/test_hardcopy.vim @@ -50,6 +50,7 @@ endfunc " We don't check much of the contents. func Test_with_syntax() if has('postscript') + edit test_hardcopy.vim set printoptions=syntax:y syn on hardcopy > Xhardcopy diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim index 1ca0f722cf..06c48d8e76 100644 --- a/src/nvim/testdir/test_help_tagjump.vim +++ b/src/nvim/testdir/test_help_tagjump.vim @@ -18,6 +18,52 @@ func Test_help_tagjump() call assert_true(getline('.') =~ '\*help.txt\*') helpclose + help | + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*bar\*') + helpclose + + help "* + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*quotestar\*') + helpclose + + help sp?it + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*:split\*') + helpclose + + help :? + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*:?\*') + helpclose + + help FileW*Post + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*FileWritePost\*') + helpclose + + help `ls` + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*:ls\*') + helpclose + + help ^X + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*CTRL-X\*') + helpclose + + help i_^_CTRL-D + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*i_^_CTRL-D\*') + helpclose + + exec "help \<C-V>" + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*CTRL-V\*') + helpclose + + exec "help! ('textwidth'" call assert_equal("help", &filetype) call assert_true(getline('.') =~ "\\*'textwidth'\\*") @@ -47,6 +93,16 @@ func Test_help_tagjump() call assert_equal("help", &filetype) call assert_true(getline('.') =~ '\*{address}\*') helpclose + + exusage + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*:index\*') + helpclose + + viusage + call assert_equal("help", &filetype) + call assert_true(getline('.') =~ '\*normal-index\*') + helpclose endfunc let s:langs = ['en', 'ab', 'ja'] @@ -89,17 +145,8 @@ func s:doc_config_teardown() endif endfunc -func s:get_cmd_compl_list(cmd) - let list = [] - let str = '' - for cnt in range(1, 999) - call feedkeys(a:cmd . repeat("\<Tab>", cnt) . "'\<C-B>let str='\<CR>", 'tx') - if str ==# a:cmd[1:] - break - endif - call add(list, str) - endfor - return list +func s:get_help_compl_list(cmd) + return getcompletion(a:cmd, 'help') endfunc func Test_help_complete() @@ -111,49 +158,49 @@ func Test_help_complete() if has('multi_lang') set helplang= endif - let list = s:get_cmd_compl_list(":h test") - call assert_equal(['h test-col', 'h test-char'], list) + let list = s:get_help_compl_list("test") + call assert_equal(['test-col', 'test-char'], list) if has('multi_lang') " 'helplang=ab' and help file lang is 'en' set helplang=ab - let list = s:get_cmd_compl_list(":h test") - call assert_equal(['h test-col', 'h test-char'], list) + let list = s:get_help_compl_list("test") + call assert_equal(['test-col', 'test-char'], list) " 'helplang=' and help file lang is 'en' and 'ab' set rtp+=Xdir1/doc-ab set helplang= - let list = s:get_cmd_compl_list(":h test") - call assert_equal(sort(['h test-col@en', 'h test-col@ab', - \ 'h test-char@en', 'h test-char@ab']), sort(list)) + let list = s:get_help_compl_list("test") + call assert_equal(sort(['test-col@en', 'test-col@ab', + \ 'test-char@en', 'test-char@ab']), sort(list)) " 'helplang=ab' and help file lang is 'en' and 'ab' set helplang=ab - let list = s:get_cmd_compl_list(":h test") - call assert_equal(sort(['h test-col', 'h test-col@en', - \ 'h test-char', 'h test-char@en']), sort(list)) + let list = s:get_help_compl_list("test") + call assert_equal(sort(['test-col', 'test-col@en', + \ 'test-char', 'test-char@en']), sort(list)) " 'helplang=' and help file lang is 'en', 'ab' and 'ja' set rtp+=Xdir1/doc-ja set helplang= - let list = s:get_cmd_compl_list(":h test") - call assert_equal(sort(['h test-col@en', 'h test-col@ab', - \ 'h test-col@ja', 'h test-char@en', - \ 'h test-char@ab', 'h test-char@ja']), sort(list)) + let list = s:get_help_compl_list("test") + call assert_equal(sort(['test-col@en', 'test-col@ab', + \ 'test-col@ja', 'test-char@en', + \ 'test-char@ab', 'test-char@ja']), sort(list)) " 'helplang=ab' and help file lang is 'en', 'ab' and 'ja' set helplang=ab - let list = s:get_cmd_compl_list(":h test") - call assert_equal(sort(['h test-col', 'h test-col@en', - \ 'h test-col@ja', 'h test-char', - \ 'h test-char@en', 'h test-char@ja']), sort(list)) + let list = s:get_help_compl_list("test") + call assert_equal(sort(['test-col', 'test-col@en', + \ 'test-col@ja', 'test-char', + \ 'test-char@en', 'test-char@ja']), sort(list)) " 'helplang=ab,ja' and help file lang is 'en', 'ab' and 'ja' set helplang=ab,ja - let list = s:get_cmd_compl_list(":h test") - call assert_equal(sort(['h test-col', 'h test-col@ja', - \ 'h test-col@en', 'h test-char', - \ 'h test-char@ja', 'h test-char@en']), sort(list)) + let list = s:get_help_compl_list("test") + call assert_equal(sort(['test-col', 'test-col@ja', + \ 'test-col@en', 'test-char', + \ 'test-char@ja', 'test-char@en']), sort(list)) endif catch call assert_exception('X') diff --git a/src/nvim/testdir/test_hide.vim b/src/nvim/testdir/test_hide.vim new file mode 100644 index 0000000000..128b8ff945 --- /dev/null +++ b/src/nvim/testdir/test_hide.vim @@ -0,0 +1,97 @@ +" Tests for :hide command/modifier and 'hidden' option + +function SetUp() + let s:save_hidden = &hidden + let s:save_bufhidden = &bufhidden + let s:save_autowrite = &autowrite + set nohidden + set bufhidden= + set noautowrite +endfunc + +function TearDown() + let &hidden = s:save_hidden + let &bufhidden = s:save_bufhidden + let &autowrite = s:save_autowrite +endfunc + +function Test_hide() + let orig_bname = bufname('') + let orig_winnr = winnr('$') + + new Xf1 + set modified + call assert_fails('edit Xf2') + bwipeout! Xf1 + + new Xf1 + set modified + edit! Xf2 + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a command + hide + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with trailing comment + hide " comment + call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + new Xf1 + set modified + " :hide as a command with bar + hide | new Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " :hide as a modifier with trailing comment + hide edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + new Xf1 + set modified + " To check that the bar is not recognized to separate commands + hide echo "one|two" + call assert_equal(['Xf1', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + + " set hidden + new Xf1 + set hidden + set modified + edit Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf1 + bwipeout! Xf2 + + " set hidden bufhidden=wipe + new Xf1 + set bufhidden=wipe + set modified + hide edit! Xf2 " comment + call assert_equal(['Xf2', 2], [bufname(''), winnr('$')]) + call assert_equal([0, 0], [buflisted('Xf1'), bufloaded('Xf1')]) + bwipeout! Xf2 +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_history.vim b/src/nvim/testdir/test_history.vim index 3163b344d3..ca31e3f06c 100644 --- a/src/nvim/testdir/test_history.vim +++ b/src/nvim/testdir/test_history.vim @@ -31,6 +31,30 @@ function History_Tests(hist) call assert_equal('ls', histget(a:hist, -1)) call assert_equal(4, histnr(a:hist)) + let a=execute('history ' . a:hist) + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history all') + call assert_match("^\n # .* history\n 3 buffers\n> 4 ls", a) + + if len(a:hist) > 0 + let a=execute('history ' . a:hist . ' 2') + call assert_match("^\n # \\S* history$", a) + let a=execute('history ' . a:hist . ' 3') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' 4') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' 3,4') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -1') + call assert_match("^\n # \\S* history\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -2') + call assert_match("^\n # \\S* history\n 3 buffers$", a) + let a=execute('history ' . a:hist . ' -2,') + call assert_match("^\n # \\S* history\n 3 buffers\n> 4 ls$", a) + let a=execute('history ' . a:hist . ' -3') + call assert_match("^\n # \\S* history$", a) + endif + " Test for removing entries matching a pattern for i in range(1, 3) call histadd(a:hist, 'text_' . i) diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim new file mode 100644 index 0000000000..c307e33cbf --- /dev/null +++ b/src/nvim/testdir/test_ins_complete.vim @@ -0,0 +1,219 @@ + +" 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", + \ "Makefile\tto\trun"], 'Xtestfile') + call writefile(['', 'start of testfile', + \ 'ru', + \ 'run1', + \ 'run2', + \ 'STARTTEST', + \ 'ENDTEST', + \ 'end of testfile'], 'Xtestdata') + set ff& + + enew! + edit Xtestdata + new + call append(0, ['#include "Xtestfile"', '']) + call cursor(2, 1) + + set cot= + set cpt=.,w + " add-expands (word from next line) from other window + exe "normal iru\<C-N>\<C-N>\<C-X>\<C-N>\<Esc>\<C-A>" + call assert_equal('run1 run3', getline('.')) + " add-expands (current buffer first) + exe "normal o\<C-P>\<C-X>\<C-N>" + call assert_equal('run3 run3', getline('.')) + " Local expansion, ends in an empty line (unless it becomes a global + " expansion) + exe "normal o\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>" + call assert_equal('', getline('.')) + " starts Local and switches to global add-expansion + exe "normal o\<C-X>\<C-P>\<C-P>\<C-X>\<C-X>\<C-N>\<C-X>\<C-N>\<C-N>" + call assert_equal('run1 run2', getline('.')) + + set cpt=.,w,i + " i-add-expands and switches to local + exe "normal OM\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-X>\<C-X>\<C-P>" + call assert_equal("Makefile\tto\trun3", getline('.')) + " add-expands lines (it would end in an empty line if it didn't ignored + " itself) + exe "normal o\<C-X>\<C-L>\<C-X>\<C-L>\<C-P>\<C-P>" + call assert_equal("Makefile\tto\trun3", getline('.')) + call assert_equal("Makefile\tto\trun3", getline(line('.') - 1)) + + set cpt=kXtestfile + " checks k-expansion, and file expansion (use Xtest11 instead of test11, + " because TEST11.OUT may match first on DOS) + write Xtest11.one + write Xtest11.two + exe "normal o\<C-N>\<Esc>IX\<Esc>A\<C-X>\<C-F>\<C-N>" + call assert_equal('Xtest11.two', getline('.')) + + " use CTRL-X CTRL-F to complete Xtest11.one, remove it and then use CTRL-X + " CTRL-F again to verify this doesn't cause trouble. + exe "normal oXt\<C-X>\<C-F>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<C-X>\<C-F>" + call assert_equal('Xtest11.one', getline('.')) + normal ddk + + set cpt=w + " checks make_cyclic in other window + exe "normal oST\<C-N>\<C-P>\<C-P>\<C-P>\<C-P>" + call assert_equal('STARTTEST', getline('.')) + + set cpt=u nohid + " checks unloaded buffer expansion + only + exe "normal oEN\<C-N>" + call assert_equal('ENDTEST', getline('.')) + " checks adding mode abortion + exe "normal ounl\<C-N>\<C-X>\<C-X>\<C-P>" + call assert_equal('unless', getline('.')) + + set cpt=t,d def=^\\k* tags=Xtestfile notagbsearch + " tag expansion, define add-expansion interrupted + exe "normal o\<C-X>\<C-]>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-D>" + call assert_equal('test11file 36Gepeto /Tag/ asd', getline('.')) + " t-expansion + exe "normal oa\<C-N>\<Esc>" + call assert_equal('asd', getline('.')) + + %bw! + call delete('Xtestfile') + call delete('Xtest11.one') + call delete('Xtest11.two') + call delete('Xtestdata') + set cpt& cot& def& tags& tagbsearch& hidden& + cd .. + call delete('Xdir', 'rf') +endfunc + +function! s:CompleteDone_CompleteFuncDict( findstart, base ) + if a:findstart + return 0 + endif + + return { + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W', + \ 'user_data': 'test' + \ } + \ ] + \ } +endfunction + +function! s:CompleteDone_CheckCompletedItemDict() + call assert_equal( 'aword', v:completed_item[ 'word' ] ) + call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) + call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) + call assert_equal( 'words are cool', v:completed_item[ 'info' ] ) + call assert_equal( 'W', v:completed_item[ 'kind' ] ) + call assert_equal( 'test', v:completed_item[ 'user_data' ] ) + + let s:called_completedone = 1 +endfunction + +function Test_CompleteDoneDict() + au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict() + + set completefunc=<SID>CompleteDone_CompleteFuncDict + execute "normal a\<C-X>\<C-U>\<C-Y>" + set completefunc& + + call assert_equal( 'test', v:completed_item[ 'user_data' ] ) + call assert_true( s:called_completedone ) + + let s:called_completedone = 0 + au! CompleteDone +endfunc + +function! s:CompleteDone_CompleteFuncDictNoUserData( findstart, base ) + if a:findstart + return 0 + endif + + return { + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W' + \ } + \ ] + \ } +endfunction + +function! s:CompleteDone_CheckCompletedItemDictNoUserData() + call assert_equal( 'aword', v:completed_item[ 'word' ] ) + call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) + call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) + call assert_equal( 'words are cool', v:completed_item[ 'info' ] ) + call assert_equal( 'W', v:completed_item[ 'kind' ] ) + call assert_equal( '', v:completed_item[ 'user_data' ] ) + + let s:called_completedone = 1 +endfunction + +function Test_CompleteDoneDictNoUserData() + au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDictNoUserData() + + set completefunc=<SID>CompleteDone_CompleteFuncDictNoUserData + execute "normal a\<C-X>\<C-U>\<C-Y>" + set completefunc& + + call assert_equal( '', v:completed_item[ 'user_data' ] ) + call assert_true( s:called_completedone ) + + let s:called_completedone = 0 + au! CompleteDone +endfunc + +function! s:CompleteDone_CompleteFuncList( findstart, base ) + if a:findstart + return 0 + endif + + return [ 'aword' ] +endfunction + +function! s:CompleteDone_CheckCompletedItemList() + call assert_equal( 'aword', v:completed_item[ 'word' ] ) + call assert_equal( '', v:completed_item[ 'abbr' ] ) + call assert_equal( '', v:completed_item[ 'menu' ] ) + call assert_equal( '', v:completed_item[ 'info' ] ) + call assert_equal( '', v:completed_item[ 'kind' ] ) + call assert_equal( '', v:completed_item[ 'user_data' ] ) + + let s:called_completedone = 1 +endfunction + +function Test_CompleteDoneList() + au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemList() + + set completefunc=<SID>CompleteDone_CompleteFuncList + execute "normal a\<C-X>\<C-U>\<C-Y>" + set completefunc& + + call assert_equal( '', v:completed_item[ 'user_data' ] ) + call assert_true( s:called_completedone ) + + let s:called_completedone = 0 + au! CompleteDone +endfunc diff --git a/src/nvim/testdir/test_let.vim b/src/nvim/testdir/test_let.vim new file mode 100644 index 0000000000..24c6ef5e01 --- /dev/null +++ b/src/nvim/testdir/test_let.vim @@ -0,0 +1,27 @@ +" Tests for the :let command. + +func Test_let() + " Test to not autoload when assigning. It causes internal error. + set runtimepath+=./sautest + let Test104#numvar = function('tr') + call assert_equal("function('tr')", string(Test104#numvar)) + + let a = 1 + let b = 2 + + let out = execute('let a b') + let s = "\na #1\nb #2" + call assert_equal(s, out) + + let out = execute('let {0 == 1 ? "a" : "b"}') + let s = "\nb #2" + call assert_equal(s, out) + + let out = execute('let {0 == 1 ? "a" : "b"} a') + let s = "\nb #2\na #1" + call assert_equal(s, out) + + let out = execute('let a {0 == 1 ? "a" : "b"}') + let s = "\na #1\nb #2" + call assert_equal(s, out) +endfunc diff --git a/src/nvim/testdir/test_lineending.vim b/src/nvim/testdir/test_lineending.vim new file mode 100644 index 0000000000..5be3be8db3 --- /dev/null +++ b/src/nvim/testdir/test_lineending.vim @@ -0,0 +1,19 @@ +" Tests for saving/loading a file with some lines ending in +" CTRL-M, some not +func Test_lineending() + let l = ["this line ends in a\<CR>", + \ "this one doesn't", + \ "this one does\<CR>", + \ "and the last one doesn't"] + set fileformat=dos + enew! + call append(0, l) + $delete + write Xfile1 + bwipe Xfile1 + edit Xfile1 + let t = getline(1, '$') + call assert_equal(l, t) + new | only + call delete('Xfile1') +endfunc diff --git a/src/nvim/testdir/test_lispwords.vim b/src/nvim/testdir/test_lispwords.vim new file mode 100644 index 0000000000..4c05504cf1 --- /dev/null +++ b/src/nvim/testdir/test_lispwords.vim @@ -0,0 +1,82 @@ +" Tests for 'lispwords' settings being global-local + +set nocompatible viminfo+=nviminfo + +func Test_global_local_lispwords() + setglobal lispwords=foo,bar,baz + setlocal lispwords-=foo | setlocal lispwords+=quux + call assert_equal('foo,bar,baz', &g:lispwords) + call assert_equal('bar,baz,quux', &l:lispwords) + call assert_equal('bar,baz,quux', &lispwords) + + setlocal lispwords< + call assert_equal('foo,bar,baz', &g:lispwords) + call assert_equal('foo,bar,baz', &l:lispwords) + call assert_equal('foo,bar,baz', &lispwords) +endfunc + +func Test_lisp_indent() + enew! + + call append(0, [ + \ '(defun html-file (base)', + \ '(format nil "~(~A~).html" base))', + \ '', + \ '(defmacro page (name title &rest body)', + \ '(let ((ti (gensym)))', + \ '`(with-open-file (*standard-output*', + \ '(html-file ,name)', + \ ':direction :output', + \ ':if-exists :supersede)', + \ '(let ((,ti ,title))', + \ '(as title ,ti)', + \ '(with center ', + \ '(as h2 (string-upcase ,ti)))', + \ '(brs 3)', + \ ',@body))))', + \ '', + \ ';;; Utilities for generating links', + \ '', + \ '(defmacro with-link (dest &rest body)', + \ '`(progn', + \ '(format t "<a href=\"~A\">" (html-file ,dest))', + \ ',@body', + \ '(princ "</a>")))' + \ ]) + set lisp + set lispwords& + let save_copt = &cpoptions + set cpoptions+=p + normal 1G=G + + call assert_equal([ + \ '(defun html-file (base)', + \ ' (format nil "~(~A~).html" base))', + \ '', + \ '(defmacro page (name title &rest body)', + \ ' (let ((ti (gensym)))', + \ ' `(with-open-file (*standard-output*', + \ ' (html-file ,name)', + \ ' :direction :output', + \ ' :if-exists :supersede)', + \ ' (let ((,ti ,title))', + \ ' (as title ,ti)', + \ ' (with center ', + \ ' (as h2 (string-upcase ,ti)))', + \ ' (brs 3)', + \ ' ,@body))))', + \ '', + \ ';;; Utilities for generating links', + \ '', + \ '(defmacro with-link (dest &rest body)', + \ ' `(progn', + \ ' (format t "<a href=\"~A\">" (html-file ,dest))', + \ ' ,@body', + \ ' (princ "</a>")))', + \ '' + \ ], getline(1, "$")) + + enew! + let &cpoptions=save_copt + set nolisp +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 new file mode 100644 index 0000000000..d28dbc444c --- /dev/null +++ b/src/nvim/testdir/test_listlbr.vim @@ -0,0 +1,238 @@ +" Test for linebreak and list option (non-utf8) + +" Nvim does not allow setting 'encoding', so skip this test. +finish + +set encoding=latin1 +scriptencoding latin1 + +if !exists("+linebreak") || !has("conceal") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=8 sw=4 sts=4 linebreak sbr= wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_set_linebreak() + call s:test_windows('setl ts=4 sbr=+') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_list() + call s:test_windows('setl ts=4 sbr=+ list listchars=') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "^Iabcdef hijklmn^I ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl ts=4 sbr=+ nolist') + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ") + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " abcdef ", +\ "+hijklmn ", +\ "+pqrstuvwxyz_1060ABC", +\ "+DEFGHIJKLMNOP ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_should_break() + call s:test_windows('setl sbr=+ nolist') + call setline(1, "1\t" . repeat('a', winwidth(0)-2)) + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "1 ", +\ "+aaaaaaaaaaaaaaaaaa ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_conceal() + call s:test_windows('setl cpo&vim sbr=+ list conceallevel=2 concealcursor=nv listchars=tab:ab') + call setline(1, "_S_\t bla") + syn match ConcealVar contained /_/ conceal + syn match All /.*/ contains=ConcealVar + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "Sabbbbbb bla ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block() + call s:test_windows('setl sbr=+') + call setline(1, [ +\ "REMOVE: this not", +\ "REMOVE: aaaaaaaaaaaaa", +\ ]) + exe "norm! 1/^REMOVE:" + exe "norm! 0\<C-V>jf x" + $put + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "this not ", +\ "aaaaaaaaaaaaa ", +\ "REMOVE: ", +\ "REMOVE: ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_block_and_vbA() + call s:test_windows() + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGET at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar foobar ", +\ "foobar TARGETx at ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_virtual_char_and_block() + call s:test_windows() + call setline(1, "1111-1111-1111-11-1111-1111-1111") + exe "norm! 0f-lv3lc2222\<Esc>bgj." + let lines = s:screen_lines([1, 2], winwidth(0)) + let expect = [ +\ "1111-2222-1111-11- ", +\ "1111-2222-1111 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_undo_after_block_visual() + call s:test_windows() + call setline(1, ["aaa", "aaa", "a"]) + exe "norm! gg\<C-V>2j~e." + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "AaA ", +\ "AaA ", +\ "A ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_norm_after_block_visual() + call s:test_windows() + call setline(1, ["abcd{ef", "ghijklm", "no}pgrs"]) + exe "norm! ggf{\<C-V>\<C-V>c%" + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "abcdpgrs ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_block_replace_after_wrapping() + call s:test_windows() + call setline(1, repeat("a", 150)) + exe "norm! 0yypk147|\<C-V>jr0" + call assert_equal(repeat("a", 146) . "0aaa", getline(1)) + call assert_equal(repeat("a", 146) . "0aaa", getline(2)) + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aaaaaa0aaa ", +\ "@ ", +\ "@ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_listchars() + call s:test_windows('setl list listchars=space:_,trail:-,tab:>-,eol:$') + call setline(1, "a aaaaaaaaaaaaaaaaaaaaaa\ta ") + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ "a_ ", +\ "aaaaaaaaaaaaaaaaaaaa", +\ "aa>-----a-$ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_with_tab_and_skipping_first_chars() + call s:test_windows('setl list listchars=tab:>- ts=70 nowrap') + call setline(1, ["iiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\taaaaaaaaaaaaaaaaaa"]) + call cursor(4,64) + norm! 2zl + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "---------------aaaaa", +\ "iiiiiiiii>-----aaaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_listlbr_utf8.vim b/src/nvim/testdir/test_listlbr_utf8.vim new file mode 100644 index 0000000000..56a4cc9b31 --- /dev/null +++ b/src/nvim/testdir/test_listlbr_utf8.vim @@ -0,0 +1,256 @@ +" Test for linebreak and list option in utf-8 mode + +set encoding=utf-8 +scriptencoding utf-8 + +if !exists("+linebreak") || !has("conceal") || !has("signs") + finish +endif + +source view_util.vim + +function s:screen_lines(lnum, width) abort + return ScreenLines(a:lnum, a:width) +endfunction + +function! s:compare_lines(expect, actual) + call assert_equal(a:expect, a:actual) +endfunction + +function s:screen_attr(lnum, chars, ...) abort + let line = getline(a:lnum) + let attr = [] + let prefix = get(a:000, 0, 0) + for i in range(a:chars[0], a:chars[1]) + let scol = strdisplaywidth(strcharpart(line, 0, i-1)) + 1 + let attr += [screenattr(a:lnum, scol + prefix)] + endfor + return attr +endfunction + +function s:test_windows(...) + call NewWindow(10, 20) + setl ts=4 sw=4 sts=4 linebreak sbr=+ wrap + exe get(a:000, 0, '') +endfunction + +function s:close_windows(...) + call CloseWindow() + exe get(a:000, 0, '') +endfunction + +func Test_linebreak_with_fancy_listchars() + call s:test_windows("setl list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "▕———abcdef ", +\ "+hijklmn▕——— ", +\ "+pqrstuvwxyz␣1060ABC", +\ "+DEFGHIJKLMNOPˑ¶ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_nolinebreak_with_list() + call s:test_windows("setl nolinebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz\u00a01060ABCDEFGHIJKLMNOP ") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ "▕———abcdef hijklmn▕—", +\ "+pqrstuvwxyz␣1060ABC", +\ "+DEFGHIJKLMNOPˑ¶ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_linebreak_with_nolist() + call s:test_windows('setl nolist') + call setline(1, "\t*mask = nil;") + redraw! + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect = [ +\ " *mask = nil; ", +\ "~ ", +\ "~ ", +\ "~ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing1() + call s:test_windows('setl list listchars=tab:>- cole=1') + call setline(1, [ +\ "#define ABCDE\t\t1", +\ "#define ABCDEF\t\t1", +\ "#define ABCDEFG\t\t1", +\ "#define ABCDEFGH\t1", +\ "#define MSG_MODE_FILE\t\t\t1", +\ "#define MSG_MODE_CONSOLE\t\t2", +\ "#define MSG_MODE_FILE_AND_CONSOLE\t3", +\ "#define MSG_MODE_FILE_THEN_CONSOLE\t4", +\ ]) + vert resize 40 + syn match Conceal conceal cchar=>'AB\|MSG_MODE' + redraw! + let lines = s:screen_lines([1, 7], winwidth(0)) + let expect = [ +\ "#define ABCDE>-->---1 ", +\ "#define >CDEF>-->---1 ", +\ "#define >CDEFG>->---1 ", +\ "#define >CDEFGH>----1 ", +\ "#define >_FILE>--------->--->---1 ", +\ "#define >_CONSOLE>---------->---2 ", +\ "#define >_FILE_AND_CONSOLE>---------3 ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_list_and_concealing2() + call s:test_windows('setl nowrap ts=2 list listchars=tab:>- cole=2 concealcursor=n') + call setline(1, "bbeeeeee\t\t;\tsome text") + vert resize 40 + syn clear + syn match meaning /;\s*\zs.*/ + syn match hasword /^\x\{8}/ contains=word + syn match word /\<\x\{8}\>/ contains=beginword,endword contained + syn match beginword /\<\x\x/ contained conceal + syn match endword /\x\{6}\>/ contained + hi meaning guibg=blue + hi beginword guibg=green + hi endword guibg=red + redraw! + let lines = s:screen_lines([1, 1], winwidth(0)) + let expect = [ +\ "eeeeee>--->-;>some text ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_screenattr_for_comment() + call s:test_windows("setl ft=c ts=7 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, " /*\t\t and some more */") + norm! gg0 + syntax on + hi SpecialKey term=underline ctermfg=red guifg=red + redraw! + let line = getline(1) + let attr = s:screen_attr(1, [1, 6]) + call assert_notequal(attr[0], attr[1]) + call assert_notequal(attr[1], attr[3]) + call assert_notequal(attr[3], attr[5]) + call s:close_windows() +endfunc + +func Test_visual_block_and_selection_exclusive() + call s:test_windows('setl selection=exclusive') + call setline(1, "long line: " . repeat("foobar ", 40) . "TARGETÃ' at end") + exe "norm! $3B\<C-v>eAx\<Esc>" + let lines = s:screen_lines([1, 10], winwidth(0)) + let expect = [ +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar foobar ", +\ "+foobar TARGETÃx' ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_multibyte_sign_and_colorcolumn() + call s:test_windows("setl nolinebreak cc=3 list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6") + call setline(1, ["", "a b c", "a b c"]) + exe "sign define foo text=\uff0b" + exe "sign place 1 name=foo line=2 buffer=" . bufnr('%') + redraw! + norm! ggj0 + let signwidth = strdisplaywidth("\uff0b") + let attr1 = s:screen_attr(2, [1, 3], signwidth) + let attr2 = s:screen_attr(3, [1, 3], signwidth) + call assert_equal(attr1[0], attr2[0]) + call assert_equal(attr1[1], attr2[1]) + call assert_equal(attr1[2], attr2[2]) + let lines = s:screen_lines([1, 3], winwidth(0)) + let expect = [ +\ " ¶ ", +\ "+a b c¶ ", +\ " a b c¶ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_illegal_byte_and_breakat() + call s:test_windows("setl sbr= brk+=<") + vert resize 18 + call setline(1, repeat("\x80", 6)) + redraw! + let lines = s:screen_lines([1, 2], winwidth(0)) + let expect = [ +\ "<80><80><80><80><8", +\ "0><80> ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('setl brk&vim') +endfunc + +func Test_multibyte_wrap_and_breakat() + call s:test_windows("setl sbr= brk+=>") + call setline(1, repeat('a', 17) . repeat('あ', 2)) + redraw! + let lines = s:screen_lines([1, 2], winwidth(0)) + let expect = [ +\ "aaaaaaaaaaaaaaaaaあ>", +\ "あ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows('setl brk&vim') +endfunc + +func Test_chinese_char_on_wrap_column() + call s:test_windows("setl nolbr wrap sbr=") + syntax off + call setline(1, [ +\ 'aaaaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'aaaaaaaaaaaaaaaaa中'. +\ 'hello']) + call cursor(1,1) + norm! $ + redraw! + let expect=[ +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中aaaaaaaaaaaaaaaaa>', +\ '中hello '] + let lines = s:screen_lines([1, 10], winwidth(0)) + call s:compare_lines(expect, lines) + call s:close_windows() +endfu diff --git a/src/nvim/testdir/test_makeencoding.py b/src/nvim/testdir/test_makeencoding.py new file mode 100644 index 0000000000..041edadc0a --- /dev/null +++ b/src/nvim/testdir/test_makeencoding.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Test program for :make, :grep and :cgetfile. + +from __future__ import print_function, unicode_literals +import locale +import io +import sys + +def set_output_encoding(enc=None): + """Set the encoding of stdout and stderr + + arguments: + enc -- Encoding name. + If omitted, locale.getpreferredencoding() is used. + """ + if enc is None: + enc = locale.getpreferredencoding() + + def get_text_writer(fo, **kwargs): + kw = dict(kwargs) + kw.setdefault('errors', 'backslashreplace') # use \uXXXX style + kw.setdefault('closefd', False) + + if sys.version_info[0] < 3: + # Work around for Python 2.x + # New line conversion isn't needed here. Done in somewhere else. + writer = io.open(fo.fileno(), mode='w', newline='', **kw) + write = writer.write # save the original write() function + enc = locale.getpreferredencoding() + def convwrite(s): + if isinstance(s, bytes): + write(s.decode(enc)) # convert to unistr + else: + write(s) + try: + writer.flush() # needed on Windows + except IOError: + pass + writer.write = convwrite + else: + writer = io.open(fo.fileno(), mode='w', **kw) + return writer + + sys.stdout = get_text_writer(sys.stdout, encoding=enc) + sys.stderr = get_text_writer(sys.stderr, encoding=enc) + + +def main(): + enc = 'utf-8' + if len(sys.argv) > 1: + enc = sys.argv[1] + set_output_encoding(enc) + + message_tbl = { + 'utf-8': 'ÀÈÌÒÙ こんにちは 你好', + 'latin1': 'ÀÈÌÒÙ', + 'cp932': 'こんにちは', + 'cp936': '你好', + } + + print('Xfoobar.c(10) : %s (%s)' % (message_tbl[enc], enc)) + + +if __name__ == "__main__": + main() diff --git a/src/nvim/testdir/test_makeencoding.vim b/src/nvim/testdir/test_makeencoding.vim new file mode 100644 index 0000000000..a3d5538a47 --- /dev/null +++ b/src/nvim/testdir/test_makeencoding.vim @@ -0,0 +1,106 @@ +" Tests for 'makeencoding'. +if !has('multi_byte') + finish +endif + +source shared.vim + +let s:python = PythonProg() +if s:python == '' + " Can't run this test. + finish +endif + +let s:script = 'test_makeencoding.py' + +let s:message_tbl = { + \ 'utf-8': 'ÀÈÌÒÙ こんにちは 你好', + \ 'latin1': 'ÀÈÌÒÙ', + \ 'cp932': 'こんにちは', + \ 'cp936': '你好', + \} + + +" Tests for :cgetfile and :lgetfile. +func Test_getfile() + set errorfile=Xerror.txt + set errorformat=%f(%l)\ :\ %m + + " :cgetfile + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile + cgetfile + copen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + cclose + endfor + + " :lgetfile + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile + lgetfile + lopen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + lclose + endfor + + call delete(&errorfile) +endfunc + + +" Tests for :grep and :lgrep. +func Test_grep() + let &grepprg = s:python + set grepformat=%f(%l)\ :\ %m + + " :grep + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent grep! " . s:script . " " . enc + copen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + cclose + endfor + + " :lgrep + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent lgrep! " . s:script . " " . enc + lopen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + lclose + endfor +endfunc + + +" Tests for :make and :lmake. +func Test_make() + let &makeprg = s:python + set errorformat=%f(%l)\ :\ %m + + " :make + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent make! " . s:script . " " . enc + copen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + cclose + endfor + + " :lmake + for enc in keys(s:message_tbl) + let &makeencoding = enc + exec "silent lmake! " . s:script . " " . enc + lopen + call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")", + \ getline('.')) + lclose + endfor +endfunc diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index 7f93ddd56e..f5e4c4b90c 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -110,6 +110,8 @@ func Test_map_langmap() call feedkeys(":call append(line('$'), '+')\<CR>", "xt") call assert_equal('+', getline('$')) + iunmap a + iunmap c set nomodified endfunc @@ -120,7 +122,7 @@ func Test_map_feedkeys() $-1 call feedkeys("0qqdw.ifoo\<Esc>qj0@q\<Esc>", "xt") call assert_equal(['fooc d', 'fooc d'], getline(line('$') - 1, line('$'))) - unmap . + nunmap . set nomodified endfunc diff --git a/src/nvim/testdir/test_matchadd_conceal.vim b/src/nvim/testdir/test_matchadd_conceal.vim index c788689e33..c11f1a84a9 100644 --- a/src/nvim/testdir/test_matchadd_conceal.vim +++ b/src/nvim/testdir/test_matchadd_conceal.vim @@ -277,6 +277,7 @@ function! Test_matchadd_and_syn_conceal() call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) call assert_equal(screenattr(1, 11) , screenattr(1, 32)) call matchadd('CheckedByCoq', '\%<2l\%>9c\%<16c') + redraw! call assert_equal(expect, s:screenline(1)) call assert_notequal(screenattr(1, 10) , screenattr(1, 11)) call assert_notequal(screenattr(1, 11) , screenattr(1, 12)) diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim new file mode 100644 index 0000000000..4774cf4af5 --- /dev/null +++ b/src/nvim/testdir/test_mksession.vim @@ -0,0 +1,155 @@ +" Test for :mksession, :mkview and :loadview in latin1 encoding + +scriptencoding latin1 + +if !has('multi_byte') || !has('mksession') + finish +endif + +func Test_mksession() + tabnew + let wrap_save = &wrap + set sessionoptions=buffers splitbelow fileencoding=latin1 + call setline(1, [ + \ 'start:', + \ 'no multibyte chAracter', + \ ' one leaDing tab', + \ ' four leadinG spaces', + \ 'two consecutive tabs', + \ 'two tabs in one line', + \ 'one multibyteCharacter', + \ 'a two multiByte characters', + \ 'A three mulTibyte characters' + \ ]) + let tmpfile = 'Xtemp' + exec 'w! ' . tmpfile + /^start: + set wrap + vsplit + norm! j16| + split + norm! j16| + split + norm! j16| + split + norm! j8| + split + norm! j8| + split + norm! j16| + split + norm! j16| + split + norm! j16| + wincmd l + + set nowrap + /^start: + norm! j16|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + norm! j08|3zl + split + norm! j08|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + call wincol() + mksession! Xtest_mks.out + let li = filter(readfile('Xtest_mks.out'), 'v:val =~# "\\(^ *normal! 0\\|^ *exe ''normal!\\)"') + let expected = [ + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 08|', + \ 'normal! 08|', + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 016|', + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", + \ " normal! 08|", + \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", + \ " normal! 08|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|" + \ ] + call assert_equal(expected, li) + tabclose! + + call delete('Xtest_mks.out') + call delete(tmpfile) + let &wrap = wrap_save +endfunc + +func Test_mksession_winheight() + new + set winheight=10 winminheight=2 + mksession! Xtest_mks.out + source Xtest_mks.out + + call delete('Xtest_mks.out') +endfunc + +" Verify that arglist is stored correctly to the session file. +func Test_mksession_arglist() + argdel * + next file1 file2 file3 file4 + mksession! Xtest_mks.out + source Xtest_mks.out + call assert_equal(['file1', 'file2', 'file3', 'file4'], argv()) + + call delete('Xtest_mks.out') + argdel * +endfunc + + +func Test_mksession_one_buffer_two_windows() + edit Xtest1 + new Xtest2 + split + mksession! Xtest_mks.out + let lines = readfile('Xtest_mks.out') + let count1 = 0 + let count2 = 0 + let count2buf = 0 + for line in lines + if line =~ 'edit \f*Xtest1$' + let count1 += 1 + endif + if line =~ 'edit \f\{-}Xtest2' + let count2 += 1 + endif + if line =~ 'buffer \f\{-}Xtest2' + let count2buf += 1 + endif + endfor + call assert_equal(1, count1, 'Xtest1 count') + call assert_equal(2, count2, 'Xtest2 count') + call assert_equal(2, count2buf, 'Xtest2 buffer count') + + close + bwipe! + call delete('Xtest_mks.out') +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_mksession_utf8.vim b/src/nvim/testdir/test_mksession_utf8.vim new file mode 100644 index 0000000000..8ffbba2a1c --- /dev/null +++ b/src/nvim/testdir/test_mksession_utf8.vim @@ -0,0 +1,105 @@ +" Test for :mksession, :mkview and :loadview in utf-8 encoding + +set encoding=utf-8 +scriptencoding utf-8 + +if !has('multi_byte') || !has('mksession') + finish +endif + +func Test_mksession_utf8() + tabnew + let wrap_save = &wrap + set sessionoptions=buffers splitbelow fileencoding=utf-8 + call setline(1, [ + \ 'start:', + \ 'no multibyte chAracter', + \ ' one leaDing tab', + \ ' four leadinG spaces', + \ 'two consecutive tabs', + \ 'two tabs in one line', + \ 'one … multibyteCharacter', + \ 'a “b” two multiByte characters', + \ '“c”1€ three mulTibyte characters' + \ ]) + let tmpfile = tempname() + exec 'w! ' . tmpfile + /^start: + set wrap + vsplit + norm! j16| + split + norm! j16| + split + norm! j16| + split + norm! j8| + split + norm! j8| + split + norm! j16| + split + norm! j16| + split + norm! j16| + wincmd l + + set nowrap + /^start: + norm! j16|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + norm! j08|3zl + split + norm! j08|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + norm! j016|3zl + split + call wincol() + mksession! test_mks.out + let li = filter(readfile('test_mks.out'), 'v:val =~# "\\(^ *normal! 0\\|^ *exe ''normal!\\)"') + let expected = [ + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 08|', + \ 'normal! 08|', + \ 'normal! 016|', + \ 'normal! 016|', + \ 'normal! 016|', + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", + \ " normal! 08|", + \ " exe 'normal! ' . s:c . '|zs' . 8 . '|'", + \ " normal! 08|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|", + \ " exe 'normal! ' . s:c . '|zs' . 16 . '|'", + \ " normal! 016|" + \ ] + call assert_equal(expected, li) + tabclose! + + 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_nested_function.vim b/src/nvim/testdir/test_nested_function.vim index f881730529..afaaea6ceb 100644 --- a/src/nvim/testdir/test_nested_function.vim +++ b/src/nvim/testdir/test_nested_function.vim @@ -1,32 +1,63 @@ "Tests for nested functions " -function! NestedFunc() - fu! Func1() +func NestedFunc() + func! Func1() let g:text .= 'Func1 ' - endfunction + endfunc call Func1() - fu! s:func2() + func! s:func2() let g:text .= 's:func2 ' - endfunction + endfunc call s:func2() - fu! s:_func3() + func! s:_func3() let g:text .= 's:_func3 ' - endfunction + endfunc call s:_func3() let fn = 'Func4' - fu! {fn}() + func! {fn}() let g:text .= 'Func4 ' - endfunction + endfunc call {fn}() let fn = 'func5' - fu! s:{fn}() + func! s:{fn}() let g:text .= 's:func5' - endfunction + endfunc call s:{fn}() -endfunction +endfunc -function! Test_nested_functions() +func Test_nested_functions() let g:text = '' call NestedFunc() call assert_equal('Func1 s:func2 s:_func3 Func4 s:func5', g:text) endfunction + +func Test_nested_argument() + func g:X() + let g:Y = function('sort') + endfunc + let g:Y = function('sort') + echo g:Y([], g:X()) + delfunc g:X + unlet g:Y +endfunc + +func Recurse(count) + if a:count > 0 + call Recurse(a:count - 1) + endif +endfunc + +func Test_max_nesting() + let call_depth_here = 2 + let ex_depth_here = 5 + set mfd& + + call Recurse(99 - call_depth_here) + call assert_fails('call Recurse(' . (100 - call_depth_here) . ')', 'E132:') + + set mfd=210 + call Recurse(209 - ex_depth_here) + call assert_fails('call Recurse(' . (210 - ex_depth_here) . ')', 'E169:') + + set mfd& +endfunc diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 6261625801..1d15c7f83d 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -1,5 +1,7 @@ " Test for various Normal mode commands +source shared.vim + func! Setup_NewWindow() 10new call setline(1, range(1,100)) @@ -1069,7 +1071,6 @@ func! Test_normal18_z_fold() endfunc func! Test_normal19_z_spell() - throw "skipped: Nvim 'spell' requires download" if !has("spell") || !has('syntax') return endif @@ -1120,6 +1121,7 @@ func! Test_normal19_z_spell() let a=execute('unsilent norm! V$zG') call assert_match("Word '2 goood' added to .*", a) let fname=matchstr(a, 'to\s\+\zs\f\+$') + let fname=Fix_truncated_tmpfile(fname) let cnt=readfile(fname) call assert_equal('2 goood', cnt[0]) @@ -1255,21 +1257,27 @@ func! Test_normal22_zet() " Test for ZZ " let shell = &shell " let &shell = 'sh' - call writefile(['1', '2'], 'Xfile') + + " Remove any stale test files from previous run. + for file in ['Xfile_Test_normal22_zet'] + call delete(file) + endfor + + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') let args = ' --headless -u NONE -N -U NONE -i NONE --noplugins' - call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile') - let a = readfile('Xfile') + call system(v:progpath . args . ' -c "%d" -c ":norm! ZZ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') call assert_equal([], a) " Test for ZQ - call writefile(['1', '2'], 'Xfile') - call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile') - let a = readfile('Xfile') + call writefile(['1', '2'], 'Xfile_Test_normal22_zet') + call system(v:progpath . args . ' -c "%d" -c ":norm! ZQ" Xfile_Test_normal22_zet') + let a = readfile('Xfile_Test_normal22_zet') call assert_equal(['1', '2'], a) - " clean up - for file in ['Xfile'] - call delete(file) - endfor + " Nvim: This sometimes hangs the TSAN build. + " for file in ['Xfile_Test_normal22_zet'] + " call delete(file) + " endfor " let &shell = shell endfunc @@ -2329,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_number.vim b/src/nvim/testdir/test_number.vim new file mode 100644 index 0000000000..59debcea0d --- /dev/null +++ b/src/nvim/testdir/test_number.vim @@ -0,0 +1,254 @@ +" Test for 'number' and 'relativenumber' + +source view_util.vim + +func! s:screen_lines(start, end) abort + return ScreenLines([a:start, a:end], 8) +endfunc + +func! s:compare_lines(expect, actual) + call assert_equal(a:expect, a:actual) +endfunc + +func! s:test_windows(h, w) abort + call NewWindow(a:h, a:w) +endfunc + +func! s:close_windows() abort + call CloseWindow() +endfunc + +func! s:validate_cursor() abort + " update skipcol. + " wincol(): + " f_wincol + " -> validate_cursor + " -> curs_columns + call wincol() +endfunc + +func Test_set_options() + set nu rnu + call assert_equal(1, &nu) + call assert_equal(1, &rnu) + + call s:test_windows(10, 20) + call assert_equal(1, &nu) + call assert_equal(1, &rnu) + call s:close_windows() + + set nu& rnu& +endfunc + +func Test_set_global_and_local() + " setlocal must NOT reset the other global value + set nonu nornu + setglobal nu + setlocal rnu + call assert_equal(1, &g:nu) + + set nonu nornu + setglobal rnu + setlocal nu + call assert_equal(1, &g:rnu) + + " setglobal MUST reset the other global value + set nonu nornu + setglobal nu + setglobal rnu + call assert_equal(1, &g:nu) + + set nonu nornu + setglobal rnu + setglobal nu + call assert_equal(1, &g:rnu) + + " set MUST reset the other global value + set nonu nornu + set nu + set rnu + call assert_equal(1, &g:nu) + + set nonu nornu + set rnu + set nu + call assert_equal(1, &g:rnu) + + set nu& rnu& +endfunc + +func Test_number() + call s:test_windows(10, 20) + call setline(1, ["abcdefghij", "klmnopqrst", "uvwxyzABCD", "EFGHIJKLMN", "OPQRSTUVWX", "YZ"]) + setl number + let lines = s:screen_lines(1, 4) + let expect = [ +\ " 1 abcd", +\ " 2 klmn", +\ " 3 uvwx", +\ " 4 EFGH", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_relativenumber() + call s:test_windows(10, 20) + call setline(1, ["abcdefghij", "klmnopqrst", "uvwxyzABCD", "EFGHIJKLMN", "OPQRSTUVWX", "YZ"]) + 3 + setl relativenumber + let lines = s:screen_lines(1, 6) + let expect = [ +\ " 2 abcd", +\ " 1 klmn", +\ " 0 uvwx", +\ " 1 EFGH", +\ " 2 OPQR", +\ " 3 YZ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_number_with_relativenumber() + call s:test_windows(10, 20) + call setline(1, ["abcdefghij", "klmnopqrst", "uvwxyzABCD", "EFGHIJKLMN", "OPQRSTUVWX", "YZ"]) + 4 + setl number relativenumber + let lines = s:screen_lines(1, 6) + let expect = [ +\ " 3 abcd", +\ " 2 klmn", +\ " 1 uvwx", +\ "4 EFGH", +\ " 1 OPQR", +\ " 2 YZ ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_number_with_linewrap1() + call s:test_windows(3, 20) + normal! 61ia + setl number wrap + call s:validate_cursor() + let lines = s:screen_lines(1, 3) + let expect = [ +\ "--1 aaaa", +\ " aaaa", +\ " aaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI +func XTest_number_with_linewrap2() + call s:test_windows(3, 20) + normal! 61ia + setl number wrap + call s:validate_cursor() + 0 + call s:validate_cursor() + let lines = s:screen_lines(1, 3) + let expect = [ +\ " 1 aaaa", +\ " aaaa", +\ " aaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI +func XTest_number_with_linewrap3() + call s:test_windows(4, 20) + normal! 81ia + setl number wrap + call s:validate_cursor() + setl nonumber + call s:validate_cursor() + let lines = s:screen_lines(1, 4) + let expect = [ +\ "aaaaaaaa", +\ "aaaaaaaa", +\ "aaaaaaaa", +\ "a ", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_numberwidth() + call s:test_windows(10, 20) + call setline(1, repeat(['aaaa'], 10)) + setl number numberwidth=6 + let lines = s:screen_lines(1, 3) + let expect = [ +\ " 1 aa", +\ " 2 aa", +\ " 3 aa", +\ ] + call s:compare_lines(expect, lines) + + set relativenumber + let lines = s:screen_lines(1, 3) + let expect = [ +\ "1 aa", +\ " 1 aa", +\ " 2 aa", +\ ] + call s:compare_lines(expect, lines) + + set nonumber + let lines = s:screen_lines(1, 3) + let expect = [ +\ " 0 aa", +\ " 1 aa", +\ " 2 aa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc + +func Test_numberwidth_adjusted() + call s:test_windows(10, 20) + call setline(1, repeat(['aaaa'], 10000)) + setl number numberwidth=4 + let lines = s:screen_lines(1, 3) + let expect = [ +\ " 1 aa", +\ " 2 aa", +\ " 3 aa", +\ ] + call s:compare_lines(expect, lines) + + $ + let lines = s:screen_lines(8, 10) + let expect = [ +\ " 9998 aa", +\ " 9999 aa", +\ "10000 aa", +\ ] + call s:compare_lines(expect, lines) + + setl relativenumber + let lines = s:screen_lines(8, 10) + let expect = [ +\ " 2 aa", +\ " 1 aa", +\ "10000 aa", +\ ] + call s:compare_lines(expect, lines) + + setl nonumber + let lines = s:screen_lines(8, 10) + let expect = [ +\ " 2 aaaa", +\ " 1 aaaa", +\ " 0 aaaa", +\ ] + call s:compare_lines(expect, lines) + call s:close_windows() +endfunc diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 5ee0919e18..a15d15213a 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -13,6 +13,12 @@ function! Test_whichwrap() set whichwrap+=h,l call assert_equal('b,s,h,l', &whichwrap) + set whichwrap=h,h + call assert_equal('h', &whichwrap) + + set whichwrap=h,h,h + call assert_equal('h', &whichwrap) + set whichwrap& endfunction @@ -97,3 +103,133 @@ func Test_keymap_valid() call assert_fails(":set kmp=trunc\x00name", "E544:") call assert_fails(":set kmp=trunc\x00name", "trunc") endfunc + +func Check_dir_option(name) + " Check that it's possible to set the option. + exe 'set ' . a:name . '=/usr/share/dict/words' + call assert_equal('/usr/share/dict/words', eval('&' . a:name)) + exe 'set ' . a:name . '=/usr/share/dict/words,/and/there' + call assert_equal('/usr/share/dict/words,/and/there', eval('&' . a:name)) + exe 'set ' . a:name . '=/usr/share/dict\ words' + call assert_equal('/usr/share/dict words', eval('&' . a:name)) + + " Check rejecting weird characters. + call assert_fails("set " . a:name . "=/not&there", "E474:") + call assert_fails("set " . a:name . "=/not>there", "E474:") + call assert_fails("set " . a:name . "=/not.*there", "E474:") +endfunc + +func Test_cinkeys() + " This used to cause invalid memory access + set cindent cinkeys=0 + norm a + set cindent& cinkeys& +endfunc + +func Test_dictionary() + call Check_dir_option('dictionary') +endfunc + +func Test_thesaurus() + call Check_dir_option('thesaurus') +endfun + +func Test_set_completion() + call feedkeys(":set di\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set dictionary diff diffexpr diffopt digraph directory display', @:) + + " Expand boolan options. When doing :set no<Tab> + " vim displays the options names without "no" but completion uses "no...". + call feedkeys(":set nodi\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set nodiff digraph', @:) + + call feedkeys(":set invdi\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set invdiff digraph', @:) + + " Expand abbreviation of options. + call feedkeys(":set ts\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set tabstop thesaurus', @:) + + " Expand current value + call feedkeys(":set fileencodings=\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set fileencodings=ucs-bom,utf-8,default,latin1', @:) + + call feedkeys(":set fileencodings:\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set fileencodings:ucs-bom,utf-8,default,latin1', @:) + + " Expand directories. + call feedkeys(":set cdpath=./\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('./samples/ ', @:) + call assert_notmatch('./small.vim ', @:) + + " Expand files and directories. + call feedkeys(":set tags=./\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('./samples/ ./sautest/ ./setup.vim ./shared.vim', @:) + + call feedkeys(":set tags=./\\\\ dif\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"set tags=./\\ diff diffexpr diffopt', @:) +endfunc + +func Test_set_errors() + call assert_fails('set scroll=-1', 'E49:') + call assert_fails('set backupcopy=', 'E474:') + call assert_fails('set regexpengine=3', 'E474:') + call assert_fails('set history=10001', 'E474:') + call assert_fails('set numberwidth=11', 'E474:') + call assert_fails('set colorcolumn=-a') + call assert_fails('set colorcolumn=a') + call assert_fails('set colorcolumn=1,') + call assert_fails('set cmdheight=-1', 'E487:') + call assert_fails('set cmdwinheight=-1', 'E487:') + if has('conceal') + call assert_fails('set conceallevel=-1', 'E487:') + call assert_fails('set conceallevel=4', 'E474:') + endif + call assert_fails('set helpheight=-1', 'E487:') + call assert_fails('set history=-1', 'E487:') + call assert_fails('set report=-1', 'E487:') + call assert_fails('set shiftwidth=-1', 'E487:') + call assert_fails('set sidescroll=-1', 'E487:') + call assert_fails('set tabstop=-1', 'E487:') + call assert_fails('set textwidth=-1', 'E487:') + call assert_fails('set timeoutlen=-1', 'E487:') + call assert_fails('set updatecount=-1', 'E487:') + call assert_fails('set updatetime=-1', 'E487:') + call assert_fails('set winheight=-1', 'E487:') + call assert_fails('set tabstop!', 'E488:') + call assert_fails('set xxx', 'E518:') + call assert_fails('set beautify?', 'E518:') + call assert_fails('set undolevels=x', 'E521:') + call assert_fails('set tabstop=', 'E521:') + call assert_fails('set comments=-', 'E524:') + call assert_fails('set comments=a', 'E525:') + call assert_fails('set foldmarker=x', 'E536:') + call assert_fails('set commentstring=x', 'E537:') + call assert_fails('set complete=x', 'E539:') + call assert_fails('set statusline=%{', 'E540:') + call assert_fails('set statusline=' . repeat("%p", 81), 'E541:') + call assert_fails('set statusline=%(', 'E542:') + if has('cursorshape') + " This invalid value for 'guicursor' used to cause Vim to crash. + call assert_fails('set guicursor=i-ci,r-cr:h', 'E545:') + call assert_fails('set guicursor=i-ci', 'E545:') + call assert_fails('set guicursor=x', 'E545:') + call assert_fails('set guicursor=r-cr:horx', 'E548:') + call assert_fails('set guicursor=r-cr:hor0', 'E549:') + endif + call assert_fails('set backupext=~ patchmode=~', 'E589:') + call assert_fails('set winminheight=10 winheight=9', 'E591:') + call assert_fails('set winminwidth=10 winwidth=9', 'E592:') + call assert_fails("set showbreak=\x01", 'E595:') + call assert_fails('set t_foo=', 'E846:') +endfunc + +func Test_complete() + " Trailing single backslash used to cause invalid memory access. + set complete=s\ + new + call feedkeys("i\<C-N>\<Esc>", 'xt') + bwipe! + set complete& +endfun + diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 519d855cd8..f5bdd717dd 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -7,10 +7,10 @@ func! ListMonths() if g:setting != '' exe ":set" g:setting endif - let mth=copy(g:months) + let mth = copy(g:months) let entered = strcharpart(getline('.'),0,col('.')) if !empty(entered) - let mth=filter(mth, 'v:val=~"^".entered') + let mth = filter(mth, 'v:val=~"^".entered') endif call complete(1, mth) return '' @@ -468,7 +468,7 @@ endfunc " auto-wrap text. func Test_completion_ctrl_e_without_autowrap() new - let tw_save=&tw + let tw_save = &tw set tw=78 let li = [ \ '" zzz', @@ -478,7 +478,7 @@ func Test_completion_ctrl_e_without_autowrap() call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx") call assert_equal(li, getline(1, '$')) - let &tw=tw_save + let &tw = tw_save q! endfunc @@ -541,4 +541,71 @@ func Test_completion_comment_formatting() bwipe! endfunc +function! DummyCompleteSix() + call complete(1, ['Hello', 'World']) + return '' +endfunction + +" complete() correctly clears the list of autocomplete candidates +func Test_completion_clear_candidate_list() + new + %d + " select first entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx") + call assert_equal('Hello', getline(1)) + %d + " select second entry from the completion popup + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx") + call assert_equal('World', getline(1)) + %d + " select original text + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx") + call assert_equal(' xxx', getline(1)) + %d + " back at first entry from completion list + call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx") + call assert_equal('Hello', getline(1)) + + bw! +endfunc + + +func Test_popup_and_preview_autocommand() + " This used to crash Vim + if !has('python') + return + endif + let h = winheight(0) + if h < 15 + return + endif + new + augroup MyBufAdd + au! + au BufAdd * nested tab sball + augroup END + set omnifunc=pythoncomplete#Complete + call setline(1, 'import os') + " make the line long + 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", 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) + norm! gt + call assert_equal(0, &previewwindow) + norm! gT + call assert_equal(12, tabpagenr('$')) + tabonly + pclose + augroup MyBufAdd + au! + augroup END + augroup! MyBufAdd + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim new file mode 100644 index 0000000000..4cbd800da5 --- /dev/null +++ b/src/nvim/testdir/test_profile.vim @@ -0,0 +1,183 @@ +" Test Vim profiler +if !has('profile') + finish +endif + +func Test_profile_func() + let lines = [ + \ "func! Foo1()", + \ "endfunc", + \ "func! Foo2()", + \ " let l:count = 100", + \ " while l:count > 0", + \ " let l:count = l:count - 1", + \ " endwhile", + \ "endfunc", + \ "func! Foo3()", + \ "endfunc", + \ "func! Bar()", + \ "endfunc", + \ "call Foo1()", + \ "call Foo1()", + \ "profile pause", + \ "call Foo1()", + \ "profile continue", + \ "call Foo2()", + \ "call Foo3()", + \ "call Bar()", + \ "if !v:profiling", + \ " delfunc Foo2", + \ "endif", + \ "delfunc Foo3", + \ ] + + call writefile(lines, 'Xprofile_func.vim') + call system(v:progpath + \ . ' -es -u NONE -U NONE -i NONE --noplugin' + \ . ' -c "profile start Xprofile_func.log"' + \ . ' -c "profile func Foo*"' + \ . ' -c "so Xprofile_func.vim"' + \ . ' -c "qall!"') + call assert_equal(0, v:shell_error) + + let lines = readfile('Xprofile_func.log') + + " - Foo1() is called 3 times but should be reported as called twice + " since one call is in between "profile pause" .. "profile continue". + " - Foo2() should come before Foo1() since Foo1() does much more work. + " - Foo3() is not reported because function is deleted. + " - Unlike Foo3(), Foo2() should not be deleted since there is a check + " for v:profiling. + " - Bar() is not reported since it does not match "profile func Foo*". + call assert_equal(28, len(lines)) + + call assert_equal('FUNCTION Foo1()', lines[0]) + call assert_equal('Called 2 times', lines[1]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3]) + call assert_equal('', lines[4]) + call assert_equal('count total (s) self (s)', lines[5]) + call assert_equal('', lines[6]) + call assert_equal('FUNCTION Foo2()', lines[7]) + call assert_equal('Called 1 time', lines[8]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[9]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[10]) + call assert_equal('', lines[11]) + call assert_equal('count total (s) self (s)', lines[12]) + call assert_match('^\s*1\s\+.*\slet l:count = 100$', lines[13]) + call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[14]) + call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[15]) + call assert_match('^\s*100\s\+.*\sendwhile$', lines[16]) + call assert_equal('', lines[17]) + call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[18]) + call assert_equal('count total (s) self (s) function', lines[19]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[20]) + call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[21]) + call assert_equal('', lines[22]) + call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[23]) + call assert_equal('count total (s) self (s) function', lines[24]) + call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[25]) + call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[26]) + call assert_equal('', lines[27]) + + call delete('Xprofile_func.vim') + call delete('Xprofile_func.log') +endfunc + +func Test_profile_file() + let lines = [ + \ 'func! Foo()', + \ 'endfunc', + \ 'for i in range(10)', + \ ' " a comment', + \ ' call Foo()', + \ 'endfor', + \ 'call Foo()', + \ ] + + call writefile(lines, 'Xprofile_file.vim') + call system(v:progpath + \ . ' -es -u NONE -U NONE -i NONE --noplugin' + \ . ' -c "profile start Xprofile_file.log"' + \ . ' -c "profile file Xprofile_file.vim"' + \ . ' -c "so Xprofile_file.vim"' + \ . ' -c "so Xprofile_file.vim"' + \ . ' -c "qall!"') + call assert_equal(0, v:shell_error) + + let lines = readfile('Xprofile_file.log') + + call assert_equal(14, len(lines)) + + call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0]) + call assert_equal('Sourced 2 times', lines[1]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3]) + call assert_equal('', lines[4]) + call assert_equal('count total (s) self (s)', lines[5]) + call assert_match(' 2 0.\d\+ func! Foo()', lines[6]) + call assert_equal(' endfunc', lines[7]) + " Loop iterates 10 times. Since script runs twice, body executes 20 times. + " First line of loop executes one more time than body to detect end of loop. + call assert_match('^\s*22\s\+\d\+\.\d\+\s\+for i in range(10)$', lines[8]) + call assert_equal(' " a comment', lines[9]) + " if self and total are equal we only get one number + call assert_match('^\s*20\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[10]) + call assert_match('^\s*20\s\+\d\+\.\d\+\s\+endfor$', lines[11]) + " if self and total are equal we only get one number + call assert_match('^\s*2\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[12]) + call assert_equal('', lines[13]) + + call delete('Xprofile_file.vim') + call delete('Xprofile_file.log') +endfunc + +func Test_profile_file_with_cont() + let lines = [ + \ 'echo "hello', + \ ' \ world"', + \ 'echo "foo ', + \ ' \bar"', + \ ] + + call writefile(lines, 'Xprofile_file.vim') + call system(v:progpath + \ . ' -es -u NONE -U NONE -i NONE --noplugin' + \ . ' -c "profile start Xprofile_file.log"' + \ . ' -c "profile file Xprofile_file.vim"' + \ . ' -c "so Xprofile_file.vim"' + \ . ' -c "qall!"') + call assert_equal(0, v:shell_error) + + let lines = readfile('Xprofile_file.log') + call assert_equal(11, len(lines)) + + call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0]) + call assert_equal('Sourced 1 time', lines[1]) + call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2]) + call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3]) + call assert_equal('', lines[4]) + call assert_equal('count total (s) self (s)', lines[5]) + call assert_match(' 1 0.\d\+ echo "hello', lines[6]) + call assert_equal(' \ world"', lines[7]) + call assert_match(' 1 0.\d\+ echo "foo ', lines[8]) + call assert_equal(' \bar"', lines[9]) + call assert_equal('', lines[10]) + + call delete('Xprofile_file.vim') + call delete('Xprofile_file.log') +endfunc + +func Test_profile_completion() + call feedkeys(":profile \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"profile continue dump file func pause start stop', @:) + + call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('^"profile start.* test_profile\.vim', @:) +endfunc + +func Test_profile_errors() + call assert_fails("profile func Foo", 'E750:') + call assert_fails("profile pause", 'E750:') + call assert_fails("profile continue", 'E750:') +endfunc diff --git a/src/nvim/testdir/test_put.vim b/src/nvim/testdir/test_put.vim new file mode 100644 index 0000000000..38c812bc9c --- /dev/null +++ b/src/nvim/testdir/test_put.vim @@ -0,0 +1,36 @@ + +func Test_put_block() + if !has('multi_byte') + return + endif + new + call feedkeys("i\<C-V>u2500\<CR>x\<ESC>", 'x') + call feedkeys("\<C-V>y", 'x') + call feedkeys("gg0p", 'x') + call assert_equal("\u2500x", getline(1)) + bwipe! +endfunc + +func Test_put_char_block() + new + call setline(1, ['Line 1', 'Line 2']) + f Xfile_put + " visually select both lines and put the cursor at the top of the visual + " selection and then put the buffer name over it + exe "norm! G0\<c-v>ke\"%p" + call assert_equal(['Xfile_put 1', 'Xfile_put 2'], getline(1,2)) + bw! +endfunc + +func Test_put_char_block2() + new + let a = [ getreg('a'), getregtype('a') ] + call setreg('a', ' one ', 'v') + call setline(1, ['Line 1', '', 'Line 3', '']) + " visually select the first 3 lines and put register a over it + exe "norm! ggl\<c-v>2j2l\"ap" + call assert_equal(['L one 1', '', 'L one 3', ''], getline(1,4)) + " clean up + bw! + call setreg('a', a[0], a[1]) +endfunc diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 75ab01f013..dd177fd633 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -6,7 +6,7 @@ endif set encoding=utf-8 -function! s:setup_commands(cchar) +func s:setup_commands(cchar) if a:cchar == 'c' command! -nargs=* -bang Xlist <mods>clist<bang> <args> command! -nargs=* Xgetexpr <mods>cgetexpr <args> @@ -24,19 +24,21 @@ function! s:setup_commands(cchar) command! -nargs=* Xgetbuffer <mods>cgetbuffer <args> command! -nargs=* Xaddbuffer <mods>caddbuffer <args> command! -nargs=* Xrewind <mods>crewind <args> - command! -nargs=* -bang Xnext <mods>cnext<bang> <args> - command! -nargs=* -bang Xprev <mods>cprev<bang> <args> + command! -count -nargs=* -bang Xnext <mods><count>cnext<bang> <args> + command! -count -nargs=* -bang Xprev <mods><count>cprev<bang> <args> command! -nargs=* -bang Xfirst <mods>cfirst<bang> <args> command! -nargs=* -bang Xlast <mods>clast<bang> <args> command! -nargs=* -bang Xnfile <mods>cnfile<bang> <args> command! -nargs=* -bang Xpfile <mods>cpfile<bang> <args> command! -nargs=* Xexpr <mods>cexpr <args> - command! -nargs=* Xvimgrep <mods>vimgrep <args> + command! -range -nargs=* Xvimgrep <mods><count>vimgrep <args> + command! -nargs=* Xvimgrepadd <mods>vimgrepadd <args> command! -nargs=* Xgrep <mods> grep <args> command! -nargs=* Xgrepadd <mods> grepadd <args> command! -nargs=* Xhelpgrep helpgrep <args> let g:Xgetlist = function('getqflist') let g:Xsetlist = function('setqflist') + call setqflist([], 'f') else command! -nargs=* -bang Xlist <mods>llist<bang> <args> command! -nargs=* Xgetexpr <mods>lgetexpr <args> @@ -54,26 +56,31 @@ function! s:setup_commands(cchar) command! -nargs=* Xgetbuffer <mods>lgetbuffer <args> command! -nargs=* Xaddbuffer <mods>laddbuffer <args> command! -nargs=* Xrewind <mods>lrewind <args> - command! -nargs=* -bang Xnext <mods>lnext<bang> <args> - command! -nargs=* -bang Xprev <mods>lprev<bang> <args> + command! -count -nargs=* -bang Xnext <mods><count>lnext<bang> <args> + command! -count -nargs=* -bang Xprev <mods><count>lprev<bang> <args> command! -nargs=* -bang Xfirst <mods>lfirst<bang> <args> command! -nargs=* -bang Xlast <mods>llast<bang> <args> command! -nargs=* -bang Xnfile <mods>lnfile<bang> <args> command! -nargs=* -bang Xpfile <mods>lpfile<bang> <args> command! -nargs=* Xexpr <mods>lexpr <args> - command! -nargs=* Xvimgrep <mods>lvimgrep <args> + command! -range -nargs=* Xvimgrep <mods><count>lvimgrep <args> + command! -nargs=* Xvimgrepadd <mods>lvimgrepadd <args> command! -nargs=* Xgrep <mods> lgrep <args> command! -nargs=* Xgrepadd <mods> lgrepadd <args> command! -nargs=* Xhelpgrep lhelpgrep <args> let g:Xgetlist = function('getloclist', [0]) let g:Xsetlist = function('setloclist', [0]) + call setloclist(0, [], 'f') endif -endfunction +endfunc " Tests for the :clist and :llist commands -function XlistTests(cchar) +func XlistTests(cchar) call s:setup_commands(a:cchar) + if a:cchar == 'l' + call assert_fails('llist', 'E776:') + endif " With an empty list, command should return error Xgetexpr [] silent! Xlist @@ -85,62 +92,68 @@ function XlistTests(cchar) \ 'non-error 3', 'Xtestfile3:3:1:Line3'] " List only valid entries - redir => result - Xlist - redir END - let l = split(result, "\n") + let l = split(execute('Xlist', ''), "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', \ ' 4 Xtestfile2:2 col 2: Line2', \ ' 6 Xtestfile3:3 col 1: Line3'], l) " List all the entries - redir => result - Xlist! - redir END - let l = split(result, "\n") + let l = split(execute('Xlist!', ''), "\n") call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2', \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l) " List a range of errors - redir => result - Xlist 3,6 - redir END - let l = split(result, "\n") + let l = split(execute('Xlist 3,6', ''), "\n") call assert_equal([' 4 Xtestfile2:2 col 2: Line2', \ ' 6 Xtestfile3:3 col 1: Line3'], l) - redir => result - Xlist! 3,4 - redir END - let l = split(result, "\n") + let l = split(execute('Xlist! 3,4', ''), "\n") call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) - redir => result - Xlist -6,-4 - redir END - let l = split(result, "\n") + let l = split(execute('Xlist -6,-4', ''), "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) - redir => result - Xlist! -5,-3 - redir END - let l = split(result, "\n") + let l = split(execute('Xlist! -5,-3', ''), "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + + " Test for '+' + let l = split(execute('Xlist! +2', ''), "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) -endfunction -function Test_clist() + " Different types of errors + call g:Xsetlist([{'lnum':10,'col':5,'type':'W', 'text':'Warning','nr':11}, + \ {'lnum':20,'col':10,'type':'e','text':'Error','nr':22}, + \ {'lnum':30,'col':15,'type':'i','text':'Info','nr':33}, + \ {'lnum':40,'col':20,'type':'x', 'text':'Other','nr':44}, + \ {'lnum':50,'col':25,'type':"\<C-A>",'text':'one','nr':55}]) + let l = split(execute('Xlist', ""), "\n") + call assert_equal([' 1:10 col 5 warning 11: Warning', + \ ' 2:20 col 10 error 22: Error', + \ ' 3:30 col 15 info 33: Info', + \ ' 4:40 col 20 x 44: Other', + \ ' 5:50 col 25 55: one'], l) + + " Error cases + call assert_fails('Xlist abc', 'E488:') +endfunc + +func Test_clist() call XlistTests('c') call XlistTests('l') -endfunction +endfunc " Tests for the :colder, :cnewer, :lolder and :lnewer commands " Note that this test assumes that a quickfix/location list is " already set by the caller. -function XageTests(cchar) +func XageTests(cchar) call s:setup_commands(a:cchar) + let list = [{'bufnr': bufnr('%'), 'lnum': 1}] + call g:Xsetlist(list) + " Jumping to a non existent list should return error silent! Xolder 99 call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') @@ -171,22 +184,23 @@ function XageTests(cchar) Xnewer 2 let l = g:Xgetlist() call assert_equal('Line3', l[0].text) -endfunction +endfunc -function Test_cage() - let list = [{'bufnr': 1, 'lnum': 1}] - call setqflist(list) +func Test_cage() call XageTests('c') - - call setloclist(0, list) call XageTests('l') -endfunction +endfunc " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen " commands -function XwindowTests(cchar) +func XwindowTests(cchar) call s:setup_commands(a:cchar) + " Opening the location list window without any errors should fail + if a:cchar == 'l' + call assert_fails('lopen', 'E776:') + endif + " Create a list with no valid entries Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3'] @@ -227,16 +241,29 @@ function XwindowTests(cchar) " Calling cwindow should close the quickfix window with no valid errors Xwindow call assert_true(winnr('$') == 1) -endfunction -function Test_cwindow() + if a:cchar == 'c' + " Opening the quickfix window in multiple tab pages should reuse the + " quickfix buffer + Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', + \ 'Xtestfile3:3:1:Line3'] + Xopen + let qfbufnum = bufnr('%') + tabnew + Xopen + call assert_equal(qfbufnum, bufnr('%')) + new | only | tabonly + endif +endfunc + +func Test_cwindow() call XwindowTests('c') call XwindowTests('l') -endfunction +endfunc " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile " commands. -function XfileTests(cchar) +func XfileTests(cchar) call s:setup_commands(a:cchar) call writefile(['Xtestfile1:700:10:Line 700', @@ -275,16 +302,16 @@ function XfileTests(cchar) \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') call delete('Xqftestfile1') -endfunction +endfunc -function Test_cfile() +func Test_cfile() call XfileTests('c') call XfileTests('l') -endfunction +endfunc " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and " :lgetbuffer commands. -function XbufferTests(cchar) +func XbufferTests(cchar) call s:setup_commands(a:cchar) enew! @@ -316,35 +343,61 @@ function XbufferTests(cchar) \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') enew! -endfunction + " Check for invalid buffer + call assert_fails('Xbuffer 199', 'E474:') -function Test_cbuffer() + " Check for unloaded buffer + edit Xtestfile1 + let bnr = bufnr('%') + enew! + call assert_fails('Xbuffer ' . bnr, 'E681:') + + " Check for invalid range + " Using Xbuffer will not run the range check in the cbuffer/lbuffer + " commands. So directly call the commands. + if (a:cchar == 'c') + call assert_fails('900,999cbuffer', 'E16:') + else + call assert_fails('900,999lbuffer', 'E16:') + endif +endfunc + +func Test_cbuffer() call XbufferTests('c') call XbufferTests('l') -endfunction +endfunc -function XexprTests(cchar) +func XexprTests(cchar) call s:setup_commands(a:cchar) call assert_fails('Xexpr 10', 'E777:') -endfunction +endfunc -function Test_cexpr() +func Test_cexpr() call XexprTests('c') call XexprTests('l') -endfunction +endfunc " Tests for :cnext, :cprev, :cfirst, :clast commands -function Xtest_browse(cchar) +func Xtest_browse(cchar) call s:setup_commands(a:cchar) + " Jumping to first or next location list entry without any error should + " result in failure + if a:cchar == 'l' + call assert_fails('lfirst', 'E776:') + call assert_fails('lnext', 'E776:') + endif + call s:create_test_file('Xqftestfile1') call s:create_test_file('Xqftestfile2') Xgetexpr ['Xqftestfile1:5:Line5', \ 'Xqftestfile1:6:Line6', \ 'Xqftestfile2:10:Line10', - \ 'Xqftestfile2:11:Line11'] + \ 'Xqftestfile2:11:Line11', + \ 'RegularLine1', + \ 'RegularLine2'] Xfirst call assert_fails('Xprev', 'E553') @@ -356,6 +409,7 @@ function Xtest_browse(cchar) call assert_equal('Xqftestfile1', bufname('%')) call assert_equal(6, line('.')) Xlast + Xprev call assert_equal('Xqftestfile2', bufname('%')) call assert_equal(11, line('.')) call assert_fails('Xnext', 'E553') @@ -364,16 +418,26 @@ function Xtest_browse(cchar) call assert_equal('Xqftestfile1', bufname('%')) call assert_equal(5, line('.')) + 10Xnext + call assert_equal('Xqftestfile2', bufname('%')) + call assert_equal(11, line('.')) + 10Xprev + call assert_equal('Xqftestfile1', bufname('%')) + call assert_equal(5, line('.')) + + Xexpr "" + call assert_fails('Xnext', 'E42:') + call delete('Xqftestfile1') call delete('Xqftestfile2') -endfunction +endfunc -function Test_browse() +func Test_browse() call Xtest_browse('c') call Xtest_browse('l') -endfunction +endfunc -function! s:test_xhelpgrep(cchar) +func s:test_xhelpgrep(cchar) call s:setup_commands(a:cchar) Xhelpgrep quickfix Xopen @@ -383,11 +447,35 @@ function! s:test_xhelpgrep(cchar) let title_text = ':lhelpgrep quickfix' endif call assert_true(w:quickfix_title =~ title_text, w:quickfix_title) + + " Jumping to a help topic should open the help window + only + Xnext + call assert_true(&buftype == 'help') + call assert_true(winnr('$') == 2) + " Jumping to the next match should reuse the help window + Xnext + call assert_true(&buftype == 'help') + call assert_true(winnr() == 1) + call assert_true(winnr('$') == 2) + " Jumping to the next match from the quickfix window should reuse the help + " window + Xopen + Xnext + call assert_true(&buftype == 'help') + call assert_true(winnr() == 1) + call assert_true(winnr('$') == 2) + " This wipes out the buffer, make sure that doesn't cause trouble. Xclose -endfunction -function Test_helpgrep() + new | only + + " Search for non existing help string + call assert_fails('Xhelpgrep a1b2c3', 'E480:') +endfunc + +func Test_helpgrep() call s:test_xhelpgrep('c') helpclose call s:test_xhelpgrep('l') @@ -425,7 +513,7 @@ func Test_vimgreptitle() augroup! QfBufWinEnter endfunc -function XqfTitleTests(cchar) +func XqfTitleTests(cchar) call s:setup_commands(a:cchar) Xgetexpr ['file:1:1:message'] @@ -444,16 +532,16 @@ function XqfTitleTests(cchar) endif call assert_equal(title, w:quickfix_title) Xclose -endfunction +endfunc " Tests for quickfix window's title -function Test_qf_title() +func Test_qf_title() call XqfTitleTests('c') call XqfTitleTests('l') -endfunction +endfunc " Tests for 'errorformat' -function Test_efm() +func Test_efm() let save_efm = &efm set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%# cgetexpr ['WWWW', 'EEEE', 'CCCC'] @@ -466,7 +554,7 @@ function Test_efm() let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l) let &efm = save_efm -endfunction +endfunc " This will test for problems in quickfix: " A. incorrectly copying location lists which caused the location list to show @@ -477,7 +565,7 @@ endfunction " window it belongs to. " " Set up the test environment: -function! ReadTestProtocol(name) +func ReadTestProtocol(name) let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') let word = substitute(base, '\v(.*)\..*', '\1', '') @@ -496,9 +584,9 @@ function! ReadTestProtocol(name) setl nomodifiable setl readonly exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '') -endfunction +endfunc -function Test_locationlist() +func Test_locationlist() enew augroup testgroup @@ -521,10 +609,7 @@ function Test_locationlist() lrewind enew lopen - lnext - lnext - lnext - lnext + 4lnext vert split wincmd L lopen @@ -578,15 +663,15 @@ function Test_locationlist() wincmd n | only augroup! testgroup -endfunction +endfunc -function Test_locationlist_curwin_was_closed() +func Test_locationlist_curwin_was_closed() augroup testgroup au! autocmd BufReadCmd test_curwin.txt call R(expand("<amatch>")) augroup END - function! R(n) + func! R(n) quit endfunc @@ -597,9 +682,9 @@ function Test_locationlist_curwin_was_closed() call assert_fails('lrewind', 'E924:') augroup! testgroup -endfunction +endfunc -function Test_locationlist_cross_tab_jump() +func Test_locationlist_cross_tab_jump() call writefile(['loclistfoo'], 'loclistfoo') call writefile(['loclistbar'], 'loclistbar') set switchbuf=usetab @@ -613,10 +698,10 @@ function Test_locationlist_cross_tab_jump() set switchbuf&vim call delete('loclistfoo') call delete('loclistbar') -endfunction +endfunc " More tests for 'errorformat' -function! Test_efm1() +func Test_efm1() if !has('unix') " The 'errorformat' setting is different on non-Unix systems. " This test works only on Unix-like systems. @@ -734,10 +819,10 @@ function! Test_efm1() call delete('Xerrorfile1') call delete('Xerrorfile2') call delete('Xtestfile') -endfunction +endfunc " Test for quickfix directory stack support -function! s:dir_stack_tests(cchar) +func s:dir_stack_tests(cchar) call s:setup_commands(a:cchar) let save_efm=&efm @@ -779,10 +864,10 @@ function! s:dir_stack_tests(cchar) call assert_equal(5, qf[11].lnum) let &efm=save_efm -endfunction +endfunc " Tests for %D and %X errorformat options -function! Test_efm_dirstack() +func Test_efm_dirstack() " Create the directory stack and files call mkdir('dir1') call mkdir('dir1/a') @@ -814,10 +899,33 @@ function! Test_efm_dirstack() call delete('dir1', 'rf') call delete('dir2', 'rf') call delete('habits1.txt') -endfunction +endfunc + +" Test for resync after continuing an ignored message +func Xefm_ignore_continuations(cchar) + call s:setup_commands(a:cchar) + + let save_efm = &efm + + let &efm = + \ '%Eerror %m %l,' . + \ '%-Wignored %m %l,' . + \ '%+Cmore ignored %m %l,' . + \ '%Zignored end' + Xgetexpr ['ignored warning 1', 'more ignored continuation 2', 'ignored end', 'error resync 4'] + let l = map(g:Xgetlist(), '[v:val.text, v:val.valid, v:val.lnum, v:val.type]') + call assert_equal([['resync', 1, 4, 'E']], l) + + let &efm = save_efm +endfunc + +func Test_efm_ignore_continuations() + call Xefm_ignore_continuations('c') + call Xefm_ignore_continuations('l') +endfunc " Tests for invalid error format specifies -function Xinvalid_efm_Tests(cchar) +func Xinvalid_efm_Tests(cchar) call s:setup_commands(a:cchar) let save_efm = &efm @@ -850,17 +958,17 @@ function Xinvalid_efm_Tests(cchar) call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:') let &efm = save_efm -endfunction +endfunc -function Test_invalid_efm() +func Test_invalid_efm() call Xinvalid_efm_Tests('c') call Xinvalid_efm_Tests('l') -endfunction +endfunc " TODO: " Add tests for the following formats in 'errorformat' " %r %O -function! Test_efm2() +func Test_efm2() let save_efm = &efm " Test for %s format in efm @@ -870,30 +978,44 @@ function! Test_efm2() call assert_equal(l[0].pattern, '^\VLine search text\$') call assert_equal(l[0].lnum, 0) + let l = split(execute('clist', ''), "\n") + call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l) + " Test for %P, %Q and %t format specifiers let lines=["[Xtestfile1]", \ "(1,17) error: ';' missing", \ "(21,2) warning: variable 'z' not defined", \ "(67,3) error: end of file found before string ended", + \ "--", \ "", \ "[Xtestfile2]", + \ "--", \ "", \ "[Xtestfile3]", \ "NEW compiler v1.1", \ "(2,2) warning: variable 'x' not defined", - \ "(67,3) warning: 's' already defined" + \ "(67,3) warning: 's' already defined", + \ "--" \] - set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q + set efm=%+P[%f]%r,(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%+Q--%r + " To exercise the push/pop file functionality in quickfix, the test files + " need to be created. + call writefile(['Line1'], 'Xtestfile1') + call writefile(['Line2'], 'Xtestfile2') + call writefile(['Line3'], 'Xtestfile3') cexpr "" for l in lines caddexpr l endfor let l = getqflist() - call assert_equal(9, len(l)) + call assert_equal(12, len(l)) call assert_equal(21, l[2].lnum) call assert_equal(2, l[2].col) call assert_equal('w', l[2].type) call assert_equal('e', l[3].type) + call delete('Xtestfile1') + call delete('Xtestfile2') + call delete('Xtestfile3') " Tests for %E, %C and %Z format specifiers let lines = ["Error 275", @@ -945,20 +1067,39 @@ function! Test_efm2() call assert_equal(1, l[4].valid) call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) + " The following sequence of commands used to crash Vim + set efm=%W%m + cgetexpr ['msg1'] + let l = getqflist() + call assert_equal(1, len(l), string(l)) + call assert_equal('msg1', l[0].text) + set efm=%C%m + lexpr 'msg2' + let l = getloclist(0) + call assert_equal(1, len(l), string(l)) + call assert_equal('msg2', l[0].text) + lopen + call setqflist([], 'r') + caddbuf + let l = getqflist() + call assert_equal(1, len(l), string(l)) + call assert_equal('|| msg2', l[0].text) + + new | only let &efm = save_efm -endfunction +endfunc -function XquickfixChangedByAutocmd(cchar) +func XquickfixChangedByAutocmd(cchar) call s:setup_commands(a:cchar) if a:cchar == 'c' let ErrorNr = 'E925' - function! ReadFunc() + func! ReadFunc() colder cgetexpr [] endfunc else let ErrorNr = 'E926' - function! ReadFunc() + func! ReadFunc() lolder lgetexpr [] endfunc @@ -981,10 +1122,10 @@ function XquickfixChangedByAutocmd(cchar) augroup! testgroup endfunc -function Test_quickfix_was_changed_by_autocmd() +func Test_quickfix_was_changed_by_autocmd() call XquickfixChangedByAutocmd('c') call XquickfixChangedByAutocmd('l') -endfunction +endfunc func Test_caddbuffer_to_empty() helpgr quickfix @@ -1006,7 +1147,7 @@ func Test_cgetexpr_works() endfunc " Tests for the setqflist() and setloclist() functions -function SetXlistTests(cchar, bnum) +func SetXlistTests(cchar, bnum) call s:setup_commands(a:cchar) call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, @@ -1041,9 +1182,35 @@ function SetXlistTests(cchar, bnum) call g:Xsetlist([]) let l = g:Xgetlist() call assert_equal(0, len(l)) -endfunction -function Test_setqflist() + " Tests for setting the 'valid' flag + call g:Xsetlist([{'bufnr':a:bnum, 'lnum':4, 'valid':0}]) + Xwindow + call assert_equal(1, winnr('$')) + let l = g:Xgetlist() + call g:Xsetlist(l) + call assert_equal(0, g:Xgetlist()[0].valid) + call g:Xsetlist([{'text':'Text1', 'valid':1}]) + Xwindow + call assert_equal(2, winnr('$')) + Xclose + let save_efm = &efm + set efm=%m + Xgetexpr 'TestMessage' + let l = g:Xgetlist() + call g:Xsetlist(l) + call assert_equal(1, g:Xgetlist()[0].valid) + let &efm = save_efm + + " Error cases: + " Refer to a non-existing buffer and pass a non-dictionary type + call assert_fails("call g:Xsetlist([{'bufnr':998, 'lnum':4}," . + \ " {'bufnr':999, 'lnum':5}])", 'E92:') + call g:Xsetlist([[1, 2,3]]) + call assert_equal(0, len(g:Xgetlist())) +endfunc + +func Test_setqflist() new Xtestfile | only let bnum = bufnr('%') call setline(1, range(1,5)) @@ -1053,13 +1220,14 @@ function Test_setqflist() enew! call delete('Xtestfile') -endfunction +endfunc -function Xlist_empty_middle(cchar) +func Xlist_empty_middle(cchar) call s:setup_commands(a:cchar) " create three quickfix lists - Xvimgrep Test_ test_quickfix.vim + let @/ = 'Test_' + Xvimgrep // test_quickfix.vim let testlen = len(g:Xgetlist()) call assert_true(testlen > 0) Xvimgrep empty test_quickfix.vim @@ -1078,12 +1246,12 @@ function Xlist_empty_middle(cchar) call assert_equal(matchlen, len(g:Xgetlist())) endfunc -function Test_setqflist_empty_middle() +func Test_setqflist_empty_middle() call Xlist_empty_middle('c') call Xlist_empty_middle('l') -endfunction +endfunc -function Xlist_empty_older(cchar) +func Xlist_empty_older(cchar) call s:setup_commands(a:cchar) " create three quickfix lists @@ -1104,14 +1272,14 @@ function Xlist_empty_older(cchar) call assert_equal(twolen, len(g:Xgetlist())) Xnewer call assert_equal(threelen, len(g:Xgetlist())) -endfunction +endfunc -function Test_setqflist_empty_older() +func Test_setqflist_empty_older() call Xlist_empty_older('c') call Xlist_empty_older('l') -endfunction +endfunc -function! XquickfixSetListWithAct(cchar) +func XquickfixSetListWithAct(cchar) call s:setup_commands(a:cchar) let list1 = [{'filename': 'fnameA', 'text': 'A'}, @@ -1185,12 +1353,12 @@ function! XquickfixSetListWithAct(cchar) call assert_fails("call g:Xsetlist(list1, 0)", 'E928:') endfunc -function Test_quickfix_set_list_with_act() +func Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('c') call XquickfixSetListWithAct('l') -endfunction +endfunc -function XLongLinesTests(cchar) +func XLongLinesTests(cchar) let l = g:Xgetlist() call assert_equal(4, len(l)) @@ -1208,9 +1376,9 @@ function XLongLinesTests(cchar) call assert_equal(10, len(l[3].text)) call g:Xsetlist([], 'r') -endfunction +endfunc -function s:long_lines_tests(cchar) +func s:long_lines_tests(cchar) call s:setup_commands(a:cchar) let testfile = 'samples/quickfix.txt' @@ -1231,22 +1399,22 @@ function s:long_lines_tests(cchar) exe 'edit' testfile exe 'Xbuffer' bufnr('%') call XLongLinesTests(a:cchar) -endfunction +endfunc -function Test_long_lines() +func Test_long_lines() call s:long_lines_tests('c') call s:long_lines_tests('l') -endfunction +endfunc -function! s:create_test_file(filename) +func s:create_test_file(filename) let l = [] for i in range(1, 20) call add(l, 'Line' . i) endfor call writefile(l, a:filename) -endfunction +endfunc -function! Test_switchbuf() +func Test_switchbuf() call s:create_test_file('Xqftestfile1') call s:create_test_file('Xqftestfile2') call s:create_test_file('Xqftestfile3') @@ -1267,18 +1435,18 @@ function! Test_switchbuf() let winid = win_getid() cfirst | cnext call assert_equal(winid, win_getid()) - cnext | cnext + 2cnext call assert_equal(winid, win_getid()) - cnext | cnext + 2cnext call assert_equal(winid, win_getid()) enew set switchbuf=useopen cfirst | cnext call assert_equal(file1_winid, win_getid()) - cnext | cnext + 2cnext call assert_equal(file2_winid, win_getid()) - cnext | cnext + 2cnext call assert_equal(file2_winid, win_getid()) enew | only @@ -1288,9 +1456,9 @@ function! Test_switchbuf() tabfirst cfirst | cnext call assert_equal(2, tabpagenr()) - cnext | cnext + 2cnext call assert_equal(3, tabpagenr()) - cnext | cnext + 2cnext call assert_equal(3, tabpagenr()) tabfirst | tabonly | enew @@ -1328,14 +1496,28 @@ function! Test_switchbuf() call assert_equal(2, winnr('$')) call assert_equal(1, bufwinnr('Xqftestfile3')) + " If only quickfix window is open in the current tabpage, jumping to an + " entry with 'switchubf' set to 'usetab' should search in other tabpages. enew | only + set switchbuf=usetab + tabedit Xqftestfile1 + tabedit Xqftestfile2 + tabedit Xqftestfile3 + tabfirst + copen | only + clast + call assert_equal(4, tabpagenr()) + tabfirst | tabonly | enew | only call delete('Xqftestfile1') call delete('Xqftestfile2') call delete('Xqftestfile3') -endfunction + set switchbuf&vim -function! Xadjust_qflnum(cchar) + enew | only +endfunc + +func Xadjust_qflnum(cchar) call s:setup_commands(a:cchar) enew | only @@ -1360,17 +1542,17 @@ function! Xadjust_qflnum(cchar) enew! call delete(fname) -endfunction +endfunc -function! Test_adjust_lnum() +func Test_adjust_lnum() call setloclist(0, []) call Xadjust_qflnum('c') call setqflist([]) call Xadjust_qflnum('l') -endfunction +endfunc " Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands -function! s:test_xgrep(cchar) +func s:test_xgrep(cchar) call s:setup_commands(a:cchar) " The following lines are used for the grep test. Don't remove. @@ -1389,9 +1571,9 @@ function! s:test_xgrep(cchar) set makeef=Temp_File_## silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim call assert_true(len(g:Xgetlist()) == 6) -endfunction +endfunc -function! Test_grep() +func Test_grep() if !has('unix') " The grepprg may not be set on non-Unix systems return @@ -1399,9 +1581,9 @@ function! Test_grep() call s:test_xgrep('c') call s:test_xgrep('l') -endfunction +endfunc -function! Test_two_windows() +func Test_two_windows() " Use one 'errorformat' for two windows. Add an expression to each of them, " make sure they each keep their own state. set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' @@ -1427,12 +1609,10 @@ function! Test_two_windows() laddexpr 'one.txt:3:one one one' let loc_one = getloclist(one_id) -echo string(loc_one) call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) call assert_equal(3, loc_one[1].lnum) let loc_two = getloclist(two_id) -echo string(loc_two) call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) call assert_equal(5, loc_two[1].lnum) @@ -1444,15 +1624,20 @@ echo string(loc_two) call delete('Xtwo', 'rf') endfunc -function XbottomTests(cchar) +func XbottomTests(cchar) call s:setup_commands(a:cchar) - call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) + " Calling lbottom without any errors should fail + if a:cchar == 'l' + call assert_fails('lbottom', 'E776:') + endif + + call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) Xopen let wid = win_getid() call assert_equal(1, line('.')) wincmd w - call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a') + call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a') Xbottom call win_gotoid(wid) call assert_equal(2, line('.')) @@ -1460,18 +1645,17 @@ function XbottomTests(cchar) endfunc " Tests for the :cbottom and :lbottom commands -function Test_cbottom() +func Test_cbottom() call XbottomTests('c') call XbottomTests('l') -endfunction +endfunc -function HistoryTest(cchar) +func HistoryTest(cchar) call s:setup_commands(a:cchar) - call assert_fails(a:cchar . 'older 99', 'E380:') " clear all lists after the first one, then replace the first one. call g:Xsetlist([]) - Xolder + call assert_fails('Xolder 99', 'E380:') let entry = {'filename': 'foo', 'lnum': 42} call g:Xsetlist([entry], 'r') call g:Xsetlist([entry, entry]) @@ -1505,7 +1689,7 @@ func Test_duplicate_buf() endfunc " Quickfix/Location list set/get properties tests -function Xproperty_tests(cchar) +func Xproperty_tests(cchar) call s:setup_commands(a:cchar) " Error cases @@ -1514,6 +1698,7 @@ function Xproperty_tests(cchar) call assert_fails('call g:Xsetlist([], "a", [])', 'E715:') " Set and get the title + call g:Xsetlist([]) Xopen wincmd p call g:Xsetlist([{'filename':'foo', 'lnum':27}]) @@ -1532,9 +1717,30 @@ function Xproperty_tests(cchar) call assert_equal('N1', g:Xgetlist({'all':1}).title) call g:Xsetlist([], ' ', {'title' : 'N2'}) call assert_equal(qfnr + 1, g:Xgetlist({'all':1}).nr) + + let res = g:Xgetlist({'nr': 0}) + call assert_equal(qfnr + 1, res.nr) + call assert_equal(['nr'], keys(res)) + call g:Xsetlist([], ' ', {'title' : 'N3'}) call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) + " Changing the title of an earlier quickfix list + call g:Xsetlist([], ' ', {'title' : 'NewTitle', 'nr' : 2}) + call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title) + + " Changing the title of an invalid quickfix list + call assert_equal(-1, g:Xsetlist([], ' ', + \ {'title' : 'SomeTitle', 'nr' : 99})) + call assert_equal(-1, g:Xsetlist([], ' ', + \ {'title' : 'SomeTitle', 'nr' : 'abc'})) + + if a:cchar == 'c' + copen + call assert_equal({'winid':win_getid()}, getqflist({'winid':1})) + cclose + endif + " Invalid arguments call assert_fails('call g:Xgetlist([])', 'E715') call assert_fails('call g:Xsetlist([], "a", [])', 'E715') @@ -1542,23 +1748,155 @@ function Xproperty_tests(cchar) call assert_equal(-1, s) call assert_equal({}, g:Xgetlist({'abc':1})) + call assert_equal({}, g:Xgetlist({'nr':99, 'title':1})) + call assert_equal({}, g:Xgetlist({'nr':[], 'title':1})) if a:cchar == 'l' - call assert_equal({}, getloclist(99, ['title'])) + call assert_equal({}, getloclist(99, {'title': 1})) endif -endfunction -function Test_qf_property() + " Context related tests + call g:Xsetlist([], 'a', {'context':[1,2,3]}) + call test_garbagecollect_now() + let d = g:Xgetlist({'context':1}) + call assert_equal([1,2,3], d.context) + call g:Xsetlist([], 'a', {'context':{'color':'green'}}) + let d = g:Xgetlist({'context':1}) + call assert_equal({'color':'green'}, d.context) + call g:Xsetlist([], 'a', {'context':"Context info"}) + let d = g:Xgetlist({'context':1}) + call assert_equal("Context info", d.context) + call g:Xsetlist([], 'a', {'context':246}) + let d = g:Xgetlist({'context':1}) + call assert_equal(246, d.context) + if a:cchar == 'l' + " Test for copying context across two different location lists + new | only + let w1_id = win_getid() + let l = [1] + call setloclist(0, [], 'a', {'context':l}) + new + let w2_id = win_getid() + call add(l, 2) + call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context) + call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) + unlet! l + call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) + only + call setloclist(0, [], 'f') + call assert_equal({}, getloclist(0, {'context':1})) + endif + + " Test for changing the context of previous quickfix lists + call g:Xsetlist([], 'f') + Xexpr "One" + Xexpr "Two" + Xexpr "Three" + call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1}) + call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2}) + " Also, check for setting the context using quickfix list number zero. + call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0}) + call test_garbagecollect_now() + let l = g:Xgetlist({'nr' : 1, 'context' : 1}) + call assert_equal([1], l.context) + let l = g:Xgetlist({'nr' : 2, 'context' : 1}) + call assert_equal([2], l.context) + let l = g:Xgetlist({'nr' : 3, 'context' : 1}) + call assert_equal([3], l.context) + + " Test for changing the context through reference and for garbage + " collection of quickfix context + let l = ["red"] + call g:Xsetlist([], ' ', {'context' : l}) + call add(l, "blue") + let x = g:Xgetlist({'context' : 1}) + call add(x.context, "green") + call assert_equal(["red", "blue", "green"], l) + call assert_equal(["red", "blue", "green"], x.context) + unlet l + call test_garbagecollect_now() + let m = g:Xgetlist({'context' : 1}) + call assert_equal(["red", "blue", "green"], m.context) + + " Test for setting/getting items + Xexpr "" + let qfprev = g:Xgetlist({'nr':0}) + call g:Xsetlist([], ' ', {'title':'Green', + \ 'items' : [{'filename':'F1', 'lnum':10}]}) + let qfcur = g:Xgetlist({'nr':0}) + call assert_true(qfcur.nr == qfprev.nr + 1) + let l = g:Xgetlist({'items':1}) + call assert_equal('F1', bufname(l.items[0].bufnr)) + call assert_equal(10, l.items[0].lnum) + call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20}, + \ {'filename':'F2', 'lnum':30}]}) + let l = g:Xgetlist({'items':1}) + call assert_equal('F2', bufname(l.items[2].bufnr)) + call assert_equal(30, l.items[2].lnum) + call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]}) + let l = g:Xgetlist({'items':1}) + call assert_equal('F3', bufname(l.items[0].bufnr)) + call assert_equal(40, l.items[0].lnum) + call g:Xsetlist([], 'r', {'items' : []}) + let l = g:Xgetlist({'items':1}) + call assert_equal(0, len(l.items)) + + " Save and restore the quickfix stack + call g:Xsetlist([], 'f') + call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) + Xexpr "File1:10:Line1" + Xexpr "File2:20:Line2" + Xexpr "File3:30:Line3" + let last_qf = g:Xgetlist({'nr':'$'}).nr + call assert_equal(3, last_qf) + let qstack = [] + for i in range(1, last_qf) + let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1})) + endfor + call g:Xsetlist([], 'f') + for i in range(len(qstack)) + call g:Xsetlist([], ' ', qstack[i]) + endfor + call assert_equal(3, g:Xgetlist({'nr':'$'}).nr) + call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum) + call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum) + call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum) + call g:Xsetlist([], 'f') + + " Swap two quickfix lists + Xexpr "File1:10:Line10" + Xexpr "File2:20:Line20" + Xexpr "File3:30:Line30" + call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']}) + call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']}) + let l1=g:Xgetlist({'nr':1,'all':1}) + let l2=g:Xgetlist({'nr':2,'all':1}) + let l1.nr=2 + let l2.nr=1 + call g:Xsetlist([], 'r', l1) + call g:Xsetlist([], 'r', l2) + let newl1=g:Xgetlist({'nr':1,'all':1}) + let newl2=g:Xgetlist({'nr':2,'all':1}) + call assert_equal(':Fruits', newl1.title) + call assert_equal(['Fruits'], newl1.context) + call assert_equal('Line20', newl1.items[0].text) + call assert_equal(':Colors', newl2.title) + call assert_equal(['Colors'], newl2.context) + call assert_equal('Line10', newl2.items[0].text) + call g:Xsetlist([], 'f') +endfunc + +func Test_qf_property() call Xproperty_tests('c') call Xproperty_tests('l') -endfunction +endfunc " Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands -function QfAutoCmdHandler(loc, cmd) +func QfAutoCmdHandler(loc, cmd) call add(g:acmds, a:loc . a:cmd) -endfunction +endfunc -function Test_Autocmd() +func Test_Autocmd() autocmd QuickFixCmdPre * call QfAutoCmdHandler('pre', expand('<amatch>')) autocmd QuickFixCmdPost * call QfAutoCmdHandler('post', expand('<amatch>')) @@ -1586,9 +1924,9 @@ function Test_Autocmd() \ 'precaddbuffer', \ 'postcaddbuffer'] call assert_equal(l, g:acmds) -endfunction +endfunc -function! Test_Autocmd_Exception() +func Test_Autocmd_Exception() set efm=%m lgetexpr '?' @@ -1603,4 +1941,271 @@ function! Test_Autocmd_Exception() call assert_equal('1', getloclist(0)[0].text) set efm&vim -endfunction +endfunc + +func Test_caddbuffer_wrong() + " This used to cause a memory access in freed memory. + let save_efm = &efm + set efm=%EEEE%m,%WWWW,%+CCCC%>%#,%GGGG%.# + cgetexpr ['WWWW', 'EEEE', 'CCCC'] + let &efm = save_efm + caddbuffer + bwipe! +endfunc + +func Test_caddexpr_wrong() + " This used to cause a memory access in freed memory. + cbuffer + cbuffer + copen + let save_efm = &efm + set efm=% + call assert_fails('caddexpr ""', 'E376:') + let &efm = save_efm +endfunc + +func Test_dirstack_cleanup() + " This used to cause a memory access in freed memory. + let save_efm = &efm + lexpr '0' + lopen + fun X(c) + let save_efm=&efm + set efm=%D%f + if a:c == 'c' + caddexpr '::' + else + laddexpr ':0:0' + endif + let &efm=save_efm + endfun + call X('c') + call X('l') + call setqflist([], 'r') + caddbuffer + let &efm = save_efm +endfunc + +" Tests for jumping to entries from the location list window and quickfix +" window +func Test_cwindow_jump() + set efm=%f%%%l%%%m + lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] + lopen | only + lfirst + call assert_true(winnr('$') == 2) + call assert_true(winnr() == 1) + " Location list for the new window should be set + call assert_true(getloclist(0)[2].text == 'Line 30') + + " Open a scratch buffer + " Open a new window and create a location list + " Open the location list window and close the other window + " Jump to an entry. + " Should create a new window and jump to the entry. The scrtach buffer + " should not be used. + enew | only + set buftype=nofile + below new + lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] + lopen + 2wincmd c + lnext + call assert_true(winnr('$') == 3) + call assert_true(winnr() == 2) + + " Open two windows with two different location lists + " Open the location list window and close the previous window + " Jump to an entry in the location list window + " Should open the file in the first window and not set the location list. + enew | only + lgetexpr ["F1%5%Line 5"] + below new + lgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] + lopen + 2wincmd c + lnext + call assert_true(winnr() == 1) + call assert_true(getloclist(0)[0].text == 'Line 5') + + enew | only + cgetexpr ["F1%10%Line 10", "F2%20%Line 20", "F3%30%Line 30"] + copen + cnext + call assert_true(winnr('$') == 2) + call assert_true(winnr() == 1) + + enew | only + set efm&vim +endfunc + +func XvimgrepTests(cchar) + call s:setup_commands(a:cchar) + + call writefile(['Editor:VIM vim', + \ 'Editor:Emacs EmAcS', + \ 'Editor:Notepad NOTEPAD'], 'Xtestfile1') + call writefile(['Linux', 'MacOS', 'MS-Windows'], 'Xtestfile2') + + " Error cases + call assert_fails('Xvimgrep /abc *', 'E682:') + + let @/='' + call assert_fails('Xvimgrep // *', 'E35:') + + call assert_fails('Xvimgrep abc', 'E683:') + call assert_fails('Xvimgrep a1b2c3 Xtestfile1', 'E480:') + call assert_fails('Xvimgrep pat Xa1b2c3', 'E480:') + + Xexpr "" + Xvimgrepadd Notepad Xtestfile1 + Xvimgrepadd MacOS Xtestfile2 + let l = g:Xgetlist() + call assert_equal(2, len(l)) + call assert_equal('Editor:Notepad NOTEPAD', l[0].text) + + Xvimgrep #\cvim#g Xtestfile? + let l = g:Xgetlist() + call assert_equal(2, len(l)) + call assert_equal(8, l[0].col) + call assert_equal(12, l[1].col) + + 1Xvimgrep ?Editor? Xtestfile* + let l = g:Xgetlist() + call assert_equal(1, len(l)) + call assert_equal('Editor:VIM vim', l[0].text) + + edit +3 Xtestfile2 + Xvimgrep +\cemacs+j Xtestfile1 + let l = g:Xgetlist() + call assert_equal('Xtestfile2', bufname('')) + call assert_equal('Editor:Emacs EmAcS', l[0].text) + + call delete('Xtestfile1') + call delete('Xtestfile2') +endfunc + +" Tests for the :vimgrep command +func Test_vimgrep() + call XvimgrepTests('c') + call XvimgrepTests('l') +endfunc + +func XfreeTests(cchar) + call s:setup_commands(a:cchar) + + enew | only + + " Deleting the quickfix stack should work even When the current list is + " somewhere in the middle of the stack + Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] + Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] + Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] + Xolder + call g:Xsetlist([], 'f') + call assert_equal(0, len(g:Xgetlist())) + + " After deleting the stack, adding a new list should create a stack with a + " single list. + Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] + call assert_equal(1, g:Xgetlist({'all':1}).nr) + + " Deleting the stack from a quickfix window should update/clear the + " quickfix/location list window. + Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] + Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] + Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] + Xolder + Xwindow + call g:Xsetlist([], 'f') + call assert_equal(2, winnr('$')) + call assert_equal(1, line('$')) + Xclose + + " Deleting the stack from a non-quickfix window should update/clear the + " quickfix/location list window. + Xexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] + Xexpr ['Xfile2:20:20:Line 20', 'Xfile2:25:25:Line 25'] + Xexpr ['Xfile3:30:30:Line 30', 'Xfile3:35:35:Line 35'] + Xolder + Xwindow + wincmd p + call g:Xsetlist([], 'f') + call assert_equal(0, len(g:Xgetlist())) + wincmd p + call assert_equal(2, winnr('$')) + call assert_equal(1, line('$')) + + " After deleting the location list stack, if the location list window is + " opened, then a new location list should be created. So opening the + " location list window again should not create a new window. + if a:cchar == 'l' + lexpr ['Xfile1:10:10:Line 10', 'Xfile1:15:15:Line 15'] + wincmd p + lopen + call assert_equal(2, winnr('$')) + endif + Xclose +endfunc + +" Tests for the quickifx free functionality +func Test_qf_free() + call XfreeTests('c') + call XfreeTests('l') +endfunc + +" Test for buffer overflow when parsing lines and adding new entries to +" the quickfix list. +func Test_bufoverflow() + set efm=%f:%l:%m + cgetexpr ['File1:100:' . repeat('x', 1025)] + + set efm=%+GCompiler:\ %.%#,%f:%l:%m + cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World'] + + set efm=%DEntering\ directory\ %f,%f:%l:%m + cgetexpr ['Entering directory ' . repeat('a', 1006), + \ 'File1:10:Hello World'] + set efm&vim +endfunc + +func Test_cclose_from_copen() + augroup QF_Test + au! + au FileType qf :cclose + augroup END + copen + augroup QF_Test + au! + augroup END + augroup! QF_Test +endfunc + +" Tests for getting the quickfix stack size +func XsizeTests(cchar) + call s:setup_commands(a:cchar) + + call g:Xsetlist([], 'f') + call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) + call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1}))) + call assert_equal(0, len(g:Xgetlist({'nr':0}))) + + Xexpr "File1:10:Line1" + Xexpr "File2:20:Line2" + Xexpr "File3:30:Line3" + Xolder | Xolder + call assert_equal(3, g:Xgetlist({'nr':'$'}).nr) + call g:Xsetlist([], 'f') + + Xexpr "File1:10:Line1" + Xexpr "File2:20:Line2" + Xexpr "File3:30:Line3" + Xolder | Xolder + call g:Xsetlist([], 'a', {'nr':'$', 'title':'Compiler'}) + call assert_equal('Compiler', g:Xgetlist({'nr':3, 'all':1}).title) +endfunc + +func Test_Qf_Size() + call XsizeTests('c') + call XsizeTests('l') +endfunc diff --git a/src/nvim/testdir/test_recover.vim b/src/nvim/testdir/test_recover.vim new file mode 100644 index 0000000000..46d884a97c --- /dev/null +++ b/src/nvim/testdir/test_recover.vim @@ -0,0 +1,63 @@ +" Test :recover + +func Test_recover_root_dir() + " This used to access invalid memory. + split Xtest + set dir=/ + call assert_fails('recover', 'E305:') + close! + + if has('win32') || filewritable('/') == 2 + " can write in / directory on MS-Windows + set dir=/notexist/ + endif + call assert_fails('split Xtest', 'E303:') + set dir& +endfunc + +" Inserts 10000 lines with text to fill the swap file with two levels of pointer +" blocks. Then recovers from the swap file and checks all text is restored. +" +" We need about 10000 lines of 100 characters to get two levels of pointer +" blocks. +func Test_swap_file() + set directory=. + set fileformat=unix undolevels=-1 + edit! Xtest + let text = "\tabcdefghijklmnoparstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnoparstuvwxyz0123456789" + let i = 1 + let linecount = 10000 + while i <= linecount + call append(i - 1, i . text) + let i += 1 + endwhile + $delete + preserve + " get the name of the swap file + let swname = split(execute("swapname"))[0] + let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '') + " make a copy of the swap file in Xswap + set binary + exe 'sp ' . swname + w! Xswap + set nobinary + new + only! + bwipe! Xtest + call rename('Xswap', swname) + recover Xtest + call delete(swname) + let linedollar = line('$') + call assert_equal(linecount, linedollar) + if linedollar < linecount + let linecount = linedollar + endif + let i = 1 + while i <= linecount + call assert_equal(i . text, getline(i)) + let i += 1 + endwhile + + set undolevels& + enew! | only +endfunc 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_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim index 7f3b31575d..a2f4286d4f 100644 --- a/src/nvim/testdir/test_regexp_utf8.vim +++ b/src/nvim/testdir/test_regexp_utf8.vim @@ -98,6 +98,21 @@ func Test_recursive_substitute() bwipe! endfunc +func Test_nested_backrefs() + " Check example in change.txt. + new + for re in range(0, 2) + exe 'set re=' . re + call setline(1, 'aa ab x') + 1s/\(\(a[a-d] \)*\)\(x\)/-\1- -\2- -\3-/ + call assert_equal('-aa ab - -ab - -x-', getline(1)) + + call assert_equal('-aa ab - -ab - -x-', substitute('aa ab x', '\(\(a[a-d] \)*\)\(x\)', '-\1- -\2- -\3-', '')) + endfor + bwipe! + set re=0 +endfunc + func Test_eow_with_optional() let expected = ['abc def', 'abc', 'def', '', '', '', '', '', '', ''] for re in range(0, 2) diff --git a/src/nvim/testdir/test_retab.vim b/src/nvim/testdir/test_retab.vim new file mode 100644 index 0000000000..f11a32bade --- /dev/null +++ b/src/nvim/testdir/test_retab.vim @@ -0,0 +1,77 @@ +" Test :retab +func SetUp() + new + call setline(1, "\ta \t b c ") +endfunc + +func TearDown() + bwipe! +endfunc + +func Retab(bang, n) + let l:old_tabstop = &tabstop + let l:old_line = getline(1) + exe "retab" . a:bang . a:n + let l:line = getline(1) + call setline(1, l:old_line) + if a:n > 0 + " :retab changes 'tabstop' to n with argument n > 0. + call assert_equal(a:n, &tabstop) + exe 'set tabstop=' . l:old_tabstop + else + " :retab does not change 'tabstop' with empty or n <= 0. + call assert_equal(l:old_tabstop, &tabstop) + endif + return l:line +endfunc + +func Test_retab() + set tabstop=8 noexpandtab + call assert_equal("\ta\t b c ", Retab('', '')) + call assert_equal("\ta\t b c ", Retab('', 0)) + call assert_equal("\ta\t b c ", Retab('', 8)) + call assert_equal("\ta\t b\t c\t ", Retab('!', '')) + call assert_equal("\ta\t b\t c\t ", Retab('!', 0)) + call assert_equal("\ta\t b\t c\t ", Retab('!', 8)) + + call assert_equal("\t\ta\t\t\tb c ", Retab('', 4)) + call assert_equal("\t\ta\t\t\tb\t\t c\t ", Retab('!', 4)) + + call assert_equal(" a\t\tb c ", Retab('', 10)) + call assert_equal(" a\t\tb c ", Retab('!', 10)) + + set tabstop=8 expandtab + call assert_equal(" a b c ", Retab('', '')) + call assert_equal(" a b c ", Retab('', 0)) + call assert_equal(" a b c ", Retab('', 8)) + call assert_equal(" a b c ", Retab('!', '')) + call assert_equal(" a b c ", Retab('!', 0)) + call assert_equal(" a b c ", Retab('!', 8)) + + call assert_equal(" a b c ", Retab(' ', 4)) + call assert_equal(" a b c ", Retab('!', 4)) + + call assert_equal(" a b c ", Retab(' ', 10)) + call assert_equal(" a b c ", Retab('!', 10)) + + set tabstop=4 noexpandtab + call assert_equal("\ta\t\tb c ", Retab('', '')) + call assert_equal("\ta\t\tb\t\t c\t ", Retab('!', '')) + call assert_equal("\t a\t\t\tb c ", Retab('', 3)) + call assert_equal("\t a\t\t\tb\t\t\tc\t ", Retab('!', 3)) + call assert_equal(" a\t b c ", Retab('', 5)) + call assert_equal(" a\t b\t\t c\t ", Retab('!', 5)) + + set tabstop=4 expandtab + call assert_equal(" a b c ", Retab('', '')) + call assert_equal(" a b c ", Retab('!', '')) + call assert_equal(" a b c ", Retab('', 3)) + call assert_equal(" a b c ", Retab('!', 3)) + call assert_equal(" a b c ", Retab('', 5)) + call assert_equal(" a b c ", Retab('!', 5)) +endfunc + +func Test_retab_error() + call assert_fails('retab -1', 'E487:') + call assert_fails('retab! -1', 'E487:') +endfunc diff --git a/src/nvim/testdir/test_scrollbind.vim b/src/nvim/testdir/test_scrollbind.vim new file mode 100644 index 0000000000..baa24f1979 --- /dev/null +++ b/src/nvim/testdir/test_scrollbind.vim @@ -0,0 +1,32 @@ +" Test for 'scrollbind' causing an unexpected scroll of one of the windows. +func Test_scrollbind() + " We don't want the status line to cause problems: + set laststatus=0 + let totalLines = &lines * 20 + let middle = totalLines / 2 + new | only + for i in range(1, totalLines) + call setline(i, 'LINE ' . i) + endfor + exe string(middle) + normal zt + normal M + aboveleft vert new + for i in range(1, totalLines) + call setline(i, 'line ' . i) + endfor + exe string(middle) + normal zt + normal M + " Execute the following two commands at once to reproduce the problem. + setl scb | wincmd p + setl scb + wincmd w + let topLineLeft = line('w0') + wincmd p + let topLineRight = line('w0') + setl noscrollbind + wincmd p + setl noscrollbind + call assert_equal(0, topLineLeft - topLineRight) +endfunc diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 2106fc2dec..5da9397be5 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -2,13 +2,13 @@ func Test_search_cmdline() " See test/functional/legacy/search_spec.lua - throw 'skipped: Nvim does not support test_disable_char_avail()' + throw 'skipped: Nvim does not support test_override()' if !exists('+incsearch') return endif " need to disable char_avail, " so that expansion of commandline works - call test_disable_char_avail(1) + call test_override("char_avail", 1) new call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar']) " Test 1 @@ -195,19 +195,19 @@ func Test_search_cmdline() call assert_equal(' 3 the', getline('.')) " clean up - call test_disable_char_avail(0) + call test_override("char_avail", 0) bw! endfunc func Test_search_cmdline2() " See test/functional/legacy/search_spec.lua - throw 'skipped: Nvim does not support test_disable_char_avail()' + throw 'skipped: Nvim does not support test_override()' if !exists('+incsearch') return endif " need to disable char_avail, " so that expansion of commandline works - call test_disable_char_avail(1) + call test_override("char_avail", 1) new call setline(1, [' 1', ' 2 these', ' 3 the theother']) " Test 1 @@ -269,7 +269,7 @@ func Test_search_cmdline2() " clean up set noincsearch - call test_disable_char_avail(0) + call test_override("char_avail", 0) bw! endfunc @@ -283,3 +283,173 @@ func Test_use_sub_pat() call X() bwipe! endfunc + +func Test_searchpair() + new + call setline(1, ['other code here', '', '[', '" cursor here', ']']) + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set nomagic + 4 + let a=searchpair('\[','',']','bW') + call assert_equal(3, a) + set magic + q! +endfunc + +func Test_searchc() + " These commands used to cause memory overflow in searchc(). + new + norm ixx + exe "norm 0t\u93cf" + bw! +endfunc + +func Test_search_cmdline3() + throw 'skipped: Nvim does not support test_override()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_override("char_avail", 1) + new + call setline(1, [' 1', ' 2 the~e', ' 3 the theother']) + set incsearch + 1 + " first match + call feedkeys("/the\<c-l>\<cr>", 'tx') + call assert_equal(' 2 the~e', getline('.')) + " clean up + set noincsearch + call test_override("char_avail", 0) + bw! +endfunc + +func Test_search_cmdline4() + " See test/functional/legacy/search_spec.lua + throw 'skipped: Nvim does not support test_override()' + if !exists('+incsearch') + return + endif + " need to disable char_avail, + " so that expansion of commandline works + call test_override("char_avail", 1) + new + call setline(1, [' 1 the first', ' 2 the second', ' 3 the third']) + set incsearch + $ + call feedkeys("?the\<c-g>\<cr>", 'tx') + call assert_equal(' 3 the third', getline('.')) + $ + call feedkeys("?the\<c-g>\<c-g>\<cr>", 'tx') + call assert_equal(' 1 the first', getline('.')) + $ + call feedkeys("?the\<c-g>\<c-g>\<c-g>\<cr>", 'tx') + call assert_equal(' 2 the second', getline('.')) + $ + call feedkeys("?the\<c-t>\<cr>", 'tx') + call assert_equal(' 1 the first', getline('.')) + $ + call feedkeys("?the\<c-t>\<c-t>\<cr>", 'tx') + call assert_equal(' 3 the third', getline('.')) + $ + call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx') + call assert_equal(' 2 the second', getline('.')) + " clean up + set noincsearch + call test_override("char_avail", 0) + bw! +endfunc + +func Test_search_cmdline5() + if !exists('+incsearch') + return + endif + " Do not call test_override("char_avail", 1) so that <C-g> and <C-t> work + " regardless char_avail. + new + call setline(1, [' 1 the first', ' 2 the second', ' 3 the third']) + set incsearch + 1 + call feedkeys("/the\<c-g>\<c-g>\<cr>", 'tx') + call assert_equal(' 3 the third', getline('.')) + $ + call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx') + call assert_equal(' 2 the second', getline('.')) + " clean up + set noincsearch + bw! +endfunc + +" Tests for regexp with various magic settings +func Test_search_regexp() + enew! + + put ='1 a aa abb abbccc' + exe 'normal! /a*b\{2}c\+/e' . "\<CR>" + call assert_equal([0, 2, 17, 0], getpos('.')) + + put ='2 d dd dee deefff' + exe 'normal! /\Md\*e\{2}f\+/e' . "\<CR>" + call assert_equal([0, 3, 17, 0], getpos('.')) + + set nomagic + put ='3 g gg ghh ghhiii' + exe 'normal! /g\*h\{2}i\+/e' . "\<CR>" + call assert_equal([0, 4, 17, 0], getpos('.')) + + put ='4 j jj jkk jkklll' + exe 'normal! /\mj*k\{2}l\+/e' . "\<CR>" + call assert_equal([0, 5, 17, 0], getpos('.')) + + put ='5 m mm mnn mnnooo' + exe 'normal! /\vm*n{2}o+/e' . "\<CR>" + call assert_equal([0, 6, 17, 0], getpos('.')) + + put ='6 x ^aa$ x' + exe 'normal! /\V^aa$' . "\<CR>" + call assert_equal([0, 7, 5, 0], getpos('.')) + + set magic + put ='7 (a)(b) abbaa' + exe 'normal! /\v(a)(b)\2\1\1/e' . "\<CR>" + call assert_equal([0, 8, 14, 0], getpos('.')) + + put ='8 axx [ab]xx' + exe 'normal! /\V[ab]\(\[xy]\)\1' . "\<CR>" + call assert_equal([0, 9, 7, 0], getpos('.')) + + set undolevels=100 + put ='9 foobar' + put ='' + exe "normal! a\<C-G>u\<Esc>" + normal G + exe 'normal! dv?bar?' . "\<CR>" + call assert_equal('9 foo', getline('.')) + call assert_equal([0, 10, 5, 0], getpos('.')) + call assert_equal(10, line('$')) + normal u + call assert_equal('9 foobar', getline('.')) + call assert_equal([0, 10, 6, 0], getpos('.')) + call assert_equal(11, line('$')) + + 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_signs.vim b/src/nvim/testdir/test_signs.vim index 75dbd74b34..a967435346 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -182,7 +182,7 @@ func Test_sign_invalid_commands() call assert_fails('sign define Sign1 xxx', 'E475:') call assert_fails('sign undefine', 'E156:') call assert_fails('sign list xxx', 'E155:') - call assert_fails('sign place 1 buffer=', 'E158:') + call assert_fails('sign place 1 buffer=999', 'E158:') call assert_fails('sign define Sign2 text=', 'E239:') endfunc diff --git a/src/nvim/testdir/test_source_utf8.vim b/src/nvim/testdir/test_source_utf8.vim index edb76fc43d..c29c2ec1f3 100644 --- a/src/nvim/testdir/test_source_utf8.vim +++ b/src/nvim/testdir/test_source_utf8.vim @@ -31,3 +31,33 @@ func Test_source_latin() bwipe! call delete('Xscript') endfunc + +" Test for sourcing a file with CTRL-V's at the end of the line +func Test_source_ctrl_v() + call writefile(['map __1 afirst', + \ 'map __2 asecond', + \ 'map __3 athird', + \ 'map __4 afourth', + \ 'map __5 afifth', + \ "map __1 asd\<C-V>", + \ "map __2 asd\<C-V>\<C-V>", + \ "map __3 asd\<C-V>\<C-V>", + \ "map __4 asd\<C-V>\<C-V>\<C-V>", + \ "map __5 asd\<C-V>\<C-V>\<C-V>", + \ ], 'Xtestfile') + source Xtestfile + enew! + exe "normal __1\<Esc>\<Esc>__2\<Esc>__3\<Esc>\<Esc>__4\<Esc>__5\<Esc>" + exe "%s/\<C-J>/0/g" + call assert_equal(['sd', + \ "map __2 asd\<Esc>secondsd\<Esc>sd0map __5 asd0fifth"], + \ getline(1, 2)) + + enew! + call delete('Xtestfile') + unmap __1 + unmap __2 + unmap __3 + unmap __4 + unmap __5 +endfunc diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim new file mode 100644 index 0000000000..21f2363731 --- /dev/null +++ b/src/nvim/testdir/test_spell.vim @@ -0,0 +1,821 @@ +" Test spell checking + +if !has('spell') + finish +endif + +func TearDown() + set nospell + call delete('Xtest.aff') + call delete('Xtest.dic') + call delete('Xtest.latin1.add') + call delete('Xtest.latin1.add.spl') + call delete('Xtest.latin1.spl') + call delete('Xtest.latin1.sug') +endfunc + +func Test_wrap_search() + new + call setline(1, ['The', '', 'A plong line with two zpelling mistakes', '', 'End']) + set spell wrapscan + normal ]s + call assert_equal('plong', expand('<cword>')) + normal ]s + call assert_equal('zpelling', expand('<cword>')) + normal ]s + call assert_equal('plong', expand('<cword>')) + bwipe! + set nospell +endfunc + +func Test_curswant() + new + call setline(1, ['Another plong line', 'abcdefghijklmnopq']) + set spell wrapscan + normal 0]s + call assert_equal('plong', expand('<cword>')) + normal j + call assert_equal(9, getcurpos()[2]) + normal 0[s + call assert_equal('plong', expand('<cword>')) + normal j + call assert_equal(9, getcurpos()[2]) + + normal 0]S + call assert_equal('plong', expand('<cword>')) + normal j + call assert_equal(9, getcurpos()[2]) + normal 0[S + call assert_equal('plong', expand('<cword>')) + normal j + call assert_equal(9, getcurpos()[2]) + + normal 1G0 + call assert_equal('plong', spellbadword()[0]) + normal j + call assert_equal(9, getcurpos()[2]) + + bwipe! + set nospell +endfunc + +func Test_z_equal_on_invalid_utf8_word() + split + set spell + call setline(1, "\xff") + norm z= + set nospell + bwipe! +endfunc + +func Test_spellreall() + new + set spell + call assert_fails('spellrepall', 'E752:') + call setline(1, ['A speling mistake. The same speling mistake.', + \ 'Another speling mistake.']) + call feedkeys(']s1z=', 'tx') + call assert_equal('A spelling mistake. The same speling mistake.', getline(1)) + call assert_equal('Another speling mistake.', getline(2)) + spellrepall + call assert_equal('A spelling mistake. The same spelling mistake.', getline(1)) + call assert_equal('Another spelling mistake.', getline(2)) + call assert_fails('spellrepall', 'E753:') + set spell& + bwipe! +endfunc + +func Test_zz_basic() + call LoadAffAndDic(g:test_data_aff1, g:test_data_dic1) + call RunGoodBad("wrong OK puts. Test the end", + \ "bad: inputs comment ok Ok. test d\xE9\xF4l end the", + \["Comment", "deol", "d\xE9\xF4r", "input", "OK", "output", "outputs", "outtest", "put", "puts", + \ "test", "testen", "testn", "the end", "uk", "wrong"], + \[ + \ ["bad", ["put", "uk", "OK"]], + \ ["inputs", ["input", "puts", "outputs"]], + \ ["comment", ["Comment", "outtest", "the end"]], + \ ["ok", ["OK", "uk", "put"]], + \ ["Ok", ["OK", "Uk", "Put"]], + \ ["test", ["Test", "testn", "testen"]], + \ ["d\xE9\xF4l", ["deol", "d\xE9\xF4r", "test"]], + \ ["end", ["put", "uk", "test"]], + \ ["the", ["put", "uk", "test"]], + \ ] + \ ) + + call assert_equal("gebletegek", soundfold('goobledygoook')) + call assert_equal("kepereneven", soundfold('koprnven')) + call assert_equal("everles gesvets etele", soundfold('oeverloos gezwets edale')) +endfunc + +" Postponed prefixes +func Test_zz_prefixes() + call LoadAffAndDic(g:test_data_aff2, g:test_data_dic1) + call RunGoodBad("puts", + \ "bad: inputs comment ok Ok end the. test d\xE9\xF4l", + \ ["Comment", "deol", "d\xE9\xF4r", "OK", "put", "input", "output", "puts", "outputs", "test", "outtest", "testen", "testn", "the end", "uk", "wrong"], + \ [ + \ ["bad", ["put", "uk", "OK"]], + \ ["inputs", ["input", "puts", "outputs"]], + \ ["comment", ["Comment"]], + \ ["ok", ["OK", "uk", "put"]], + \ ["Ok", ["OK", "Uk", "Put"]], + \ ["end", ["put", "uk", "deol"]], + \ ["the", ["put", "uk", "test"]], + \ ["test", ["Test", "testn", "testen"]], + \ ["d\xE9\xF4l", ["deol", "d\xE9\xF4r", "test"]], + \ ]) +endfunc + +"Compound words +func Test_zz_compound() + call LoadAffAndDic(g:test_data_aff3, g:test_data_dic3) + call RunGoodBad("foo m\xEF foobar foofoobar barfoo barbarfoo", + \ "bad: bar la foom\xEF barm\xEF m\xEFfoo m\xEFbar m\xEFm\xEF lala m\xEFla lam\xEF foola labar", + \ ["foo", "m\xEF"], + \ [ + \ ["bad", ["foo", "m\xEF"]], + \ ["bar", ["barfoo", "foobar", "foo"]], + \ ["la", ["m\xEF", "foo"]], + \ ["foom\xEF", ["foo m\xEF", "foo", "foofoo"]], + \ ["barm\xEF", ["barfoo", "m\xEF", "barbar"]], + \ ["m\xEFfoo", ["m\xEF foo", "foo", "foofoo"]], + \ ["m\xEFbar", ["foobar", "barbar", "m\xEF"]], + \ ["m\xEFm\xEF", ["m\xEF m\xEF", "m\xEF"]], + \ ["lala", []], + \ ["m\xEFla", ["m\xEF", "m\xEF m\xEF"]], + \ ["lam\xEF", ["m\xEF", "m\xEF m\xEF"]], + \ ["foola", ["foo", "foobar", "foofoo"]], + \ ["labar", ["barbar", "foobar"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff4, g:test_data_dic4) + call RunGoodBad("word util bork prebork start end wordutil wordutils pro-ok bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork tomato tomatotomato startend startword startwordword startwordend startwordwordend startwordwordwordend prebork preborkbork preborkborkbork nouword", + \ "bad: wordutilize pro borkborkborkborkborkbork tomatotomatotomato endstart endend startstart wordend wordstart preborkprebork preborkpreborkbork startwordwordwordwordend borkpreborkpreborkbork utilsbork startnouword", + \ ["bork", "prebork", "end", "pro-ok", "start", "tomato", "util", "utilize", "utils", "word", "nouword"], + \ [ + \ ["bad", ["end", "bork", "word"]], + \ ["wordutilize", ["word utilize", "wordutils", "wordutil"]], + \ ["pro", ["bork", "word", "end"]], + \ ["borkborkborkborkborkbork", ["bork borkborkborkborkbork", "borkbork borkborkborkbork", "borkborkbork borkborkbork"]], + \ ["tomatotomatotomato", ["tomato tomatotomato", "tomatotomato tomato", "tomato tomato tomato"]], + \ ["endstart", ["end start", "start"]], + \ ["endend", ["end end", "end"]], + \ ["startstart", ["start start"]], + \ ["wordend", ["word end", "word", "wordword"]], + \ ["wordstart", ["word start", "bork start"]], + \ ["preborkprebork", ["prebork prebork", "preborkbork", "preborkborkbork"]], + \ ["preborkpreborkbork", ["prebork preborkbork", "preborkborkbork", "preborkborkborkbork"]], + \ ["startwordwordwordwordend", ["startwordwordwordword end", "startwordwordwordword", "start wordwordwordword end"]], + \ ["borkpreborkpreborkbork", ["bork preborkpreborkbork", "bork prebork preborkbork", "bork preborkprebork bork"]], + \ ["utilsbork", ["utilbork", "utils bork", "util bork"]], + \ ["startnouword", ["start nouword", "startword", "startborkword"]], + \ ]) + +endfunc + +"Test affix flags with two characters +func Test_zz_affix() + call LoadAffAndDic(g:test_data_aff5, g:test_data_dic5) + call RunGoodBad("fooa1 fooa\xE9 bar prebar barbork prebarbork startprebar start end startend startmiddleend nouend", + \ "bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart startprobar startnouend", + \ ["bar", "barbork", "end", "fooa1", "fooa\xE9", "nouend", "prebar", "prebarbork", "start"], + \ [ + \ ["bad", ["bar", "end", "fooa1"]], + \ ["foo", ["fooa1", "fooa\xE9", "bar"]], + \ ["fooa2", ["fooa1", "fooa\xE9", "bar"]], + \ ["prabar", ["prebar", "bar", "bar bar"]], + \ ["probarbirk", ["prebarbork"]], + \ ["middle", []], + \ ["startmiddle", ["startmiddleend", "startmiddlebar"]], + \ ["middleend", []], + \ ["endstart", ["end start", "start"]], + \ ["startprobar", ["startprebar", "start prebar", "startbar"]], + \ ["startnouend", ["start nouend", "startend"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff6, g:test_data_dic6) + call RunGoodBad("meea1 meea\xE9 bar prebar barbork prebarbork leadprebar lead end leadend leadmiddleend", + \ "bad: mee meea2 prabar probarbirk middle leadmiddle middleend endlead leadprobar", + \ ["bar", "barbork", "end", "lead", "meea1", "meea\xE9", "prebar", "prebarbork"], + \ [ + \ ["bad", ["bar", "end", "lead"]], + \ ["mee", ["meea1", "meea\xE9", "bar"]], + \ ["meea2", ["meea1", "meea\xE9", "lead"]], + \ ["prabar", ["prebar", "bar", "leadbar"]], + \ ["probarbirk", ["prebarbork"]], + \ ["middle", []], + \ ["leadmiddle", ["leadmiddleend", "leadmiddlebar"]], + \ ["middleend", []], + \ ["endlead", ["end lead", "lead", "end end"]], + \ ["leadprobar", ["leadprebar", "lead prebar", "leadbar"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff7, g:test_data_dic7) + call RunGoodBad("meea1 meea\xE9 bar prebar barmeat prebarmeat leadprebar lead tail leadtail leadmiddletail", + \ "bad: mee meea2 prabar probarmaat middle leadmiddle middletail taillead leadprobar", + \ ["bar", "barmeat", "lead", "meea1", "meea\xE9", "prebar", "prebarmeat", "tail"], + \ [ + \ ["bad", ["bar", "lead", "tail"]], + \ ["mee", ["meea1", "meea\xE9", "bar"]], + \ ["meea2", ["meea1", "meea\xE9", "lead"]], + \ ["prabar", ["prebar", "bar", "leadbar"]], + \ ["probarmaat", ["prebarmeat"]], + \ ["middle", []], + \ ["leadmiddle", ["leadmiddlebar"]], + \ ["middletail", []], + \ ["taillead", ["tail lead", "tail"]], + \ ["leadprobar", ["leadprebar", "lead prebar", "leadbar"]], + \ ]) +endfunc + +func Test_zz_NOSLITSUGS() + call LoadAffAndDic(g:test_data_aff8, g:test_data_dic8) + call RunGoodBad("foo bar faabar", "bad: foobar barfoo", + \ ["bar", "faabar", "foo"], + \ [ + \ ["bad", ["bar", "foo"]], + \ ["foobar", ["faabar", "foo bar", "bar"]], + \ ["barfoo", ["bar foo", "bar", "foo"]], + \ ]) +endfunc + +" Numbers +func Test_zz_Numbers() + call LoadAffAndDic(g:test_data_aff9, g:test_data_dic9) + call RunGoodBad("0b1011 0777 1234 0x01ff", "", + \ ["bar", "foo"], + \ [ + \ ]) +endfunc + +function FirstSpellWord() + call feedkeys("/^start:\n", 'tx') + normal ]smm + let [str, a] = spellbadword() + return str +endfunc + +function SecondSpellWord() + normal `m]s + let [str, a] = spellbadword() + return str +endfunc + +"Test with SAL instead of SOFO items; test automatic reloading +func Test_zz_sal_and_addition() + throw 'skipped: Nvim does not support enc=latin1' + set enc=latin1 + set spellfile= + call writefile(g:test_data_dic1, "Xtest.dic") + call writefile(g:test_data_aff_sal, "Xtest.aff") + mkspell! Xtest Xtest + set spl=Xtest.latin1.spl spell + call assert_equal('kbltykk', soundfold('goobledygoook')) + call assert_equal('kprnfn', soundfold('koprnven')) + call assert_equal('*fls kswts tl', soundfold('oeverloos gezwets edale')) + + "also use an addition file + call writefile(["/regions=usgbnz", "elequint/2", "elekwint/3"], "Xtest.latin1.add") + mkspell! Xtest.latin1.add.spl Xtest.latin1.add + + bwipe! + call setline(1, ["start: elequint test elekwint test elekwent asdf"]) + + set spellfile=Xtest.latin1.add + call assert_equal("elekwent", FirstSpellWord()) + + set spl=Xtest_us.latin1.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwint", SecondSpellWord()) + + set spl=Xtest_gb.latin1.spl + call assert_equal("elekwint", FirstSpellWord()) + call assert_equal("elekwent", SecondSpellWord()) + + set spl=Xtest_nz.latin1.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwent", SecondSpellWord()) + + set spl=Xtest_ca.latin1.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwint", SecondSpellWord()) +endfunc + +func Test_region_error() + messages clear + call writefile(["/regions=usgbnz", "elequint/0"], "Xtest.latin1.add") + mkspell! Xtest.latin1.add.spl Xtest.latin1.add + call assert_match('Invalid region nr in Xtest.latin1.add line 2: 0', execute('messages')) + call delete('Xtest.latin1.add') + call delete('Xtest.latin1.add.spl') +endfunc + +" Check using z= in new buffer (crash fixed by patch 7.4a.028). +func Test_zeq_crash() + new + set maxmem=512 spell + call feedkeys('iasdz=:\"', 'tx') + + bwipe! +endfunc + +func LoadAffAndDic(aff_contents, dic_contents) + throw 'skipped: Nvim does not support enc=latin1' + set enc=latin1 + set spellfile= + call writefile(a:aff_contents, "Xtest.aff") + call writefile(a:dic_contents, "Xtest.dic") + " Generate a .spl file from a .dic and .aff file. + mkspell! Xtest Xtest + " use that spell file + set spl=Xtest.latin1.spl spell +endfunc + +func ListWords() + spelldump + %yank + quit + return split(@", "\n") +endfunc + +func TestGoodBadBase() + exe '1;/^good:' + normal 0f:]s + let prevbad = '' + let result = [] + while 1 + let [bad, a] = spellbadword() + if bad == '' || bad == prevbad || bad == 'badend' + break + endif + let prevbad = bad + let lst = spellsuggest(bad, 3) + normal mm + + call add(result, [bad, lst]) + normal `m]s + endwhile + return result +endfunc + +func RunGoodBad(good, bad, expected_words, expected_bad_words) + bwipe! + call setline(1, ["good: ", a:good, a:bad, " badend "]) + let words = ListWords() + call assert_equal(a:expected_words, words[1:-1]) + let bad_words = TestGoodBadBase() + call assert_equal(a:expected_bad_words, bad_words) + bwipe! +endfunc + +let g:test_data_aff1 = [ + \"SET ISO8859-1", + \"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"SOFOFROM abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xBF", + \"SOFOTO ebctefghejklnnepkrstevvkesebctefghejklnnepkrstevvkeseeeeeeeceeeeeeeedneeeeeeeeeeepseeeeeeeeceeeeeeeedneeeeeeeeeeep?", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out .", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \ ] +let g:test_data_dic1 = [ + \"123456", + \"test/NO", + \"# comment", + \"wrong", + \"Comment", + \"OK", + \"uk", + \"put/ISO", + \"the end", + \"deol", + \"d\xE9\xF4r", + \ ] +let g:test_data_aff2 = [ + \"SET ISO8859-1", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"PFXPOSTPONE", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out [a-z]", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \ ] +let g:test_data_aff3 = [ + \"SET ISO8859-1", + \"", + \"COMPOUNDMIN 3", + \"COMPOUNDRULE m*", + \"NEEDCOMPOUND x", + \ ] +let g:test_data_dic3 = [ + \"1234", + \"foo/m", + \"bar/mx", + \"m\xEF/m", + \"la/mx", + \ ] +let g:test_data_aff4 = [ + \"SET ISO8859-1", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"COMPOUNDRULE m+", + \"COMPOUNDRULE sm*e", + \"COMPOUNDRULE sm+", + \"COMPOUNDMIN 3", + \"COMPOUNDWORDMAX 3", + \"COMPOUNDFORBIDFLAG t", + \"", + \"COMPOUNDSYLMAX 5", + \"SYLLABLE a\xE1e\xE9i\xEDo\xF3\xF6\xF5u\xFA\xFC\xFBy/aa/au/ea/ee/ei/ie/oa/oe/oo/ou/uu/ui", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \"", + \"NEEDAFFIX x", + \"", + \"PFXPOSTPONE", + \"", + \"MIDWORD '-", + \"", + \"SFX q N 1", + \"SFX q 0 -ok .", + \"", + \"SFX a Y 2", + \"SFX a 0 s .", + \"SFX a 0 ize/t .", + \"", + \"PFX p N 1", + \"PFX p 0 pre .", + \"", + \"PFX P N 1", + \"PFX P 0 nou .", + \ ] +let g:test_data_dic4 = [ + \"1234", + \"word/mP", + \"util/am", + \"pro/xq", + \"tomato/m", + \"bork/mp", + \"start/s", + \"end/e", + \ ] +let g:test_data_aff5 = [ + \"SET ISO8859-1", + \"", + \"FLAG long", + \"", + \"NEEDAFFIX !!", + \"", + \"COMPOUNDRULE ssmm*ee", + \"", + \"NEEDCOMPOUND xx", + \"COMPOUNDPERMITFLAG pp", + \"", + \"SFX 13 Y 1", + \"SFX 13 0 bork .", + \"", + \"SFX a1 Y 1", + \"SFX a1 0 a1 .", + \"", + \"SFX a\xE9 Y 1", + \"SFX a\xE9 0 a\xE9 .", + \"", + \"PFX zz Y 1", + \"PFX zz 0 pre/pp .", + \"", + \"PFX yy Y 1", + \"PFX yy 0 nou .", + \ ] +let g:test_data_dic5 = [ + \"1234", + \"foo/a1a\xE9!!", + \"bar/zz13ee", + \"start/ss", + \"end/eeyy", + \"middle/mmxx", + \ ] +let g:test_data_aff6 = [ + \"SET ISO8859-1", + \"", + \"FLAG caplong", + \"", + \"NEEDAFFIX A!", + \"", + \"COMPOUNDRULE sMm*Ee", + \"", + \"NEEDCOMPOUND Xx", + \"", + \"COMPOUNDPERMITFLAG p", + \"", + \"SFX N3 Y 1", + \"SFX N3 0 bork .", + \"", + \"SFX A1 Y 1", + \"SFX A1 0 a1 .", + \"", + \"SFX A\xE9 Y 1", + \"SFX A\xE9 0 a\xE9 .", + \"", + \"PFX Zz Y 1", + \"PFX Zz 0 pre/p .", + \ ] +let g:test_data_dic6 = [ + \"1234", + \"mee/A1A\xE9A!", + \"bar/ZzN3Ee", + \"lead/s", + \"end/Ee", + \"middle/MmXx", + \ ] +let g:test_data_aff7 = [ + \"SET ISO8859-1", + \"", + \"FLAG num", + \"", + \"NEEDAFFIX 9999", + \"", + \"COMPOUNDRULE 2,77*123", + \"", + \"NEEDCOMPOUND 1", + \"COMPOUNDPERMITFLAG 432", + \"", + \"SFX 61003 Y 1", + \"SFX 61003 0 meat .", + \"", + \"SFX 391 Y 1", + \"SFX 391 0 a1 .", + \"", + \"SFX 111 Y 1", + \"SFX 111 0 a\xE9 .", + \"", + \"PFX 17 Y 1", + \"PFX 17 0 pre/432 .", + \ ] +let g:test_data_dic7 = [ + \"1234", + \"mee/391,111,9999", + \"bar/17,61003,123", + \"lead/2", + \"tail/123", + \"middle/77,1", + \ ] +let g:test_data_aff8 = [ + \"SET ISO8859-1", + \"", + \"NOSPLITSUGS", + \ ] +let g:test_data_dic8 = [ + \"1234", + \"foo", + \"bar", + \"faabar", + \ ] +let g:test_data_aff9 = [ + \ ] +let g:test_data_dic9 = [ + \"1234", + \"foo", + \"bar", + \ ] +let g:test_data_aff_sal = [ + \"SET ISO8859-1", + \"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out .", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \"", + \"SAL AH(AEIOUY)-^ *H", + \"SAL AR(AEIOUY)-^ *R", + \"SAL A(HR)^ *", + \"SAL A^ *", + \"SAL AH(AEIOUY)- H", + \"SAL AR(AEIOUY)- R", + \"SAL A(HR) _", + \"SAL \xC0^ *", + \"SAL \xC5^ *", + \"SAL BB- _", + \"SAL B B", + \"SAL CQ- _", + \"SAL CIA X", + \"SAL CH X", + \"SAL C(EIY)- S", + \"SAL CK K", + \"SAL COUGH^ KF", + \"SAL CC< C", + \"SAL C K", + \"SAL DG(EIY) K", + \"SAL DD- _", + \"SAL D T", + \"SAL \xC9< E", + \"SAL EH(AEIOUY)-^ *H", + \"SAL ER(AEIOUY)-^ *R", + \"SAL E(HR)^ *", + \"SAL ENOUGH^$ *NF", + \"SAL E^ *", + \"SAL EH(AEIOUY)- H", + \"SAL ER(AEIOUY)- R", + \"SAL E(HR) _", + \"SAL FF- _", + \"SAL F F", + \"SAL GN^ N", + \"SAL GN$ N", + \"SAL GNS$ NS", + \"SAL GNED$ N", + \"SAL GH(AEIOUY)- K", + \"SAL GH _", + \"SAL GG9 K", + \"SAL G K", + \"SAL H H", + \"SAL IH(AEIOUY)-^ *H", + \"SAL IR(AEIOUY)-^ *R", + \"SAL I(HR)^ *", + \"SAL I^ *", + \"SAL ING6 N", + \"SAL IH(AEIOUY)- H", + \"SAL IR(AEIOUY)- R", + \"SAL I(HR) _", + \"SAL J K", + \"SAL KN^ N", + \"SAL KK- _", + \"SAL K K", + \"SAL LAUGH^ LF", + \"SAL LL- _", + \"SAL L L", + \"SAL MB$ M", + \"SAL MM M", + \"SAL M M", + \"SAL NN- _", + \"SAL N N", + \"SAL OH(AEIOUY)-^ *H", + \"SAL OR(AEIOUY)-^ *R", + \"SAL O(HR)^ *", + \"SAL O^ *", + \"SAL OH(AEIOUY)- H", + \"SAL OR(AEIOUY)- R", + \"SAL O(HR) _", + \"SAL PH F", + \"SAL PN^ N", + \"SAL PP- _", + \"SAL P P", + \"SAL Q K", + \"SAL RH^ R", + \"SAL ROUGH^ RF", + \"SAL RR- _", + \"SAL R R", + \"SAL SCH(EOU)- SK", + \"SAL SC(IEY)- S", + \"SAL SH X", + \"SAL SI(AO)- X", + \"SAL SS- _", + \"SAL S S", + \"SAL TI(AO)- X", + \"SAL TH @", + \"SAL TCH-- _", + \"SAL TOUGH^ TF", + \"SAL TT- _", + \"SAL T T", + \"SAL UH(AEIOUY)-^ *H", + \"SAL UR(AEIOUY)-^ *R", + \"SAL U(HR)^ *", + \"SAL U^ *", + \"SAL UH(AEIOUY)- H", + \"SAL UR(AEIOUY)- R", + \"SAL U(HR) _", + \"SAL V^ W", + \"SAL V F", + \"SAL WR^ R", + \"SAL WH^ W", + \"SAL W(AEIOU)- W", + \"SAL X^ S", + \"SAL X KS", + \"SAL Y(AEIOU)- Y", + \"SAL ZZ- _", + \"SAL Z S", + \ ] diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 5996b2cd4a..11e26d03aa 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -24,28 +24,34 @@ func Test_after_comes_later() \ 'set guioptions+=M', \ 'let $HOME = "/does/not/exist"', \ 'set loadplugins', - \ 'set rtp=Xhere,Xafter', + \ 'set rtp=Xhere,Xafter,Xanother', \ 'set packpath=Xhere,Xafter', \ 'set nomore', + \ 'let g:sequence = ""', \ ] let after = [ \ 'redir! > Xtestout', \ 'scriptnames', \ 'redir END', + \ 'redir! > Xsequence', + \ 'echo g:sequence', + \ 'redir END', \ 'quit', \ ] call mkdir('Xhere/plugin', 'p') - call writefile(['let done = 1'], 'Xhere/plugin/here.vim') + call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim') + call mkdir('Xanother/plugin', 'p') + call writefile(['let g:sequence .= "another "'], 'Xanother/plugin/another.vim') call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p') - call writefile(['let done = 1'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') + call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim') call mkdir('Xafter/plugin', 'p') - call writefile(['let done = 1'], 'Xafter/plugin/later.vim') + call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim') if RunVim(before, after, '') let lines = readfile('Xtestout') - let expected = ['Xbefore.vim', 'here.vim', 'foo.vim', 'later.vim', 'Xafter.vim'] + let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim'] let found = [] for line in lines for one in expected @@ -57,11 +63,47 @@ func Test_after_comes_later() call assert_equal(expected, found) endif + call assert_equal('here another pack after', substitute(join(readfile('Xsequence', 1), ''), '\s\+$', '', '')) + call delete('Xtestout') + call delete('Xsequence') call delete('Xhere', 'rf') + call delete('Xanother', 'rf') call delete('Xafter', 'rf') endfunc +func Test_pack_in_rtp_when_plugins_run() + if !has('packages') + return + endif + let before = [ + \ 'set nocp viminfo+=nviminfo', + \ 'set guioptions+=M', + \ 'let $HOME = "/does/not/exist"', + \ 'set loadplugins', + \ 'set rtp=Xhere', + \ 'set packpath=Xhere', + \ 'set nomore', + \ ] + let after = [ + \ 'quit', + \ ] + call mkdir('Xhere/plugin', 'p') + call writefile(['redir! > Xtestout', 'silent set runtimepath?', 'silent! call foo#Trigger()', 'redir END'], 'Xhere/plugin/here.vim') + call mkdir('Xhere/pack/foo/start/foobar/autoload', 'p') + call writefile(['function! foo#Trigger()', 'echo "autoloaded foo"', 'endfunction'], 'Xhere/pack/foo/start/foobar/autoload/foo.vim') + + if RunVim(before, after, '') + + let lines = filter(readfile('Xtestout'), '!empty(v:val)') + call assert_match('Xhere[/\\]pack[/\\]foo[/\\]start[/\\]foobar', get(lines, 0)) + call assert_match('autoloaded foo', get(lines, 1)) + endif + + call delete('Xtestout') + call delete('Xhere', 'rf') +endfunc + func Test_help_arg() if !has('unix') && has('gui') " this doesn't work with gvim on MS-Windows @@ -75,12 +117,12 @@ func Test_help_arg() " check if couple of lines are there let found = [] for line in lines - if line =~ '-R.*Readonly mode' - call add(found, 'Readonly mode') + if line =~ '-R.*Read-only mode' + call add(found, 'Readonly mode') endif " Watch out for a second --version line in the Gnome version. - if line =~ '--version.*Print version information and exit' - call add(found, "--version") + if line =~ '--version.*Print version information' + call add(found, "--version") endif endfor call assert_equal(['Readonly mode', '--version'], found) diff --git a/src/nvim/testdir/test_startup_utf8.vim b/src/nvim/testdir/test_startup_utf8.vim new file mode 100644 index 0000000000..d179a4cc79 --- /dev/null +++ b/src/nvim/testdir/test_startup_utf8.vim @@ -0,0 +1,64 @@ +" Tests for startup using utf-8. +if !has('multi_byte') + finish +endif + +source shared.vim + +func Test_read_stdin_utf8() + let linesin = ['テスト', '€ÀÈÌÒÙ'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if has('win32') + let pipecmd = 'type Xtestin | ' + else + let pipecmd = 'cat Xtestin | ' + endif + if RunVimPiped(before, after, '-', pipecmd) + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVimPiped failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc + +func Test_read_fifo_utf8() + if !has('unix') + return + endif + " Using bash/zsh's process substitution. + if executable('bash') + set shell=bash + elseif executable('zsh') + set shell=zsh + else + return + endif + let linesin = ['テスト', '€ÀÈÌÒÙ'] + call writefile(linesin, 'Xtestin') + let before = [ + \ 'set enc=utf-8', + \ 'set fencs=cp932,utf-8', + \ ] + let after = [ + \ 'write ++enc=utf-8 Xtestout', + \ 'quit!', + \ ] + if RunVim(before, after, '<(cat Xtestin)') + let lines = readfile('Xtestout') + call assert_equal(linesin, lines) + else + call assert_equal('', 'RunVim failed.') + endif + call delete('Xtestout') + call delete('Xtestin') +endfunc diff --git a/src/nvim/testdir/test_stat.vim b/src/nvim/testdir/test_stat.vim index 89ca9ef379..1239fe9427 100644 --- a/src/nvim/testdir/test_stat.vim +++ b/src/nvim/testdir/test_stat.vim @@ -1,24 +1,45 @@ " Tests for stat functions and checktime -func Test_existent_file() - let fname='Xtest.tmp' +func CheckFileTime(doSleep) + let fname = 'Xtest.tmp' + let result = 0 - let ts=localtime() - sleep 1 - let fl=['Hello World!'] + let ts = localtime() + if a:doSleep + sleep 1 + endif + let fl = ['Hello World!'] call writefile(fl, fname) - let tf=getftime(fname) - sleep 1 - let te=localtime() + let tf = getftime(fname) + if a:doSleep + sleep 1 + endif + let te = localtime() + + let time_correct = (ts <= tf && tf <= te) + if a:doSleep || time_correct + call assert_true(time_correct) + call assert_equal(strlen(fl[0] . "\n"), getfsize(fname)) + call assert_equal('file', getftype(fname)) + call assert_equal('rw-', getfperm(fname)[0:2]) + let result = 1 + endif + + call delete(fname) + return result +endfunc - call assert_true(ts <= tf && tf <= te) - call assert_equal(strlen(fl[0] . "\n"), getfsize(fname)) - call assert_equal('file', getftype(fname)) - call assert_equal('rw-', getfperm(fname)[0:2]) +func Test_existent_file() + " On some systems the file timestamp is rounded to a multiple of 2 seconds. + " We need to sleep to handle that, but that makes the test slow. First try + " without the sleep, and if it fails try again with the sleep. + if CheckFileTime(0) == 0 + call CheckFileTime(1) + endif endfunc func Test_existent_directory() - let dname='.' + let dname = '.' call assert_equal(0, getfsize(dname)) call assert_equal('dir', getftype(dname)) @@ -26,22 +47,29 @@ func Test_existent_directory() endfunc func Test_checktime() - let fname='Xtest.tmp' + let fname = 'Xtest.tmp' - let fl=['Hello World!'] + let fl = ['Hello World!'] call writefile(fl, fname) set autoread exec 'e' fname - sleep 2 - let fl=readfile(fname) + " FAT has a granularity of 2 seconds, otherwise it's usually 1 second + if has('win32') + sleep 2 + else + sleep 2 + endif + let fl = readfile(fname) let fl[0] .= ' - checktime' call writefile(fl, fname) checktime call assert_equal(fl[0], getline(1)) + + call delete(fname) endfunc func Test_nonexistent_file() - let fname='Xtest.tmp' + let fname = 'Xtest.tmp' call delete(fname) call assert_equal(-1, getftime(fname)) @@ -55,7 +83,7 @@ func Test_win32_symlink_dir() " So we use an existing symlink for this test. if has('win32') " Check if 'C:\Users\All Users' is a symlink to a directory. - let res=system('dir C:\Users /a') + let res = system('dir C:\Users /a') if match(res, '\C<SYMLINKD> *All Users') >= 0 " Get the filetype of the symlink. call assert_equal('dir', getftype('C:\Users\All Users')) diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim index 82898df92d..cf85bd58ac 100644 --- a/src/nvim/testdir/test_statusline.vim +++ b/src/nvim/testdir/test_statusline.vim @@ -1,19 +1,39 @@ -function! StatuslineWithCaughtError() +" Test 'statusline' +" +" Not tested yet: +" %a +" %N +" %T +" %X +" %* + +source view_util.vim + +func s:get_statusline() + return ScreenLines(&lines - 1, &columns)[0] +endfunc + +func StatuslineWithCaughtError() let s:func_in_statusline_called = 1 try call eval('unknown expression') catch endtry return '' -endfunction +endfunc -function! StatuslineWithError() +func StatuslineWithError() let s:func_in_statusline_called = 1 call eval('unknown expression') return '' -endfunction +endfunc -function! Test_caught_error_in_statusline() +" Function used to display syntax group. +func SyntaxItem() + return synIDattr(synID(line("."),col("."),1),"name") +endfunc + +func Test_caught_error_in_statusline() let s:func_in_statusline_called = 0 set laststatus=2 let statusline = '%{StatuslineWithCaughtError()}' @@ -22,9 +42,9 @@ function! Test_caught_error_in_statusline() call assert_true(s:func_in_statusline_called) call assert_equal(statusline, &statusline) set statusline= -endfunction +endfunc -function! Test_statusline_will_be_disabled_with_error() +func Test_statusline_will_be_disabled_with_error() let s:func_in_statusline_called = 0 set laststatus=2 let statusline = '%{StatuslineWithError()}' @@ -36,4 +56,219 @@ function! Test_statusline_will_be_disabled_with_error() call assert_true(s:func_in_statusline_called) call assert_equal('', &statusline) set statusline= -endfunction +endfunc + +func Test_statusline() + new Xstatusline + only + set laststatus=2 + set splitbelow + call setline(1, range(1, 200)) + + " %b: Value of character under cursor. + " %B: As above, in hexadecimal. + call cursor(180, 2) + set statusline=%b,%B + call assert_match('^56,38\s*$', s:get_statusline()) + + " %o: Byte number in file of byte under cursor, first byte is 1. + " %O: As above, in hexadecimal. + set statusline=%o,%O + set fileformat=dos + call assert_match('^789,315\s*$', s:get_statusline()) + set fileformat=mac + call assert_match('^610,262\s*$', s:get_statusline()) + set fileformat=unix + call assert_match('^610,262\s*$', s:get_statusline()) + set fileformat& + + " %f: Path to the file in the buffer, as typed or relative to current dir. + set statusline=%f + call assert_match('^Xstatusline\s*$', s:get_statusline()) + + " %F: Full path to the file in the buffer. + set statusline=%F + call assert_match('/testdir/Xstatusline\s*$', s:get_statusline()) + + " %h: Help buffer flag, text is "[help]". + " %H: Help buffer flag, text is ",HLP". + set statusline=%h,%H + call assert_match('^,\s*$', s:get_statusline()) + help + call assert_match('^\[Help\],HLP\s*$', s:get_statusline()) + helpclose + + " %k: Value of "b:keymap_name" or 'keymap' + " when :lmap mappings are being used: <keymap>" + set statusline=%k + if has('keymap') + set keymap=esperanto + call assert_match('^<Eo>\s*$', s:get_statusline()) + set keymap& + else + call assert_match('^\s*$', s:get_statusline()) + endif + + " %l: Line number. + " %L: Number of line in buffer. + " %c: Column number. + set statusline=%l/%L,%c + call assert_match('^180/200,2\s*$', s:get_statusline()) + + " %m: Modified flag, text is "[+]", "[-]" if 'modifiable' is off. + " %M: Modified flag, text is ",+" or ",-". + set statusline=%m%M + call assert_match('^\[+\],+\s*$', s:get_statusline()) + set nomodifiable + call assert_match('^\[+-\],+-\s*$', s:get_statusline()) + write + call assert_match('^\[-\],-\s*$', s:get_statusline()) + set modifiable& + call assert_match('^\s*$', s:get_statusline()) + + " %n: Buffer number. + set statusline=%n + call assert_match('^'.bufnr('%').'\s*$', s:get_statusline()) + + " %p: Percentage through file in lines as in CTRL-G. + " %P: Percentage through file of displayed window. + set statusline=%p,%P + 0 + call assert_match('^0,Top\s*$', s:get_statusline()) + norm G + call assert_match('^100,Bot\s*$', s:get_statusline()) + 180 + " Don't check the exact percentage as it depends on the window size + call assert_match('^90,\(Top\|Bot\|\d\+%\)\s*$', s:get_statusline()) + + " %q: "[Quickfix List]", "[Location List]" or empty. + set statusline=%q + call assert_match('^\s*$', s:get_statusline()) + copen + call assert_match('^\[Quickfix List\]\s*$', s:get_statusline()) + cclose + lexpr getline(1, 2) + lopen + call assert_match('^\[Location List\]\s*$', s:get_statusline()) + lclose + + " %r: Readonly flag, text is "[RO]". + " %R: Readonly flag, text is ",RO". + set statusline=%r,%R + call assert_match('^,\s*$', s:get_statusline()) + help + call assert_match('^\[RO\],RO\s*$', s:get_statusline()) + helpclose + + " %t: File name (tail) of file in the buffer. + set statusline=%t + call assert_match('^Xstatusline\s*$', s:get_statusline()) + + " %v: Virtual column number. + " %V: Virtual column number as -{num}. Not displayed if equal to 'c'. + call cursor(180, 2) + set statusline=%v,%V + call assert_match('^2,\s*$', s:get_statusline()) + set virtualedit=all + norm 10| + call assert_match('^10,-10\s*$', s:get_statusline()) + set virtualedit& + + " %w: Preview window flag, text is "[Preview]". + " %W: Preview window flag, text is ",PRV". + set statusline=%w%W + call assert_match('^\s*$', s:get_statusline()) + pedit + wincmd j + call assert_match('^\[Preview\],PRV\s*$', s:get_statusline()) + pclose + + " %y: Type of file in the buffer, e.g., "[vim]". See 'filetype'. + " %Y: Type of file in the buffer, e.g., ",VIM". See 'filetype'. + set statusline=%y\ %Y + call assert_match('^\s*$', s:get_statusline()) + setfiletype vim + call assert_match('^\[vim\] VIM\s*$', s:get_statusline()) + + " %=: Separation point between left and right aligned items. + set statusline=foo%=bar + call assert_match('^foo\s\+bar\s*$', s:get_statusline()) + + " Test min/max width, leading zeroes, left/right justify. + set statusline=%04B + call cursor(180, 2) + call assert_match('^0038\s*$', s:get_statusline()) + set statusline=#%4B# + call assert_match('^# 38#\s*$', s:get_statusline()) + set statusline=#%-4B# + call assert_match('^#38 #\s*$', s:get_statusline()) + set statusline=%.6f + call assert_match('^<sline\s*$', s:get_statusline()) + + " %<: Where to truncate. + exe 'set statusline=a%<b' . repeat('c', 1000) . 'd' + call assert_match('^a<c*d$', s:get_statusline()) + exe 'set statusline=a' . repeat('b', 1000) . '%<c' + call assert_match('^ab*>$', s:get_statusline()) + + "%{: Evaluate expression between '%{' and '}' and substitute result. + syntax on + set statusline=%{SyntaxItem()} + call assert_match('^vimNumber\s*$', s:get_statusline()) + s/^/"/ + call assert_match('^vimLineComment\s*$', s:get_statusline()) + syntax off + + "%(: Start of item group. + set statusline=ab%(cd%q%)de + call assert_match('^abde\s*$', s:get_statusline()) + copen + call assert_match('^abcd\[Quickfix List\1]de\s*$', s:get_statusline()) + cclose + + " %#: Set highlight group. The name must follow and then a # again. + set statusline=ab%#Todo#cd%#Error#ef + call assert_match('^abcdef\s*$', s:get_statusline()) + let sa1=screenattr(&lines - 1, 1) + let sa2=screenattr(&lines - 1, 3) + let sa3=screenattr(&lines - 1, 5) + call assert_notequal(sa1, sa2) + call assert_notequal(sa1, sa3) + call assert_notequal(sa2, sa3) + call assert_equal(sa1, screenattr(&lines - 1, 2)) + call assert_equal(sa2, screenattr(&lines - 1, 4)) + call assert_equal(sa3, screenattr(&lines - 1, 6)) + call assert_equal(sa3, screenattr(&lines - 1, 7)) + + " %*: Set highlight group to User{N} + set statusline=a%1*b%0*c + call assert_match('^abc\s*$', s:get_statusline()) + let sa1=screenattr(&lines - 1, 1) + let sa2=screenattr(&lines - 1, 2) + let sa3=screenattr(&lines - 1, 3) + call assert_equal(sa1, sa3) + call assert_notequal(sa1, sa2) + + " %%: a percent sign. + set statusline=10%% + call assert_match('^10%\s*$', s:get_statusline()) + + " %!: evaluated expression is used as the option value + set statusline=%!2*3+1 + call assert_match('7\s*$', s:get_statusline()) + + " Check statusline in current and non-current window + " with the 'fillchars' option. + set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- + vsplit + set statusline=x%=y + call assert_match('^x^\+y^x=\+y$', s:get_statusline()) + set fillchars& + close + + %bw! + call delete('Xstatusline') + set statusline& + set laststatus& + set splitbelow& +endfunc diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index e2b6de03c3..75ce24de46 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -39,3 +39,285 @@ function! Test_multiline_subst() call assert_equal('xxxxx', getline(13)) enew! endfunction + +function! Test_substitute_variants() + " Validate that all the 2-/3-letter variants which embed the flags into the + " command name actually work. + enew! + let ln = 'Testing string' + let variants = [ + \ { 'cmd': ':s/Test/test/c', 'exp': 'testing string', 'prompt': 'y' }, + \ { 'cmd': ':s/foo/bar/ce', 'exp': ln }, + \ { 'cmd': ':s/t/r/cg', 'exp': 'Tesring srring', 'prompt': 'a' }, + \ { 'cmd': ':s/t/r/ci', 'exp': 'resting string', 'prompt': 'y' }, + \ { 'cmd': ':s/t/r/cI', 'exp': 'Tesring string', 'prompt': 'y' }, + \ { 'cmd': ':s/t/r/cn', 'exp': ln }, + \ { 'cmd': ':s/t/r/cp', 'exp': 'Tesring string', 'prompt': 'y' }, + \ { 'cmd': ':s/t/r/cl', 'exp': 'Tesring string', 'prompt': 'y' }, + \ { 'cmd': ':s/t/r/gc', 'exp': 'Tesring srring', 'prompt': 'a' }, + \ { 'cmd': ':s/foo/bar/ge', 'exp': ln }, + \ { 'cmd': ':s/t/r/g', 'exp': 'Tesring srring' }, + \ { 'cmd': ':s/t/r/gi', 'exp': 'resring srring' }, + \ { 'cmd': ':s/t/r/gI', 'exp': 'Tesring srring' }, + \ { 'cmd': ':s/t/r/gn', 'exp': ln }, + \ { 'cmd': ':s/t/r/gp', 'exp': 'Tesring srring' }, + \ { 'cmd': ':s/t/r/gl', 'exp': 'Tesring srring' }, + \ { 'cmd': ':s//r/gr', 'exp': 'Testr strr' }, + \ { 'cmd': ':s/t/r/ic', 'exp': 'resting string', 'prompt': 'y' }, + \ { 'cmd': ':s/foo/bar/ie', 'exp': ln }, + \ { 'cmd': ':s/t/r/i', 'exp': 'resting string' }, + \ { 'cmd': ':s/t/r/iI', 'exp': 'Tesring string' }, + \ { 'cmd': ':s/t/r/in', 'exp': ln }, + \ { 'cmd': ':s/t/r/ip', 'exp': 'resting string' }, + \ { 'cmd': ':s//r/ir', 'exp': 'Testr string' }, + \ { 'cmd': ':s/t/r/Ic', 'exp': 'Tesring string', 'prompt': 'y' }, + \ { 'cmd': ':s/foo/bar/Ie', 'exp': ln }, + \ { 'cmd': ':s/t/r/Ig', 'exp': 'Tesring srring' }, + \ { 'cmd': ':s/t/r/Ii', 'exp': 'resting string' }, + \ { 'cmd': ':s/t/r/I', 'exp': 'Tesring string' }, + \ { 'cmd': ':s/t/r/Ip', 'exp': 'Tesring string' }, + \ { 'cmd': ':s/t/r/Il', 'exp': 'Tesring string' }, + \ { 'cmd': ':s//r/Ir', 'exp': 'Testr string' }, + \ { 'cmd': ':s//r/rc', 'exp': 'Testr string', 'prompt': 'y' }, + \ { 'cmd': ':s//r/rg', 'exp': 'Testr strr' }, + \ { 'cmd': ':s//r/ri', 'exp': 'Testr string' }, + \ { 'cmd': ':s//r/rI', 'exp': 'Testr string' }, + \ { 'cmd': ':s//r/rn', 'exp': 'Testing string' }, + \ { 'cmd': ':s//r/rp', 'exp': 'Testr string' }, + \ { 'cmd': ':s//r/rl', 'exp': 'Testr string' }, + \ { 'cmd': ':s//r/r', 'exp': 'Testr string' }, + \] + + for var in variants + for run in [1, 2] + let cmd = var.cmd + if run == 2 && cmd =~ "/.*/.*/." + " Change :s/from/to/{flags} to :s{flags} + let cmd = substitute(cmd, '/.*/', '', '') + endif + call setline(1, [ln]) + let msg = printf('using "%s"', cmd) + let @/='ing' + let v:errmsg = '' + call feedkeys(cmd . "\<CR>" . get(var, 'prompt', ''), 'ntx') + " No error should exist (matters for testing e flag) + call assert_equal('', v:errmsg, msg) + call assert_equal(var.exp, getline('.'), msg) + endfor + endfor +endfunction + +func Test_substitute_repeat() + " This caused an invalid memory access. + split Xfile + s/^/x + call feedkeys("Qsc\<CR>y", 'tx') + bwipe! +endfunc + +" Tests for *sub-replace-special* and *sub-replace-expression* on :substitute. + +" Execute a list of :substitute command tests +func Run_SubCmd_Tests(tests) + enew! + for t in a:tests + let start = line('.') + 1 + let end = start + len(t[2]) - 1 + exe "normal o" . t[0] + call cursor(start, 1) + exe t[1] + call assert_equal(t[2], getline(start, end), t[1]) + endfor + enew! +endfunc + +func Test_sub_cmd_1() + set magic + set cpo& + + " List entry format: [input, cmd, output] + let tests = [['A', 's/A/&&/', ['AA']], + \ ['B', 's/B/\&/', ['&']], + \ ['C123456789', 's/C\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\0\9\8\7\6\5\4\3\2\1/', ['C123456789987654321']], + \ ['D', 's/D/d/', ['d']], + \ ['E', 's/E/~/', ['d']], + \ ['F', 's/F/\~/', ['~']], + \ ['G', 's/G/\ugg/', ['Gg']], + \ ['H', 's/H/\Uh\Eh/', ['Hh']], + \ ['I', 's/I/\lII/', ['iI']], + \ ['J', 's/J/\LJ\EJ/', ['jJ']], + \ ['K', 's/K/\Uk\ek/', ['Kk']], + \ ['lLl', "s/L/\<C-V>\<C-M>/", ["l\<C-V>", 'l']], + \ ['mMm', 's/M/\r/', ['m', 'm']], + \ ['nNn', "s/N/\\\<C-V>\<C-M>/", ["n\<C-V>", 'n']], + \ ['oOo', 's/O/\n/', ["o\no"]], + \ ['pPp', 's/P/\b/', ["p\<C-H>p"]], + \ ['qQq', 's/Q/\t/', ["q\tq"]], + \ ['rRr', 's/R/\\/', ['r\r']], + \ ['sSs', 's/S/\c/', ['scs']], + \ ['tTt', "s/T/\<C-V>\<C-J>/", ["t\<C-V>\<C-J>t"]], + \ ['U', 's/U/\L\uuUu\l\EU/', ['UuuU']], + \ ['V', 's/V/\U\lVvV\u\Ev/', ['vVVv']] + \ ] + call Run_SubCmd_Tests(tests) +endfunc + +func Test_sub_cmd_2() + set nomagic + set cpo& + + " List entry format: [input, cmd, output] + let tests = [['A', 's/A/&&/', ['&&']], + \ ['B', 's/B/\&/', ['B']], + \ ['C123456789', 's/\mC\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\0\9\8\7\6\5\4\3\2\1/', ['C123456789987654321']], + \ ['D', 's/D/d/', ['d']], + \ ['E', 's/E/~/', ['~']], + \ ['F', 's/F/\~/', ['~']], + \ ['G', 's/G/\ugg/', ['Gg']], + \ ['H', 's/H/\Uh\Eh/', ['Hh']], + \ ['I', 's/I/\lII/', ['iI']], + \ ['J', 's/J/\LJ\EJ/', ['jJ']], + \ ['K', 's/K/\Uk\ek/', ['Kk']], + \ ['lLl', "s/L/\<C-V>\<C-M>/", ["l\<C-V>", 'l']], + \ ['mMm', 's/M/\r/', ['m', 'm']], + \ ['nNn', "s/N/\\\<C-V>\<C-M>/", ["n\<C-V>", 'n']], + \ ['oOo', 's/O/\n/', ["o\no"]], + \ ['pPp', 's/P/\b/', ["p\<C-H>p"]], + \ ['qQq', 's/Q/\t/', ["q\tq"]], + \ ['rRr', 's/R/\\/', ['r\r']], + \ ['sSs', 's/S/\c/', ['scs']], + \ ['tTt', "s/T/\<C-V>\<C-J>/", ["t\<C-V>\<C-J>t"]], + \ ['U', 's/U/\L\uuUu\l\EU/', ['UuuU']], + \ ['V', 's/V/\U\lVvV\u\Ev/', ['vVVv']] + \ ] + call Run_SubCmd_Tests(tests) +endfunc + +func Test_sub_cmd_3() + set nomagic + set cpo& + + " List entry format: [input, cmd, output] + let tests = [['aAa', "s/A/\\='\\'/", ['a\a']], + \ ['bBb', "s/B/\\='\\\\'/", ['b\\b']], + \ ['cCc', "s/C/\\='\<C-V>\<C-M>'/", ["c\<C-V>", 'c']], + \ ['dDd', "s/D/\\='\\\<C-V>\<C-M>'/", ["d\\\<C-V>", 'd']], + \ ['eEe', "s/E/\\='\\\\\<C-V>\<C-M>'/", ["e\\\\\<C-V>", 'e']], + \ ['fFf', "s/F/\\='\r'/", ['f', 'f']], + \ ['gGg', "s/G/\\='\<C-V>\<C-J>'/", ["g\<C-V>", 'g']], + \ ['hHh', "s/H/\\='\\\<C-V>\<C-J>'/", ["h\\\<C-V>", 'h']], + \ ['iIi', "s/I/\\='\\\\\<C-V>\<C-J>'/", ["i\\\\\<C-V>", 'i']], + \ ['jJj', "s/J/\\='\n'/", ['j', 'j']], + \ ['kKk', 's/K/\="\r"/', ['k', 'k']], + \ ['lLl', 's/L/\="\n"/', ['l', 'l']] + \ ] + call Run_SubCmd_Tests(tests) +endfunc + +" Test for submatch() on :substitue. +func Test_sub_cmd_4() + set magic& + set cpo& + + " List entry format: [input, cmd, output] + let tests = [ ['aAa', "s/A/\\=substitute(submatch(0), '.', '\\', '')/", + \ ['a\a']], + \ ['bBb', "s/B/\\=substitute(submatch(0), '.', '\\', '')/", + \ ['b\b']], + \ ['cCc', "s/C/\\=substitute(submatch(0), '.', '\<C-V>\<C-M>', '')/", + \ ["c\<C-V>", 'c']], + \ ['dDd', "s/D/\\=substitute(submatch(0), '.', '\\\<C-V>\<C-M>', '')/", + \ ["d\<C-V>", 'd']], + \ ['eEe', "s/E/\\=substitute(submatch(0), '.', '\\\\\<C-V>\<C-M>', '')/", + \ ["e\\\<C-V>", 'e']], + \ ['fFf', "s/F/\\=substitute(submatch(0), '.', '\\r', '')/", + \ ['f', 'f']], + \ ['gGg', 's/G/\=substitute(submatch(0), ".", "\<C-V>\<C-J>", "")/', + \ ["g\<C-V>", 'g']], + \ ['hHh', 's/H/\=substitute(submatch(0), ".", "\\\<C-V>\<C-J>", "")/', + \ ["h\<C-V>", 'h']], + \ ['iIi', 's/I/\=substitute(submatch(0), ".", "\\\\\<C-V>\<C-J>", "")/', + \ ["i\\\<C-V>", 'i']], + \ ['jJj', "s/J/\\=substitute(submatch(0), '.', '\\n', '')/", + \ ['j', 'j']], + \ ['kKk', "s/K/\\=substitute(submatch(0), '.', '\\r', '')/", + \ ['k', 'k']], + \ ['lLl', "s/L/\\=substitute(submatch(0), '.', '\\n', '')/", + \ ['l', 'l']], + \ ] + call Run_SubCmd_Tests(tests) +endfunc + +func Test_sub_cmd_5() + set magic& + set cpo& + + " List entry format: [input, cmd, output] + let tests = [ ['A123456789', 's/A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . submatch(6) . submatch(5) . submatch(4) . submatch(3) . submatch(2) . submatch(1)/', ['A123456789987654321']], + \ ['B123456789', 's/B\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\=string([submatch(0, 1), submatch(9, 1), submatch(8, 1), submatch(7, 1), submatch(6, 1), submatch(5, 1), submatch(4, 1), submatch(3, 1), submatch(2, 1), submatch(1, 1)])/', ["[['B123456789'], ['9'], ['8'], ['7'], ['6'], ['5'], ['4'], ['3'], ['2'], ['1']]"]], + \ ] + call Run_SubCmd_Tests(tests) +endfunc + +" Test for *:s%* on :substitute. +func Test_sub_cmd_6() + throw "skipped: Nvim removed POSIX-related 'cpoptions' flags" + set magic& + set cpo+=/ + + " List entry format: [input, cmd, output] + let tests = [ ['A', 's/A/a/', ['a']], + \ ['B', 's/B/%/', ['a']], + \ ] + call Run_SubCmd_Tests(tests) + + set cpo-=/ + let tests = [ ['C', 's/C/c/', ['c']], + \ ['D', 's/D/%/', ['%']], + \ ] + call Run_SubCmd_Tests(tests) + + set cpo& +endfunc + +" Test for :s replacing \n with line break. +func Test_sub_cmd_7() + set magic& + set cpo& + + " List entry format: [input, cmd, output] + let tests = [ ["A\<C-V>\<C-M>A", 's/A./\=submatch(0)/', ['A', 'A']], + \ ["B\<C-V>\<C-J>B", 's/B./\=submatch(0)/', ['B', 'B']], + \ ["C\<C-V>\<C-J>C", 's/C./\=strtrans(string(submatch(0, 1)))/', [strtrans("['C\<C-J>']C")]], + \ ["D\<C-V>\<C-J>\nD", 's/D.\nD/\=strtrans(string(submatch(0, 1)))/', [strtrans("['D\<C-J>', 'D']")]], + \ ["E\<C-V>\<C-J>\n\<C-V>\<C-J>\n\<C-V>\<C-J>\n\<C-V>\<C-J>\n\<C-V>\<C-J>E", 's/E\_.\{-}E/\=strtrans(string(submatch(0, 1)))/', [strtrans("['E\<C-J>', '\<C-J>', '\<C-J>', '\<C-J>', '\<C-J>E']")]], + \ ] + call Run_SubCmd_Tests(tests) + + exe "normal oQ\nQ\<Esc>k" + call assert_fails('s/Q[^\n]Q/\=submatch(0)."foobar"/', 'E486') + enew! +endfunc + +func TitleString() + let check = 'foo' =~ 'bar' + return "" +endfunc + +func Test_sub_cmd_8() + set titlestring=%{TitleString()} + + enew! + call append(0, ['', 'test_one', 'test_two']) + call cursor(1,1) + /^test_one/s/.*/\="foo\nbar"/ + call assert_equal('foo', getline(2)) + call assert_equal('bar', getline(3)) + call feedkeys(':/^test_two/s/.*/\="foo\nbar"/c', "t") + call feedkeys("\<CR>y", "xt") + call assert_equal('foo', getline(4)) + call assert_equal('bar', getline(5)) + + enew! + set titlestring& +endfunc diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim index af2cbbfe8e..8465fe7d45 100644 --- a/src/nvim/testdir/test_syntax.vim +++ b/src/nvim/testdir/test_syntax.vim @@ -1,5 +1,7 @@ " Test for syntax and syntax iskeyword option +source view_util.vim + func GetSyntaxItem(pat) let c = '' let a = ['a', getreg('a'), getregtype('a')] @@ -50,7 +52,7 @@ func Test_syn_iskeyword() setlocal isk-=_ call assert_equal('DLTD_BY', GetSyntaxItem('DLTD')) /\<D\k\+\>/:norm! ygn - let b2=@0 + let b2 = @0 call assert_equal('DLTD', @0) syn iskeyword clear @@ -76,3 +78,307 @@ func Test_syntax_after_reload() call assert_true(exists('g:gotit')) call delete('Xsomefile') endfunc + +func Test_syntime() + if !has('profile') + return + endif + + syntax on + syntime on + let a = execute('syntime report') + call assert_equal("\nNo Syntax items defined for this buffer", a) + + view ../memfile_test.c + setfiletype cpp + redraw + let a = execute('syntime report') + call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) + call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a) + call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a) + + syntime off + syntime clear + let a = execute('syntime report') + call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a) + call assert_notmatch('.* cppRawString *', a) + call assert_notmatch('.* cppNumber*', a) + call assert_notmatch('[1-9]', a) + + call assert_fails('syntime abc', 'E475') + + syntax clear + let a = execute('syntime report') + call assert_equal("\nNo Syntax items defined for this buffer", a) + + bd +endfunc + +func Test_syntax_list() + syntax on + let a = execute('syntax list') + call assert_equal("\nNo Syntax items defined for this buffer", a) + + view ../memfile_test.c + setfiletype c + + let a = execute('syntax list') + call assert_match('cInclude*', a) + call assert_match('cDefine', a) + + let a = execute('syntax list cDefine') + call assert_notmatch('cInclude*', a) + call assert_match('cDefine', a) + call assert_match(' links to Macro$', a) + + call assert_fails('syntax list ABCD', 'E28:') + call assert_fails('syntax list @ABCD', 'E392:') + + syntax clear + let a = execute('syntax list') + call assert_equal("\nNo Syntax items defined for this buffer", a) + + bd +endfunc + +func Test_syntax_completion() + call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:) + + call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"syn case ignore match', @:) + + call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"syn spell default notoplevel toplevel', @:) + + call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:) + + " Check that clearing "Aap" avoids it showing up before Boolean. + hi Aap ctermfg=blue + call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('^"syn list Aap Boolean Character ', @:) + hi clear Aap + + call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('^"syn list Boolean Character ', @:) + + call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match('^"syn match Boolean Character ', @:) +endfunc + +func Test_syntax_arg_skipped() + syn clear + syntax case ignore + if 0 + syntax case match + endif + call assert_match('case ignore', execute('syntax case')) + + syn keyword Foo foo + call assert_match('Foo', execute('syntax')) + syn clear + call assert_match('case match', execute('syntax case')) + call assert_notmatch('Foo', execute('syntax')) + + if has('conceal') + syn clear + syntax conceal on + if 0 + syntax conceal off + endif + call assert_match('conceal on', execute('syntax conceal')) + syn clear + call assert_match('conceal off', execute('syntax conceal')) + endif + + syntax conceal on + syntax conceal off + call assert_match('conceal off', execute('syntax conceal')) + + syntax region Bar start=/</ end=/>/ + if 0 + syntax region NotTest start=/</ end=/>/ contains=@Spell + endif + call assert_match('Bar', execute('syntax')) + call assert_notmatch('NotTest', execute('syntax')) + call assert_notmatch('Spell', execute('syntax')) + + hi Foo ctermfg=blue + let a = execute('hi Foo') + if 0 + syntax rest + endif + call assert_equal(a, execute('hi Foo')) + hi clear Bar + hi clear Foo + + set ft=tags + syn off + if 0 + syntax enable + endif + call assert_match('No Syntax items defined', execute('syntax')) + syntax enable + call assert_match('tagComment', execute('syntax')) + set ft= + + syn clear + if 0 + syntax include @Spell nothing + endif + call assert_notmatch('Spell', execute('syntax')) + + syn clear + syn iskeyword 48-57,$,_ + call assert_match('48-57,$,_', execute('syntax iskeyword')) + if 0 + syn clear + syn iskeyword clear + endif + call assert_match('48-57,$,_', execute('syntax iskeyword')) + syn iskeyword clear + call assert_match('not set', execute('syntax iskeyword')) + syn iskeyword 48-57,$,_ + syn clear + call assert_match('not set', execute('syntax iskeyword')) + + syn clear + syn keyword Foo foo + if 0 + syn keyword NotAdded bar + endif + call assert_match('Foo', execute('syntax')) + call assert_notmatch('NotAdded', execute('highlight')) + + syn clear + syn keyword Foo foo + call assert_match('Foo', execute('syntax')) + call assert_match('Foo', execute('syntax list')) + call assert_notmatch('Foo', execute('if 0 | syntax | endif')) + call assert_notmatch('Foo', execute('if 0 | syntax list | endif')) + + syn clear + syn match Fopi /asdf/ + if 0 + syn match Fopx /asdf/ + endif + call assert_match('Fopi', execute('syntax')) + call assert_notmatch('Fopx', execute('syntax')) + + syn clear + syn spell toplevel + call assert_match('spell toplevel', execute('syntax spell')) + if 0 + syn spell notoplevel + endif + call assert_match('spell toplevel', execute('syntax spell')) + syn spell notoplevel + call assert_match('spell notoplevel', execute('syntax spell')) + syn spell default + call assert_match('spell default', execute('syntax spell')) + + syn clear + if 0 + syntax cluster Spell + endif + call assert_notmatch('Spell', execute('syntax')) + + syn clear + syn keyword Foo foo + syn sync ccomment + syn sync maxlines=5 + if 0 + syn sync maxlines=11 + endif + call assert_match('on C-style comments', execute('syntax sync')) + call assert_match('maximal 5 lines', execute('syntax sync')) + syn sync clear + if 0 + syn sync ccomment + endif + call assert_notmatch('on C-style comments', execute('syntax sync')) + + syn clear +endfunc + +func Test_invalid_arg() + call assert_fails('syntax case asdf', 'E390:') + call assert_fails('syntax conceal asdf', 'E390:') + call assert_fails('syntax spell asdf', 'E390:') +endfunc + +func Test_syn_sync() + syntax region HereGroup start=/this/ end=/that/ + syntax sync match SyncHere grouphere HereGroup "pattern" + call assert_match('SyncHere', execute('syntax sync')) + syn sync clear + call assert_notmatch('SyncHere', execute('syntax sync')) + syn clear +endfunc + +func Test_syn_clear() + syntax keyword Foo foo + syntax keyword Bar tar + call assert_match('Foo', execute('syntax')) + call assert_match('Bar', execute('syntax')) + call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) + syn clear Foo + call assert_notmatch('Foo', execute('syntax')) + call assert_match('Bar', execute('syntax')) + call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) + syn clear Foo Bar + call assert_notmatch('Foo', execute('syntax')) + call assert_notmatch('Bar', execute('syntax')) + hi clear Foo + call assert_equal('Foo', synIDattr(hlID("Foo"), "name")) + hi clear Bar +endfunc + +func Test_invalid_name() + syn clear + syn keyword Nop yes + call assert_fails("syntax keyword Wr\x17ong bar", 'E669:') + syntax keyword @Wrong bar + call assert_match('W18:', execute('1messages')) + syn clear + hi clear Nop + hi clear @Wrong +endfunc + + +func Test_conceal() + if !has('conceal') + return + endif + + new + call setline(1, ['', '123456']) + syn match test23 "23" conceal cchar=X + syn match test45 "45" conceal + + set conceallevel=0 + call assert_equal('123456 ', ScreenLines(2, 7)[0]) + call assert_equal([[0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) + + set conceallevel=1 + call assert_equal('1X 6 ', ScreenLines(2, 7)[0]) + call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, ' ', 2], [1, ' ', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) + + set conceallevel=1 + set listchars=conceal:Y + call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, 'Y', 2], [1, 'Y', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) + call assert_equal('1XY6 ', ScreenLines(2, 7)[0]) + + set conceallevel=2 + call assert_match('1X6 ', ScreenLines(2, 7)[0]) + call assert_equal([[0, '', 0], [1, 'X', 1], [1, 'X', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) + + set conceallevel=3 + call assert_match('16 ', ScreenLines(2, 7)[0]) + call assert_equal([[0, '', 0], [1, '', 1], [1, '', 1], [1, '', 2], [1, '', 2], [0, '', 0]], map(range(1, 6), 'synconcealed(2, v:val)')) + + syn clear + set conceallevel& + bw! +endfunc diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim new file mode 100644 index 0000000000..ce9d110d82 --- /dev/null +++ b/src/nvim/testdir/test_system.vim @@ -0,0 +1,92 @@ +" Tests for system() and systemlist() + +function! Test_System() + if !executable('echo') || !executable('cat') || !executable('wc') + return + endif + let out = system('echo 123') + " On Windows we may get a trailing space. + if out != "123 \n" + call assert_equal("123\n", out) + endif + + let out = systemlist('echo 123') + " On Windows we may get a trailing space and CR. + if out != ["123 \r"] + call assert_equal(['123'], out) + endif + + call assert_equal('123', system('cat', '123')) + call assert_equal(['123'], systemlist('cat', '123')) + call assert_equal(["as\<NL>df"], systemlist('cat', ["as\<NL>df"])) + + new Xdummy + call setline(1, ['asdf', "pw\<NL>er", 'xxxx']) + let out = system('wc -l', bufnr('%')) + " On OS/X we get leading spaces + let out = substitute(out, '^ *', '', '') + call assert_equal("3\n", out) + + let out = systemlist('wc -l', bufnr('%')) + " On Windows we may get a trailing CR. + if out != ["3\r"] + " On OS/X we get leading spaces + if type(out) == v:t_list + let out[0] = substitute(out[0], '^ *', '', '') + endif + call assert_equal(['3'], out) + endif + + let out = systemlist('cat', bufnr('%')) + " On Windows we may get a trailing CR. + if out != ["asdf\r", "pw\<NL>er\r", "xxxx\r"] + call assert_equal(['asdf', "pw\<NL>er", 'xxxx'], out) + endif + bwipe! + + call assert_fails('call system("wc -l", 99999)', 'E86:') +endfunction + +function! Test_system_exmode() + if has('unix') " echo $? only works on Unix + let cmd = ' -es --headless -u NONE -c "source Xscript" +q; echo "result=$?"' + " Need to put this in a script, "catch" isn't found after an unknown + " function. + call writefile(['try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript') + let a = system(v:progpath . cmd) + call assert_match('result=0', a) + call assert_equal(0, v:shell_error) + endif + + " Error before try does set error flag. + call writefile(['call nosuchfunction()', 'try', 'call doesnotexist()', 'catch', 'endtry'], 'Xscript') + if has('unix') " echo $? only works on Unix + let a = system(v:progpath . cmd) + call assert_notequal('0', a[0]) + endif + + let cmd = ' -es --headless -u NONE -c "source Xscript" +q' + let a = system(v:progpath . cmd) + call assert_notequal(0, v:shell_error) + call delete('Xscript') + + if has('unix') " echo $? only works on Unix + let cmd = ' -es --headless -u NONE -c "call doesnotexist()" +q; echo $?' + let a = system(v:progpath. cmd) + call assert_notequal(0, a[0]) + endif + + let cmd = ' -es --headless -u NONE -c "call doesnotexist()" +q' + let a = system(v:progpath. cmd) + call assert_notequal(0, v:shell_error) + + if has('unix') " echo $? only works on Unix + let cmd = ' -es --headless -u NONE -c "call doesnotexist()|let a=1" +q; echo $?' + let a = system(v:progpath. cmd) + call assert_notequal(0, a[0]) + endif + + let cmd = ' -es --headless -u NONE -c "call doesnotexist()|let a=1" +q' + let a = system(v:progpath. cmd) + call assert_notequal(0, v:shell_error) +endfunc diff --git a/src/nvim/testdir/test_tab.vim b/src/nvim/testdir/test_tab.vim new file mode 100644 index 0000000000..b847dbd962 --- /dev/null +++ b/src/nvim/testdir/test_tab.vim @@ -0,0 +1,45 @@ + +" Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set. +" Also test that dv_ works correctly +func Test_smarttab() + enew! + set smarttab expandtab ts=8 sw=4 + " make sure that backspace works, no matter what termcap is used + exe "set t_kD=\<C-V>x7f t_kb=\<C-V>x08" + call append(0, ['start text', + \ "\t\tsome test text", + \ 'test text', + \ "\t\tother test text", + \ ' a cde', + \ ' f ghi', + \ 'test text', + \ ' Second line beginning with whitespace' + \ ]) + call cursor(1, 1) + exe "normal /some\<CR>" + exe "normal r\t" + call assert_equal("\t\t ome test text", getline('.')) + set noexpandtab + exe "normal /other\<CR>" + exe "normal r\t" + call assert_equal("\t\t ther test text", getline('.')) + + " Test replacing with Tabs and then backspacing to undo it + exe "normal j0wR\t\t\t\<BS>\<BS>\<BS>" + call assert_equal(" a cde", getline('.')) + " Test replacing with Tabs + exe "normal j0wR\t\t\t" + call assert_equal(" \t\thi", getline('.')) + + " Test that copyindent works with expandtab set + set expandtab smartindent copyindent ts=8 sw=8 sts=8 + exe "normal jo{\<CR>x" + call assert_equal('{', getline(line('.') - 1)) + call assert_equal(' x', getline('.')) + set nosol + exe "normal /Second line/\<CR>" + exe "normal fwdv_" + call assert_equal(' with whitespace', getline('.')) + enew! + set expandtab& smartindent& copyindent& ts& sw& sts& +endfunc diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index 33139fcda0..180563ebbd 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -473,5 +473,24 @@ func Test_tabnext_on_buf_unload2() endwhile endfunc +func Test_close_on_quitpre() + " This once caused a crash + edit Xtest + new + only + set bufhidden=delete + au QuitPre <buffer> close + tabnew tab1 + tabnew tab2 + 1tabn + q! + call assert_equal(1, tabpagenr()) + call assert_equal(2, tabpagenr('$')) + " clean up + while tabpagenr('$') > 1 + bwipe! + endwhile + buf Xtest +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index 0d697b3f3e..d5ce193bc6 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -95,4 +95,41 @@ function Test_keyword_jump() call delete('Xinclude') endfunction +" Test for jumping to a tag with 'hidden' set, with symbolic link in path of +" tag. This only works for Unix, because of the symbolic link. +func Test_tag_symbolic() + if !has('unix') + return + endif + set hidden + call delete("Xtest.dir", "rf") + call system("ln -s . Xtest.dir") + " Create a tags file with the current directory name inserted. + call writefile([ + \ "SECTION_OFF " . getcwd() . "/Xtest.dir/Xtest.c /^#define SECTION_OFF 3$/", + \ '', + \ ], 'Xtags') + call writefile(['#define SECTION_OFF 3', + \ '#define NUM_SECTIONS 3'], 'Xtest.c') + + " Try jumping to a tag, but with a path that contains a symbolic link. When + " wrong, this will give the ATTENTION message. The next space will then be + " eaten by hit-return, instead of moving the cursor to 'd'. + set tags=Xtags + enew! + call append(0, 'SECTION_OFF') + call cursor(1,1) + exe "normal \<C-]> " + call assert_equal('Xtest.c', expand('%:t')) + call assert_equal(2, col('.')) + + set hidden& + set tags& + enew! + call delete('Xtags') + call delete('Xtest.c') + call delete("Xtest.dir", "rf") + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab 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_textobjects.vim b/src/nvim/testdir/test_textobjects.vim index 630ae5d3a4..684f197f5f 100644 --- a/src/nvim/testdir/test_textobjects.vim +++ b/src/nvim/testdir/test_textobjects.vim @@ -4,7 +4,7 @@ if !has('textobjects') finish endif -function! CpoM(line, useM, expected) +func CpoM(line, useM, expected) new if a:useM @@ -28,16 +28,127 @@ function! CpoM(line, useM, expected) call assert_equal(getreg('"'), a:expected[2]) q! -endfunction +endfunc -function! Test_inner_block_without_cpo_M() +func Test_inner_block_without_cpo_M() call CpoM('(red \(blue) green)', 0, ['red \(blue', 'red \(blue', '']) -endfunction +endfunc -function! Test_inner_block_with_cpo_M_left_backslash() +func Test_inner_block_with_cpo_M_left_backslash() call CpoM('(red \(blue) green)', 1, ['red \(blue) green', 'blue', 'red \(blue) green']) -endfunction +endfunc -function! Test_inner_block_with_cpo_M_right_backslash() +func Test_inner_block_with_cpo_M_right_backslash() call CpoM('(red (blue\) green)', 1, ['red (blue\) green', 'blue\', 'red (blue\) green']) -endfunction +endfunc + +func Test_quote_selection_selection_exclusive() + new + call setline(1, "a 'bcde' f") + set selection=exclusive + exe "norm! fdvhi'y" + call assert_equal('bcde', @") + set selection&vim + bw! +endfunc + +" Tests for string and html text objects +func Test_string_html_objects() + enew! + + let t = '"wo\"rd\\" foo' + put =t + normal! da" + call assert_equal('foo', getline('.')) + + let t = "'foo' 'bar' 'piep'" + put =t + normal! 0va'a'rx + call assert_equal("xxxxxxxxxxxx'piep'", getline('.')) + + let t = "bla bla `quote` blah" + put =t + normal! 02f`da` + call assert_equal("bla bla blah", getline('.')) + + let t = 'out " in "noXno"' + put =t + normal! 0fXdi" + call assert_equal('out " in ""', getline('.')) + + let t = "\"'\" 'blah' rep 'buh'" + put =t + normal! 03f'vi'ry + call assert_equal("\"'\" 'blah'yyyyy'buh'", getline('.')) + + set quoteescape=+*- + let t = "bla `s*`d-`+++`l**` b`la" + put =t + normal! di` + call assert_equal("bla `` b`la", getline('.')) + + let t = 'voo "nah" sdf " asdf" sdf " sdf" sd' + put =t + normal! $F"va"oha"i"rz + call assert_equal('voo "zzzzzzzzzzzzzzzzzzzzzzzzzzzzsd', getline('.')) + + let t = "-<b>asdf<i>Xasdf</i>asdf</b>-" + put =t + normal! fXdit + call assert_equal('-<b>asdf<i></i>asdf</b>-', getline('.')) + + let t = "-<b>asdX<i>a<i />sdf</i>asdf</b>-" + put =t + normal! 0fXdit + call assert_equal('-<b></b>-', getline('.')) + + let t = "-<b>asdf<i>Xasdf</i>asdf</b>-" + put =t + normal! fXdat + call assert_equal('-<b>asdfasdf</b>-', getline('.')) + + let t = "-<b>asdX<i>as<b />df</i>asdf</b>-" + put =t + normal! 0fXdat + call assert_equal('--', getline('.')) + + let t = "-<b>\ninnertext object\n</b>" + put =t + normal! dit + call assert_equal('-<b></b>', getline('.')) + + set quoteescape& + enew! +endfunc + +" Tests for match() and matchstr() +func Test_match() + call assert_equal("b", matchstr("abcd", ".", 0, 2)) + call assert_equal("bc", matchstr("abcd", "..", 0, 2)) + call assert_equal("c", matchstr("abcd", ".", 2, 0)) + call assert_equal("a", matchstr("abcd", ".", 0, -1)) + call assert_equal(-1, match("abcd", ".", 0, 5)) + call assert_equal(0 , match("abcd", ".", 0, -1)) + call assert_equal(0 , match('abc', '.', 0, 1)) + call assert_equal(1 , match('abc', '.', 0, 2)) + call assert_equal(2 , match('abc', '.', 0, 3)) + call assert_equal(-1, match('abc', '.', 0, 4)) + call assert_equal(1 , match('abc', '.', 1, 1)) + call assert_equal(2 , match('abc', '.', 2, 1)) + call assert_equal(-1, match('abc', '.', 3, 1)) + call assert_equal(3 , match('abc', '$', 0, 1)) + call assert_equal(-1, match('abc', '$', 0, 2)) + call assert_equal(3 , match('abc', '$', 1, 1)) + call assert_equal(3 , match('abc', '$', 2, 1)) + call assert_equal(3 , match('abc', '$', 3, 1)) + call assert_equal(-1, match('abc', '$', 4, 1)) + call assert_equal(0 , match('abc', '\zs', 0, 1)) + call assert_equal(1 , match('abc', '\zs', 0, 2)) + call assert_equal(2 , match('abc', '\zs', 0, 3)) + call assert_equal(3 , match('abc', '\zs', 0, 4)) + call assert_equal(-1, match('abc', '\zs', 0, 5)) + call assert_equal(1 , match('abc', '\zs', 1, 1)) + call assert_equal(2 , match('abc', '\zs', 2, 1)) + call assert_equal(3 , match('abc', '\zs', 3, 1)) + call assert_equal(-1, match('abc', '\zs', 4, 1)) +endfunc diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim index 9ff73fd870..2bc6073d52 100644 --- a/src/nvim/testdir/test_undo.vim +++ b/src/nvim/testdir/test_undo.vim @@ -237,3 +237,54 @@ func Test_insert_expr() close! endfunc + +func Test_undofile_earlier() + throw 'skipped: Nvim does not support test_settime()' + + let t0 = localtime() - 43200 + call test_settime(t0) + new Xfile + call feedkeys("ione\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 1) + call feedkeys("otwo\<Esc>", 'xt') + set ul=100 + call test_settime(t0 + 2) + call feedkeys("othree\<Esc>", 'xt') + set ul=100 + w + wundo Xundofile + bwipe! + " restore normal timestamps. + call test_settime(0) + new Xfile + rundo Xundofile + earlier 1d + call assert_equal('', getline(1)) + bwipe! + call delete('Xfile') + call delete('Xundofile') +endfunc + +" Test for undo working properly when executing commands from a register. +" Also test this in an empty buffer. +func Test_cmd_in_reg_undo() + enew! + let @a="Ox\<Esc>jAy\<Esc>kdd" + edit +/^$ test_undo.vim + normal @au + call assert_equal(0, &modified) + return + new + normal @au + call assert_equal(0, &modified) + only! + let @a='' +endfunc + +func Test_redo_empty_line() + new + exe "norm\x16r\x160" + exe "norm." + bwipe! +endfunc diff --git a/src/nvim/testdir/test_unlet.vim b/src/nvim/testdir/test_unlet.vim index f6705997a9..3f06058d03 100644 --- a/src/nvim/testdir/test_unlet.vim +++ b/src/nvim/testdir/test_unlet.vim @@ -3,7 +3,7 @@ func Test_read_only() try " this caused a crash - unlet count + unlet v:count catch call assert_true(v:exception =~ ':E795:') endtry @@ -24,3 +24,7 @@ func Test_not_existing() call assert_true(v:exception =~ ':E108:') endtry endfunc + +func Test_unlet_fails() + call assert_fails('unlet v:["count"]', 'E46:') +endfunc diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim index d0864ec64c..db603610da 100644 --- a/src/nvim/testdir/test_usercommands.vim +++ b/src/nvim/testdir/test_usercommands.vim @@ -102,3 +102,107 @@ func Test_CmdUndefined() call assert_fails('Dothat', 'E492:') call assert_equal('yes', g:didnot) endfunc + +func Test_CmdErrors() + call assert_fails('com! docmd :', 'E183:') + call assert_fails('com! \<Tab> :', 'E182:') + call assert_fails('com! _ :', 'E182:') + call assert_fails('com! X :', 'E841:') + call assert_fails('com! - DoCmd :', 'E175:') + call assert_fails('com! -xxx DoCmd :', 'E181:') + call assert_fails('com! -addr DoCmd :', 'E179:') + call assert_fails('com! -complete DoCmd :', 'E179:') + call assert_fails('com! -complete=xxx DoCmd :', 'E180:') + call assert_fails('com! -complete=custom DoCmd :', 'E467:') + call assert_fails('com! -complete=customlist DoCmd :', 'E467:') + call assert_fails('com! -complete=behave,CustomComplete DoCmd :', 'E468:') + call assert_fails('com! -nargs=x DoCmd :', 'E176:') + call assert_fails('com! -count=1 -count=2 DoCmd :', 'E177:') + call assert_fails('com! -count=x DoCmd :', 'E178:') + call assert_fails('com! -range=x DoCmd :', 'E178:') + + com! -nargs=0 DoCmd : + call assert_fails('DoCmd x', 'E488:') + + com! -nargs=1 DoCmd : + call assert_fails('DoCmd', 'E471:') + + com! -nargs=+ DoCmd : + call assert_fails('DoCmd', 'E471:') + + call assert_fails('com DoCmd :', 'E174:') + comclear + call assert_fails('delcom DoCmd', 'E184:') +endfunc + +func CustomComplete(A, L, P) + return "January\nFebruary\nMars\n" +endfunc + +func CustomCompleteList(A, L, P) + return [ "Monday", "Tuesday", "Wednesday" ] +endfunc + +func Test_CmdCompletion() + call feedkeys(":com -\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com -addr bang bar buffer complete count nargs range register', @:) + + call feedkeys(":com -nargs=0 -\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com -nargs=0 -addr bang bar buffer complete count nargs range register', @:) + + call feedkeys(":com -nargs=\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com -nargs=* + 0 1 ?', @:) + + call feedkeys(":com -addr=\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com -addr=arguments buffers lines loaded_buffers quickfix tabs windows', @:) + + call feedkeys(":com -complete=co\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com -complete=color command compiler', @:) + + command! DoCmd1 : + command! DoCmd2 : + call feedkeys(":com \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com DoCmd1 DoCmd2', @:) + + call feedkeys(":DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"DoCmd1 DoCmd2', @:) + + call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"delcom DoCmd1 DoCmd2', @:) + + delcom DoCmd1 + call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"delcom DoCmd2', @:) + + call feedkeys(":com DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com DoCmd2', @:) + + delcom DoCmd2 + call feedkeys(":delcom DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"delcom DoC', @:) + + call feedkeys(":com DoC\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"com DoC', @:) + + com! -complete=behave DoCmd : + call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"DoCmd mswin xterm', @:) + + " This does not work. Why? + "call feedkeys(":DoCmd x\<C-A>\<C-B>\"\<CR>", 'tx') + "call assert_equal('"DoCmd xterm', @:) + + com! -complete=custom,CustomComplete DoCmd : + call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"DoCmd January February Mars', @:) + + com! -complete=customlist,CustomCompleteList DoCmd : + call feedkeys(":DoCmd \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"DoCmd Monday Tuesday Wednesday', @:) + + com! -complete=custom,CustomCompleteList DoCmd : + call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E730:') + + com! -complete=customlist,CustomComp DoCmd : + call assert_fails("call feedkeys(':DoCmd \<C-D>', 'tx')", 'E117:') +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/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index 4e0f1bbd2f..c449fc91b0 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1215,6 +1215,62 @@ func Test_bitwise_functions() call assert_fails("call invert({})", 'E728:') endfunc +" Test trailing text after :endfunction {{{1 +func Test_endfunction_trailing() + call assert_false(exists('*Xtest')) + + exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'" + call assert_true(exists('*Xtest')) + call assert_equal('yes', done) + delfunc Xtest + unlet done + + exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'" + call assert_true(exists('*Xtest')) + call assert_equal('yes', done) + delfunc Xtest + unlet done + + " trailing line break + exe "func Xtest()\necho 'hello'\nendfunc\n" + call assert_true(exists('*Xtest')) + delfunc Xtest + + set verbose=1 + exe "func Xtest()\necho 'hello'\nendfunc \" garbage" + call assert_true(exists('*Xtest')) + delfunc Xtest + + call assert_fails("func Xtest()\necho 'hello'\nendfunc garbage", 'E946') + call assert_true(exists('*Xtest')) + delfunc Xtest + set verbose=0 + + function Foo() + echo 'hello' + endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' + delfunc Foo +endfunc + +func Test_delfunction_force() + delfunc! Xtest + delfunc! Xtest + func Xtest() + echo 'nothing' + endfunc + delfunc! Xtest + delfunc! Xtest +endfunc + +" Test using bang after user command {{{1 +func Test_user_command_with_bang() + command -bang Nieuw let nieuw = 1 + Ni! + call assert_equal(1, nieuw) + unlet nieuw + delcommand Nieuw +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim new file mode 100644 index 0000000000..2b8849f488 --- /dev/null +++ b/src/nvim/testdir/test_virtualedit.vim @@ -0,0 +1,43 @@ +" Tests for 'virtualedit'. + +func Test_yank_move_change() + new + call setline(1, [ + \ "func foo() error {", + \ "\tif n, err := bar();", + \ "\terr != nil {", + \ "\t\treturn err", + \ "\t}", + \ "\tn = n * n", + \ ]) + set virtualedit=all + set ts=4 + function! MoveSelectionDown(count) abort + normal! m` + silent! exe "'<,'>move'>+".a:count + norm! `` + endfunction + + xmap ]e :<C-U>call MoveSelectionDown(v:count1)<CR> + 2 + normal 2gg + normal J + normal jVj + normal ]e + normal ce + bwipe! + set virtualedit= + set ts=8 +endfunc + +func Test_paste_end_of_line() + new + set virtualedit=all + call setline(1, ['456', '123']) + normal! gg0"ay$ + exe "normal! 2G$lllA\<C-O>:normal! \"agP\r" + call assert_equal('123456', getline(2)) + + bwipe! + set virtualedit= +endfunc diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index cf0e535937..0f2e7e493e 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1,13 +1,14 @@ -" Tests for Visual mode -if !has('multi_byte') - finish -endif - +" Tests for various Visual mode. if !has('visual') finish endif + func Test_block_shift_multibyte() + " Uses double-wide character. + if !has('multi_byte') + return + endif split call setline(1, ['xヹxxx', 'ヹxxx']) exe "normal 1G0l\<C-V>jl>" @@ -15,3 +16,139 @@ func Test_block_shift_multibyte() call assert_equal(' ヹxxx', getline(2)) q! endfunc + +func Test_Visual_ctrl_o() + new + call setline(1, ['one', 'two', 'three']) + call cursor(1,2) + set noshowmode + set tw=0 + call feedkeys("\<c-v>jjlIa\<c-\>\<c-o>:set tw=88\<cr>\<esc>", 'tx') + call assert_equal(['oane', 'tawo', 'tahree'], getline(1, 3)) + call assert_equal(88, &tw) + set tw& + bw! +endfu + +func Test_Visual_vapo() + new + normal oxx + normal vapo + bwipe! +endfunc + +func Test_dotregister_paste() + new + exe "norm! ihello world\<esc>" + norm! 0ve".p + call assert_equal('hello world world', getline(1)) + q! +endfunc + +func Test_Visual_inner_quote() + new + normal oxX + normal vki' + bwipe! +endfunc + +" Test for visual block shift and tab characters. +func Test_block_shift_tab() + enew! + call append(0, repeat(['one two three'], 5)) + call cursor(1,1) + exe "normal i\<C-G>u" + exe "normal fe\<C-V>4jR\<Esc>ugvr1" + call assert_equal('on1 two three', getline(1)) + call assert_equal('on1 two three', getline(2)) + call assert_equal('on1 two three', getline(5)) + + enew! + call append(0, repeat(['abcdefghijklmnopqrstuvwxyz'], 5)) + call cursor(1,1) + exe "normal \<C-V>4jI \<Esc>j<<11|D" + exe "normal j7|a\<Tab>\<Tab>" + exe "normal j7|a\<Tab>\<Tab> " + exe "normal j7|a\<Tab> \<Tab>\<Esc>4k13|\<C-V>4j<" + call assert_equal(' abcdefghijklmnopqrstuvwxyz', getline(1)) + call assert_equal('abcdefghij', getline(2)) + call assert_equal(" abc\<Tab> defghijklmnopqrstuvwxyz", getline(3)) + call assert_equal(" abc\<Tab> defghijklmnopqrstuvwxyz", getline(4)) + call assert_equal(" abc\<Tab> defghijklmnopqrstuvwxyz", getline(5)) + + %s/\s\+//g + call cursor(1,1) + exe "normal \<C-V>4jI \<Esc>j<<" + exe "normal j7|a\<Tab>\<Tab>" + exe "normal j7|a\<Tab>\<Tab>\<Tab>\<Tab>\<Tab>" + exe "normal j7|a\<Tab> \<Tab>\<Tab>\<Esc>4k13|\<C-V>4j3<" + call assert_equal(' abcdefghijklmnopqrstuvwxyz', getline(1)) + call assert_equal('abcdefghij', getline(2)) + call assert_equal(" abc\<Tab> defghijklmnopqrstuvwxyz", getline(3)) + call assert_equal(" abc\<Tab>\<Tab>defghijklmnopqrstuvwxyz", getline(4)) + call assert_equal(" abc\<Tab> defghijklmnopqrstuvwxyz", getline(5)) + + enew! +endfunc + +" Tests Blockwise Visual when there are TABs before the text. +func Test_blockwise_visual() + enew! + call append(0, ['123456', + \ '234567', + \ '345678', + \ '', + \ 'test text test tex start here', + \ "\t\tsome text", + \ "\t\ttest text", + \ 'test text']) + call cursor(1,1) + exe "normal /start here$\<CR>" + exe 'normal "by$' . "\<C-V>jjlld" + exe "normal /456$\<CR>" + exe "normal \<C-V>jj" . '"bP' + call assert_equal(['123start here56', + \ '234start here67', + \ '345start here78', + \ '', + \ 'test text test tex rt here', + \ "\t\tsomext", + \ "\t\ttesext"], getline(1, 7)) + + enew! +endfunc + +" Test Virtual replace mode. +func Test_virtual_replace() + throw 'skipped: TODO: ' + exe "set t_kD=\<C-V>x7f t_kb=\<C-V>x08" + enew! + exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz" + call cursor(1,1) + set ai bs=2 + exe "normal gR0\<C-D> 1\nA\nBCDEFGHIJ\n\tKL\nMNO\nPQR" + call assert_equal([' 1', + \ ' A', + \ ' BCDEFGHIJ', + \ ' KL', + \ ' MNO', + \ ' PQR', + \ ], getline(1, 6)) + normal G + mark a + inoremap <C-D> <Del> + exe "normal o0\<C-D>\nabcdefghi\njk\tlmn\n opq\trst\n\<C-D>uvwxyz\n" + exe "normal 'ajgR0\<C-D> 1\nA\nBCDEFGHIJ\n\tKL\nMNO\nPQR" . repeat("\<BS>", 29) + call assert_equal([' 1', + \ 'abcdefghi', + \ 'jk lmn', + \ ' opq rst', + \ 'uvwxyz'], getline(7, 11)) + normal G + exe "normal iab\tcdefghi\tjkl" + exe "normal 0gRAB......CDEFGHI.J\<Esc>o" + exe "normal iabcdefghijklmnopqrst\<Esc>0gRAB\tIJKLMNO\tQR" + call assert_equal(['AB......CDEFGHI.Jkl', + \ 'AB IJKLMNO QRst'], getline(12, 13)) + enew! +endfunc diff --git a/src/nvim/testdir/test_winbuf_close.vim b/src/nvim/testdir/test_winbuf_close.vim new file mode 100644 index 0000000000..ed64dd79b7 --- /dev/null +++ b/src/nvim/testdir/test_winbuf_close.vim @@ -0,0 +1,124 @@ +" Test for commands that close windows and/or buffers: +" :quit +" :close +" :hide +" :only +" :sall +" :all +" :ball +" :buf +" :edit +" +func Test_winbuf_close() + enew | only + + call writefile(['testtext 1'], 'Xtest1') + call writefile(['testtext 2'], 'Xtest2') + call writefile(['testtext 3'], 'Xtest3') + + next! Xtest1 Xtest2 + call setline(1, 'testtext 1 1') + + " test for working :n when hidden set + set hidden + next + call assert_equal('Xtest2', bufname('%')) + + " test for failing :rew when hidden not set + set nohidden + call setline(1, 'testtext 2 2') + call assert_fails('rewind', 'E37') + call assert_equal('Xtest2', bufname('%')) + call assert_equal('testtext 2 2', getline(1)) + + " test for working :rew when hidden set + set hidden + rewind + call assert_equal('Xtest1', bufname('%')) + call assert_equal('testtext 1 1', getline(1)) + + " test for :all keeping a buffer when it's modified + set nohidden + call setline(1, 'testtext 1 1 1') + split + next Xtest2 Xtest3 + all + 1wincmd w + call assert_equal('Xtest1', bufname('%')) + call assert_equal('testtext 1 1 1', getline(1)) + + " test abandoning changed buffer, should be unloaded even when 'hidden' set + set hidden + call setline(1, 'testtext 1 1 1 1') + quit! + call assert_equal('Xtest2', bufname('%')) + call assert_equal('testtext 2 2', getline(1)) + unhide + call assert_equal('Xtest2', bufname('%')) + call assert_equal('testtext 2 2', getline(1)) + + " test ":hide" hides anyway when 'hidden' not set + set nohidden + call setline(1, 'testtext 2 2 2') + hide + call assert_equal('Xtest3', bufname('%')) + call assert_equal('testtext 3', getline(1)) + + " test ":edit" failing in modified buffer when 'hidden' not set + call setline(1, 'testtext 3 3') + call assert_fails('edit Xtest1', 'E37') + call assert_equal('Xtest3', bufname('%')) + call assert_equal('testtext 3 3', getline(1)) + + " test ":edit" working in modified buffer when 'hidden' set + set hidden + edit Xtest1 + call assert_equal('Xtest1', bufname('%')) + call assert_equal('testtext 1', getline(1)) + + " test ":close" not hiding when 'hidden' not set in modified buffer + split Xtest3 + set nohidden + call setline(1, 'testtext 3 3 3') + call assert_fails('close', 'E37') + call assert_equal('Xtest3', bufname('%')) + call assert_equal('testtext 3 3 3', getline(1)) + + " test ":close!" does hide when 'hidden' not set in modified buffer; + call setline(1, 'testtext 3 3 3 3') + close! + call assert_equal('Xtest1', bufname('%')) + call assert_equal('testtext 1', getline(1)) + + set nohidden + + " test ":all!" hides changed buffer + split Xtest4 + call setline(1, 'testtext 4') + all! + 1wincmd w + call assert_equal('Xtest2', bufname('%')) + call assert_equal('testtext 2 2 2', getline(1)) + + " test ":q!" and hidden buffer. + bwipe! Xtest1 Xtest2 Xtest3 Xtest4 + split Xtest1 + wincmd w + bwipe! + set modified + bot split Xtest2 + set modified + bot split Xtest3 + set modified + wincmd t + hide + call assert_equal('Xtest2', bufname('%')) + quit! + call assert_equal('Xtest3', bufname('%')) + call assert_fails('silent! quit!', 'E162') + call assert_equal('Xtest1', bufname('%')) + + call delete('Xtest1') + call delete('Xtest2') + call delete('Xtest3') +endfunc diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 188a7ed0f3..139d29a48b 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -306,20 +306,14 @@ func Test_window_width() set winfixwidth vsplit Xc let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)] - " FIXME: commented out: I would expect the width of 2nd window to - " remain 2 but it's actually 1?! - "call assert_equal(2, winwidth(2)) + call assert_equal(2, winwidth(2)) call assert_inrange(ww3, ww3 + 1, ww1) 3wincmd > - " FIXME: commented out: I would expect the width of 2nd window to - " remain 2 but it's actually 1?! - "call assert_equal(2, winwidth(2)) + call assert_equal(2, winwidth(2)) call assert_equal(ww1 + 3, winwidth(1)) call assert_equal(ww3 - 3, winwidth(3)) wincmd = - " FIXME: commented out: I would expect the width of 2nd window to - " remain 2 but it's actually 1?! - "call assert_equal(2, winwidth(2)) + call assert_equal(2, winwidth(2)) call assert_equal(ww1, winwidth(1)) call assert_equal(ww3, winwidth(3)) @@ -336,6 +330,50 @@ func Test_window_width() bw Xa Xb Xc endfunc +func Test_equalalways_on_close() + set equalalways + vsplit + windo split + split + wincmd J + " now we have a frame top-left with two windows, a frame top-right with two + " windows and a frame at the bottom, full-width. + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_3 = winheight(3) + let height_4 = winheight(4) + " closing the bottom window causes all windows to be resized. + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_notequal(height_3, winheight(3)) + call assert_notequal(height_4, winheight(4)) + call assert_equal(winheight(1), winheight(3)) + call assert_equal(winheight(2), winheight(4)) + + 1wincmd w + split + 4wincmd w + resize + 5 + " left column has three windows, equalized heights. + " right column has two windows, top one a bit higher + let height_1 = winheight(1) + let height_2 = winheight(2) + let height_4 = winheight(4) + let height_5 = winheight(5) + 3wincmd w + " closing window in left column equalizes heights in left column but not in + " the right column + close + call assert_notequal(height_1, winheight(1)) + call assert_notequal(height_2, winheight(2)) + call assert_equal(height_4, winheight(3)) + call assert_equal(height_5, winheight(4)) + + only + set equalalways& +endfunc + func Test_window_jump_tag() help /iccf diff --git a/src/nvim/testdir/unix.vim b/src/nvim/testdir/unix.vim index a7daacf8cf..ce2beff7fe 100644 --- a/src/nvim/testdir/unix.vim +++ b/src/nvim/testdir/unix.vim @@ -2,6 +2,12 @@ " Always use "sh", don't use the value of "$SHELL". set shell=sh +if has('win32') + set shellcmdflag=-c shellxquote= shellxescape= shellquote= + let &shellredir = '>%s 2>&1' + set shellslash +endif + " Don't depend on system locale, always use utf-8 set encoding=utf-8 diff --git a/src/nvim/testdir/view_util.vim b/src/nvim/testdir/view_util.vim new file mode 100644 index 0000000000..eb92630761 --- /dev/null +++ b/src/nvim/testdir/view_util.vim @@ -0,0 +1,30 @@ +" Functions about view shared by several tests + +" ScreenLines(lnum, width) or +" ScreenLines([start, end], width) +function! ScreenLines(lnum, width) abort + redraw! + if type(a:lnum) == v:t_list + let start = a:lnum[0] + let end = a:lnum[1] + else + let start = a:lnum + let end = a:lnum + endif + let lines = [] + for l in range(start, end) + let lines += [join(map(range(1, a:width), 'nr2char(screenchar(l, v:val))'), '')] + endfor + return lines +endfunction + +function! NewWindow(height, width) abort + exe a:height . 'new' + exe a:width . 'vsp' + redraw! +endfunction + +function! CloseWindow() abort + bw! + redraw! +endfunction |