aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/testdir
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2017-12-03 16:49:30 +0300
committerZyX <kp-pav@yandex.ru>2017-12-03 16:49:30 +0300
commitc49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57 (patch)
treeb7e59c416d1435725c65f8952b6e55c70544d97e /src/nvim/testdir
parent62108c3b0be46936c83f6d4c98b44ceb5e6f77fd (diff)
parent27a577586eace687c47e7398845178208cae524a (diff)
downloadrneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.gz
rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.bz2
rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.zip
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'src/nvim/testdir')
-rw-r--r--src/nvim/testdir/Makefile38
-rw-r--r--src/nvim/testdir/runtest.vim136
-rw-r--r--src/nvim/testdir/samples/memfile_test.c3
-rw-r--r--src/nvim/testdir/setup.vim3
-rw-r--r--src/nvim/testdir/shared.vim214
-rw-r--r--src/nvim/testdir/test13.in63
-rw-r--r--src/nvim/testdir/test13.ok31
-rw-r--r--src/nvim/testdir/test49.vim2
-rw-r--r--src/nvim/testdir/test_alot.vim13
-rw-r--r--src/nvim/testdir/test_autocmd.vim246
-rw-r--r--src/nvim/testdir/test_breakindent.vim298
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim13
-rw-r--r--src/nvim/testdir/test_charsearch.vim62
-rw-r--r--src/nvim/testdir/test_cmdline.vim146
-rw-r--r--src/nvim/testdir/test_command_count.vim191
-rw-r--r--src/nvim/testdir/test_cscope.vim2
-rw-r--r--src/nvim/testdir/test_cursor_func.vim8
-rw-r--r--src/nvim/testdir/test_diffmode.vim54
-rw-r--r--src/nvim/testdir/test_display.vim71
-rw-r--r--src/nvim/testdir/test_expr.vim196
-rw-r--r--src/nvim/testdir/test_fileformat.vim33
-rw-r--r--src/nvim/testdir/test_filter_cmd.vim76
-rw-r--r--src/nvim/testdir/test_float_func.vim332
-rw-r--r--src/nvim/testdir/test_fnameescape.vim21
-rw-r--r--src/nvim/testdir/test_fold.vim254
-rw-r--r--src/nvim/testdir/test_functions.vim313
-rw-r--r--src/nvim/testdir/test_ga.vim37
-rw-r--r--src/nvim/testdir/test_gf.vim33
-rw-r--r--src/nvim/testdir/test_goto.vim281
-rw-r--r--src/nvim/testdir/test_help.vim16
-rw-r--r--src/nvim/testdir/test_help_tagjump.vim89
-rw-r--r--src/nvim/testdir/test_hide.vim97
-rw-r--r--src/nvim/testdir/test_history.vim41
-rw-r--r--src/nvim/testdir/test_hlsearch.vim34
-rw-r--r--src/nvim/testdir/test_largefile.vim34
-rw-r--r--src/nvim/testdir/test_listlbr.vim235
-rw-r--r--src/nvim/testdir/test_listlbr_utf8.vim229
-rw-r--r--src/nvim/testdir/test_mapping.vim94
-rw-r--r--src/nvim/testdir/test_match.vim10
-rw-r--r--src/nvim/testdir/test_matchadd_conceal.vim23
-rw-r--r--src/nvim/testdir/test_menu.vim2
-rw-r--r--src/nvim/testdir/test_mksession.vim155
-rw-r--r--src/nvim/testdir/test_mksession_utf8.vim104
-rw-r--r--src/nvim/testdir/test_nested_function.vim57
-rw-r--r--src/nvim/testdir/test_normal.vim2337
-rw-r--r--src/nvim/testdir/test_options.vim39
-rw-r--r--src/nvim/testdir/test_popup.vim39
-rw-r--r--src/nvim/testdir/test_profile.vim183
-rw-r--r--src/nvim/testdir/test_quickfix.vim311
-rw-r--r--src/nvim/testdir/test_regexp_utf8.vim24
-rw-r--r--src/nvim/testdir/test_retab.vim77
-rw-r--r--src/nvim/testdir/test_search.vim300
-rw-r--r--src/nvim/testdir/test_smartindent.vim14
-rw-r--r--src/nvim/testdir/test_startup.vim242
-rw-r--r--src/nvim/testdir/test_startup_utf8.vim64
-rw-r--r--src/nvim/testdir/test_stat.vim71
-rw-r--r--src/nvim/testdir/test_substitute.vim41
-rw-r--r--src/nvim/testdir/test_syntax.vim84
-rw-r--r--src/nvim/testdir/test_tabpage.vim245
-rw-r--r--src/nvim/testdir/test_tagjump.vim72
-rw-r--r--src/nvim/testdir/test_taglist.vim58
-rw-r--r--src/nvim/testdir/test_timers.vim153
-rw-r--r--src/nvim/testdir/test_undo.vim61
-rw-r--r--src/nvim/testdir/test_unlet.vim2
-rw-r--r--src/nvim/testdir/test_usercommands.vim104
-rw-r--r--src/nvim/testdir/test_utf8.vim65
-rw-r--r--src/nvim/testdir/test_vimscript.vim (renamed from src/nvim/testdir/test_viml.vim)151
-rw-r--r--src/nvim/testdir/test_virtualedit.vim43
-rw-r--r--src/nvim/testdir/test_visual.vim38
-rw-r--r--src/nvim/testdir/test_window_cmd.vim356
-rw-r--r--src/nvim/testdir/test_window_id.vim9
-rw-r--r--src/nvim/testdir/view_util.vim30
72 files changed, 9172 insertions, 431 deletions
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 9f9ecbc6c9..111bd172ef 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -1,12 +1,14 @@
-#
+# vim: noet ts=8
# Makefile to run all tests for Vim
#
NVIM_PRG ?= ../../../build/bin/nvim
+TMPDIR ?= Xtest-tmpdir
SCRIPTSOURCE := ../../../runtime
export SHELL := sh
export NVIM_PRG := $(NVIM_PRG)
+export TMPDIR
SCRIPTS ?= \
test13.out \
@@ -28,17 +30,27 @@ SCRIPTS ?= \
# Tests using runtest.vim.
# Keep test_alot*.res as the last one, sort the others.
NEW_TESTS ?= \
+ test_autocmd.res \
test_bufwintabinfo.res \
+ test_charsearch.res \
test_cmdline.res \
+ test_command_count.res \
test_cscope.res \
test_digraph.res \
test_diffmode.res \
test_farsi.res \
test_filter_map.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_lambda.res \
@@ -46,14 +58,28 @@ NEW_TESTS ?= \
test_marks.res \
test_match.res \
test_matchadd_conceal.res \
+ test_matchadd_conceal_utf8.res \
+ test_mksession.res \
+ test_mksession_utf8.res \
test_nested_function.res \
+ test_normal.res \
+ test_profile.res \
test_quickfix.res \
+ test_retab.res \
+ test_search.res \
test_signs.res \
+ test_smartindent.res \
+ test_stat.res \
+ test_startup.res \
+ test_startup_utf8.res \
+ test_substitute.res \
test_syntax.res \
+ test_tabpage.res \
test_textobjects.res \
test_timers.res \
+ test_undo.res \
test_usercommands.res \
- test_viml.res \
+ test_vimscript.res \
test_visual.res \
test_window_id.res \
test_writefile.res \
@@ -114,7 +140,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 := VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in
clean:
-rm -rf *.out \
@@ -130,10 +156,12 @@ clean:
.*.swp \
.*.swo \
.gdbinit \
+ $(TMPDIR) \
del
test1.out: .gdbinit test1.in
-rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize
+ mkdir -p $(TMPDIR)
$(RUN_VIM) $*.in
@/bin/sh -c "if test -e wrongtermsize; then \
echo; \
@@ -151,6 +179,7 @@ test1.out: .gdbinit test1.in
%.out: %.in .gdbinit
-rm -rf $*.failed test.ok $(RM_ON_RUN)
+ mkdir -p $(TMPDIR)
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
@@ -183,7 +212,7 @@ nolog:
# 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 = VIMRUNTIME=$(SCRIPTSOURCE); export VIMRUNTIME; $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE --headless --noplugin
newtests: newtestssilent
@/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \
@@ -193,4 +222,5 @@ newtests: newtestssilent
newtestssilent: $(NEW_TESTS)
%.res: %.vim .gdbinit
+ mkdir -p $(TMPDIR)
$(RUN_VIMTEST) -u NONE -S runtest.vim $*.vim
diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim
index 0403a53f9c..4de1345679 100644
--- a/src/nvim/testdir/runtest.vim
+++ b/src/nvim/testdir/runtest.vim
@@ -68,15 +68,22 @@ let $HOME = '/does/not/exist'
" Prepare for calling garbagecollect_for_testing().
let v:testing = 1
-" Align with vim defaults.
+" Align Nvim defaults to Vim.
set directory^=.
-set nohidden
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'
-function RunTheTest(test)
+func RunTheTest(test)
echo 'Executing ' . a:test
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)
@@ -91,7 +98,11 @@ function RunTheTest(test)
endtry
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.
@@ -110,6 +121,60 @@ function RunTheTest(test)
set nomodified
endfunc
+func AfterTheTest()
+ if len(v:errors) > 0
+ let s:fail += 1
+ call add(s:errors, 'Found errors in ' . s:test . ':')
+ call extend(s:errors, v:errors)
+ let v:errors = []
+ endif
+endfunc
+
+" This function can be called by a test if it wants to abort testing.
+func FinishTesting()
+ call AfterTheTest()
+
+ " Don't write viminfo on exit.
+ set viminfo=
+
+ if s:fail == 0
+ " Success, create the .res file so that make knows it's done.
+ exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
+ write
+ endif
+
+ if len(s:errors) > 0
+ " Append errors to test.log
+ split test.log
+ call append(line('$'), '')
+ call append(line('$'), 'From ' . g:testname . ':')
+ call append(line('$'), s:errors)
+ write
+ endif
+
+ let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
+ echo message
+ call add(s:messages, message)
+ if s:fail > 0
+ let message = s:fail . ' FAILED:'
+ echo message
+ call add(s:messages, message)
+ call extend(s:messages, s:errors)
+ endif
+
+ " Add SKIPPED messages
+ call extend(s:messages, s:skipped)
+
+ " Append messages to the file "messages"
+ split messages
+ call append(line('$'), '')
+ call append(line('$'), 'From ' . g:testname . ':')
+ call append(line('$'), s:messages)
+ write
+
+ qall!
+endfunc
+
" Source the test script. First grab the file name, in case the script
" navigates away. g:testname can be used by the tests.
let g:testname = expand('%')
@@ -118,7 +183,7 @@ let s:fail = 0
let s:errors = []
let s:messages = []
let s:skipped = []
-if expand('%') =~ 'test_viml.vim'
+if expand('%') =~ 'test_vimscript.vim'
" this test has intentional s:errors, don't use try/catch.
source %
else
@@ -131,10 +196,13 @@ else
endif
" Names of flaky tests.
-let s:flaky = []
+let s:flaky = [
+ \ 'Test_with_partial_callback()',
+ \ 'Test_oneshot()',
+ \ 'Test_lambda_with_timer()',
+ \ ]
" Locate Test_ functions and execute them.
-set nomore
redir @q
silent function /^Test_
redir END
@@ -150,56 +218,14 @@ for s:test in sort(s:tests)
call RunTheTest(s:test)
if len(v:errors) > 0 && index(s:flaky, s:test) >= 0
- call add(s:messages, 'Flaky test failed, running it again')
- let v:errors = []
- call RunTheTest(s:test)
- endif
-
- if len(v:errors) > 0
- let s:fail += 1
- call add(s:errors, 'Found errors in ' . s:test . ':')
- call extend(s:errors, v:errors)
+ call add(s:messages, 'Flaky test failed, running it again')
let v:errors = []
+ call RunTheTest(s:test)
endif
+ call AfterTheTest()
endfor
-" Don't write viminfo on exit.
-set viminfo=
-
-if s:fail == 0
- " Success, create the .res file so that make knows it's done.
- exe 'split ' . fnamemodify(g:testname, ':r') . '.res'
- write
-endif
-
-if len(s:errors) > 0
- " Append errors to test.log
- split test.log
- call append(line('$'), '')
- call append(line('$'), 'From ' . g:testname . ':')
- call append(line('$'), s:errors)
- write
-endif
-
-let message = 'Executed ' . s:done . (s:done > 1 ? ' tests': ' test')
-echo message
-call add(s:messages, message)
-if s:fail > 0
- let message = s:fail . ' FAILED'
- echo message
- call add(s:messages, message)
- call extend(s:messages, s:errors)
-endif
-
-" Add SKIPPED messages
-call extend(s:messages, s:skipped)
-
-" Append messages to the file "messages"
-split messages
-call append(line('$'), '')
-call append(line('$'), 'From ' . g:testname . ':')
-call append(line('$'), s:messages)
-write
+call FinishTesting()
-qall!
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/samples/memfile_test.c b/src/nvim/testdir/samples/memfile_test.c
index 0fa1e14c40..3c8f108255 100644
--- a/src/nvim/testdir/samples/memfile_test.c
+++ b/src/nvim/testdir/samples/memfile_test.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim
index 05257d566d..06f2199214 100644
--- a/src/nvim/testdir/setup.vim
+++ b/src/nvim/testdir/setup.vim
@@ -4,8 +4,9 @@ set noruler
set noshowcmd
set belloff=
-" Make sure 'runtimepath' does not include $HOME.
+" Make sure 'runtimepath' and 'packpath' does not include $HOME.
set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after
+let &packpath = &rtp
" Make sure $HOME does not get read or written.
let $HOME = '/does/not/exist'
diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim
new file mode 100644
index 0000000000..72cfea96c6
--- /dev/null
+++ b/src/nvim/testdir/shared.vim
@@ -0,0 +1,214 @@
+" Functions shared by several tests.
+
+" Get the name of the Python executable.
+" Also keeps it in s:python.
+func PythonProg()
+ " This test requires the Python command to run the test server.
+ " This most likely only works on Unix and Windows.
+ if has('unix')
+ " We also need the job feature or the pkill command to make sure the server
+ " can be stopped.
+ if !(executable('python') && (has('job') || executable('pkill')))
+ return ''
+ endif
+ let s:python = 'python'
+ elseif has('win32')
+ " Use Python Launcher for Windows (py.exe) if available.
+ if executable('py.exe')
+ let s:python = 'py.exe'
+ elseif executable('python.exe')
+ let s:python = 'python.exe'
+ else
+ return ''
+ endif
+ else
+ return ''
+ endif
+ return s:python
+endfunc
+
+" Run "cmd". Returns the job if using a job.
+func RunCommand(cmd)
+ let job = 0
+ if has('job')
+ let job = job_start(a:cmd, {"stoponexit": "hup"})
+ call job_setoptions(job, {"stoponexit": "kill"})
+ elseif has('win32')
+ exe 'silent !start cmd /c start "test_channel" ' . a:cmd
+ else
+ exe 'silent !' . a:cmd . '&'
+ endif
+ return job
+endfunc
+
+" Read the port number from the Xportnr file.
+func GetPort()
+ let l = []
+ for i in range(200)
+ try
+ let l = readfile("Xportnr")
+ catch
+ endtry
+ if len(l) >= 1
+ break
+ endif
+ sleep 10m
+ endfor
+ call delete("Xportnr")
+
+ if len(l) == 0
+ " Can't make the connection, give up.
+ return 0
+ endif
+ return l[0]
+endfunc
+
+" Run a Python server for "cmd" and call "testfunc".
+" Always kills the server before returning.
+func RunServer(cmd, testfunc, args)
+ " The Python program writes the port number in Xportnr.
+ call delete("Xportnr")
+
+ if len(a:args) == 1
+ let arg = ' ' . a:args[0]
+ else
+ let arg = ''
+ endif
+ let pycmd = s:python . " " . a:cmd . arg
+
+ try
+ let g:currentJob = RunCommand(pycmd)
+
+ " Wait for up to 2 seconds for the port number to be there.
+ let port = GetPort()
+ if port == 0
+ call assert_false(1, "Can't start " . a:cmd)
+ return
+ endif
+
+ call call(function(a:testfunc), [port])
+ catch
+ call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint)
+ finally
+ call s:kill_server(a:cmd)
+ endtry
+endfunc
+
+func s:kill_server(cmd)
+ if has('job')
+ if exists('g:currentJob')
+ call job_stop(g:currentJob)
+ unlet g:currentJob
+ endif
+ elseif has('win32')
+ let cmd = substitute(a:cmd, ".py", '', '')
+ call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"')
+ else
+ call system("pkill -f " . a:cmd)
+ endif
+endfunc
+
+" Wait for up to a second for "expr" to become true.
+" Return time slept in milliseconds. With the +reltime feature this can be
+" more than the actual waiting time. Without +reltime it can also be less.
+func WaitFor(expr)
+ " using reltime() is more accurate, but not always available
+ if has('reltime')
+ let start = reltime()
+ else
+ let slept = 0
+ endif
+ for i in range(100)
+ try
+ if eval(a:expr)
+ if has('reltime')
+ return float2nr(reltimefloat(reltime(start)) * 1000)
+ endif
+ return slept
+ endif
+ catch
+ endtry
+ if !has('reltime')
+ let slept += 10
+ endif
+ sleep 10m
+ endfor
+ return 1000
+endfunc
+
+" Wait for up to a given milliseconds.
+" With the +timers feature this waits for key-input by getchar(), Resume()
+" feeds key-input and resumes process. Return time waited in milliseconds.
+" Without +timers it uses simply :sleep.
+func Standby(msec)
+ if has('timers')
+ let start = reltime()
+ let g:_standby_timer = timer_start(a:msec, function('s:feedkeys'))
+ call getchar()
+ return float2nr(reltimefloat(reltime(start)) * 1000)
+ else
+ execute 'sleep ' a:msec . 'm'
+ return a:msec
+ endif
+endfunc
+
+func Resume()
+ if exists('g:_standby_timer')
+ call timer_stop(g:_standby_timer)
+ call s:feedkeys(0)
+ unlet g:_standby_timer
+ endif
+endfunc
+
+func s:feedkeys(timer)
+ call feedkeys('x', 'nt')
+endfunc
+
+" Get the command to run Vim, with -u NONE and --headless arguments.
+" Returns an empty string on error.
+func GetVimCommand()
+ let cmd = v:progpath
+ let cmd = substitute(cmd, '-u \f\+', '-u NONE', '')
+ if cmd !~ '-u NONE'
+ let cmd = cmd . ' -u NONE'
+ endif
+ let cmd .= ' --headless -i NONE'
+ let cmd = substitute(cmd, 'VIMRUNTIME=.*VIMRUNTIME;', '', '')
+ return cmd
+endfunc
+
+" Run Vim, using the "vimcmd" file and "-u NORC".
+" "before" is a list of Vim commands to be executed before loading plugins.
+" "after" is a list of Vim commands to be executed after loading plugins.
+" Plugins are not loaded, unless 'loadplugins' is set in "before".
+" Return 1 if Vim could be executed.
+func RunVim(before, after, arguments)
+ return RunVimPiped(a:before, a:after, a:arguments, '')
+endfunc
+
+func RunVimPiped(before, after, arguments, pipecmd)
+ let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log'
+ let cmd = GetVimCommand()
+ if cmd == ''
+ return 0
+ endif
+ let args = ''
+ if len(a:before) > 0
+ call writefile(a:before, 'Xbefore.vim')
+ let args .= ' --cmd "so Xbefore.vim"'
+ endif
+ if len(a:after) > 0
+ call writefile(a:after, 'Xafter.vim')
+ let args .= ' -S Xafter.vim'
+ endif
+
+ exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments
+
+ if len(a:before) > 0
+ call delete('Xbefore.vim')
+ endif
+ if len(a:after) > 0
+ call delete('Xafter.vim')
+ endif
+ return 1
+endfunc
diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in
deleted file mode 100644
index fa9ba312b7..0000000000
--- a/src/nvim/testdir/test13.in
+++ /dev/null
@@ -1,63 +0,0 @@
-Tests for autocommands on :close command
-
-Write three files and open them, each in a window.
-Then go to next window, with autocommand that deletes the previous one.
-Do this twice, writing the file.
-
-Also test deleting the buffer on a Unload event. If this goes wrong there
-will be the ATTENTION prompt.
-
-Also test changing buffers in a BufDel autocommand. If this goes wrong there
-are ml_line errors and/or a Crash.
-
-STARTTEST
-:/^start of testfile/,/^end of testfile/w! Xtestje1
-:/^start of testfile/,/^end of testfile/w! Xtestje2
-:/^start of testfile/,/^end of testfile/w! Xtestje3
-:e Xtestje1
-otestje1
-:w
-:sp Xtestje2
-otestje2
-:w
-:sp Xtestje3
-otestje3
-:w
-
-:au WinLeave Xtestje2 bwipe
-
-:w! test.out
-:au WinLeave Xtestje1 bwipe Xtestje3
-:close
-:w >>test.out
-:e Xtestje1
-:bwipe Xtestje2 Xtestje3 test.out
-:au!
-:au! BufUnload Xtestje1 bwipe
-:e Xtestje3
-:w >>test.out
-:e Xtestje2
-:sp Xtestje1
-:e
-:w >>test.out
-:au!
-:only
-:e Xtestje1
-:bwipe Xtestje2 Xtestje3 test.out test13.in
-:au BufWipeout Xtestje1 buf Xtestje1
-:bwipe
-:w >>test.out
-:only
-:new|set buftype=help
-:wincmd w
-:1quit
-:$put ='Final line'
-:$w >>test.out
-:qa!
-ENDTEST
-
-start of testfile
- contents
- contents
- contents
-end of testfile
diff --git a/src/nvim/testdir/test13.ok b/src/nvim/testdir/test13.ok
deleted file mode 100644
index 66ebce63f7..0000000000
--- a/src/nvim/testdir/test13.ok
+++ /dev/null
@@ -1,31 +0,0 @@
-start of testfile
-testje1
- contents
- contents
- contents
-end of testfile
-start of testfile
-testje1
- contents
- contents
- contents
-end of testfile
-start of testfile
-testje3
- contents
- contents
- contents
-end of testfile
-start of testfile
-testje2
- contents
- contents
- contents
-end of testfile
-start of testfile
-testje1
- contents
- contents
- contents
-end of testfile
-Final line
diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
index adbabd61b9..467abcd9b9 100644
--- a/src/nvim/testdir/test49.vim
+++ b/src/nvim/testdir/test49.vim
@@ -608,7 +608,7 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
-" Tests 1 to 15 were moved to test_viml.vim
+" Tests 1 to 15 were moved to test_vimscript.vim
let Xtest = 16
"-------------------------------------------------------------------------------
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index 8aa0f417d1..c1f6405579 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -2,19 +2,21 @@
" This makes testing go faster, since Vim doesn't need to restart.
source test_assign.vim
-source test_autocmd.vim
source test_cursor_func.vim
source test_execute_func.vim
source test_ex_undo.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_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_lambda.vim
-source test_match.vim
-source test_matchadd_conceal_utf8.vim
source test_menu.vim
source test_mapping.vim
source test_messages.vim
@@ -26,9 +28,12 @@ source test_source_utf8.vim
source test_statusline.vim
source test_syn_attr.vim
source test_tabline.vim
-source test_tabpage.vim
+" source test_tabpage.vim
source test_tagcase.vim
source test_tagjump.vim
+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_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index f05a55f1aa..82c04abf5b 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -1,5 +1,15 @@
" Tests for autocommands
+set belloff=all
+
+function! s:cleanup_buffers() abort
+ for bnr in range(1, bufnr('$'))
+ if bufloaded(bnr) && bufnr('%') != bnr
+ execute 'bd! ' . bnr
+ endif
+ endfor
+endfunction
+
func Test_vim_did_enter()
call assert_false(v:vim_did_enter)
@@ -13,6 +23,9 @@ if has('timers')
endfunc
func Test_cursorhold_insert()
+ " Need to move the cursor.
+ call feedkeys("ggG", "xt")
+
let g:triggered = 0
au CursorHoldI * let g:triggered += 1
set updatetime=20
@@ -20,6 +33,7 @@ if has('timers')
call feedkeys('a', 'x!')
call assert_equal(1, g:triggered)
au! CursorHoldI
+ set updatetime&
endfunc
func Test_cursorhold_insert_ctrl_x()
@@ -31,6 +45,7 @@ if has('timers')
call feedkeys("a\<C-X>", 'x!')
call assert_equal(0, g:triggered)
au! CursorHoldI
+ set updatetime&
endfunc
endif
@@ -77,11 +92,60 @@ function Test_autocmd_bufunload_with_tabnext()
quit
call assert_equal(2, tabpagenr('$'))
+ autocmd! test_autocmd_bufunload_with_tabnext_group
augroup! test_autocmd_bufunload_with_tabnext_group
tablast
quit
endfunc
+function Test_autocmd_bufwinleave_with_tabfirst()
+ tabedit
+ augroup sample
+ autocmd!
+ autocmd BufWinLeave <buffer> tabfirst
+ augroup END
+ call setline(1, ['a', 'b', 'c'])
+ edit! a.txt
+ tabclose
+endfunc
+
+" SEGV occurs in older versions. (At least 7.4.2321 or older)
+function Test_autocmd_bufunload_avoiding_SEGV_01()
+ split aa.txt
+ let lastbuf = bufnr('$')
+
+ augroup test_autocmd_bufunload
+ autocmd!
+ exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
+ augroup END
+
+ call assert_fails('edit bb.txt', 'E937:')
+
+ autocmd! test_autocmd_bufunload
+ augroup! test_autocmd_bufunload
+ bwipe! aa.txt
+ bwipe! bb.txt
+endfunc
+
+" SEGV occurs in older versions. (At least 7.4.2321 or older)
+function Test_autocmd_bufunload_avoiding_SEGV_02()
+ setlocal buftype=nowrite
+ let lastbuf = bufnr('$')
+
+ augroup test_autocmd_bufunload
+ autocmd!
+ exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
+ augroup END
+
+ normal! i1
+ call assert_fails('edit a.txt', 'E517:')
+ call feedkeys("\<CR>")
+
+ autocmd! test_autocmd_bufunload
+ augroup! test_autocmd_bufunload
+ bwipe! a.txt
+endfunc
+
func Test_win_tab_autocmd()
let g:record = []
@@ -172,6 +236,7 @@ func Test_augroup_warning()
augroup Another
augroup END
call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
+ augroup! Another
" no warning for postpone aucmd delete
augroup StartOK
@@ -196,3 +261,184 @@ func Test_augroup_deleted()
au! VimEnter
endfunc
+" Tests for autocommands on :close command.
+" This used to be in test13.
+func Test_three_windows()
+ " Clean up buffers, because in some cases this function fails.
+ call s:cleanup_buffers()
+
+ " Write three files and open them, each in a window.
+ " Then go to next window, with autocommand that deletes the previous one.
+ " Do this twice, writing the file.
+ e! Xtestje1
+ call setline(1, 'testje1')
+ w
+ sp Xtestje2
+ call setline(1, 'testje2')
+ w
+ sp Xtestje3
+ call setline(1, 'testje3')
+ w
+ wincmd w
+ au WinLeave Xtestje2 bwipe
+ wincmd w
+ call assert_equal('Xtestje1', expand('%'))
+
+ au WinLeave Xtestje1 bwipe Xtestje3
+ close
+ call assert_equal('Xtestje1', expand('%'))
+
+ " Test deleting the buffer on a Unload event. If this goes wrong there
+ " will be the ATTENTION prompt.
+ e Xtestje1
+ au!
+ au! BufUnload Xtestje1 bwipe
+ call assert_fails('e Xtestje3', 'E937:')
+ call assert_equal('Xtestje3', expand('%'))
+
+ e Xtestje2
+ sp Xtestje1
+ call assert_fails('e', 'E937:')
+ call assert_equal('Xtestje2', expand('%'))
+
+ " Test changing buffers in a BufWipeout autocommand. If this goes wrong
+ " there are ml_line errors and/or a Crash.
+ au!
+ only
+ e Xanother
+ e Xtestje1
+ bwipe Xtestje2
+ bwipe Xtestje3
+ au BufWipeout Xtestje1 buf Xtestje1
+ bwipe
+ call assert_equal('Xanother', expand('%'))
+
+ only
+
+ helptags ALL
+ help
+ wincmd w
+ 1quit
+ call assert_equal('Xanother', expand('%'))
+
+ au!
+ enew
+ bwipe! Xtestje1
+ call delete('Xtestje1')
+ call delete('Xtestje2')
+ call delete('Xtestje3')
+endfunc
+
+func Test_BufEnter()
+ au! BufEnter
+ au Bufenter * let val = val . '+'
+ let g:val = ''
+ split NewFile
+ call assert_equal('+', g:val)
+ bwipe!
+ call assert_equal('++', g:val)
+
+ " Also get BufEnter when editing a directory
+ call mkdir('Xdir')
+ split Xdir
+ call assert_equal('+++', g:val)
+
+ " On MS-Windows we can't edit the directory, make sure we wipe the right
+ " buffer.
+ bwipe! Xdir
+
+ call delete('Xdir', 'd')
+ au! BufEnter
+endfunc
+
+" Closing a window might cause an endless loop
+" E814 for older Vims
+function Test_autocmd_bufwipe_in_SessLoadPost()
+ tabnew
+ set noswapfile
+ mksession!
+
+ let content = ['set nocp noswapfile',
+ \ 'let v:swapchoice="e"',
+ \ 'augroup test_autocmd_sessionload',
+ \ 'autocmd!',
+ \ 'autocmd SessionLoadPost * 4bw!',
+ \ 'augroup END',
+ \ '',
+ \ 'func WriteErrors()',
+ \ ' call writefile([execute("messages")], "Xerrors")',
+ \ 'endfunc',
+ \ 'au VimLeave * call WriteErrors()',
+ \ ]
+ call writefile(content, 'Xvimrc')
+ 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)
+
+ set swapfile
+ for file in ['Session.vim', 'Xvimrc', 'Xerrors']
+ call delete(file)
+ endfor
+endfunc
+
+" SEGV occurs in older versions.
+function Test_autocmd_bufwipe_in_SessLoadPost2()
+ tabnew
+ set noswapfile
+ mksession!
+
+ let content = ['set nocp noswapfile',
+ \ 'function! DeleteInactiveBufs()',
+ \ ' tabfirst',
+ \ ' let tabblist = []',
+ \ ' for i in range(1, tabpagenr(''$''))',
+ \ ' call extend(tabblist, tabpagebuflist(i))',
+ \ ' endfor',
+ \ ' for b in range(1, bufnr(''$''))',
+ \ ' if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')',
+ \ ' exec ''bwipeout '' . b',
+ \ ' endif',
+ \ ' endfor',
+ \ ' echomsg "SessionLoadPost DONE"',
+ \ 'endfunction',
+ \ 'au SessionLoadPost * call DeleteInactiveBufs()',
+ \ '',
+ \ 'func WriteErrors()',
+ \ ' call writefile([execute("messages")], "Xerrors")',
+ \ 'endfunc',
+ \ 'au VimLeave * call WriteErrors()',
+ \ ]
+ call writefile(content, 'Xvimrc')
+ 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)
+
+ set swapfile
+ for file in ['Session.vim', 'Xvimrc', 'Xerrors']
+ call delete(file)
+ endfor
+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
+ call feedkeys("/hello<CR>", 'xt')
+ call assert_equal('/', g:entered)
+ call assert_equal('/', g:left)
+ au! CmdlineEnter
+ au! CmdlineLeave
+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..1c9350c416 100644
--- a/src/nvim/testdir/test_bufwintabinfo.vim
+++ b/src/nvim/testdir/test_bufwintabinfo.vim
@@ -87,9 +87,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 +105,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_charsearch.vim b/src/nvim/testdir/test_charsearch.vim
new file mode 100644
index 0000000000..8b313b5a35
--- /dev/null
+++ b/src/nvim/testdir/test_charsearch.vim
@@ -0,0 +1,62 @@
+
+function! Test_charsearch()
+ enew!
+ call append(0, ['Xabcdefghijkemnopqretuvwxyz',
+ \ 'Yabcdefghijkemnopqretuvwxyz',
+ \ 'Zabcdefghijkemnokqretkvwxyz'])
+ " check that "fe" and ";" work
+ 1
+ normal! ylfep;;p,,p
+ call assert_equal('XabcdeXfghijkeXmnopqreXtuvwxyz', getline(1))
+ " check that save/restore works
+ 2
+ normal! ylfep
+ let csave = getcharsearch()
+ normal! fip
+ call setcharsearch(csave)
+ normal! ;p;p
+ call assert_equal('YabcdeYfghiYjkeYmnopqreYtuvwxyz', getline(2))
+
+ " check that setcharsearch() changes the settings.
+ 3
+ normal! ylfep
+ call setcharsearch({'char': 'k'})
+ normal! ;p
+ call setcharsearch({'forward': 0})
+ normal! $;p
+ call setcharsearch({'until': 1})
+ set cpo-=;
+ normal! ;;p
+ call assert_equal('ZabcdeZfghijkZZemnokqretkZvwxyz', getline(3))
+ enew!
+endfunction
+
+" Test for t,f,F,T movement commands and 'cpo-;' setting
+function! Test_search_cmds()
+ enew!
+ call append(0, ["aaa two three four", " zzz", "yyy ",
+ \ "bbb yee yoo four", "ccc two three four",
+ \ "ddd yee yoo four"])
+ set cpo-=;
+ 1
+ normal! 0tt;D
+ 2
+ normal! 0fz;D
+ 3
+ normal! $Fy;D
+ 4
+ normal! $Ty;D
+ set cpo+=;
+ 5
+ normal! 0tt;;D
+ 6
+ normal! $Ty;;D
+
+ call assert_equal('aaa two', getline(1))
+ call assert_equal(' z', getline(2))
+ call assert_equal('y', getline(3))
+ call assert_equal('bbb y', getline(4))
+ call assert_equal('ccc', getline(5))
+ call assert_equal('ddd yee y', getline(6))
+ enew!
+endfunction
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 40db227d97..ac44e09a5a 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -2,7 +2,7 @@
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 +17,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 +25,34 @@ func Test_complete_wildmenu()
set nowildmenu
endfunc
+func Test_expr_completion()
+ if !(has('cmdline_compl') && has('eval'))
+ 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 +158,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']
@@ -156,6 +189,20 @@ func Test_getcompletion()
call assert_equal(['Testing'], l)
endif
+ " Command line completion tests
+ let l = getcompletion('cd ', 'cmdline')
+ call assert_true(index(l, 'sautest/') >= 0)
+ let l = getcompletion('cd NoMatch', 'cmdline')
+ call assert_equal([], l)
+ let l = getcompletion('let v:n', 'cmdline')
+ call assert_true(index(l, 'v:null') >= 0)
+ let l = getcompletion('let v:notexists', 'cmdline')
+ call assert_equal([], l)
+ let l = getcompletion('call tag', 'cmdline')
+ call assert_true(index(l, 'taglist(') >= 0)
+ let l = getcompletion('call paint', 'cmdline')
+ call assert_equal([], l)
+
" For others test if the name is recognized.
let names = ['buffer', 'environment', 'file_in_path',
\ 'mapping', 'shellcmd', 'tag', 'tag_listfiles', 'user']
@@ -187,5 +234,100 @@ func Test_expand_star_star()
call writefile(['asdfasdf'], 'a/b/fileXname')
call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt')
call assert_equal('find a/b/fileXname', getreg(':'))
+ 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
+
+set cpo&
diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim
new file mode 100644
index 0000000000..e438a8b077
--- /dev/null
+++ b/src/nvim/testdir/test_command_count.vim
@@ -0,0 +1,191 @@
+" Test for user command counts.
+
+func Test_command_count_0()
+ set hidden
+ set noswapfile
+
+ split DoesNotExistEver
+ let lastbuf = bufnr('$')
+ call setline(1, 'asdf')
+ quit!
+
+ command! -range -addr=loaded_buffers RangeLoadedBuffers :let lines = [<line1>, <line2>]
+ command! -range=% -addr=loaded_buffers RangeLoadedBuffersAll :let lines = [<line1>, <line2>]
+ command! -range -addr=buffers RangeBuffers :let lines = [<line1>, <line2>]
+ command! -range=% -addr=buffers RangeBuffersAll :let lines = [<line1>, <line2>]
+
+ .,$RangeLoadedBuffers
+ call assert_equal([1, 1], lines)
+ %RangeLoadedBuffers
+ call assert_equal([1, 1], lines)
+ RangeLoadedBuffersAll
+ call assert_equal([1, 1], lines)
+ .,$RangeBuffers
+ call assert_equal([1, lastbuf], lines)
+ %RangeBuffers
+ call assert_equal([1, lastbuf], lines)
+ RangeBuffersAll
+ call assert_equal([1, lastbuf], lines)
+
+ delcommand RangeLoadedBuffers
+ delcommand RangeLoadedBuffersAll
+ delcommand RangeBuffers
+ delcommand RangeBuffersAll
+
+ set hidden&
+ set swapfile&
+endfunc
+
+func Test_command_count_1()
+ silent! %argd
+ arga a b c d e
+ argdo echo "loading buffers"
+ argu 3
+ command! -range -addr=arguments RangeArguments :let lines = [<line1>, <line2>]
+ command! -range=% -addr=arguments RangeArgumentsAll :let lines = [<line1>, <line2>]
+ .-,$-RangeArguments
+ call assert_equal([2, 4], lines)
+ %RangeArguments
+ call assert_equal([1, 5], lines)
+ RangeArgumentsAll
+ call assert_equal([1, 5], lines)
+ N
+ .RangeArguments
+ call assert_equal([2, 2], lines)
+ delcommand RangeArguments
+ delcommand RangeArgumentsAll
+
+ split|split|split|split
+ 3wincmd w
+ command! -range -addr=windows RangeWindows :let lines = [<line1>, <line2>]
+ .,$RangeWindows
+ call assert_equal([3, 5], lines)
+ %RangeWindows
+ call assert_equal([1, 5], lines)
+ delcommand RangeWindows
+
+ command! -range=% -addr=windows RangeWindowsAll :let lines = [<line1>, <line2>]
+ RangeWindowsAll
+ call assert_equal([1, 5], lines)
+ delcommand RangeWindowsAll
+ only
+ blast|bd
+
+ tabe|tabe|tabe|tabe
+ normal 2gt
+ command! -range -addr=tabs RangeTabs :let lines = [<line1>, <line2>]
+ .,$RangeTabs
+ call assert_equal([2, 5], lines)
+ %RangeTabs
+ call assert_equal([1, 5], lines)
+ delcommand RangeTabs
+
+ command! -range=% -addr=tabs RangeTabsAll :let lines = [<line1>, <line2>]
+ RangeTabsAll
+ call assert_equal([1, 5], lines)
+ delcommand RangeTabsAll
+ 1tabonly
+
+ s/\n/\r\r\r\r\r/
+ 2ma<
+ $-ma>
+ command! -range=% RangeLines :let lines = [<line1>, <line2>]
+ '<,'>RangeLines
+ call assert_equal([2, 5], lines)
+ delcommand RangeLines
+
+ command! -range=% -buffer LocalRangeLines :let lines = [<line1>, <line2>]
+ '<,'>LocalRangeLines
+ call assert_equal([2, 5], lines)
+ delcommand LocalRangeLines
+endfunc
+
+func Test_command_count_2()
+ silent! %argd
+ arga a b c d
+ call assert_fails('5argu', 'E16:')
+
+ $argu
+ call assert_equal('d', expand('%:t'))
+
+ 1argu
+ call assert_equal('a', expand('%:t'))
+
+ call assert_fails('300b', 'E16:')
+
+ split|split|split|split
+ 0close
+
+ $wincmd w
+ $close
+ call assert_equal(3, winnr())
+
+ call assert_fails('$+close', 'E16:')
+
+ $tabe
+ call assert_equal(2, tabpagenr())
+
+ call assert_fails('$+tabe', 'E16:')
+
+ only!
+ e x
+ 0tabm
+ normal 1gt
+ call assert_equal('x', expand('%:t'))
+
+ tabonly!
+ only!
+endfunc
+
+func Test_command_count_3()
+ se nohidden
+ e aaa
+ let buf_aaa = bufnr('%')
+ e bbb
+ let buf_bbb = bufnr('%')
+ e ccc
+ let buf_ccc = bufnr('%')
+ buf 1
+ 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)])
+ exe buf_aaa . "bdelete"
+ call assert_equal([0, 0, 0], [buflisted(buf_aaa), buflisted(buf_bbb), buflisted(buf_ccc)])
+endfunc
+
+func Test_command_count_4()
+ %argd
+ let bufnr = bufnr('$') + 1
+ arga aa bb cc dd ee ff
+ 3argu
+ let args = []
+ .,$-argdo call add(args, expand('%'))
+ call assert_equal(['cc', 'dd', 'ee'], args)
+
+ " create windows to get 5
+ split|split|split|split
+ 2wincmd w
+ let windows = []
+ .,$-windo call add(windows, winnr())
+ call assert_equal([2, 3, 4], windows)
+ only!
+
+ exe bufnr . 'buf'
+ let buffers = []
+ .,$-bufdo call add(buffers, bufnr('%'))
+ call assert_equal([bufnr, bufnr + 1, bufnr + 2, bufnr + 3, bufnr + 4], buffers)
+
+ exe (bufnr + 3) . 'bdel'
+ let buffers = []
+ exe (bufnr + 2) . ',' . (bufnr + 5) . "bufdo call add(buffers, bufnr('%'))"
+ call assert_equal([bufnr + 2, bufnr + 4, bufnr + 5], buffers)
+
+ " create tabpages to get 5
+ tabe|tabe|tabe|tabe
+ normal! 2gt
+ let tabpages = []
+ .,$-tabdo call add(tabpages, tabpagenr())
+ call assert_equal([2, 3, 4], tabpages)
+ tabonly!
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim
index c8d2ebd7da..01a9a3f9ad 100644
--- a/src/nvim/testdir/test_cscope.vim
+++ b/src/nvim/testdir/test_cscope.vim
@@ -28,7 +28,7 @@ func Test_cscopeWithCscopeConnections()
cscope add Xcscope.out
set cscopeverbose
catch
- call assert_true(0)
+ call assert_report('exception thrown')
endtry
call assert_fails('cscope add', 'E560')
call assert_fails('cscope add Xcscope.out', 'E568')
diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim
index d819b7b092..e1b9651c84 100644
--- a/src/nvim/testdir/test_cursor_func.vim
+++ b/src/nvim/testdir/test_cursor_func.vim
@@ -1,13 +1,7 @@
" Tests for cursor().
func Test_wrong_arguments()
- try
- call cursor(1. 3)
- " not reached
- call assert_false(1)
- catch
- call assert_exception('E474:')
- endtry
+ call assert_fails('call cursor(1. 3)', 'E474:')
endfunc
func Test_move_cursor()
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 5de394de8e..8ee82bd538 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -212,9 +212,63 @@ func Test_diffoff()
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_diffoff_hidden()
+ set diffopt=filler,foldcolumn:0
+ e! one
+ call setline(1, ['Two', 'Three'])
+ 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
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_expr.vim b/src/nvim/testdir/test_expr.vim
index 7f7811dc7a..d32facaa98 100644
--- a/src/nvim/testdir/test_expr.vim
+++ b/src/nvim/testdir/test_expr.vim
@@ -78,7 +78,7 @@ endfunc
func Test_loop_over_null_list()
let null_list = submatch(1, 1)
for i in null_list
- call assert_true(0, 'should not get here')
+ call assert_report('should not get here')
endfor
endfunc
@@ -98,11 +98,44 @@ func Test_special_char()
call assert_fails('echo "\<C-">')
endfunc
+func Test_option_value()
+ " boolean
+ set bri
+ call assert_equal(1, &bri)
+ set nobri
+ call assert_equal(0, &bri)
+
+ " number
+ set ts=1
+ call assert_equal(1, &ts)
+ set ts=8
+ call assert_equal(8, &ts)
+
+ " string
+ exe "set cedit=\<Esc>"
+ call assert_equal("\<Esc>", &cedit)
+ set cpo=
+ call assert_equal("", &cpo)
+ set cpo=abcdefi
+ call assert_equal("abcdefi", &cpo)
+ set cpo&vim
+endfunc
+
+function Test_printf_64bit()
+ if has('num64')
+ call assert_equal("123456789012345", printf('%d', 123456789012345))
+ endif
+endfunc
+
func Test_setmatches()
hi def link 1 Comment
hi def link 2 PreProc
- let set = [{"group": 1, "pattern": 2, "id": 3, "priority": 4, "conceal": 5}]
- let exp = [{"group": '1', "pattern": '2', "id": 3, "priority": 4, "conceal": '5'}]
+ let set = [{"group": 1, "pattern": 2, "id": 3, "priority": 4}]
+ let exp = [{"group": '1', "pattern": '2', "id": 3, "priority": 4}]
+ if has('conceal')
+ let set[0]['conceal'] = 5
+ let exp[0]['conceal'] = '5'
+ endif
call setmatches(set)
call assert_equal(exp, getmatches())
endfunc
@@ -152,20 +185,52 @@ function Test_printf_misc()
call assert_equal(' 123', printf('% d', 123))
call assert_equal('-123', printf('% d', -123))
+ call assert_equal('123', printf('%2d', 123))
+ call assert_equal(' 123', printf('%6d', 123))
+ call assert_equal('000123', printf('%06d', 123))
+ call assert_equal('+00123', printf('%+06d', 123))
+ call assert_equal(' 00123', printf('% 06d', 123))
+ call assert_equal(' +123', printf('%+6d', 123))
+ call assert_equal(' 123', printf('% 6d', 123))
+ call assert_equal(' -123', printf('% 6d', -123))
+
+ " Test left adjusted.
+ call assert_equal('123 ', printf('%-6d', 123))
+ call assert_equal('+123 ', printf('%-+6d', 123))
+ call assert_equal(' 123 ', printf('%- 6d', 123))
+ call assert_equal('-123 ', printf('%- 6d', -123))
+
+ call assert_equal(' 00123', printf('%7.5d', 123))
+ call assert_equal(' -00123', printf('%7.5d', -123))
+ call assert_equal(' +00123', printf('%+7.5d', 123))
+ " Precision field should not be used when combined with %0
+ call assert_equal(' 00123', printf('%07.5d', 123))
+ call assert_equal(' -00123', printf('%07.5d', -123))
+
+ call assert_equal(' 123', printf('%*d', 5, 123))
+ call assert_equal('123 ', printf('%*d', -5, 123))
call assert_equal('00123', printf('%.*d', 5, 123))
call assert_equal(' 123', printf('% *d', 5, 123))
call assert_equal(' +123', printf('%+ *d', 5, 123))
- call assert_equal('123', printf('%2d', 123))
- call assert_equal(' 123', printf('%5d', 123))
- call assert_equal('00123', printf('%05d', 123))
- call assert_equal('123 ', printf('%-5d', 123))
+ " Simple quote (thousand grouping char) is ignored.
+ call assert_equal('+00123456', printf("%+'09d", 123456))
+
+ " Unrecognized format specifier kept as-is.
+ call assert_equal('_123', printf("%_%d", 123))
+
+ " Test alternate forms.
call assert_equal('0x7b', printf('%#x', 123))
call assert_equal('0X7B', printf('%#X', 123))
call assert_equal('0173', printf('%#o', 123))
call assert_equal('0173', printf('%#O', 123))
call assert_equal('abc', printf('%#s', 'abc'))
call assert_equal('abc', printf('%#S', 'abc'))
+ call assert_equal(' 0173', printf('%#6o', 123))
+ call assert_equal(' 00173', printf('%#6.5o', 123))
+ call assert_equal(' 0173', printf('%#6.2o', 123))
+ call assert_equal(' 0173', printf('%#6.2o', 123))
+ call assert_equal('0173', printf('%#2.2o', 123))
call assert_equal(' 00123', printf('%6.5d', 123))
call assert_equal(' 0007b', printf('%6.5x', 123))
@@ -189,24 +254,104 @@ function Test_printf_misc()
endfunc
function Test_printf_float()
+ call assert_equal('1.000000', printf('%f', 1))
call assert_equal('1.230000', printf('%f', 1.23))
call assert_equal('1.230000', printf('%F', 1.23))
- call assert_equal('1.23', printf('%g', 1.23))
- call assert_equal('1.23', printf('%G', 1.23))
+ call assert_equal('9999999.9', printf('%g', 9999999.9))
+ call assert_equal('9999999.9', printf('%G', 9999999.9))
+ call assert_equal('1.00000001e7', printf('%.8g', 10000000.1))
+ call assert_equal('1.00000001E7', printf('%.8G', 10000000.1))
call assert_equal('1.230000e+00', printf('%e', 1.23))
call assert_equal('1.230000E+00', printf('%E', 1.23))
call assert_equal('1.200000e-02', printf('%e', 0.012))
call assert_equal('-1.200000e-02', printf('%e', -0.012))
- call assert_equal('1.2', printf('%.1f', 1.23))
-
+ call assert_equal('0.33', printf('%.2f', 1.0/3.0))
+ call assert_equal(' 0.33', printf('%6.2f', 1.0/3.0))
+ call assert_equal(' -0.33', printf('%6.2f', -1.0/3.0))
+ call assert_equal('000.33', printf('%06.2f', 1.0/3.0))
+ call assert_equal('-00.33', printf('%06.2f', -1.0/3.0))
+ call assert_equal('-00.33', printf('%+06.2f', -1.0/3.0))
+ call assert_equal('+00.33', printf('%+06.2f', 1.0/3.0))
+ call assert_equal(' 00.33', printf('% 06.2f', 1.0/3.0))
+ call assert_equal('000.33', printf('%06.2g', 1.0/3.0))
+ call assert_equal('-00.33', printf('%06.2g', -1.0/3.0))
+ call assert_equal('0.33', printf('%3.2f', 1.0/3.0))
+ call assert_equal('003.33e-01', printf('%010.2e', 1.0/3.0))
+ call assert_equal(' 03.33e-01', printf('% 010.2e', 1.0/3.0))
+ call assert_equal('+03.33e-01', printf('%+010.2e', 1.0/3.0))
+ call assert_equal('-03.33e-01', printf('%010.2e', -1.0/3.0))
+
+ " When precision is 0, the dot should be omitted.
+ call assert_equal(' 2', printf('%3.f', 7.0/3.0))
+ call assert_equal(' 2', printf('%3.g', 7.0/3.0))
+ call assert_equal(' 2e+00', printf('%7.e', 7.0/3.0))
+
+ " Float zero can be signed.
+ call assert_equal('+0.000000', printf('%+f', 0.0))
+ call assert_equal('0.000000', printf('%f', 1.0/(1.0/0.0)))
+ call assert_equal('-0.000000', printf('%f', 1.0/(-1.0/0.0)))
+ call assert_equal('0.0', printf('%s', 1.0/(1.0/0.0)))
+ call assert_equal('-0.0', printf('%s', 1.0/(-1.0/0.0)))
+ call assert_equal('0.0', printf('%S', 1.0/(1.0/0.0)))
+ call assert_equal('-0.0', printf('%S', 1.0/(-1.0/0.0)))
+
+ " Float infinity can be signed.
call assert_equal('inf', printf('%f', 1.0/0.0))
-
- " This prints inf but shouldn't it print -inf instead?
- call assert_match('^-\?inf$', printf('%f', -1.0/0.0))
-
- " This prints -nan but shouldn't it print nan instead?
- call assert_match('^-\?nan$', printf('%f', sqrt(-1.0)))
- call assert_match('^-\?nan$', printf('%f', 0.0/0.0))
+ call assert_equal('-inf', printf('%f', -1.0/0.0))
+ call assert_equal('inf', printf('%g', 1.0/0.0))
+ call assert_equal('-inf', printf('%g', -1.0/0.0))
+ call assert_equal('inf', printf('%e', 1.0/0.0))
+ call assert_equal('-inf', printf('%e', -1.0/0.0))
+ call assert_equal('INF', printf('%F', 1.0/0.0))
+ call assert_equal('-INF', printf('%F', -1.0/0.0))
+ call assert_equal('INF', printf('%E', 1.0/0.0))
+ call assert_equal('-INF', printf('%E', -1.0/0.0))
+ call assert_equal('INF', printf('%E', 1.0/0.0))
+ call assert_equal('-INF', printf('%G', -1.0/0.0))
+ call assert_equal('+inf', printf('%+f', 1.0/0.0))
+ call assert_equal('-inf', printf('%+f', -1.0/0.0))
+ call assert_equal(' inf', printf('% f', 1.0/0.0))
+ call assert_equal(' inf', printf('%6f', 1.0/0.0))
+ call assert_equal(' -inf', printf('%6f', -1.0/0.0))
+ call assert_equal(' inf', printf('%6g', 1.0/0.0))
+ call assert_equal(' -inf', printf('%6g', -1.0/0.0))
+ call assert_equal(' +inf', printf('%+6f', 1.0/0.0))
+ call assert_equal(' inf', printf('% 6f', 1.0/0.0))
+ call assert_equal(' +inf', printf('%+06f', 1.0/0.0))
+ call assert_equal('inf ', printf('%-6f', 1.0/0.0))
+ call assert_equal('-inf ', printf('%-6f', -1.0/0.0))
+ call assert_equal('+inf ', printf('%-+6f', 1.0/0.0))
+ call assert_equal(' inf ', printf('%- 6f', 1.0/0.0))
+ call assert_equal('-INF ', printf('%-6F', -1.0/0.0))
+ call assert_equal('+INF ', printf('%-+6F', 1.0/0.0))
+ call assert_equal(' INF ', printf('%- 6F', 1.0/0.0))
+ call assert_equal('INF ', printf('%-6G', 1.0/0.0))
+ call assert_equal('-INF ', printf('%-6G', -1.0/0.0))
+ call assert_equal('INF ', printf('%-6E', 1.0/0.0))
+ call assert_equal('-INF ', printf('%-6E', -1.0/0.0))
+ call assert_equal("str2float('inf')", printf('%s', 1.0/0.0))
+ call assert_equal("-str2float('inf')", printf('%s', -1.0/0.0))
+
+ " Float nan (not a number) has no sign.
+ call assert_equal('nan', printf('%f', sqrt(-1.0)))
+ call assert_equal('nan', printf('%f', 0.0/0.0))
+ call assert_equal('nan', printf('%f', -0.0/0.0))
+ call assert_equal('nan', printf('%g', 0.0/0.0))
+ call assert_equal('nan', printf('%e', 0.0/0.0))
+ call assert_equal('NAN', printf('%F', 0.0/0.0))
+ call assert_equal('NAN', printf('%G', 0.0/0.0))
+ call assert_equal('NAN', printf('%E', 0.0/0.0))
+ call assert_equal('NAN', printf('%F', -0.0/0.0))
+ call assert_equal('NAN', printf('%G', -0.0/0.0))
+ call assert_equal('NAN', printf('%E', -0.0/0.0))
+ call assert_equal(' nan', printf('%6f', 0.0/0.0))
+ call assert_equal(' nan', printf('%06f', 0.0/0.0))
+ call assert_equal('nan ', printf('%-6f', 0.0/0.0))
+ call assert_equal('nan ', printf('%- 6f', 0.0/0.0))
+ call assert_equal("str2float('nan')", printf('%s', 0.0/0.0))
+ call assert_equal("str2float('nan')", printf('%s', -0.0/0.0))
+ call assert_equal("str2float('nan')", printf('%S', 0.0/0.0))
+ call assert_equal("str2float('nan')", printf('%S', -0.0/0.0))
call assert_fails('echo printf("%f", "a")', 'E807:')
endfunc
@@ -219,6 +364,13 @@ function Test_printf_errors()
call assert_fails('echo printf("%d", 1.2)', 'E805:')
endfunc
+function Test_max_min_errors()
+ call assert_fails('call max(v:true)', 'E712:')
+ call assert_fails('call max(v:true)', 'max()')
+ call assert_fails('call min(v:true)', 'E712:')
+ call assert_fails('call min(v:true)', 'min()')
+endfunc
+
func Test_substitute_expr()
let g:val = 'XXX'
call assert_equal('XXX', substitute('yyy', 'y*', '\=g:val', ''))
@@ -232,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()
@@ -266,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()
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_filter_cmd.vim b/src/nvim/testdir/test_filter_cmd.vim
new file mode 100644
index 0000000000..5aa5fa64df
--- /dev/null
+++ b/src/nvim/testdir/test_filter_cmd.vim
@@ -0,0 +1,76 @@
+" Test the :filter command modifier
+
+func Test_filter()
+ edit Xdoesnotmatch
+ edit Xwillmatch
+ call assert_equal('"Xwillmatch"', substitute(execute('filter willma ls'), '[^"]*\(".*"\)[^"]*', '\1', ''))
+ bwipe Xdoesnotmatch
+ bwipe Xwillmatch
+
+ new
+ call setline(1, ['foo1', 'foo2', 'foo3', 'foo4', 'foo5'])
+ call assert_equal("\nfoo2\nfoo4", execute('filter /foo[24]/ 1,$print'))
+ call assert_equal("\n 2 foo2\n 4 foo4", execute('filter /foo[24]/ 1,$number'))
+ call assert_equal("\nfoo2$\nfoo4$", execute('filter /foo[24]/ 1,$list'))
+
+ call assert_equal("\nfoo1$\nfoo3$\nfoo5$", execute('filter! /foo[24]/ 1,$list'))
+ bwipe!
+
+ command XTryThis echo 'this'
+ command XTryThat echo 'that'
+ command XDoThat echo 'that'
+ let lines = split(execute('filter XTry command'), "\n")
+ call assert_equal(3, len(lines))
+ call assert_match("XTryThat", lines[1])
+ call assert_match("XTryThis", lines[2])
+ delcommand XTryThis
+ delcommand XTryThat
+ delcommand XDoThat
+
+ map f1 the first key
+ map f2 the second key
+ map f3 not a key
+ let lines = split(execute('filter the map f'), "\n")
+ call assert_equal(2, len(lines))
+ call assert_match("f2", lines[0])
+ call assert_match("f1", lines[1])
+ unmap f1
+ unmap f2
+ unmap f3
+endfunc
+
+func Test_filter_fails()
+ call assert_fails('filter', 'E471:')
+ call assert_fails('filter pat', 'E476:')
+ call assert_fails('filter /pat', 'E476:')
+ call assert_fails('filter /pat/', 'E476:')
+ call assert_fails('filter /pat/ asdf', 'E492:')
+
+ call assert_fails('filter!', 'E471:')
+ call assert_fails('filter! pat', 'E476:')
+ call assert_fails('filter! /pat', 'E476:')
+ call assert_fails('filter! /pat/', 'E476:')
+ call assert_fails('filter! /pat/ asdf', 'E492:')
+endfunc
+
+function s:complete_filter_cmd(filtcmd)
+ let keystroke = "\<TAB>\<C-R>=execute('let cmdline = getcmdline()')\<CR>\<C-C>"
+ let cmdline = ''
+ call feedkeys(':' . a:filtcmd . keystroke, 'ntx')
+ return cmdline
+endfunction
+
+func Test_filter_cmd_completion()
+ " Do not complete pattern
+ call assert_equal("filter \t", s:complete_filter_cmd('filter '))
+ call assert_equal("filter pat\t", s:complete_filter_cmd('filter pat'))
+ call assert_equal("filter /pat\t", s:complete_filter_cmd('filter /pat'))
+ call assert_equal("filter /pat/\t", s:complete_filter_cmd('filter /pat/'))
+
+ " Complete after string pattern
+ call assert_equal('filter pat print', s:complete_filter_cmd('filter pat pri'))
+
+ " Complete after regexp pattern
+ call assert_equal('filter /pat/ print', s:complete_filter_cmd('filter /pat/ pri'))
+ call assert_equal('filter #pat# print', s:complete_filter_cmd('filter #pat# pri'))
+endfunc
diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim
new file mode 100644
index 0000000000..5ea5192994
--- /dev/null
+++ b/src/nvim/testdir/test_float_func.vim
@@ -0,0 +1,332 @@
+" test float functions
+
+if !has('float')
+ finish
+end
+
+func Test_abs()
+ call assert_equal('1.23', string(abs(1.23)))
+ call assert_equal('1.23', string(abs(-1.23)))
+ call assert_equal('0.0', string(abs(0.0)))
+ call assert_equal('0.0', string(abs(1.0/(1.0/0.0))))
+ call assert_equal('0.0', string(abs(-1.0/(1.0/0.0))))
+ call assert_equal("str2float('inf')", string(abs(1.0/0.0)))
+ call assert_equal("str2float('inf')", string(abs(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(abs(0.0/0.0)))
+ call assert_equal('12', string(abs('-12abc')))
+ call assert_fails("call abs([])", 'E745:')
+ call assert_fails("call abs({})", 'E728:')
+ call assert_fails("call abs(function('string'))", 'E703:')
+endfunc
+
+func Test_sqrt()
+ call assert_equal('0.0', string(sqrt(0.0)))
+ call assert_equal('1.414214', string(sqrt(2.0)))
+ call assert_equal("str2float('inf')", string(sqrt(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(sqrt(-1.0)))
+ call assert_equal("str2float('nan')", string(sqrt(0.0/0.0)))
+ call assert_fails('call sqrt("")', 'E808:')
+endfunc
+
+func Test_log()
+ call assert_equal('0.0', string(log(1.0)))
+ call assert_equal('-0.693147', string(log(0.5)))
+ call assert_equal("-str2float('inf')", string(log(0.0)))
+ call assert_equal("str2float('nan')", string(log(-1.0)))
+ call assert_equal("str2float('inf')", string(log(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(log(0.0/0.0)))
+ call assert_fails('call log("")', 'E808:')
+endfunc
+
+func Test_log10()
+ call assert_equal('0.0', string(log10(1.0)))
+ call assert_equal('2.0', string(log10(100.0)))
+ call assert_equal('2.079181', string(log10(120.0)))
+ call assert_equal("-str2float('inf')", string(log10(0.0)))
+ call assert_equal("str2float('nan')", string(log10(-1.0)))
+ call assert_equal("str2float('inf')", string(log10(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(log10(0.0/0.0)))
+ call assert_fails('call log10("")', 'E808:')
+endfunc
+
+func Test_exp()
+ call assert_equal('1.0', string(exp(0.0)))
+ call assert_equal('7.389056', string(exp(2.0)))
+ call assert_equal('0.367879', string(exp(-1.0)))
+ call assert_equal("str2float('inf')", string(exp(1.0/0.0)))
+ call assert_equal('0.0', string(exp(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(exp(0.0/0.0)))
+ call assert_fails('call exp("")', 'E808:')
+endfunc
+
+func Test_sin()
+ call assert_equal('0.0', string(sin(0.0)))
+ call assert_equal('0.841471', string(sin(1.0)))
+ call assert_equal('-0.479426', string(sin(-0.5)))
+ call assert_equal("str2float('nan')", string(sin(0.0/0.0)))
+ call assert_equal("str2float('nan')", string(sin(1.0/0.0)))
+ call assert_equal('0.0', string(sin(1.0/(1.0/0.0))))
+ call assert_equal('-0.0', string(sin(-1.0/(1.0/0.0))))
+ call assert_fails('call sin("")', 'E808:')
+endfunc
+
+func Test_asin()
+ call assert_equal('0.0', string(asin(0.0)))
+ call assert_equal('1.570796', string(asin(1.0)))
+ call assert_equal('-0.523599', string(asin(-0.5)))
+ call assert_equal("str2float('nan')", string(asin(1.1)))
+ call assert_equal("str2float('nan')", string(asin(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(asin(0.0/0.0)))
+ call assert_fails('call asin("")', 'E808:')
+endfunc
+
+func Test_sinh()
+ call assert_equal('0.0', string(sinh(0.0)))
+ call assert_equal('0.521095', string(sinh(0.5)))
+ call assert_equal('-1.026517', string(sinh(-0.9)))
+ call assert_equal("str2float('inf')", string(sinh(1.0/0.0)))
+ call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(sinh(0.0/0.0)))
+ call assert_fails('call sinh("")', 'E808:')
+endfunc
+
+func Test_cos()
+ call assert_equal('1.0', string(cos(0.0)))
+ call assert_equal('0.540302', string(cos(1.0)))
+ call assert_equal('0.877583', string(cos(-0.5)))
+ call assert_equal("str2float('nan')", string(cos(0.0/0.0)))
+ call assert_equal("str2float('nan')", string(cos(1.0/0.0)))
+ call assert_fails('call cos("")', 'E808:')
+endfunc
+
+func Test_acos()
+ call assert_equal('1.570796', string(acos(0.0)))
+ call assert_equal('0.0', string(acos(1.0)))
+ call assert_equal('3.141593', string(acos(-1.0)))
+ call assert_equal('2.094395', string(acos(-0.5)))
+ call assert_equal("str2float('nan')", string(acos(1.1)))
+ call assert_equal("str2float('nan')", string(acos(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(acos(0.0/0.0)))
+ call assert_fails('call acos("")', 'E808:')
+endfunc
+
+func Test_cosh()
+ call assert_equal('1.0', string(cosh(0.0)))
+ call assert_equal('1.127626', string(cosh(0.5)))
+ call assert_equal("str2float('inf')", string(cosh(1.0/0.0)))
+ call assert_equal("str2float('inf')", string(cosh(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(cosh(0.0/0.0)))
+ call assert_fails('call cosh("")', 'E808:')
+endfunc
+
+func Test_tan()
+ call assert_equal('0.0', string(tan(0.0)))
+ call assert_equal('0.546302', string(tan(0.5)))
+ call assert_equal('-0.546302', string(tan(-0.5)))
+ call assert_equal("str2float('nan')", string(tan(1.0/0.0)))
+ call assert_equal("str2float('nan')", string(cos(0.0/0.0)))
+ call assert_equal('0.0', string(tan(1.0/(1.0/0.0))))
+ call assert_equal('-0.0', string(tan(-1.0/(1.0/0.0))))
+ call assert_fails('call tan("")', 'E808:')
+endfunc
+
+func Test_atan()
+ call assert_equal('0.0', string(atan(0.0)))
+ call assert_equal('0.463648', string(atan(0.5)))
+ call assert_equal('-0.785398', string(atan(-1.0)))
+ call assert_equal('1.570796', string(atan(1.0/0.0)))
+ call assert_equal('-1.570796', string(atan(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(atan(0.0/0.0)))
+ call assert_fails('call atan("")', 'E808:')
+endfunc
+
+func Test_atan2()
+ call assert_equal('-2.356194', string(atan2(-1, -1)))
+ call assert_equal('2.356194', string(atan2(1, -1)))
+ call assert_equal('0.0', string(atan2(1.0, 1.0/0.0)))
+ call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0)))
+ call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0)))
+ call assert_fails('call atan2("", -1)', 'E808:')
+ call assert_fails('call atan2(-1, "")', 'E808:')
+endfunc
+
+func Test_tanh()
+ call assert_equal('0.0', string(tanh(0.0)))
+ call assert_equal('0.462117', string(tanh(0.5)))
+ call assert_equal('-0.761594', string(tanh(-1.0)))
+ call assert_equal('1.0', string(tanh(1.0/0.0)))
+ call assert_equal('-1.0', string(tanh(-1.0/0.0)))
+ call assert_equal("str2float('nan')", string(tanh(0.0/0.0)))
+ call assert_fails('call tanh("")', 'E808:')
+endfunc
+
+func Test_fmod()
+ call assert_equal('0.13', string(fmod(12.33, 1.22)))
+ call assert_equal('-0.13', string(fmod(-12.33, 1.22)))
+ call assert_equal("str2float('nan')", string(fmod(1.0/0.0, 1.0)))
+ " On Windows we get "nan" instead of 1.0, accept both.
+ let res = string(fmod(1.0, 1.0/0.0))
+ if res != "str2float('nan')"
+ call assert_equal('1.0', res)
+ endif
+ call assert_equal("str2float('nan')", string(fmod(1.0, 0.0)))
+ call assert_fails("call fmod('', 1.22)", 'E808:')
+ call assert_fails("call fmod(12.33, '')", 'E808:')
+endfunc
+
+func Test_pow()
+ call assert_equal('1.0', string(pow(0.0, 0.0)))
+ call assert_equal('8.0', string(pow(2.0, 3.0)))
+ call assert_equal("str2float('nan')", string(pow(2.0, 0.0/0.0)))
+ call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0)))
+ call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0)))
+ call assert_equal("str2float('inf')", string(pow(2.0, 1.0/0.0)))
+ call assert_equal("str2float('inf')", string(pow(1.0/0.0, 3.0)))
+ call assert_fails("call pow('', 2.0)", 'E808:')
+ call assert_fails("call pow(2.0, '')", 'E808:')
+endfunc
+
+func Test_str2float()
+ call assert_equal('1.0', string(str2float('1')))
+ call assert_equal('1.0', string(str2float(' 1 ')))
+ call assert_equal('1.0', string(str2float(' 1.0 ')))
+ call assert_equal('1.23', string(str2float('1.23')))
+ call assert_equal('1.23', string(str2float('1.23abc')))
+ call assert_equal('1.0e40', string(str2float('1e40')))
+ call assert_equal('-1.23', string(str2float('-1.23')))
+ call assert_equal('1.23', string(str2float(' + 1.23 ')))
+
+ call assert_equal('1.0', string(str2float('+1')))
+ call assert_equal('1.0', string(str2float('+1')))
+ call assert_equal('1.0', string(str2float(' +1 ')))
+ call assert_equal('1.0', string(str2float(' + 1 ')))
+
+ call assert_equal('-1.0', string(str2float('-1')))
+ call assert_equal('-1.0', string(str2float('-1')))
+ call assert_equal('-1.0', string(str2float(' -1 ')))
+ call assert_equal('-1.0', string(str2float(' - 1 ')))
+
+ call assert_equal('0.0', string(str2float('+0.0')))
+ call assert_equal('-0.0', string(str2float('-0.0')))
+ call assert_equal("str2float('inf')", string(str2float('1e1000')))
+ call assert_equal("str2float('inf')", string(str2float('inf')))
+ call assert_equal("-str2float('inf')", string(str2float('-inf')))
+ call assert_equal("str2float('inf')", string(str2float('+inf')))
+ call assert_equal("str2float('inf')", string(str2float('Inf')))
+ call assert_equal("str2float('inf')", string(str2float(' +inf ')))
+ call assert_equal("str2float('nan')", string(str2float('nan')))
+ call assert_equal("str2float('nan')", string(str2float('NaN')))
+ call assert_equal("str2float('nan')", string(str2float(' nan ')))
+
+ call assert_fails("call str2float(1.2)", 'E806:')
+ call assert_fails("call str2float([])", 'E730:')
+ call assert_fails("call str2float({})", 'E731:')
+ call assert_fails("call str2float(function('string'))", 'E729:')
+endfunc
+
+func Test_float2nr()
+ call assert_equal(1, float2nr(1.234))
+ call assert_equal(123, float2nr(1.234e2))
+ call assert_equal(12, float2nr(123.4e-1))
+ let max_number = 1/0
+ let min_number = -max_number
+ call assert_equal(max_number/2+1, float2nr(pow(2, 62)))
+ call assert_equal(max_number, float2nr(pow(2, 63)))
+ call assert_equal(max_number, float2nr(pow(2, 64)))
+ call assert_equal(min_number/2-1, float2nr(-pow(2, 62)))
+ call assert_equal(min_number, float2nr(-pow(2, 63)))
+ call assert_equal(min_number, float2nr(-pow(2, 64)))
+endfunc
+
+func Test_floor()
+ call assert_equal('2.0', string(floor(2.0)))
+ call assert_equal('2.0', string(floor(2.11)))
+ call assert_equal('2.0', string(floor(2.99)))
+ call assert_equal('-3.0', string(floor(-2.11)))
+ call assert_equal('-3.0', string(floor(-2.99)))
+ call assert_equal("str2float('nan')", string(floor(0.0/0.0)))
+ call assert_equal("str2float('inf')", string(floor(1.0/0.0)))
+ call assert_equal("-str2float('inf')", string(floor(-1.0/0.0)))
+ call assert_fails("call floor('')", 'E808:')
+endfunc
+
+func Test_ceil()
+ call assert_equal('2.0', string(ceil(2.0)))
+ call assert_equal('3.0', string(ceil(2.11)))
+ call assert_equal('3.0', string(ceil(2.99)))
+ call assert_equal('-2.0', string(ceil(-2.11)))
+ call assert_equal('-2.0', string(ceil(-2.99)))
+ call assert_equal("str2float('nan')", string(ceil(0.0/0.0)))
+ call assert_equal("str2float('inf')", string(ceil(1.0/0.0)))
+ call assert_equal("-str2float('inf')", string(ceil(-1.0/0.0)))
+ call assert_fails("call ceil('')", 'E808:')
+endfunc
+
+func Test_round()
+ call assert_equal('2.0', string(round(2.1)))
+ call assert_equal('3.0', string(round(2.5)))
+ call assert_equal('3.0', string(round(2.9)))
+ call assert_equal('-2.0', string(round(-2.1)))
+ call assert_equal('-3.0', string(round(-2.5)))
+ call assert_equal('-3.0', string(round(-2.9)))
+ call assert_equal("str2float('nan')", string(round(0.0/0.0)))
+ call assert_equal("str2float('inf')", string(round(1.0/0.0)))
+ call assert_equal("-str2float('inf')", string(round(-1.0/0.0)))
+ call assert_fails("call round('')", 'E808:')
+endfunc
+
+func Test_trunc()
+ call assert_equal('2.0', string(trunc(2.1)))
+ call assert_equal('2.0', string(trunc(2.5)))
+ call assert_equal('2.0', string(trunc(2.9)))
+ call assert_equal('-2.0', string(trunc(-2.1)))
+ call assert_equal('-2.0', string(trunc(-2.5)))
+ call assert_equal('-2.0', string(trunc(-2.9)))
+ call assert_equal("str2float('nan')", string(trunc(0.0/0.0)))
+ call assert_equal("str2float('inf')", string(trunc(1.0/0.0)))
+ call assert_equal("-str2float('inf')", string(trunc(-1.0/0.0)))
+ call assert_fails("call trunc('')", 'E808:')
+endfunc
+
+func Test_isnan()
+ throw 'skipped: Nvim does not support isnan()'
+ call assert_equal(0, isnan(1.0))
+ call assert_equal(1, isnan(0.0/0.0))
+ call assert_equal(0, isnan(1.0/0.0))
+ call assert_equal(0, isnan('a'))
+ call assert_equal(0, isnan([]))
+ call assert_equal(0, isnan({}))
+endfunc
+
+" This was converted from test65
+func Test_float_misc()
+ call assert_equal('123.456000', printf('%f', 123.456))
+ call assert_equal('1.234560e+02', printf('%e', 123.456))
+ call assert_equal('123.456', printf('%g', 123.456))
+ " +=
+ let v = 1.234
+ let v += 6.543
+ call assert_equal('7.777', printf('%g', v))
+ let v = 1.234
+ let v += 5
+ call assert_equal('6.234', printf('%g', v))
+ let v = 5
+ let v += 3.333
+ call assert_equal('8.333', string(v))
+ " ==
+ let v = 1.234
+ call assert_true(v == 1.234)
+ call assert_false(v == 1.2341)
+ " add-subtract
+ call assert_equal('5.234', printf('%g', 4 + 1.234))
+ call assert_equal('-6.766', printf('%g', 1.234 - 8))
+ " mult-div
+ call assert_equal('4.936', printf('%g', 4 * 1.234))
+ call assert_equal('0.003241', printf('%g', 4.0 / 1234))
+ " dict
+ call assert_equal("{'x': 1.234, 'y': -2.0e20}", string({'x': 1.234, 'y': -2.0e20}))
+ " list
+ call assert_equal('[-123.4, 2.0e-20]', string([-123.4, 2.0e-20]))
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_fnameescape.vim b/src/nvim/testdir/test_fnameescape.vim
new file mode 100644
index 0000000000..cdff0dfbd9
--- /dev/null
+++ b/src/nvim/testdir/test_fnameescape.vim
@@ -0,0 +1,21 @@
+
+" Test if fnameescape is correct for special chars like !
+function! Test_fnameescape()
+ let fname = 'Xspa ce'
+ let status = v:false
+ try
+ exe "w! " . fnameescape(fname)
+ let status = v:true
+ endtry
+ call assert_true(status, "Space")
+ call delete(fname)
+
+ let fname = 'Xemark!'
+ let status = v:false
+ try
+ exe "w! " . fnameescape(fname)
+ let status = v:true
+ endtry
+ call assert_true(status, "ExclamationMark")
+ call delete(fname)
+endfunction
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 7cb9faa75f..46c54e8614 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -1,5 +1,9 @@
" Test for folding
+func! PrepIndent(arg)
+ return [a:arg] + repeat(["\t".a:arg], 5)
+endfu
+
func! Test_address_fold()
new
call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
@@ -96,6 +100,78 @@ func! Test_indent_fold2()
bw!
endfunc
+func Test_manual_fold_with_filter()
+ if !executable('cat')
+ return
+ endif
+ for type in ['manual', 'marker']
+ exe 'set foldmethod=' . type
+ new
+ call setline(1, range(1, 20))
+ 4,$fold
+ %foldopen
+ 10,$fold
+ %foldopen
+ " This filter command should not have an effect
+ 1,8! cat
+ call feedkeys('5ggzdzMGdd', 'xt')
+ call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
+
+ bwipe!
+ set foldmethod&
+ endfor
+endfunc
+
+func! Test_indent_fold_with_read()
+ new
+ set foldmethod=indent
+ call setline(1, repeat(["\<Tab>a"], 4))
+ for n in range(1, 4)
+ call assert_equal(1, foldlevel(n))
+ endfor
+
+ call writefile(["a", "", "\<Tab>a"], 'Xfile')
+ foldopen
+ 2read Xfile
+ %foldclose
+ call assert_equal(1, foldlevel(1))
+ call assert_equal(2, foldclosedend(1))
+ call assert_equal(0, foldlevel(3))
+ call assert_equal(0, foldlevel(4))
+ call assert_equal(1, foldlevel(5))
+ call assert_equal(7, foldclosedend(5))
+
+ bwipe!
+ set foldmethod&
+ call delete('Xfile')
+endfunc
+
+func Test_combining_folds_indent()
+ new
+ let one = "\<Tab>a"
+ let zero = 'a'
+ call setline(1, [one, one, zero, zero, zero, one, one, one])
+ set foldmethod=indent
+ 3,5d
+ %foldclose
+ call assert_equal(5, foldclosedend(1))
+
+ set foldmethod&
+ bwipe!
+endfunc
+
+func Test_combining_folds_marker()
+ new
+ call setline(1, ['{{{', '}}}', '', '', '', '{{{', '', '}}}'])
+ set foldmethod=marker
+ 3,5d
+ %foldclose
+ call assert_equal(2, foldclosedend(1))
+
+ set foldmethod&
+ bwipe!
+endfunc
+
func Test_folds_marker_in_comment()
new
call setline(1, ['" foo', 'bar', 'baz'])
@@ -112,19 +188,175 @@ func Test_folds_marker_in_comment()
bwipe!
endfunc
-func Test_manual_fold_with_filter()
- if !executable('cat')
- return
+func s:TestFoldExpr(lnum)
+ let thisline = getline(a:lnum)
+ if thisline == 'a'
+ return 1
+ elseif thisline == 'b'
+ return 0
+ elseif thisline == 'c'
+ return '<1'
+ elseif thisline == 'd'
+ return '>1'
endif
+ return 0
+endfunction
+
+func Test_update_folds_expr_read()
new
- call setline(1, range(1, 20))
- 4,$fold
+ call setline(1, ['a', 'a', 'a', 'a', 'a', 'a'])
+ set foldmethod=expr
+ set foldexpr=s:TestFoldExpr(v:lnum)
+ 2
+ foldopen
+ call writefile(['b', 'b', 'a', 'a', 'd', 'a', 'a', 'c'], 'Xfile')
+ read Xfile
+ %foldclose
+ call assert_equal(2, foldclosedend(1))
+ call assert_equal(0, foldlevel(3))
+ call assert_equal(0, foldlevel(4))
+ call assert_equal(6, foldclosedend(5))
+ call assert_equal(10, foldclosedend(7))
+ call assert_equal(14, foldclosedend(11))
+
+ call delete('Xfile')
+ bwipe!
+ set foldmethod& foldexpr&
+endfunc
+
+func! Test_move_folds_around_manual()
+ new
+ let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
+ call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+ let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
+ " all folds closed
+ set foldenable foldlevel=0 fdm=indent
+ " needs a forced redraw
+ redraw!
+ set fdm=manual
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ call assert_equal(input, getline(1, '$'))
+ 7,12m0
+ call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ 10,12m0
+ call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
+ call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+ " moving should not close the folds
+ %d
+ call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+ set fdm=indent
+ redraw!
+ set fdm=manual
+ call cursor(2, 1)
%foldopen
- 10,$fold
+ 7,12m0
+ let folds=repeat([-1], 18)
+ call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ norm! zM
+ " folds are not corrupted and all have been closed
+ call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+ %d
+ call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
+ set fdm=indent
+ redraw!
+ set fdm=manual
%foldopen
- " This filter command should not have an effect
- 1,8! cat
- call feedkeys('5ggzdzMGdd', 'xt')
- call assert_equal(['1', '2', '3', '4', '5', '6', '7', '8', '9'], getline(1, '$'))
- bwipe!
+ 3m4
+ %foldclose
+ call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
+ call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
+ %d
+ call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
+ set fdm=indent foldlevel=0
+ set fdm=manual
+ %foldopen
+ 3m1
+ %foldclose
+ call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
+ call assert_equal(0, foldlevel(2))
+ call assert_equal(5, foldclosedend(3))
+ call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
+ 2,6m$
+ %foldclose
+ call assert_equal(5, foldclosedend(2))
+ call assert_equal(0, foldlevel(6))
+ call assert_equal(9, foldclosedend(7))
+ call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
+ %d
+ " Ensure moving around the edges still works.
+ call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
+ set fdm=indent foldlevel=0
+ set fdm=manual
+ %foldopen
+ 6m$
+ " The first fold has been truncated to the 5'th line.
+ " Second fold has been moved up because the moved line is now below it.
+ call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 0], map(range(1, line('$')), 'foldlevel(v:val)'))
+ bw!
+endfunc
+
+func! Test_move_folds_around_indent()
+ new
+ let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
+ call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+ let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
+ " all folds closed
+ set fdm=indent
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ call assert_equal(input, getline(1, '$'))
+ 7,12m0
+ call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ 10,12m0
+ call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] + PrepIndent("c"), getline(1, '$'))
+ call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+ " moving should not close the folds
+ %d
+ call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+ set fdm=indent
+ call cursor(2, 1)
+ %foldopen
+ 7,12m0
+ let folds=repeat([-1], 18)
+ call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+ call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+ norm! zM
+ " folds are not corrupted and all have been closed
+ call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+ %d
+ call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
+ set fdm=indent
+ %foldopen
+ 3m4
+ %foldclose
+ call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
+ call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
+ %d
+ call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
+ set fdm=indent foldlevel=0
+ %foldopen
+ 3m1
+ %foldclose
+ call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
+ call assert_equal(1, foldlevel(2))
+ call assert_equal(5, foldclosedend(3))
+ call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
+ 2,6m$
+ %foldclose
+ call assert_equal(9, foldclosedend(2))
+ call assert_equal(1, foldlevel(6))
+ call assert_equal(9, foldclosedend(7))
+ call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
+ " Ensure moving around the edges still works.
+ %d
+ call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
+ set fdm=indent foldlevel=0
+ %foldopen
+ 6m$
+ " The first fold has been truncated to the 5'th line.
+ " Second fold has been moved up because the moved line is now below it.
+ call assert_equal([0, 1, 1, 1, 1, 0, 0, 0, 1, 1], map(range(1, line('$')), 'foldlevel(v:val)'))
+ bw!
endfunc
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
new file mode 100644
index 0000000000..0ce034b63e
--- /dev/null
+++ b/src/nvim/testdir/test_functions.vim
@@ -0,0 +1,313 @@
+" Tests for various functions.
+
+func Test_str2nr()
+ call assert_equal(0, str2nr(''))
+ call assert_equal(1, str2nr('1'))
+ call assert_equal(1, str2nr(' 1 '))
+
+ call assert_equal(1, str2nr('+1'))
+ call assert_equal(1, str2nr('+ 1'))
+ call assert_equal(1, str2nr(' + 1 '))
+
+ call assert_equal(-1, str2nr('-1'))
+ call assert_equal(-1, str2nr('- 1'))
+ call assert_equal(-1, str2nr(' - 1 '))
+
+ call assert_equal(123456789, str2nr('123456789'))
+ call assert_equal(-123456789, str2nr('-123456789'))
+endfunc
+
+func Test_setbufvar_options()
+ " This tests that aucmd_prepbuf() and aucmd_restbuf() properly restore the
+ " window layout.
+ call assert_equal(1, winnr('$'))
+ split dummy_preview
+ resize 2
+ set winfixheight winfixwidth
+ let prev_id = win_getid()
+
+ wincmd j
+ let wh = winheight('.')
+ let dummy_buf = bufnr('dummy_buf1', v:true)
+ call setbufvar(dummy_buf, '&buftype', 'nofile')
+ execute 'belowright vertical split #' . dummy_buf
+ call assert_equal(wh, winheight('.'))
+ let dum1_id = win_getid()
+
+ wincmd h
+ let wh = winheight('.')
+ let dummy_buf = bufnr('dummy_buf2', v:true)
+ call setbufvar(dummy_buf, '&buftype', 'nofile')
+ execute 'belowright vertical split #' . dummy_buf
+ call assert_equal(wh, winheight('.'))
+
+ bwipe!
+ call win_gotoid(prev_id)
+ bwipe!
+ call win_gotoid(dum1_id)
+ bwipe!
+endfunc
+
+func Test_tolower()
+ call assert_equal("", tolower(""))
+
+ " Test with all printable ASCII characters.
+ call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
+ \ tolower(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'))
+
+ if !has('multi_byte')
+ return
+ endif
+
+ " Test with a few uppercase diacritics.
+ call assert_equal("aàáâãäåāăąǎǟǡả", tolower("AÀÁÂÃÄÅĀĂĄǍǞǠẢ"))
+ call assert_equal("bḃḇ", tolower("BḂḆ"))
+ call assert_equal("cçćĉċč", tolower("CÇĆĈĊČ"))
+ call assert_equal("dďđḋḏḑ", tolower("DĎĐḊḎḐ"))
+ call assert_equal("eèéêëēĕėęěẻẽ", tolower("EÈÉÊËĒĔĖĘĚẺẼ"))
+ call assert_equal("fḟ ", tolower("FḞ "))
+ call assert_equal("gĝğġģǥǧǵḡ", tolower("GĜĞĠĢǤǦǴḠ"))
+ call assert_equal("hĥħḣḧḩ", tolower("HĤĦḢḦḨ"))
+ call assert_equal("iìíîïĩīĭįiǐỉ", tolower("IÌÍÎÏĨĪĬĮİǏỈ"))
+ call assert_equal("jĵ", tolower("JĴ"))
+ call assert_equal("kķǩḱḵ", tolower("KĶǨḰḴ"))
+ call assert_equal("lĺļľŀłḻ", tolower("LĹĻĽĿŁḺ"))
+ call assert_equal("mḿṁ", tolower("MḾṀ"))
+ call assert_equal("nñńņňṅṉ", tolower("NÑŃŅŇṄṈ"))
+ call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ"))
+ call assert_equal("pṕṗ", tolower("PṔṖ"))
+ call assert_equal("q", tolower("Q"))
+ call assert_equal("rŕŗřṙṟ", tolower("RŔŖŘṘṞ"))
+ call assert_equal("sśŝşšṡ", tolower("SŚŜŞŠṠ"))
+ call assert_equal("tţťŧṫṯ", tolower("TŢŤŦṪṮ"))
+ call assert_equal("uùúûüũūŭůűųưǔủ", tolower("UÙÚÛÜŨŪŬŮŰŲƯǓỦ"))
+ call assert_equal("vṽ", tolower("VṼ"))
+ call assert_equal("wŵẁẃẅẇ", tolower("WŴẀẂẄẆ"))
+ call assert_equal("xẋẍ", tolower("XẊẌ"))
+ call assert_equal("yýŷÿẏỳỷỹ", tolower("YÝŶŸẎỲỶỸ"))
+ call assert_equal("zźżžƶẑẕ", tolower("ZŹŻŽƵẐẔ"))
+
+ " Test with a few lowercase diacritics, which should remain unchanged.
+ call assert_equal("aàáâãäåāăąǎǟǡả", tolower("aàáâãäåāăąǎǟǡả"))
+ call assert_equal("bḃḇ", tolower("bḃḇ"))
+ call assert_equal("cçćĉċč", tolower("cçćĉċč"))
+ call assert_equal("dďđḋḏḑ", tolower("dďđḋḏḑ"))
+ call assert_equal("eèéêëēĕėęěẻẽ", tolower("eèéêëēĕėęěẻẽ"))
+ call assert_equal("fḟ", tolower("fḟ"))
+ call assert_equal("gĝğġģǥǧǵḡ", tolower("gĝğġģǥǧǵḡ"))
+ call assert_equal("hĥħḣḧḩẖ", tolower("hĥħḣḧḩẖ"))
+ call assert_equal("iìíîïĩīĭįǐỉ", tolower("iìíîïĩīĭįǐỉ"))
+ call assert_equal("jĵǰ", tolower("jĵǰ"))
+ call assert_equal("kķǩḱḵ", tolower("kķǩḱḵ"))
+ call assert_equal("lĺļľŀłḻ", tolower("lĺļľŀłḻ"))
+ call assert_equal("mḿṁ ", tolower("mḿṁ "))
+ call assert_equal("nñńņňʼnṅṉ", tolower("nñńņňʼnṅṉ"))
+ call assert_equal("oòóôõöøōŏőơǒǫǭỏ", tolower("oòóôõöøōŏőơǒǫǭỏ"))
+ call assert_equal("pṕṗ", tolower("pṕṗ"))
+ call assert_equal("q", tolower("q"))
+ call assert_equal("rŕŗřṙṟ", tolower("rŕŗřṙṟ"))
+ call assert_equal("sśŝşšṡ", tolower("sśŝşšṡ"))
+ call assert_equal("tţťŧṫṯẗ", tolower("tţťŧṫṯẗ"))
+ call assert_equal("uùúûüũūŭůűųưǔủ", tolower("uùúûüũūŭůűųưǔủ"))
+ call assert_equal("vṽ", tolower("vṽ"))
+ call assert_equal("wŵẁẃẅẇẘ", tolower("wŵẁẃẅẇẘ"))
+ call assert_equal("ẋẍ", tolower("ẋẍ"))
+ call assert_equal("yýÿŷẏẙỳỷỹ", tolower("yýÿŷẏẙỳỷỹ"))
+ call assert_equal("zźżžƶẑẕ", tolower("zźżžƶẑẕ"))
+
+ " According to https://twitter.com/jifa/status/625776454479970304
+ " Ⱥ (U+023A) and Ⱦ (U+023E) are the *only* code points to increase
+ " in length (2 to 3 bytes) when lowercased. So let's test them.
+ call assert_equal("ⱥ ⱦ", tolower("Ⱥ Ⱦ"))
+endfunc
+
+func Test_toupper()
+ call assert_equal("", toupper(""))
+
+ " Test with all printable ASCII characters.
+ call assert_equal(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~',
+ \ toupper(' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'))
+
+ if !has('multi_byte')
+ return
+ endif
+
+ " Test with a few lowercase diacritics.
+ call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("aàáâãäåāăąǎǟǡả"))
+ call assert_equal("BḂḆ", toupper("bḃḇ"))
+ call assert_equal("CÇĆĈĊČ", toupper("cçćĉċč"))
+ call assert_equal("DĎĐḊḎḐ", toupper("dďđḋḏḑ"))
+ call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("eèéêëēĕėęěẻẽ"))
+ call assert_equal("FḞ", toupper("fḟ"))
+ call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("gĝğġģǥǧǵḡ"))
+ call assert_equal("HĤĦḢḦḨẖ", toupper("hĥħḣḧḩẖ"))
+ call assert_equal("IÌÍÎÏĨĪĬĮǏỈ", toupper("iìíîïĩīĭįǐỉ"))
+ call assert_equal("JĴǰ", toupper("jĵǰ"))
+ call assert_equal("KĶǨḰḴ", toupper("kķǩḱḵ"))
+ call assert_equal("LĹĻĽĿŁḺ", toupper("lĺļľŀłḻ"))
+ call assert_equal("MḾṀ ", toupper("mḿṁ "))
+ call assert_equal("NÑŃŅŇʼnṄṈ", toupper("nñńņňʼnṅṉ"))
+ call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("oòóôõöøōŏőơǒǫǭỏ"))
+ call assert_equal("PṔṖ", toupper("pṕṗ"))
+ call assert_equal("Q", toupper("q"))
+ call assert_equal("RŔŖŘṘṞ", toupper("rŕŗřṙṟ"))
+ call assert_equal("SŚŜŞŠṠ", toupper("sśŝşšṡ"))
+ call assert_equal("TŢŤŦṪṮẗ", toupper("tţťŧṫṯẗ"))
+ call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("uùúûüũūŭůűųưǔủ"))
+ call assert_equal("VṼ", toupper("vṽ"))
+ call assert_equal("WŴẀẂẄẆẘ", toupper("wŵẁẃẅẇẘ"))
+ call assert_equal("ẊẌ", toupper("ẋẍ"))
+ call assert_equal("YÝŸŶẎẙỲỶỸ", toupper("yýÿŷẏẙỳỷỹ"))
+ call assert_equal("ZŹŻŽƵẐẔ", toupper("zźżžƶẑẕ"))
+
+ " Test that uppercase diacritics, which should remain unchanged.
+ call assert_equal("AÀÁÂÃÄÅĀĂĄǍǞǠẢ", toupper("AÀÁÂÃÄÅĀĂĄǍǞǠẢ"))
+ call assert_equal("BḂḆ", toupper("BḂḆ"))
+ call assert_equal("CÇĆĈĊČ", toupper("CÇĆĈĊČ"))
+ call assert_equal("DĎĐḊḎḐ", toupper("DĎĐḊḎḐ"))
+ call assert_equal("EÈÉÊËĒĔĖĘĚẺẼ", toupper("EÈÉÊËĒĔĖĘĚẺẼ"))
+ call assert_equal("FḞ ", toupper("FḞ "))
+ call assert_equal("GĜĞĠĢǤǦǴḠ", toupper("GĜĞĠĢǤǦǴḠ"))
+ call assert_equal("HĤĦḢḦḨ", toupper("HĤĦḢḦḨ"))
+ call assert_equal("IÌÍÎÏĨĪĬĮİǏỈ", toupper("IÌÍÎÏĨĪĬĮİǏỈ"))
+ call assert_equal("JĴ", toupper("JĴ"))
+ call assert_equal("KĶǨḰḴ", toupper("KĶǨḰḴ"))
+ call assert_equal("LĹĻĽĿŁḺ", toupper("LĹĻĽĿŁḺ"))
+ call assert_equal("MḾṀ", toupper("MḾṀ"))
+ call assert_equal("NÑŃŅŇṄṈ", toupper("NÑŃŅŇṄṈ"))
+ call assert_equal("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ", toupper("OÒÓÔÕÖØŌŎŐƠǑǪǬỎ"))
+ call assert_equal("PṔṖ", toupper("PṔṖ"))
+ call assert_equal("Q", toupper("Q"))
+ call assert_equal("RŔŖŘṘṞ", toupper("RŔŖŘṘṞ"))
+ call assert_equal("SŚŜŞŠṠ", toupper("SŚŜŞŠṠ"))
+ call assert_equal("TŢŤŦṪṮ", toupper("TŢŤŦṪṮ"))
+ call assert_equal("UÙÚÛÜŨŪŬŮŰŲƯǓỦ", toupper("UÙÚÛÜŨŪŬŮŰŲƯǓỦ"))
+ call assert_equal("VṼ", toupper("VṼ"))
+ call assert_equal("WŴẀẂẄẆ", toupper("WŴẀẂẄẆ"))
+ call assert_equal("XẊẌ", toupper("XẊẌ"))
+ call assert_equal("YÝŶŸẎỲỶỸ", toupper("YÝŶŸẎỲỶỸ"))
+ call assert_equal("ZŹŻŽƵẐẔ", toupper("ZŹŻŽƵẐẔ"))
+
+ 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
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_gf.vim b/src/nvim/testdir/test_gf.vim
new file mode 100644
index 0000000000..c4aa6f9218
--- /dev/null
+++ b/src/nvim/testdir/test_gf.vim
@@ -0,0 +1,33 @@
+
+" This is a test if a URL is recognized by "gf", with the cursor before and
+" after the "://". Also test ":\\".
+function! Test_gf_url()
+ enew!
+ call append(0, [
+ \ "first test for URL://machine.name/tmp/vimtest2a and other text",
+ \ "second test for URL://machine.name/tmp/vimtest2b. And other text",
+ \ "third test for URL:\\\\machine.name\\vimtest2c and other text",
+ \ "fourth test for URL:\\\\machine.name\\tmp\\vimtest2d, and other text"
+ \ ])
+ call cursor(1,1)
+ call search("^first")
+ call search("tmp")
+ call assert_equal("URL://machine.name/tmp/vimtest2a", expand("<cfile>"))
+ call search("^second")
+ call search("URL")
+ call assert_equal("URL://machine.name/tmp/vimtest2b", expand("<cfile>"))
+ if has("ebcdic")
+ set isf=@,240-249,/,.,-,_,+,,,$,:,~,\
+ else
+ set isf=@,48-57,/,.,-,_,+,,,$,:,~,\
+ endif
+ call search("^third")
+ call search("name")
+ call assert_equal("URL:\\\\machine.name\\vimtest2c", expand("<cfile>"))
+ call search("^fourth")
+ call search("URL")
+ call assert_equal("URL:\\\\machine.name\\tmp\\vimtest2d", expand("<cfile>"))
+
+ set isf&vim
+ enew!
+endfunction
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_help.vim b/src/nvim/testdir/test_help.vim
new file mode 100644
index 0000000000..26edc16107
--- /dev/null
+++ b/src/nvim/testdir/test_help.vim
@@ -0,0 +1,16 @@
+
+" Tests for :help
+
+func Test_help_restore_snapshot()
+ help
+ set buftype=
+ help
+ edit x
+ help
+ helpclose
+endfunc
+
+func Test_help_errors()
+ call assert_fails('help doesnotexist', 'E149:')
+ call assert_fails('help!', 'E478:')
+endfunc
diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim
index aabfe40537..65d99c644c 100644
--- a/src/nvim/testdir/test_help_tagjump.vim
+++ b/src/nvim/testdir/test_help_tagjump.vim
@@ -89,17 +89,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 +102,81 @@ 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')
+ finally
+ call s:doc_config_teardown()
+ endtry
+endfunc
+
+func Test_help_respect_current_file_lang()
+ try
+ let list = []
+ call s:doc_config_setup()
+
+ if has('multi_lang')
+ function s:check_help_file_ext(help_keyword, ext)
+ exec 'help ' . a:help_keyword
+ call assert_equal(a:ext, expand('%:e'))
+ call feedkeys("\<C-]>", 'tx')
+ call assert_equal(a:ext, expand('%:e'))
+ pop
+ helpclose
+ endfunc
+
+ set rtp+=Xdir1/doc-ab
+ set rtp+=Xdir1/doc-ja
+
+ set helplang=ab
+ call s:check_help_file_ext('test-char', 'abx')
+ call s:check_help_file_ext('test-char@ja', 'jax')
+ set helplang=ab,ja
+ call s:check_help_file_ext('test-char@ja', 'jax')
+ call s:check_help_file_ext('test-char@en', 'txt')
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 ee6acfffc3..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)
@@ -63,3 +87,20 @@ function Test_History()
call assert_equal(-1, histnr('abc'))
call assert_fails('call histnr([])', 'E730:')
endfunction
+
+function Test_Search_history_window()
+ new
+ call setline(1, ['a', 'b', 'a', 'b'])
+ 1
+ call feedkeys("/a\<CR>", 'xt')
+ call assert_equal('a', getline('.'))
+ 1
+ call feedkeys("/b\<CR>", 'xt')
+ call assert_equal('b', getline('.'))
+ 1
+ " select the previous /a command
+ call feedkeys("q/kk\<CR>", 'x!')
+ call assert_equal('a', getline('.'))
+ call assert_equal('a', @/)
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_hlsearch.vim b/src/nvim/testdir/test_hlsearch.vim
new file mode 100644
index 0000000000..066fdd0250
--- /dev/null
+++ b/src/nvim/testdir/test_hlsearch.vim
@@ -0,0 +1,34 @@
+" Test for v:hlsearch
+
+function! Test_hlsearch()
+ new
+ call setline(1, repeat(['aaa'], 10))
+ set hlsearch nolazyredraw
+ let r=[]
+ " redraw is needed to make hlsearch highlight the matches
+ exe "normal! /aaa\<CR>" | redraw
+ let r1 = screenattr(1, 1)
+ nohlsearch | redraw
+ call assert_notequal(r1, screenattr(1,1))
+ let v:hlsearch=1 | redraw
+ call assert_equal(r1, screenattr(1,1))
+ let v:hlsearch=0 | redraw
+ call assert_notequal(r1, screenattr(1,1))
+ set hlsearch | redraw
+ call assert_equal(r1, screenattr(1,1))
+ let v:hlsearch=0 | redraw
+ call assert_notequal(r1, screenattr(1,1))
+ exe "normal! n" | redraw
+ call assert_equal(r1, screenattr(1,1))
+ let v:hlsearch=0 | redraw
+ call assert_notequal(r1, screenattr(1,1))
+ exe "normal! /\<CR>" | redraw
+ call assert_equal(r1, screenattr(1,1))
+ set nohls
+ exe "normal! /\<CR>" | redraw
+ call assert_notequal(r1, screenattr(1,1))
+ call assert_fails('let v:hlsearch=[]', 'E745')
+ call garbagecollect(1)
+ call getchar(1)
+ enew!
+endfunction
diff --git a/src/nvim/testdir/test_largefile.vim b/src/nvim/testdir/test_largefile.vim
new file mode 100644
index 0000000000..1b3e02a0c8
--- /dev/null
+++ b/src/nvim/testdir/test_largefile.vim
@@ -0,0 +1,34 @@
+" Tests for large files
+" This is only executed manually: "make test_largefile".
+" This is not run as part of "make test".
+
+func Test_largefile()
+ let fname = 'Xlarge.txt'
+
+ call delete(fname)
+ exe "e" fname
+ " Make sure that a line break is 1 byte (LF).
+ set ff=unix
+ set undolevels=-1
+ " Input 99 'A's. The line becomes 100 bytes including a line break.
+ exe "normal 99iA\<Esc>"
+ yank
+ " Put 39,999,999 times. The file becomes 4,000,000,000 bytes.
+ normal 39999999p
+ " Moving around in the file randomly.
+ normal G
+ normal 10%
+ normal 90%
+ normal 50%
+ normal gg
+ w
+ " Check if the file size is 4,000,000,000 bytes.
+ let fsize=getfsize(fname)
+ if has('num64')
+ call assert_true(fsize == 4000000000)
+ else
+ " getfsize() returns -2 if a Number is 32 bits.
+ call assert_true(fsize == -2)
+ endif
+ call delete(fname)
+endfunc
diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim
new file mode 100644
index 0000000000..7856ee82ab
--- /dev/null
+++ b/src/nvim/testdir/test_listlbr.vim
@@ -0,0 +1,235 @@
+" Test for linebreak and list option (non-utf8)
+
+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..980d67d49d
--- /dev/null
+++ b/src/nvim/testdir/test_listlbr_utf8.vim
@@ -0,0 +1,229 @@
+" 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_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_mapping.vim b/src/nvim/testdir/test_mapping.vim
index d937565ce5..f5e4c4b90c 100644
--- a/src/nvim/testdir/test_mapping.vim
+++ b/src/nvim/testdir/test_mapping.vim
@@ -35,29 +35,83 @@ func Test_map_ctrl_c_visual()
endfunc
func Test_map_langmap()
- " langmap should not get remapped in insert mode
- inoremap { FAIL_ilangmap
- set langmap=+{ langnoremap
+ if !has('langmap')
+ return
+ endif
+
+ " check langmap applies in normal mode
+ set langmap=+- nolangremap
+ new
+ call setline(1, ['a', 'b', 'c'])
+ 2
+ call assert_equal('b', getline('.'))
+ call feedkeys("+", "xt")
+ call assert_equal('a', getline('.'))
+
+ " check no remapping
+ map x +
+ 2
+ call feedkeys("x", "xt")
+ call assert_equal('c', getline('.'))
+
+ " check with remapping
+ set langremap
+ 2
+ call feedkeys("x", "xt")
+ call assert_equal('a', getline('.'))
+
+ unmap x
+ bwipe!
+
+ " 'langnoremap' follows 'langremap' and vise versa
+ set langremap
+ set langnoremap
+ call assert_equal(0, &langremap)
+ set langremap
+ call assert_equal(0, &langnoremap)
+ set nolangremap
+ call assert_equal(1, &langnoremap)
+
+ " check default values
+ set langnoremap&
+ call assert_equal(1, &langnoremap)
+ call assert_equal(0, &langremap)
+ set langremap&
+ call assert_equal(1, &langnoremap)
+ call assert_equal(0, &langremap)
+
+ " langmap should not apply in insert mode, 'langremap' doesn't matter
+ set langmap=+{ nolangremap
call feedkeys("Go+\<Esc>", "xt")
call assert_equal('+', getline('$'))
-
- " Insert-mode expr mapping with langmap
- inoremap <expr> { "FAIL_iexplangmap"
+ set langmap=+{ langremap
call feedkeys("Go+\<Esc>", "xt")
call assert_equal('+', getline('$'))
- iunmap <expr> {
- " langmap should not get remapped in Command-line mode
- cnoremap { FAIL_clangmap
+ " langmap used for register name in insert mode.
+ call setreg('a', 'aaaa')
+ call setreg('b', 'bbbb')
+ call setreg('c', 'cccc')
+ set langmap=ab langremap
+ call feedkeys("Go\<C-R>a\<Esc>", "xt")
+ call assert_equal('bbbb', getline('$'))
+ call feedkeys("Go\<C-R>\<C-R>a\<Esc>", "xt")
+ call assert_equal('bbbb', getline('$'))
+ " mapping does not apply
+ imap c a
+ call feedkeys("Go\<C-R>c\<Esc>", "xt")
+ call assert_equal('cccc', getline('$'))
+ imap a c
+ call feedkeys("Go\<C-R>a\<Esc>", "xt")
+ call assert_equal('bbbb', getline('$'))
+
+ " langmap should not apply in Command-line mode
+ set langmap=+{ nolangremap
call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
call assert_equal('+', getline('$'))
- cunmap {
- " Command-line mode expr mapping with langmap
- cnoremap <expr> { "FAIL_cexplangmap"
- call feedkeys(":call append(line('$'), '+')\<CR>", "xt")
- call assert_equal('+', getline('$'))
- cunmap {
+ iunmap a
+ iunmap c
set nomodified
endfunc
@@ -68,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
@@ -98,3 +152,11 @@ func Test_break_undo()
call assert_equal('new line here', getline(line('$') - 1))
set nomodified
endfunc
+
+func Test_map_meta_quotes()
+ imap <M-"> foo
+ call feedkeys("Go-\<M-\">-\<Esc>", "xt")
+ call assert_equal("-foo-", getline('$'))
+ set nomodified
+ iunmap <M-">
+endfunc
diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim
index 9398ef2f27..066bb2f6a1 100644
--- a/src/nvim/testdir/test_match.vim
+++ b/src/nvim/testdir/test_match.vim
@@ -198,6 +198,16 @@ func Test_matchaddpos()
call assert_equal(screenattr(2,2), screenattr(1,10))
call assert_notequal(screenattr(2,2), screenattr(1,11))
+ " Check overlapping pos
+ call clearmatches()
+ call setline(1, ['1234567890', 'NH'])
+ call matchaddpos('Error', [[1,1,5], [1,3,5], [2,2]])
+ redraw!
+ call assert_notequal(screenattr(2,2), 0)
+ call assert_equal(screenattr(2,2), screenattr(1,5))
+ call assert_equal(screenattr(2,2), screenattr(1,7))
+ call assert_notequal(screenattr(2,2), screenattr(1,8))
+
nohl
call clearmatches()
syntax off
diff --git a/src/nvim/testdir/test_matchadd_conceal.vim b/src/nvim/testdir/test_matchadd_conceal.vim
index bc1c28d6e9..c11f1a84a9 100644
--- a/src/nvim/testdir/test_matchadd_conceal.vim
+++ b/src/nvim/testdir/test_matchadd_conceal.vim
@@ -260,3 +260,26 @@ function! Test_matchadd_repeat_conceal_with_syntax_off()
quit!
endfunction
+
+function! Test_matchadd_and_syn_conceal()
+ new
+ let cnt='Inductive bool : Type := | true : bool | false : bool.'
+ let expect = 'Inductive - : Type := | true : - | false : -.'
+ 0put =cnt
+ " set filetype and :syntax on to change screenattr()
+ set cole=1 cocu=nv
+ hi link CheckedByCoq WarningMsg
+ syntax on
+ syntax keyword coqKwd bool conceal cchar=-
+ 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))
+ 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))
+ call assert_equal(screenattr(1, 11) , screenattr(1, 32))
+endfunction
diff --git a/src/nvim/testdir/test_menu.vim b/src/nvim/testdir/test_menu.vim
index be559467c8..af18760065 100644
--- a/src/nvim/testdir/test_menu.vim
+++ b/src/nvim/testdir/test_menu.vim
@@ -4,6 +4,6 @@ func Test_load_menu()
try
source $VIMRUNTIME/menu.vim
catch
- call assert_false(1, 'error while loading menus: ' . v:exception)
+ call assert_report('error while loading menus: ' . v:exception)
endtry
endfunc
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..c05a1d3b6d
--- /dev/null
+++ b/src/nvim/testdir/test_mksession_utf8.vim
@@ -0,0 +1,104 @@
+" 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
+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
new file mode 100644
index 0000000000..4747d5704d
--- /dev/null
+++ b/src/nvim/testdir/test_normal.vim
@@ -0,0 +1,2337 @@
+" Test for various Normal mode commands
+
+func! Setup_NewWindow()
+ 10new
+ call setline(1, range(1,100))
+endfunc
+
+func! MyFormatExpr()
+ " Adds '->$' at lines having numbers followed by trailing whitespace
+ for ln in range(v:lnum, v:lnum+v:count-1)
+ let line = getline(ln)
+ if getline(ln) =~# '\d\s\+$'
+ call setline(ln, substitute(line, '\s\+$', '', '') . '->$')
+ endif
+ endfor
+endfunc
+
+func! CountSpaces(type, ...)
+ " for testing operatorfunc
+ " will count the number of spaces
+ " and return the result in g:a
+ let sel_save = &selection
+ let &selection = "inclusive"
+ let reg_save = @@
+
+ if a:0 " Invoked from Visual mode, use gv command.
+ silent exe "normal! gvy"
+ elseif a:type == 'line'
+ silent exe "normal! '[V']y"
+ else
+ silent exe "normal! `[v`]y"
+ endif
+ let g:a=strlen(substitute(@@, '[^ ]', '', 'g'))
+ let &selection = sel_save
+ let @@ = reg_save
+endfunc
+
+func! OpfuncDummy(type, ...)
+ " for testing operatorfunc
+ let g:opt=&linebreak
+
+ if a:0 " Invoked from Visual mode, use gv command.
+ silent exe "normal! gvy"
+ elseif a:type == 'line'
+ silent exe "normal! '[V']y"
+ else
+ silent exe "normal! `[v`]y"
+ endif
+ " Create a new dummy window
+ new
+ let g:bufnr=bufnr('%')
+endfunc
+
+fun! Test_normal00_optrans()
+ new
+ call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line'])
+ 1
+ exe "norm! Sfoobar\<esc>"
+ call assert_equal(['foobar', '2 This is the second line', '3 this is the third line', ''], getline(1,'$'))
+ 2
+ exe "norm! $vbsone"
+ call assert_equal(['foobar', '2 This is the second one', '3 this is the third line', ''], getline(1,'$'))
+ norm! VS Second line here
+ call assert_equal(['foobar', ' Second line here', '3 this is the third line', ''], getline(1, '$'))
+ %d
+ call append(0, ['4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line'])
+ call append(0, ['1 This is a simple test: abcd', '2 This is the second line', '3 this is the third line'])
+
+ 1
+ norm! 2D
+ call assert_equal(['3 this is the third line', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$'))
+ " Nvim: no "#" flag in 'cpoptions'.
+ " set cpo+=#
+ " norm! 4D
+ " call assert_equal(['', '4 This is a simple test: abcd', '5 This is the second line', '6 this is the third line', ''], getline(1,'$'))
+
+ " clean up
+ set cpo-=#
+ bw!
+endfunc
+
+func! Test_normal01_keymodel()
+ throw "skipped: Nvim regression: 'keymodel'"
+ call Setup_NewWindow()
+ " Test 1: depending on 'keymodel' <s-down> does something different
+ 50
+ call feedkeys("V\<S-Up>y", 'tx')
+ call assert_equal(['47', '48', '49', '50'], getline("'<", "'>"))
+ set keymodel=startsel
+ 50
+ call feedkeys("V\<S-Up>y", 'tx')
+ call assert_equal(['49', '50'], getline("'<", "'>"))
+ " Start visual mode when keymodel = startsel
+ 50
+ call feedkeys("\<S-Up>y", 'tx')
+ call assert_equal(['49', '5'], getreg(0, 0, 1))
+ " Do not start visual mode when keymodel=
+ set keymodel=
+ 50
+ call feedkeys("\<S-Up>y$", 'tx')
+ call assert_equal(['42'], getreg(0, 0, 1))
+ " Stop visual mode when keymodel=stopsel
+ set keymodel=stopsel
+ 50
+ call feedkeys("Vkk\<Up>yy", 'tx')
+ call assert_equal(['47'], getreg(0, 0, 1))
+
+ set keymodel=
+ 50
+ call feedkeys("Vkk\<Up>yy", 'tx')
+ call assert_equal(['47', '48', '49', '50'], getreg(0, 0, 1))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal02_selectmode()
+ " some basic select mode tests
+ call Setup_NewWindow()
+ 50
+ norm! gHy
+ call assert_equal('y51', getline('.'))
+ call setline(1, range(1,100))
+ 50
+ exe ":norm! V9jo\<c-g>y"
+ call assert_equal('y60', getline('.'))
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal02_selectmode2()
+ " some basic select mode tests
+ call Setup_NewWindow()
+ 50
+ call feedkeys(":set im\n\<c-o>gHc\<c-o>:set noim\n", 'tx')
+ call assert_equal('c51', getline('.'))
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal03_join()
+ " basic join test
+ call Setup_NewWindow()
+ 50
+ norm! VJ
+ call assert_equal('50 51', getline('.'))
+ $
+ norm! J
+ call assert_equal('100', getline('.'))
+ $
+ norm! V9-gJ
+ call assert_equal('919293949596979899100', getline('.'))
+ call setline(1, range(1,100))
+ $
+ :j 10
+ call assert_equal('100', getline('.'))
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal04_filter()
+ " basic filter test
+ " only test on non windows platform
+ if has('win32')
+ return
+ endif
+ call Setup_NewWindow()
+ 1
+ call feedkeys("!!sed -e 's/^/| /'\n", 'tx')
+ call assert_equal('| 1', getline('.'))
+ 90
+ :sil :!echo one
+ call feedkeys('.', 'tx')
+ call assert_equal('| 90', getline('.'))
+ 95
+ set cpo+=!
+ " 2 <CR>, 1: for executing the command,
+ " 2: clear hit-enter-prompt
+ call feedkeys("!!\n", 'tx')
+ call feedkeys(":!echo one\n\n", 'tx')
+ call feedkeys(".", 'tx')
+ call assert_equal('one', getline('.'))
+ set cpo-=!
+ bw!
+endfunc
+
+func! Test_normal05_formatexpr()
+ " basic formatexpr test
+ call Setup_NewWindow()
+ %d_
+ call setline(1, ['here: 1 ', '2', 'here: 3 ', '4', 'not here: '])
+ 1
+ set formatexpr=MyFormatExpr()
+ norm! gqG
+ call assert_equal(['here: 1->$', '2', 'here: 3->$', '4', 'not here: '], getline(1,'$'))
+ set formatexpr=
+ bw!
+endfunc
+
+func Test_normal05_formatexpr_newbuf()
+ " Edit another buffer in the 'formatexpr' function
+ new
+ func! Format()
+ edit another
+ endfunc
+ set formatexpr=Format()
+ norm gqG
+ bw!
+ set formatexpr=
+endfunc
+
+func Test_normal05_formatexpr_setopt()
+ " Change the 'formatexpr' value in the function
+ new
+ func! Format()
+ set formatexpr=
+ endfunc
+ set formatexpr=Format()
+ norm gqG
+ bw!
+ set formatexpr=
+endfunc
+
+func! Test_normal06_formatprg()
+ " basic test for formatprg
+ " only test on non windows platform
+ if has('win32')
+ return
+ endif
+
+ " uses sed to number non-empty lines
+ call writefile(['#!/bin/sh', 'sed ''/./=''|sed ''/./{', 'N', 's/\n/ /', '}'''], 'Xsed_format.sh')
+ call system('chmod +x ./Xsed_format.sh')
+ let text = ['a', '', 'c', '', ' ', 'd', 'e']
+ let expected = ['1 a', '', '3 c', '', '5 ', '6 d', '7 e']
+
+ 10new
+ call setline(1, text)
+ set formatprg=./Xsed_format.sh
+ norm! gggqG
+ call assert_equal(expected, getline(1, '$'))
+ bw!
+
+ 10new
+ call setline(1, text)
+ set formatprg=donothing
+ setlocal formatprg=./Xsed_format.sh
+ norm! gggqG
+ call assert_equal(expected, getline(1, '$'))
+ bw!
+
+ " clean up
+ set formatprg=
+ setlocal formatprg=
+ call delete('Xsed_format.sh')
+endfunc
+
+func! Test_normal07_internalfmt()
+ " basic test for internal formmatter to textwidth of 12
+ let list=range(1,11)
+ call map(list, 'v:val." "')
+ 10new
+ call setline(1, list)
+ set tw=12
+ norm! gggqG
+ call assert_equal(['1 2 3', '4 5 6', '7 8 9', '10 11 '], getline(1, '$'))
+ " clean up
+ set tw=0
+ bw!
+endfunc
+
+func! Test_normal08_fold()
+ " basic tests for foldopen/folddelete
+ if !has("folding")
+ return
+ endif
+ call Setup_NewWindow()
+ 50
+ setl foldenable fdm=marker
+ " First fold
+ norm! V4jzf
+ " check that folds have been created
+ call assert_equal(['50/*{{{*/', '51', '52', '53', '54/*}}}*/'], getline(50,54))
+ " Second fold
+ 46
+ norm! V10jzf
+ " check that folds have been created
+ call assert_equal('46/*{{{*/', getline(46))
+ call assert_equal('60/*}}}*/', getline(60))
+ norm! k
+ call assert_equal('45', getline('.'))
+ norm! j
+ call assert_equal('46/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('61', getline('.'))
+ norm! k
+ " open a fold
+ norm! Vzo
+ norm! k
+ call assert_equal('45', getline('.'))
+ norm! j
+ call assert_equal('46/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('47', getline('.'))
+ norm! k
+ norm! zcVzO
+ call assert_equal('46/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('47', getline('.'))
+ norm! j
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51', getline('.'))
+ " delete folds
+ :46
+ " collapse fold
+ norm! V14jzC
+ " delete all folds recursively
+ norm! VzD
+ call assert_equal(['46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60'], getline(46,60))
+
+ " clean up
+ setl nofoldenable fdm=marker
+ bw!
+endfunc
+
+func! Test_normal09_operatorfunc()
+ " Test operatorfunc
+ call Setup_NewWindow()
+ " Add some spaces for counting
+ 50,60s/$/ /
+ unlet! g:a
+ let g:a=0
+ nmap <buffer><silent> ,, :set opfunc=CountSpaces<CR>g@
+ vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR>
+ 50
+ norm V2j,,
+ call assert_equal(6, g:a)
+ norm V,,
+ call assert_equal(2, g:a)
+ norm ,,l
+ call assert_equal(0, g:a)
+ 50
+ exe "norm 0\<c-v>10j2l,,"
+ call assert_equal(11, g:a)
+ 50
+ norm V10j,,
+ call assert_equal(22, g:a)
+
+ " clean up
+ unmap <buffer> ,,
+ set opfunc=
+ unlet! g:a
+ bw!
+endfunc
+
+func! Test_normal09a_operatorfunc()
+ " Test operatorfunc
+ call Setup_NewWindow()
+ " Add some spaces for counting
+ 50,60s/$/ /
+ unlet! g:opt
+ set linebreak
+ nmap <buffer><silent> ,, :set opfunc=OpfuncDummy<CR>g@
+ 50
+ norm ,,j
+ exe "bd!" g:bufnr
+ call assert_true(&linebreak)
+ call assert_equal(g:opt, &linebreak)
+ set nolinebreak
+ norm ,,j
+ exe "bd!" g:bufnr
+ call assert_false(&linebreak)
+ call assert_equal(g:opt, &linebreak)
+
+ " clean up
+ unmap <buffer> ,,
+ set opfunc=
+ bw!
+ unlet! g:opt
+endfunc
+
+func! Test_normal10_expand()
+ " Test for expand()
+ 10new
+ call setline(1, ['1', 'ifooar,,cbar'])
+ 2
+ norm! $
+ let a=expand('<cword>')
+ let b=expand('<cWORD>')
+ call assert_equal('cbar', a)
+ call assert_equal('ifooar,,cbar', b)
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal11_showcmd()
+ " test for 'showcmd'
+ 10new
+ exe "norm! ofoobar\<esc>"
+ call assert_equal(2, line('$'))
+ set showcmd
+ exe "norm! ofoobar2\<esc>"
+ call assert_equal(3, line('$'))
+ exe "norm! VAfoobar3\<esc>"
+ call assert_equal(3, line('$'))
+ exe "norm! 0d3\<del>2l"
+ call assert_equal('obar2foobar3', getline('.'))
+ bw!
+endfunc
+
+func! Test_normal12_nv_error()
+ " Test for nv_error
+ 10new
+ call setline(1, range(1,5))
+ " should not do anything, just beep
+ exe "norm! <c-k>"
+ call assert_equal(map(range(1,5), 'string(v:val)'), getline(1,'$'))
+ bw!
+endfunc
+
+func! Test_normal13_help()
+ " Test for F1
+ call assert_equal(1, winnr())
+ call feedkeys("\<f1>", 'txi')
+ call assert_match('help\.txt', bufname('%'))
+ call assert_equal(2, winnr('$'))
+ bw!
+endfunc
+
+func! Test_normal14_page()
+ " basic test for Ctrl-F and Ctrl-B
+ call Setup_NewWindow()
+ exe "norm! \<c-f>"
+ call assert_equal('9', getline('.'))
+ exe "norm! 2\<c-f>"
+ call assert_equal('25', getline('.'))
+ exe "norm! 2\<c-b>"
+ call assert_equal('18', getline('.'))
+ 1
+ set scrolloff=5
+ exe "norm! 2\<c-f>"
+ call assert_equal('21', getline('.'))
+ exe "norm! \<c-b>"
+ call assert_equal('13', getline('.'))
+ 1
+ set scrolloff=99
+ exe "norm! \<c-f>"
+ call assert_equal('13', getline('.'))
+ set scrolloff=0
+ 100
+ exe "norm! $\<c-b>"
+ call assert_equal('92', getline('.'))
+ call assert_equal([0, 92, 1, 0, 1], getcurpos())
+ 100
+ set nostartofline
+ exe "norm! $\<c-b>"
+ call assert_equal('92', getline('.'))
+ call assert_equal([0, 92, 2, 0, 2147483647], getcurpos())
+ " cleanup
+ set startofline
+ bw!
+endfunc
+
+func! Test_normal14_page_eol()
+ 10new
+ norm oxxxxxxx
+ exe "norm 2\<c-f>"
+ " check with valgrind that cursor is put back in column 1
+ exe "norm 2\<c-b>"
+ bw!
+endfunc
+
+func! Test_normal15_z_scroll_vert()
+ " basic test for z commands that scroll the window
+ call Setup_NewWindow()
+ 100
+ norm! >>
+ " Test for z<cr>
+ exe "norm! z\<cr>"
+ call assert_equal(' 100', getline('.'))
+ call assert_equal(100, winsaveview()['topline'])
+ call assert_equal([0, 100, 2, 0, 9], getcurpos())
+
+ " Test for zt
+ 21
+ norm! >>0zt
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(21, winsaveview()['topline'])
+ call assert_equal([0, 21, 1, 0, 8], getcurpos())
+
+ " Test for zb
+ 30
+ norm! >>$ztzb
+ call assert_equal(' 30', getline('.'))
+ call assert_equal(30, winsaveview()['topline']+winheight(0)-1)
+ call assert_equal([0, 30, 3, 0, 2147483647], getcurpos())
+
+ " Test for z-
+ 1
+ 30
+ norm! 0z-
+ call assert_equal(' 30', getline('.'))
+ call assert_equal(30, winsaveview()['topline']+winheight(0)-1)
+ call assert_equal([0, 30, 2, 0, 9], getcurpos())
+
+ " Test for z{height}<cr>
+ call assert_equal(10, winheight(0))
+ exe "norm! z12\<cr>"
+ call assert_equal(12, winheight(0))
+ exe "norm! z10\<cr>"
+ call assert_equal(10, winheight(0))
+
+ " Test for z.
+ 1
+ 21
+ norm! 0z.
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(17, winsaveview()['topline'])
+ call assert_equal([0, 21, 2, 0, 9], getcurpos())
+
+ " Test for zz
+ 1
+ 21
+ norm! 0zz
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(17, winsaveview()['topline'])
+ call assert_equal([0, 21, 1, 0, 8], getcurpos())
+
+ " Test for z+
+ 11
+ norm! zt
+ norm! z+
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(21, winsaveview()['topline'])
+ call assert_equal([0, 21, 2, 0, 9], getcurpos())
+
+ " Test for [count]z+
+ 1
+ norm! 21z+
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(21, winsaveview()['topline'])
+ call assert_equal([0, 21, 2, 0, 9], getcurpos())
+
+ " Test for z^
+ norm! 22z+0
+ norm! z^
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(12, winsaveview()['topline'])
+ call assert_equal([0, 21, 2, 0, 9], getcurpos())
+
+ " Test for [count]z^
+ 1
+ norm! 30z^
+ call assert_equal(' 21', getline('.'))
+ call assert_equal(12, winsaveview()['topline'])
+ call assert_equal([0, 21, 2, 0, 9], getcurpos())
+
+ " cleanup
+ bw!
+endfunc
+
+func! Test_normal16_z_scroll_hor()
+ " basic test for z commands that scroll the window
+ 10new
+ 15vsp
+ set nowrap listchars=
+ let lineA='abcdefghijklmnopqrstuvwxyz'
+ let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ $put =lineA
+ $put =lineB
+ 1d
+
+ " Test for zl
+ 1
+ norm! 5zl
+ call assert_equal(lineA, getline('.'))
+ call assert_equal(6, col('.'))
+ call assert_equal(5, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('f', @0)
+
+ " Test for zh
+ norm! 2zh
+ call assert_equal(lineA, getline('.'))
+ call assert_equal(6, col('.'))
+ norm! yl
+ call assert_equal('f', @0)
+ call assert_equal(3, winsaveview()['leftcol'])
+
+ " Test for zL
+ norm! zL
+ call assert_equal(11, col('.'))
+ norm! yl
+ call assert_equal('k', @0)
+ call assert_equal(10, winsaveview()['leftcol'])
+ norm! 2zL
+ call assert_equal(25, col('.'))
+ norm! yl
+ call assert_equal('y', @0)
+ call assert_equal(24, winsaveview()['leftcol'])
+
+ " Test for zH
+ norm! 2zH
+ call assert_equal(25, col('.'))
+ call assert_equal(10, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('y', @0)
+
+ " Test for zs
+ norm! $zs
+ call assert_equal(26, col('.'))
+ call assert_equal(25, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('z', @0)
+
+ " Test for ze
+ norm! ze
+ call assert_equal(26, col('.'))
+ call assert_equal(11, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('z', @0)
+
+ " cleanup
+ set wrap listchars=eol:$
+ bw!
+endfunc
+
+func! Test_normal17_z_scroll_hor2()
+ " basic test for z commands that scroll the window
+ " using 'sidescrolloff' setting
+ 10new
+ 20vsp
+ set nowrap listchars= sidescrolloff=5
+ let lineA='abcdefghijklmnopqrstuvwxyz'
+ let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ $put =lineA
+ $put =lineB
+ 1d
+
+ " Test for zl
+ 1
+ norm! 5zl
+ call assert_equal(lineA, getline('.'))
+ call assert_equal(11, col('.'))
+ call assert_equal(5, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('k', @0)
+
+ " Test for zh
+ norm! 2zh
+ call assert_equal(lineA, getline('.'))
+ call assert_equal(11, col('.'))
+ norm! yl
+ call assert_equal('k', @0)
+ call assert_equal(3, winsaveview()['leftcol'])
+
+ " Test for zL
+ norm! 0zL
+ call assert_equal(16, col('.'))
+ norm! yl
+ call assert_equal('p', @0)
+ call assert_equal(10, winsaveview()['leftcol'])
+ norm! 2zL
+ call assert_equal(26, col('.'))
+ norm! yl
+ call assert_equal('z', @0)
+ call assert_equal(15, winsaveview()['leftcol'])
+
+ " Test for zH
+ norm! 2zH
+ call assert_equal(15, col('.'))
+ call assert_equal(0, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('o', @0)
+
+ " Test for zs
+ norm! $zs
+ call assert_equal(26, col('.'))
+ call assert_equal(20, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('z', @0)
+
+ " Test for ze
+ norm! ze
+ call assert_equal(26, col('.'))
+ call assert_equal(11, winsaveview()['leftcol'])
+ norm! yl
+ call assert_equal('z', @0)
+
+ " cleanup
+ set wrap listchars=eol:$ sidescrolloff=0
+ bw!
+endfunc
+
+func! Test_normal18_z_fold()
+ " basic tests for foldopen/folddelete
+ if !has("folding")
+ return
+ endif
+ call Setup_NewWindow()
+ 50
+ setl foldenable fdm=marker foldlevel=5
+
+ " Test for zF
+ " First fold
+ norm! 4zF
+ " check that folds have been created
+ call assert_equal(['50/*{{{*/', '51', '52', '53/*}}}*/'], getline(50,53))
+
+ " Test for zd
+ 51
+ norm! 2zF
+ call assert_equal(2, foldlevel('.'))
+ norm! kzd
+ call assert_equal(['50', '51/*{{{*/', '52/*}}}*/', '53'], getline(50,53))
+ norm! j
+ call assert_equal(1, foldlevel('.'))
+
+ " Test for zD
+ " also deletes partially selected folds recursively
+ 51
+ norm! zF
+ call assert_equal(2, foldlevel('.'))
+ norm! kV2jzD
+ call assert_equal(['50', '51', '52', '53'], getline(50,53))
+
+ " Test for zE
+ 85
+ norm! 4zF
+ 86
+ norm! 2zF
+ 90
+ norm! 4zF
+ call assert_equal(['85/*{{{*/', '86/*{{{*/', '87/*}}}*/', '88/*}}}*/', '89', '90/*{{{*/', '91', '92', '93/*}}}*/'], getline(85,93))
+ norm! zE
+ call assert_equal(['85', '86', '87', '88', '89', '90', '91', '92', '93'], getline(85,93))
+
+ " Test for zn
+ 50
+ set foldlevel=0
+ norm! 2zF
+ norm! zn
+ norm! k
+ call assert_equal('49', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ call assert_equal(0, &foldenable)
+
+ " Test for zN
+ 49
+ norm! zN
+ call assert_equal('49', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ call assert_equal(1, &foldenable)
+
+ " Test for zi
+ norm! zi
+ call assert_equal(0, &foldenable)
+ norm! zi
+ call assert_equal(1, &foldenable)
+ norm! zi
+ call assert_equal(0, &foldenable)
+ norm! zi
+ call assert_equal(1, &foldenable)
+
+ " Test for za
+ 50
+ norm! za
+ norm! k
+ call assert_equal('49', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ 50
+ norm! za
+ norm! k
+ call assert_equal('49', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+
+ 49
+ norm! 5zF
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+ 49
+ norm! za
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ set nofoldenable
+ " close fold and set foldenable
+ norm! za
+ call assert_equal(1, &foldenable)
+
+ 50
+ " have to use {count}za to open all folds and make the cursor visible
+ norm! 2za
+ norm! 2k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+
+ " Test for zA
+ 49
+ set foldlevel=0
+ 50
+ norm! zA
+ norm! 2k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+
+ " zA on a opened fold when foldenale is not set
+ 50
+ set nofoldenable
+ norm! zA
+ call assert_equal(1, &foldenable)
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zc
+ norm! zE
+ 50
+ norm! 2zF
+ 49
+ norm! 5zF
+ set nofoldenable
+ 50
+ " There most likely is a bug somewhere:
+ " https://groups.google.com/d/msg/vim_dev/v2EkfJ_KQjI/u-Cvv94uCAAJ
+ " TODO: Should this only close the inner most fold or both folds?
+ norm! zc
+ call assert_equal(1, &foldenable)
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+ set nofoldenable
+ 50
+ norm! Vjzc
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zC
+ set nofoldenable
+ 50
+ norm! zCk
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zx
+ " 1) close folds at line 49-54
+ set nofoldenable
+ 48
+ norm! zx
+ call assert_equal(1, &foldenable)
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " 2) do not close fold under curser
+ 51
+ set nofoldenable
+ norm! zx
+ call assert_equal(1, &foldenable)
+ norm! 3k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ norm! j
+ call assert_equal('53', getline('.'))
+ norm! j
+ call assert_equal('54/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " 3) close one level of folds
+ 48
+ set nofoldenable
+ set foldlevel=1
+ norm! zx
+ call assert_equal(1, &foldenable)
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ norm! j
+ call assert_equal('53', getline('.'))
+ norm! j
+ call assert_equal('54/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zX
+ " Close all folds
+ set foldlevel=0 nofoldenable
+ 50
+ norm! zX
+ call assert_equal(1, &foldenable)
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zm
+ 50
+ set nofoldenable foldlevel=2
+ norm! zm
+ call assert_equal(1, &foldenable)
+ call assert_equal(1, &foldlevel)
+ norm! zm
+ call assert_equal(0, &foldlevel)
+ norm! zm
+ call assert_equal(0, &foldlevel)
+ norm! k
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zM
+ 48
+ set nofoldenable foldlevel=99
+ norm! zM
+ call assert_equal(1, &foldenable)
+ call assert_equal(0, &foldlevel)
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('55', getline('.'))
+
+ " Test for zr
+ 48
+ set nofoldenable foldlevel=0
+ norm! zr
+ call assert_equal(0, &foldenable)
+ call assert_equal(1, &foldlevel)
+ set foldlevel=0 foldenable
+ norm! zr
+ call assert_equal(1, &foldenable)
+ call assert_equal(1, &foldlevel)
+ norm! zr
+ call assert_equal(2, &foldlevel)
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+
+ " Test for zR
+ 48
+ set nofoldenable foldlevel=0
+ norm! zR
+ call assert_equal(0, &foldenable)
+ call assert_equal(2, &foldlevel)
+ set foldenable foldlevel=0
+ norm! zR
+ call assert_equal(1, &foldenable)
+ call assert_equal(2, &foldlevel)
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ call append(50, ['a /*{{{*/', 'b /*}}}*/'])
+ 48
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('a /*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+ 48
+ norm! zR
+ call assert_equal(1, &foldenable)
+ call assert_equal(3, &foldlevel)
+ call assert_equal('48', getline('.'))
+ norm! j
+ call assert_equal('49/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('50/*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('a /*{{{*/', getline('.'))
+ norm! j
+ call assert_equal('b /*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('51/*}}}*/', getline('.'))
+ norm! j
+ call assert_equal('52', getline('.'))
+
+ " clean up
+ setl nofoldenable fdm=marker foldlevel=0
+ bw!
+endfunc
+
+func! Test_normal19_z_spell()
+ throw "skipped: Nvim 'spell' requires download"
+ if !has("spell") || !has('syntax')
+ return
+ endif
+ new
+ call append(0, ['1 good', '2 goood', '3 goood'])
+ set spell spellfile=./Xspellfile.add spelllang=en
+ let oldlang=v:lang
+ lang C
+
+ " Test for zg
+ 1
+ norm! ]s
+ call assert_equal('2 goood', getline('.'))
+ norm! zg
+ 1
+ let a=execute('unsilent :norm! ]s')
+ call assert_equal('1 good', getline('.'))
+ call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('goood', cnt[0])
+
+ " Test for zw
+ 2
+ norm! $zw
+ 1
+ norm! ]s
+ call assert_equal('2 goood', getline('.'))
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('#oood', cnt[0])
+ call assert_equal('goood/!', cnt[1])
+
+ " Test for zg in visual mode
+ let a=execute('unsilent :norm! V$zg')
+ call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
+ 1
+ norm! ]s
+ call assert_equal('3 goood', getline('.'))
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('2 goood', cnt[2])
+ " Remove "2 good" from spellfile
+ 2
+ let a=execute('unsilent norm! V$zw')
+ call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('2 goood/!', cnt[3])
+
+ " Test for zG
+ 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 cnt=readfile(fname)
+ call assert_equal('2 goood', cnt[0])
+
+ " Test for zW
+ let a=execute('unsilent norm! V$zW')
+ call assert_match("Word '2 goood' added to .*", a)
+ let cnt=readfile(fname)
+ call assert_equal('# goood', cnt[0])
+ call assert_equal('2 goood/!', cnt[1])
+
+ " Test for zuW
+ let a=execute('unsilent norm! V$zuW')
+ call assert_match("Word '2 goood' removed from .*", a)
+ let cnt=readfile(fname)
+ call assert_equal('# goood', cnt[0])
+ call assert_equal('# goood/!', cnt[1])
+
+ " Test for zuG
+ let a=execute('unsilent norm! $zG')
+ call assert_match("Word 'goood' added to .*", a)
+ let cnt=readfile(fname)
+ call assert_equal('# goood', cnt[0])
+ call assert_equal('# goood/!', cnt[1])
+ call assert_equal('goood', cnt[2])
+ let a=execute('unsilent norm! $zuG')
+ let cnt=readfile(fname)
+ call assert_match("Word 'goood' removed from .*", a)
+ call assert_equal('# goood', cnt[0])
+ call assert_equal('# goood/!', cnt[1])
+ call assert_equal('#oood', cnt[2])
+ " word not found in wordlist
+ let a=execute('unsilent norm! V$zuG')
+ let cnt=readfile(fname)
+ call assert_match("", a)
+ call assert_equal('# goood', cnt[0])
+ call assert_equal('# goood/!', cnt[1])
+ call assert_equal('#oood', cnt[2])
+
+ " Test for zug
+ call delete('./Xspellfile.add')
+ 2
+ let a=execute('unsilent norm! $zg')
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('goood', cnt[0])
+ let a=execute('unsilent norm! $zug')
+ call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('#oood', cnt[0])
+ " word not in wordlist
+ let a=execute('unsilent norm! V$zug')
+ call assert_match('', a)
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('#oood', cnt[0])
+
+ " Test for zuw
+ call delete('./Xspellfile.add')
+ 2
+ let a=execute('unsilent norm! Vzw')
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('2 goood/!', cnt[0])
+ let a=execute('unsilent norm! Vzuw')
+ call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('# goood/!', cnt[0])
+ " word not in wordlist
+ let a=execute('unsilent norm! $zug')
+ call assert_match('', a)
+ let cnt=readfile('./Xspellfile.add')
+ call assert_equal('# goood/!', cnt[0])
+
+ " add second entry to spellfile setting
+ set spellfile=./Xspellfile.add,./Xspellfile2.add
+ call delete('./Xspellfile.add')
+ 2
+ let a=execute('unsilent norm! $2zg')
+ let cnt=readfile('./Xspellfile2.add')
+ call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
+ call assert_equal('goood', cnt[0])
+
+ " clean up
+ exe "lang" oldlang
+ call delete("./Xspellfile.add")
+ call delete("./Xspellfile2.add")
+ call delete("./Xspellfile.add.spl")
+ call delete("./Xspellfile2.add.spl")
+
+ " zux -> no-op
+ 2
+ norm! $zux
+ call assert_equal([], glob('Xspellfile.add',0,1))
+ call assert_equal([], glob('Xspellfile2.add',0,1))
+
+ set spellfile=
+ bw!
+endfunc
+
+func! Test_normal20_exmode()
+ if !has("unix")
+ " Reading from redirected file doesn't work on MS-Windows
+ return
+ endif
+ call writefile(['1a', 'foo', 'bar', '.', 'w! Xfile2', 'q!'], 'Xscript')
+ call writefile(['1', '2'], 'Xfile')
+ call system(v:progpath .' -e -s < Xscript Xfile')
+ let a=readfile('Xfile2')
+ call assert_equal(['1', 'foo', 'bar', '2'], a)
+
+ " clean up
+ for file in ['Xfile', 'Xfile2', 'Xscript']
+ call delete(file)
+ endfor
+ bw!
+endfunc
+
+func! Test_normal21_nv_hat()
+ set hidden
+ new
+ " to many buffers opened already, will not work
+ "call assert_fails(":b#", 'E23')
+ "call assert_equal('', @#)
+ e Xfoobar
+ e Xfile2
+ call feedkeys("\<c-^>", 't')
+ call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t'))
+ call feedkeys("f\<c-^>", 't')
+ call assert_equal("Xfile2", fnamemodify(bufname('%'), ':t'))
+ " clean up
+ set nohidden
+ bw!
+endfunc
+
+func! Test_normal22_zet()
+ " Test for ZZ
+ " let shell = &shell
+ " let &shell = 'sh'
+
+ " 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_Test_normal22_zet')
+ let a = readfile('Xfile_Test_normal22_zet')
+ call assert_equal([], a)
+ " Test for ZQ
+ 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)
+
+ " Nvim: This sometimes hangs the TSAN build.
+ " for file in ['Xfile_Test_normal22_zet']
+ " call delete(file)
+ " endfor
+ " let &shell = shell
+endfunc
+
+func! Test_normal23_K()
+ " Test for K command
+ new
+ call append(0, ['helphelp.txt', 'man', 'aa%bb', 'cc|dd'])
+ let k = &keywordprg
+ set keywordprg=:help
+ 1
+ norm! VK
+ call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t'))
+ call assert_equal('help', &ft)
+ call assert_match('\*helphelp.txt\*', getline('.'))
+ helpclose
+ norm! 0K
+ call assert_equal('helphelp.txt', fnamemodify(bufname('%'), ':t'))
+ call assert_equal('help', &ft)
+ call assert_match('Help on help files', getline('.'))
+ helpclose
+
+ set keywordprg=:new
+ set iskeyword+=%
+ set iskeyword+=\|
+ 2
+ norm! K
+ call assert_equal('man', fnamemodify(bufname('%'), ':t'))
+ bwipe!
+ 3
+ norm! K
+ call assert_equal('aa%bb', fnamemodify(bufname('%'), ':t'))
+ bwipe!
+ if !has('win32')
+ 4
+ norm! K
+ call assert_equal('cc|dd', fnamemodify(bufname('%'), ':t'))
+ bwipe!
+ endif
+ set iskeyword-=%
+ set iskeyword-=\|
+
+ " Only expect "man" to work on Unix
+ if !has("unix")
+ let &keywordprg = k
+ bw!
+ return
+ endif
+ set keywordprg=man\ --pager=cat
+ " Test for using man
+ 2
+ let a = execute('unsilent norm! K')
+ call assert_match("man --pager=cat 'man'", a)
+
+ " clean up
+ let &keywordprg = k
+ bw!
+endfunc
+
+func! Test_normal24_rot13()
+ " This test uses multi byte characters
+ if !has("multi_byte")
+ return
+ endif
+ " Testing for g?? g?g?
+ new
+ call append(0, 'abcdefghijklmnopqrstuvwxyzäüö')
+ 1
+ norm! g??
+ call assert_equal('nopqrstuvwxyzabcdefghijklmäüö', getline('.'))
+ norm! g?g?
+ call assert_equal('abcdefghijklmnopqrstuvwxyzäüö', getline('.'))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal25_tag()
+ " Testing for CTRL-] g CTRL-] g]
+ " CTRL-W g] CTRL-W CTRL-] CTRL-W g CTRL-]
+ h
+ " Test for CTRL-]
+ call search('\<x\>$')
+ exe "norm! \<c-]>"
+ call assert_equal("change.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*x*", @0)
+ exe ":norm \<c-o>"
+
+ " Test for g_CTRL-]
+ call search('\<v_u\>$')
+ exe "norm! g\<c-]>"
+ call assert_equal("change.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*v_u*", @0)
+ exe ":norm \<c-o>"
+
+ " Test for g]
+ call search('\<i_<Esc>$')
+ let a = execute(":norm! g]")
+ call assert_match('i_<Esc>.*insert.txt', a)
+
+ if !empty(exepath('cscope')) && has('cscope')
+ " setting cscopetag changes how g] works
+ set cst
+ exe "norm! g]"
+ call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*i_<Esc>*", @0)
+ exe ":norm \<c-o>"
+ " Test for CTRL-W g]
+ exe "norm! \<C-W>g]"
+ call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*i_<Esc>*", @0)
+ call assert_equal(3, winnr('$'))
+ helpclose
+ set nocst
+ endif
+
+ " Test for CTRL-W g]
+ let a = execute("norm! \<C-W>g]")
+ call assert_match('i_<Esc>.*insert.txt', a)
+
+ " Test for CTRL-W CTRL-]
+ exe "norm! \<C-W>\<C-]>"
+ call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*i_<Esc>*", @0)
+ call assert_equal(3, winnr('$'))
+ helpclose
+
+ " Test for CTRL-W g CTRL-]
+ exe "norm! \<C-W>g\<C-]>"
+ call assert_equal("insert.txt", fnamemodify(bufname('%'), ':t'))
+ norm! yiW
+ call assert_equal("*i_<Esc>*", @0)
+ call assert_equal(3, winnr('$'))
+ helpclose
+
+ " clean up
+ helpclose
+endfunc
+
+func! Test_normal26_put()
+ " Test for ]p ]P [p and [P
+ new
+ call append(0, ['while read LINE', 'do', ' ((count++))', ' if [ $? -ne 0 ]; then', " echo 'Error writing file'", ' fi', 'done'])
+ 1
+ /Error/y a
+ 2
+ norm! "a]pj"a[p
+ call assert_equal(['do', "echo 'Error writing file'", " echo 'Error writing file'", ' ((count++))'], getline(2,5))
+ 1
+ /^\s\{4}/
+ exe "norm! \"a]P3Eldt'"
+ exe "norm! j\"a[P2Eldt'"
+ call assert_equal([' if [ $? -ne 0 ]; then', " echo 'Error writing'", " echo 'Error'", " echo 'Error writing file'", ' fi'], getline(6,10))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal27_bracket()
+ " Test for [' [` ]' ]`
+ call Setup_NewWindow()
+ 1,21s/.\+/ & b/
+ 1
+ norm! $ma
+ 5
+ norm! $mb
+ 10
+ norm! $mc
+ 15
+ norm! $md
+ 20
+ norm! $me
+
+ " Test for ['
+ 9
+ norm! 2['
+ call assert_equal(' 1 b', getline('.'))
+ call assert_equal(1, line('.'))
+ call assert_equal(3, col('.'))
+
+ " Test for ]'
+ norm! ]'
+ call assert_equal(' 5 b', getline('.'))
+ call assert_equal(5, line('.'))
+ call assert_equal(3, col('.'))
+
+ " No mark after line 21, cursor moves to first non blank on current line
+ 21
+ norm! $]'
+ call assert_equal(' 21 b', getline('.'))
+ call assert_equal(21, line('.'))
+ call assert_equal(3, col('.'))
+
+ " Test for [`
+ norm! 2[`
+ call assert_equal(' 15 b', getline('.'))
+ call assert_equal(15, line('.'))
+ call assert_equal(8, col('.'))
+
+ " Test for ]`
+ norm! ]`
+ call assert_equal(' 20 b', getline('.'))
+ call assert_equal(20, line('.'))
+ call assert_equal(8, col('.'))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal28_parenthesis()
+ " basic testing for ( and )
+ new
+ call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])
+
+ $
+ norm! d(
+ call assert_equal(['This is a test. With some sentences!', '', 'Even with a question? And one more. ', ''], getline(1, '$'))
+ norm! 2d(
+ call assert_equal(['This is a test. With some sentences!', '', ' ', ''], getline(1, '$'))
+ 1
+ norm! 0d)
+ call assert_equal(['With some sentences!', '', ' ', ''], getline(1, '$'))
+
+ call append('$', ['This is a long sentence', '', 'spanning', 'over several lines. '])
+ $
+ norm! $d(
+ call assert_equal(['With some sentences!', '', ' ', '', 'This is a long sentence', ''], getline(1, '$'))
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal29_brace()
+ " basic test for { and } movements
+ let text= ['A paragraph begins after each empty line, and also at each of a set of',
+ \ 'paragraph macros, specified by the pairs of characters in the ''paragraphs''',
+ \ 'option. The default is "IPLPPPQPP TPHPLIPpLpItpplpipbp", which corresponds to',
+ \ 'the macros ".IP", ".LP", etc. (These are nroff macros, so the dot must be in',
+ \ 'the first column). A section boundary is also a paragraph boundary.',
+ \ 'Note that a blank line (only containing white space) is NOT a paragraph',
+ \ 'boundary.',
+ \ '',
+ \ '',
+ \ 'Also note that this does not include a ''{'' or ''}'' in the first column. When',
+ \ 'the ''{'' flag is in ''cpoptions'' then ''{'' in the first column is used as a',
+ \ 'paragraph boundary |posix|.',
+ \ '{',
+ \ 'This is no paragaraph',
+ \ 'unless the ''{'' is set',
+ \ 'in ''cpoptions''',
+ \ '}',
+ \ '.IP',
+ \ 'The nroff macros IP seperates a paragraph',
+ \ 'That means, it must be a ''.''',
+ \ 'followed by IP',
+ \ '.LPIt does not matter, if afterwards some',
+ \ 'more characters follow.',
+ \ '.SHAlso section boundaries from the nroff',
+ \ 'macros terminate a paragraph. That means',
+ \ 'a character like this:',
+ \ '.NH',
+ \ 'End of text here']
+ new
+ call append(0, text)
+ 1
+ norm! 0d2}
+ call assert_equal(['.IP',
+ \ 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''', 'followed by IP',
+ \ '.LPIt does not matter, if afterwards some', 'more characters follow.', '.SHAlso section boundaries from the nroff',
+ \ 'macros terminate a paragraph. That means', 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
+ norm! 0d}
+ call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.',
+ \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means',
+ \ 'a character like this:', '.NH', 'End of text here', ''], getline(1, '$'))
+ $
+ norm! d{
+ call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.',
+ \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means', 'a character like this:', ''], getline(1, '$'))
+ norm! d{
+ call assert_equal(['.LPIt does not matter, if afterwards some', 'more characters follow.', ''], getline(1,'$'))
+ " Test with { in cpooptions
+ %d
+ call append(0, text)
+ " Nvim: no "{" flag in 'cpoptions'.
+ " set cpo+={
+ " 1
+ " norm! 0d2}
+ " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
+ " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''',
+ " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.',
+ " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means',
+ " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
+ " $
+ " norm! d}
+ " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}',
+ " \ '.IP', 'The nroff macros IP seperates a paragraph', 'That means, it must be a ''.''',
+ " \ 'followed by IP', '.LPIt does not matter, if afterwards some', 'more characters follow.',
+ " \ '.SHAlso section boundaries from the nroff', 'macros terminate a paragraph. That means',
+ " \ 'a character like this:', '.NH', 'End of text here', ''], getline(1,'$'))
+ " norm! gg}
+ " norm! d5}
+ " call assert_equal(['{', 'This is no paragaraph', 'unless the ''{'' is set', 'in ''cpoptions''', '}', ''], getline(1,'$'))
+
+ " clean up
+ set cpo-={
+ bw!
+endfunc
+
+fun! Test_normal30_changecase()
+ " This test uses multi byte characters
+ if !has("multi_byte")
+ return
+ endif
+ new
+ call append(0, 'This is a simple test: äüöß')
+ norm! 1ggVu
+ call assert_equal('this is a simple test: äüöß', getline('.'))
+ norm! VU
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ norm! guu
+ call assert_equal('this is a simple test: äüöss', getline('.'))
+ norm! gUgU
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ norm! gugu
+ call assert_equal('this is a simple test: äüöss', getline('.'))
+ norm! gUU
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ norm! 010~
+ call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.'))
+ norm! V~
+ call assert_equal('THIS IS A simple test: äüöss', getline('.'))
+
+ " Turkish ASCII turns to multi-byte. On some systems Turkish locale
+ " is available but toupper()/tolower() don't do the right thing.
+ try
+ lang tr_TR.UTF-8
+ set casemap=
+ let iupper = toupper('i')
+ if iupper == "\u0130"
+ call setline(1, 'iI')
+ 1normal gUU
+ call assert_equal("\u0130I", getline(1))
+ call assert_equal("\u0130I", toupper("iI"))
+
+ call setline(1, 'iI')
+ 1normal guu
+ call assert_equal("i\u0131", getline(1))
+ call assert_equal("i\u0131", tolower("iI"))
+ elseif iupper == "I"
+ call setline(1, 'iI')
+ 1normal gUU
+ call assert_equal("II", getline(1))
+ call assert_equal("II", toupper("iI"))
+
+ call setline(1, 'iI')
+ 1normal guu
+ call assert_equal("ii", getline(1))
+ call assert_equal("ii", tolower("iI"))
+ else
+ call assert_true(false, "expected toupper('i') to be either 'I' or '\u0131'")
+ endif
+ set casemap&
+ call setline(1, 'iI')
+ 1normal gUU
+ call assert_equal("II", getline(1))
+ call assert_equal("II", toupper("iI"))
+
+ call setline(1, 'iI')
+ 1normal guu
+ call assert_equal("ii", getline(1))
+ call assert_equal("ii", tolower("iI"))
+
+ lang en_US.UTF-8
+ catch /E197:/
+ " can't use Turkish locale
+ throw 'Skipped: Turkish locale not available'
+ endtry
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal31_r_cmd()
+ " Test for r command
+ new
+ call append(0, 'This is a simple test: abcd')
+ exe "norm! 1gg$r\<cr>"
+ call assert_equal(['This is a simple test: abc', '', ''], getline(1,'$'))
+ exe "norm! 1gg2wlr\<cr>"
+ call assert_equal(['This is a', 'simple test: abc', '', ''], getline(1,'$'))
+ exe "norm! 2gg0W5r\<cr>"
+ call assert_equal(['This is a', 'simple ', ' abc', '', ''], getline('1', '$'))
+ set autoindent
+ call setline(2, ['simple test: abc', ''])
+ exe "norm! 2gg0W5r\<cr>"
+ call assert_equal(['This is a', 'simple ', 'abc', '', '', ''], getline('1', '$'))
+ exe "norm! 1ggVr\<cr>"
+ call assert_equal('^M^M^M^M^M^M^M^M^M', strtrans(getline(1)))
+ call setline(1, 'This is a')
+ exe "norm! 1gg05rf"
+ call assert_equal('fffffis a', getline(1))
+
+ " clean up
+ set noautoindent
+ bw!
+endfunc
+
+func! Test_normal32_g_cmd1()
+ " Test for g*, g#
+ new
+ call append(0, ['abc.x_foo', 'x_foobar.abc'])
+ 1
+ norm! $g*
+ call assert_equal('x_foo', @/)
+ call assert_equal('x_foobar.abc', getline('.'))
+ norm! $g#
+ call assert_equal('abc', @/)
+ call assert_equal('abc.x_foo', getline('.'))
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal33_g_cmd2()
+ if !has("jumplist")
+ return
+ endif
+ " Tests for g cmds
+ call Setup_NewWindow()
+ " Test for g`
+ clearjumps
+ norm! ma10j
+ let a=execute(':jumps')
+ " empty jumplist
+ call assert_equal('>', a[-1:])
+ norm! g`a
+ call assert_equal('>', a[-1:])
+ call assert_equal(1, line('.'))
+ call assert_equal('1', getline('.'))
+
+ " Test for g; and g,
+ norm! g;
+ " there is only one change in the changelist
+ " currently, when we setup the window
+ call assert_equal(2, line('.'))
+ call assert_fails(':norm! g;', 'E662')
+ call assert_fails(':norm! g,', 'E663')
+ let &ul=&ul
+ call append('$', ['a', 'b', 'c', 'd'])
+ let &ul=&ul
+ call append('$', ['Z', 'Y', 'X', 'W'])
+ let a = execute(':changes')
+ call assert_match('2\s\+0\s\+2', a)
+ call assert_match('101\s\+0\s\+a', a)
+ call assert_match('105\s\+0\s\+Z', a)
+ norm! 3g;
+ call assert_equal(2, line('.'))
+ norm! 2g,
+ call assert_equal(105, line('.'))
+
+ " Test for g& - global substitute
+ %d
+ call setline(1, range(1,10))
+ call append('$', ['a', 'b', 'c', 'd'])
+ $s/\w/&&/g
+ exe "norm! /[1-8]\<cr>"
+ norm! g&
+ call assert_equal(['11', '22', '33', '44', '55', '66', '77', '88', '9', '110', 'a', 'b', 'c', 'dd'], getline(1, '$'))
+
+ " Test for gv
+ %d
+ call append('$', repeat(['abcdefgh'], 8))
+ exe "norm! 2gg02l\<c-v>2j2ly"
+ call assert_equal(['cde', 'cde', 'cde'], getreg(0, 1, 1))
+ " in visual mode, gv swaps current and last selected region
+ exe "norm! G0\<c-v>4k4lgvd"
+ call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh', 'abcdefgh'], getline(1,'$'))
+ exe "norm! G0\<c-v>4k4ly"
+ exe "norm! gvood"
+ call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'fgh', 'fgh', 'fgh', 'fgh', 'fgh'], getline(1,'$'))
+
+ " Test for gk/gj
+ %d
+ 15vsp
+ set wrap listchars= sbr=
+ let lineA='abcdefghijklmnopqrstuvwxyz'
+ let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ $put =lineA
+ $put =lineB
+
+ norm! 3gg0dgk
+ call assert_equal(['', 'abcdefghijklmno', '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'], getline(1, '$'))
+ set nu
+ norm! 3gg0gjdgj
+ call assert_equal(['', 'abcdefghijklmno', '0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
+
+ " Test for gJ
+ norm! 2gggJ
+ call assert_equal(['', 'abcdefghijklmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
+ call assert_equal(16, col('.'))
+ " shouldn't do anything
+ norm! 10gJ
+ call assert_equal(1, col('.'))
+
+ " Test for g0 g^ gm g$
+ exe "norm! 2gg0gji "
+ call assert_equal(['', 'abcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
+ norm! g0yl
+ call assert_equal(12, col('.'))
+ call assert_equal(' ', getreg(0))
+ norm! g$yl
+ call assert_equal(22, col('.'))
+ call assert_equal('3', getreg(0))
+ norm! gmyl
+ call assert_equal(17, col('.'))
+ call assert_equal('n', getreg(0))
+ norm! g^yl
+ call assert_equal(15, col('.'))
+ call assert_equal('l', getreg(0))
+
+ " Test for g Ctrl-G
+ set ff=unix
+ let a=execute(":norm! g\<c-g>")
+ call assert_match('Col 15 of 43; Line 2 of 2; Word 2 of 2; Byte 16 of 45', a)
+
+ " Test for gI
+ norm! gIfoo
+ call assert_equal(['', 'fooabcdefghijk lmno0123456789AMNOPQRSTUVWXYZ'], getline(1,'$'))
+
+ " Test for gi
+ wincmd c
+ %d
+ set tw=0
+ call setline(1, ['foobar', 'new line'])
+ norm! A next word
+ $put ='third line'
+ norm! gi another word
+ call assert_equal(['foobar next word another word', 'new line', 'third line'], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal34_g_cmd3()
+ if !has("multi_byte")
+ return
+ endif
+ " Test for g8
+ new
+ call append(0, 'abcdefghijklmnopqrstuvwxyzäüö')
+ let a=execute(':norm! 1gg$g8')
+ call assert_equal('c3 b6 ', a[1:])
+
+ " Test for gp gP
+ call append(1, range(1,10))
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal35_g_cmd4()
+ " Test for g<
+ " Cannot capture its output,
+ " probably a bug, therefore, test disabled:
+ throw "Skipped: output of g< can't be tested currently"
+ echo "a\nb\nc\nd"
+ let b=execute(':norm! g<')
+ call assert_true(!empty(b), 'failed `execute(g<)`')
+endfunc
+
+fun! Test_normal36_g_cmd5()
+ new
+ call append(0, 'abcdefghijklmnopqrstuvwxyz')
+ set ff=unix
+ " Test for gp gP
+ call append(1, range(1,10))
+ 1
+ norm! 1yy
+ 3
+ norm! gp
+ call assert_equal([0, 5, 1, 0, 1], getcurpos())
+ $
+ norm! gP
+ call assert_equal([0, 14, 1, 0, 1], getcurpos())
+
+ " Test for go
+ norm! 26go
+ call assert_equal([0, 1, 26, 0, 26], getcurpos())
+ norm! 27go
+ call assert_equal([0, 1, 26, 0, 26], getcurpos())
+ norm! 28go
+ call assert_equal([0, 2, 1, 0, 1], getcurpos())
+ set ff=dos
+ norm! 29go
+ call assert_equal([0, 2, 1, 0, 1], getcurpos())
+ set ff=unix
+ norm! gg0
+ norm! 101go
+ call assert_equal([0, 13, 26, 0, 26], getcurpos())
+ norm! 103go
+ call assert_equal([0, 14, 1, 0, 1], getcurpos())
+ " count > buffer content
+ norm! 120go
+ call assert_equal([0, 14, 1, 0, 2147483647], getcurpos())
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal37_g_cmd6()
+ " basic test for gt and gT
+ tabnew 1.txt
+ tabnew 2.txt
+ tabnew 3.txt
+ norm! 1gt
+ call assert_equal(1, tabpagenr())
+ norm! 3gt
+ call assert_equal(3, tabpagenr())
+ norm! 1gT
+ " count gT goes not to the absolute tabpagenumber
+ " but, but goes to the count previous tabpagenumber
+ call assert_equal(2, tabpagenr())
+ " wrap around
+ norm! 3gT
+ call assert_equal(3, tabpagenr())
+ " gt does not wrap around
+ norm! 5gt
+ call assert_equal(3, tabpagenr())
+
+ for i in range(3)
+ tabclose
+ endfor
+ " clean up
+ call assert_fails(':tabclose', 'E784')
+endfunc
+
+fun! Test_normal38_nvhome()
+ " Test for <Home> and <C-Home> key
+ new
+ call setline(1, range(10))
+ $
+ setl et sw=2
+ norm! V10>$
+ " count is ignored
+ exe "norm! 10\<home>"
+ call assert_equal(1, col('.'))
+ exe "norm! \<home>"
+ call assert_equal([0, 10, 1, 0, 1], getcurpos())
+ exe "norm! 5\<c-home>"
+ call assert_equal([0, 5, 1, 0, 1], getcurpos())
+ exe "norm! \<c-home>"
+ call assert_equal([0, 1, 1, 0, 1], getcurpos())
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal39_cw()
+ " Test for cw and cW on whitespace
+ " and cpo+=w setting
+ new
+ set tw=0
+ call append(0, 'here are some words')
+ norm! 1gg0elcwZZZ
+ call assert_equal('hereZZZare some words', getline('.'))
+ norm! 1gg0elcWYYY
+ call assert_equal('hereZZZareYYYsome words', getline('.'))
+ " Nvim: no "w" flag in 'cpoptions'.
+ " set cpo+=w
+ " call setline(1, 'here are some words')
+ " norm! 1gg0elcwZZZ
+ " call assert_equal('hereZZZ are some words', getline('.'))
+ " norm! 1gg2elcWYYY
+ " call assert_equal('hereZZZ areYYY some words', getline('.'))
+ set cpo-=w
+ norm! 2gg0cwfoo
+ call assert_equal('foo', getline('.'))
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal40_ctrl_bsl()
+ " Basic test for CTRL-\ commands
+ new
+ call append(0, 'here are some words')
+ exe "norm! 1gg0a\<C-\>\<C-N>"
+ call assert_equal('n', mode())
+ call assert_equal(1, col('.'))
+ call assert_equal('', visualmode())
+ exe "norm! 1gg0viw\<C-\>\<C-N>"
+ call assert_equal('n', mode())
+ call assert_equal(4, col('.'))
+ exe "norm! 1gg0a\<C-\>\<C-G>"
+ call assert_equal('n', mode())
+ call assert_equal(1, col('.'))
+ "imap <buffer> , <c-\><c-n>
+ set im
+ exe ":norm! \<c-\>\<c-n>dw"
+ set noim
+ call assert_equal('are some words', getline(1))
+ call assert_false(&insertmode)
+
+ " clean up
+ bw!
+endfunc
+
+fun! Test_normal41_insert_reg()
+ " Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>=
+ " in insert mode
+ new
+ set sts=2 sw=2 ts=8 tw=0
+ call append(0, ["aaa\tbbb\tccc", '', '', ''])
+ let a=getline(1)
+ norm! 2gg0
+ exe "norm! a\<c-r>=a\<cr>"
+ norm! 3gg0
+ exe "norm! a\<c-r>\<c-r>=a\<cr>"
+ norm! 4gg0
+ exe "norm! a\<c-r>\<c-o>=a\<cr>"
+ call assert_equal(['aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', 'aaa bbb ccc', ''], getline(1, '$'))
+
+ " clean up
+ set sts=0 sw=8 ts=8
+ bw!
+endfunc
+
+func! Test_normal42_halfpage()
+ " basic test for Ctrl-D and Ctrl-U
+ call Setup_NewWindow()
+ call assert_equal(5, &scroll)
+ exe "norm! \<c-d>"
+ call assert_equal('6', getline('.'))
+ exe "norm! 2\<c-d>"
+ call assert_equal('8', getline('.'))
+ call assert_equal(2, &scroll)
+ set scroll=5
+ exe "norm! \<c-u>"
+ call assert_equal('3', getline('.'))
+ 1
+ set scrolloff=5
+ exe "norm! \<c-d>"
+ call assert_equal('10', getline('.'))
+ exe "norm! \<c-u>"
+ call assert_equal('5', getline('.'))
+ 1
+ set scrolloff=99
+ exe "norm! \<c-d>"
+ call assert_equal('10', getline('.'))
+ set scrolloff=0
+ 100
+ exe "norm! $\<c-u>"
+ call assert_equal('95', getline('.'))
+ call assert_equal([0, 95, 1, 0, 1], getcurpos())
+ 100
+ set nostartofline
+ exe "norm! $\<c-u>"
+ call assert_equal('95', getline('.'))
+ call assert_equal([0, 95, 2, 0, 2147483647], getcurpos())
+ " cleanup
+ set startofline
+ bw!
+endfunc
+
+fun! Test_normal43_textobject1()
+ " basic tests for text object aw
+ new
+ call append(0, ['foobar,eins,foobar', 'foo,zwei,foo '])
+ " diw
+ norm! 1gg0diw
+ call assert_equal([',eins,foobar', 'foo,zwei,foo ', ''], getline(1,'$'))
+ " daw
+ norm! 2ggEdaw
+ call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
+ %d
+ call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
+ " diW
+ norm! 2ggwd2iW
+ call assert_equal(['foo eins foobar', 'foo foo ', ''], getline(1,'$'))
+ " daW
+ norm! 1ggd2aW
+ call assert_equal(['foobar', 'foo foo ', ''], getline(1,'$'))
+
+ %d
+ call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
+ " aw in visual line mode switches to characterwise mode
+ norm! 2gg$Vawd
+ call assert_equal(['foo eins foobar', 'foo zwei foo'], getline(1,'$'))
+ norm! 1gg$Viwd
+ call assert_equal(['foo eins ', 'foo zwei foo'], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal44_textobjects2()
+ " basic testing for is and as text objects
+ new
+ call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])
+ " Test for dis - does not remove trailing whitespace
+ norm! 1gg0dis
+ call assert_equal([' With some sentences!', '', 'Even with a question? And one more. And no sentence here', ''], getline(1,'$'))
+ " Test for das - removes leading whitespace
+ norm! 3ggf?ldas
+ call assert_equal([' With some sentences!', '', 'Even with a question? And no sentence here', ''], getline(1,'$'))
+ " when used in visual mode, is made characterwise
+ norm! 3gg$Visy
+ call assert_equal('v', visualmode())
+ " reset visualmode()
+ norm! 3ggVy
+ norm! 3gg$Vasy
+ call assert_equal('v', visualmode())
+ " basic testing for textobjects a< and at
+ %d
+ call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
+ " a<
+ norm! 1gg0da<
+ call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! 1pj
+ call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ " at
+ norm! d2at
+ call assert_equal([' '], getline(1,'$'))
+ %d
+ call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
+ " i<
+ norm! 1gg0di<
+ call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! 1Pj
+ call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! d2it
+ call assert_equal(['<div></div>',' '], getline(1,'$'))
+ " basic testing for a[ and i[ text object
+ %d
+ call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
+ norm! 3gg0di[
+ call assert_equal([' ', '[', ']'], getline(1,'$'))
+ call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
+ norm! 3gg0ftd2a[
+ call assert_equal([' '], getline(1,'$'))
+ %d
+ " Test for i" when cursor is in front of a quoted object
+ call append(0, 'foo "bar"')
+ norm! 1gg0di"
+ call assert_equal(['foo ""', ''], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal45_drop()
+ if !has("dnd")
+ return
+ endif
+ " basic test for :drop command
+ " unfortunately, without a gui, we can't really test much here,
+ " so simply test that ~p fails (which uses the drop register)
+ new
+ call assert_fails(':norm! "~p', 'E353')
+ call assert_equal([], getreg('~', 1, 1))
+ " the ~ register is read only
+ call assert_fails(':let @~="1"', 'E354')
+ bw!
+endfunc
+
+func! Test_normal46_ignore()
+ " This test uses multi byte characters
+ if !has("multi_byte")
+ return
+ endif
+
+ new
+ " How to test this?
+ " let's just for now test, that the buffer
+ " does not change
+ call feedkeys("\<c-s>", 't')
+ call assert_equal([''], getline(1,'$'))
+
+ " no valid commands
+ exe "norm! \<char-0x100>"
+ call assert_equal([''], getline(1,'$'))
+
+ exe "norm! ä"
+ call assert_equal([''], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
+
+func! Test_normal47_visual_buf_wipe()
+ " This was causing a crash or ml_get error.
+ enew!
+ call setline(1,'xxx')
+ normal $
+ new
+ call setline(1, range(1,2))
+ 2
+ exe "norm \<C-V>$"
+ bw!
+ norm yp
+ set nomodified
+endfunc
+
+func! Test_normal47_autocmd()
+ " disabled, does not seem to be possible currently
+ throw "Skipped: not possible to test cursorhold autocmd while waiting for input in normal_cmd"
+ new
+ call append(0, repeat('-',20))
+ au CursorHold * call feedkeys('2l', '')
+ 1
+ set updatetime=20
+ " should delete 12 chars (d12l)
+ call feedkeys('d1', '!')
+ call assert_equal('--------', getline(1))
+
+ " clean up
+ au! CursorHold
+ set updatetime=4000
+ bw!
+endfunc
+
+func! Test_normal48_wincmd()
+ new
+ exe "norm! \<c-w>c"
+ call assert_equal(1, winnr('$'))
+ call assert_fails(":norm! \<c-w>c", "E444")
+endfunc
+
+func! Test_normal49_counts()
+ new
+ call setline(1, 'one two three four five six seven eight nine ten')
+ 1
+ norm! 3d2w
+ call assert_equal('seven eight nine ten', getline(1))
+ bw!
+endfunc
+
+func! Test_normal50_commandline()
+ if !has("timers") || !has("cmdline_hist") || !has("vertsplit")
+ return
+ endif
+ func! DoTimerWork(id)
+ call assert_equal('[Command Line]', bufname(''))
+ " should fail, with E11, but does fail with E23?
+ "call feedkeys("\<c-^>", 'tm')
+
+ " should also fail with E11
+ call assert_fails(":wincmd p", 'E11')
+ " return from commandline window
+ call feedkeys("\<cr>")
+ endfunc
+
+ let oldlang=v:lang
+ lang C
+ set updatetime=20
+ call timer_start(100, 'DoTimerWork')
+ try
+ " throws E23, for whatever reason...
+ call feedkeys('q:', 'x!')
+ catch /E23/
+ " no-op
+ endtry
+ " clean up
+ set updatetime=4000
+ exe "lang" oldlang
+ bw!
+endfunc
+
+func! Test_normal51_FileChangedRO()
+ if !has("autocmd")
+ return
+ endif
+ call writefile(['foo'], 'Xreadonly.log')
+ new Xreadonly.log
+ setl ro
+ au FileChangedRO <buffer> :call feedkeys("\<c-^>", 'tix')
+ call assert_fails(":norm! Af", 'E788')
+ call assert_equal(['foo'], getline(1,'$'))
+ call assert_equal('Xreadonly.log', bufname(''))
+
+ " cleanup
+ bw!
+ call delete("Xreadonly.log")
+endfunc
+
+func! Test_normal52_rl()
+ if !has("rightleft")
+ return
+ endif
+ new
+ call setline(1, 'abcde fghij klmnopq')
+ norm! 1gg$
+ set rl
+ call assert_equal(19, col('.'))
+ call feedkeys('l', 'tx')
+ call assert_equal(18, col('.'))
+ call feedkeys('h', 'tx')
+ call assert_equal(19, col('.'))
+ call feedkeys("\<right>", 'tx')
+ call assert_equal(18, col('.'))
+ call feedkeys("\<s-right>", 'tx')
+ call assert_equal(13, col('.'))
+ call feedkeys("\<c-right>", 'tx')
+ call assert_equal(7, col('.'))
+ call feedkeys("\<c-left>", 'tx')
+ call assert_equal(13, col('.'))
+ call feedkeys("\<s-left>", 'tx')
+ call assert_equal(19, col('.'))
+ call feedkeys("<<", 'tx')
+ call assert_equal(' abcde fghij klmnopq',getline(1))
+ call feedkeys(">>", 'tx')
+ call assert_equal('abcde fghij klmnopq',getline(1))
+
+ " cleanup
+ set norl
+ bw!
+endfunc
+
+func! Test_normal53_digraph()
+ if !has('digraphs')
+ return
+ endif
+ new
+ call setline(1, 'abcdefgh|')
+ exe "norm! 1gg0f\<c-k>!!"
+ call assert_equal(9, col('.'))
+ set cpo+=D
+ exe "norm! 1gg0f\<c-k>!!"
+ call assert_equal(1, col('.'))
+
+ set cpo-=D
+ bw!
+endfunc
+
+func! Test_normal54_Ctrl_bsl()
+ new
+ call setline(1, 'abcdefghijklmn')
+ exe "norm! df\<c-\>\<c-n>"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+ exe "norm! df\<c-\>\<c-g>"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+ exe "norm! df\<c-\>m"
+ call assert_equal(['abcdefghijklmn'], getline(1,'$'))
+ if !has("multi_byte")
+ return
+ endif
+ call setline(2, 'abcdefghijklmnāf')
+ norm! 2gg0
+ exe "norm! df\<Char-0x101>"
+ call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
+ norm! 1gg0
+ exe "norm! df\<esc>"
+ call assert_equal(['abcdefghijklmn', 'f'], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 5ee0919e18..08ee00e352 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,36 @@ 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_dictionary()
+ call Check_dir_option('dictionary')
+endfunc
+
+func Test_thesaurus()
+ call Check_dir_option('thesaurus')
+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 fd0f3c0d2d..e1ba142d1c 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
@@ -533,7 +533,7 @@ func Test_completion_comment_formatting()
%d
try
call feedkeys("o/*\<cr>\<cr>\<c-x>\<c-u>/\<esc>", 'tx')
- call assert_false(1, 'completefunc not set, should have failed')
+ call assert_report('completefunc not set, should have failed')
catch
call assert_exception('E764:')
endtry
@@ -541,4 +541,33 @@ 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
+
+
" 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_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 640918b343..aff5fc2eed 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>
@@ -68,10 +68,10 @@ function! s:setup_commands(cchar)
let g:Xgetlist = function('getloclist', [0])
let g:Xsetlist = function('setloclist', [0])
endif
-endfunction
+endfunc
" Tests for the :clist and :llist commands
-function XlistTests(cchar)
+func XlistTests(cchar)
call s:setup_commands(a:cchar)
" With an empty list, command should return error
@@ -128,17 +128,17 @@ function XlistTests(cchar)
let l = split(result, "\n")
call assert_equal([' 2 Xtestfile1:1 col 3: Line1',
\ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l)
-endfunction
+endfunc
-function Test_clist()
+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)
" Jumping to a non existent list should return error
@@ -171,20 +171,20 @@ function XageTests(cchar)
Xnewer 2
let l = g:Xgetlist()
call assert_equal('Line3', l[0].text)
-endfunction
+endfunc
-function Test_cage()
+func Test_cage()
let list = [{'bufnr': 1, 'lnum': 1}]
call setqflist(list)
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)
" Create a list with no valid entries
@@ -227,16 +227,16 @@ function XwindowTests(cchar)
" Calling cwindow should close the quickfix window with no valid errors
Xwindow
call assert_true(winnr('$') == 1)
-endfunction
+endfunc
-function Test_cwindow()
+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 +275,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,26 +316,26 @@ function XbufferTests(cchar)
\ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750')
enew!
-endfunction
+endfunc
-function Test_cbuffer()
+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)
call s:create_test_file('Xqftestfile1')
@@ -366,14 +366,14 @@ function Xtest_browse(cchar)
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
@@ -385,9 +385,9 @@ function! s:test_xhelpgrep(cchar)
call assert_true(w:quickfix_title =~ title_text, w:quickfix_title)
" This wipes out the buffer, make sure that doesn't cause trouble.
Xclose
-endfunction
+endfunc
-function Test_helpgrep()
+func Test_helpgrep()
call s:test_xhelpgrep('c')
helpclose
call s:test_xhelpgrep('l')
@@ -425,7 +425,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 +444,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 +466,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 +477,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 +496,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
@@ -578,15 +578,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,10 +597,26 @@ function Test_locationlist_curwin_was_closed()
call assert_fails('lrewind', 'E924:')
augroup! testgroup
-endfunction
+ endfunc
+
+func Test_locationlist_cross_tab_jump()
+ call writefile(['loclistfoo'], 'loclistfoo')
+ call writefile(['loclistbar'], 'loclistbar')
+ set switchbuf=usetab
+
+ edit loclistfoo
+ tabedit loclistbar
+ silent lgrep loclistfoo loclist*
+ call assert_equal(1, tabpagenr())
+
+ enew | only | tabonly
+ set switchbuf&vim
+ call delete('loclistfoo')
+ call delete('loclistbar')
+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.
@@ -718,10 +734,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
@@ -763,10 +779,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')
@@ -798,10 +814,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
@@ -834,17 +873,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
@@ -930,19 +969,19 @@ function! Test_efm2()
call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr))
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
@@ -965,10 +1004,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
@@ -990,7 +1029,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},
@@ -1025,9 +1064,9 @@ function SetXlistTests(cchar, bnum)
call g:Xsetlist([])
let l = g:Xgetlist()
call assert_equal(0, len(l))
-endfunction
+endfunc
-function Test_setqflist()
+func Test_setqflist()
new Xtestfile | only
let bnum = bufnr('%')
call setline(1, range(1,5))
@@ -1037,9 +1076,9 @@ 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
@@ -1062,12 +1101,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
@@ -1088,14 +1127,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'},
@@ -1169,12 +1208,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))
@@ -1192,9 +1231,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'
@@ -1215,22 +1254,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')
@@ -1317,9 +1356,9 @@ function! Test_switchbuf()
call delete('Xqftestfile1')
call delete('Xqftestfile2')
call delete('Xqftestfile3')
-endfunction
+endfunc
-function! Xadjust_qflnum(cchar)
+func Xadjust_qflnum(cchar)
call s:setup_commands(a:cchar)
enew | only
@@ -1344,17 +1383,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.
@@ -1373,9 +1412,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
@@ -1383,9 +1422,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'
@@ -1411,12 +1450,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)
@@ -1428,7 +1465,7 @@ 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}])
@@ -1444,12 +1481,12 @@ 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:')
@@ -1489,7 +1526,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
@@ -1516,6 +1553,11 @@ 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)
@@ -1528,21 +1570,21 @@ function Xproperty_tests(cchar)
call assert_equal({}, g:Xgetlist({'abc':1}))
if a:cchar == 'l'
- call assert_equal({}, getloclist(99, ['title']))
+ call assert_equal({}, getloclist(99, {'title': 1}))
endif
-endfunction
+ endfunc
-function Test_qf_property()
+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>'))
@@ -1570,9 +1612,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 '?'
@@ -1587,4 +1629,47 @@ 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
diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim
index 9e9a3de500..a2f4286d4f 100644
--- a/src/nvim/testdir/test_regexp_utf8.vim
+++ b/src/nvim/testdir/test_regexp_utf8.vim
@@ -97,3 +97,27 @@ func Test_recursive_substitute()
call setwinvar(1, 'myvar', 1)
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)
+ exe 'set re=' . re
+ let actual = matchlist('abc def', '\(abc\>\)\?\s*\(def\)')
+ call assert_equal(expected, actual)
+ endfor
+endfunc
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_search.vim b/src/nvim/testdir/test_search.vim
new file mode 100644
index 0000000000..a333e7f206
--- /dev/null
+++ b/src/nvim/testdir/test_search.vim
@@ -0,0 +1,300 @@
+" Test for the search command
+
+func Test_search_cmdline()
+ " See test/functional/legacy/search_spec.lua
+ throw 'skipped: Nvim does not support test_disable_char_avail()'
+ if !exists('+incsearch')
+ return
+ endif
+ " need to disable char_avail,
+ " so that expansion of commandline works
+ call test_disable_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
+ " CTRL-N / CTRL-P skips through the previous search history
+ set noincsearch
+ :1
+ call feedkeys("/foobar\<cr>", 'tx')
+ call feedkeys("/the\<cr>",'tx')
+ call assert_equal('the', @/)
+ call feedkeys("/thes\<C-P>\<C-P>\<cr>",'tx')
+ call assert_equal('foobar', @/)
+
+ " Test 2
+ " Ctrl-G goes from one match to the next
+ " until the end of the buffer
+ set incsearch nowrapscan
+ :1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ :1
+ " second match
+ call feedkeys("/the\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+ call assert_equal([0, 0, 0, 0], getpos('"'))
+ :1
+ " third match
+ call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " no further match
+ call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ call assert_equal([0, 0, 0, 0], getpos('"'))
+
+ " Test 3
+ " Ctrl-G goes from one match to the next
+ " and continues back at the top
+ set incsearch wrapscan
+ :1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ :1
+ " second match
+ call feedkeys("/the\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+ :1
+ " third match
+ call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ :1
+ " fourth match
+ call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
+ call assert_equal(' 5 there', getline('.'))
+ :1
+ " fifth match
+ call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
+ call assert_equal(' 6 their', getline('.'))
+ :1
+ " sixth match
+ call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
+ call assert_equal(' 7 the', getline('.'))
+ :1
+ " seventh match
+ call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ :1
+ " eigth match
+ call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ :1
+ " back at first match
+ call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 4
+ " CTRL-T goes to the previous match
+ set incsearch nowrapscan
+ $
+ " first match
+ call feedkeys("?the\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " first match
+ call feedkeys("?the\<C-G>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 5
+ " CTRL-T goes to the previous match
+ set incsearch wrapscan
+ $
+ " first match
+ call feedkeys("?the\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ $
+ " first match at the top
+ call feedkeys("?the\<C-G>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " second match
+ call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
+ call assert_equal(' 8 them', getline('.'))
+ $
+ " last match
+ call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ $
+ " back at the bottom of the buffer
+ call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+
+ " Test 6
+ " CTRL-L adds to the search pattern
+ set incsearch wrapscan
+ 1
+ " first match
+ call feedkeys("/the\<c-l>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " go to next match of 'thes'
+ call feedkeys("/the\<c-l>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ 1
+ " wrap around
+ call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " wrap around
+ set nowrapscan
+ call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+
+ " Test 7
+ " <bs> remove from match, but stay at current match
+ set incsearch wrapscan
+ 1
+ " first match
+ call feedkeys("/thei\<cr>", 'tx')
+ call assert_equal(' 4 their', getline('.'))
+ 1
+ " delete one char, add another
+ call feedkeys("/thei\<bs>s\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " delete one char, add another, go to previous match, add one char
+ call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx')
+ call assert_equal(' 9 these', getline('.'))
+ 1
+ " delete all chars, start from the beginning again
+ call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx')
+ call assert_equal(' 3 the', getline('.'))
+
+ " clean up
+ call test_disable_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()'
+ if !exists('+incsearch')
+ return
+ endif
+ " need to disable char_avail,
+ " so that expansion of commandline works
+ call test_disable_char_avail(1)
+ new
+ call setline(1, [' 1', ' 2 these', ' 3 the theother'])
+ " Test 1
+ " Ctrl-T goes correctly back and forth
+ set incsearch
+ 1
+ " first match
+ call feedkeys("/the\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+ 1
+ " go to next match (on next line)
+ call feedkeys("/the\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to next match (still on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 3)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx')
+ call assert_equal(' 3 the theother', getline('.'))
+ 1
+ " go to previous match (on line 2)
+ call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx')
+ call assert_equal(' 2 these', getline('.'))
+
+ " Test 2: keep the view,
+ " after deleting a character from the search cmd
+ call setline(1, [' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there', ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar'])
+ resize 5
+ 1
+ call feedkeys("/foo\<bs>\<cr>", 'tx')
+ redraw
+ call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview())
+
+ " remove all history entries
+ for i in range(10)
+ call histdel('/')
+ endfor
+
+ " Test 3: reset the view,
+ " after deleting all characters from the search cmd
+ norm! 1gg0
+ " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>",
+ " nor "/foo\<c-u>\<cr>" works to delete the commandline.
+ " In that case Vim should return "E35 no previous regular expression",
+ " but it looks like Vim still sees /foo and therefore the test fails.
+ " Therefore, disableing this test
+ "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35')
+ "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview())
+
+ " clean up
+ set noincsearch
+ call test_disable_char_avail(0)
+ bw!
+endfunc
+
+func Test_use_sub_pat()
+ split
+ let @/ = ''
+ func X()
+ s/^/a/
+ /
+ endfunc
+ 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
+
diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim
new file mode 100644
index 0000000000..d00eac9798
--- /dev/null
+++ b/src/nvim/testdir/test_smartindent.vim
@@ -0,0 +1,14 @@
+
+" Tests for not doing smart indenting when it isn't set.
+function! Test_nosmartindent()
+ new
+ call append(0, [" some test text",
+ \ " test text",
+ \ "test text",
+ \ " test text"])
+ set nocindent nosmartindent autoindent
+ exe "normal! gg/some\<CR>"
+ exe "normal! 2cc#test\<Esc>"
+ call assert_equal(" #test", getline(1))
+ enew! | close
+endfunction
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
new file mode 100644
index 0000000000..11e26d03aa
--- /dev/null
+++ b/src/nvim/testdir/test_startup.vim
@@ -0,0 +1,242 @@
+" Tests for startup.
+
+source shared.vim
+
+" Check that loading startup.vim works.
+func Test_startup_script()
+ throw 'skipped: Nvim does not need defaults.vim'
+ set compatible
+ source $VIMRUNTIME/defaults.vim
+
+ call assert_equal(0, &compatible)
+endfunc
+
+" Verify the order in which plugins are loaded:
+" 1. plugins in non-after directories
+" 2. packages
+" 3. plugins in after directories
+func Test_after_comes_later()
+ if !has('packages')
+ return
+ endif
+ let before = [
+ \ 'set nocp viminfo+=nviminfo',
+ \ 'set guioptions+=M',
+ \ 'let $HOME = "/does/not/exist"',
+ \ 'set loadplugins',
+ \ '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 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 g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim')
+
+ call mkdir('Xafter/plugin', 'p')
+ call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim')
+
+ if RunVim(before, after, '')
+
+ let lines = readfile('Xtestout')
+ let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim']
+ let found = []
+ for line in lines
+ for one in expected
+ if line =~ one
+ call add(found, one)
+ endif
+ endfor
+ endfor
+ 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
+ return
+ endif
+ if RunVim([], [], '--help >Xtestout')
+ let lines = readfile('Xtestout')
+ call assert_true(len(lines) > 20)
+ call assert_match('Usage:', lines[0])
+
+ " check if couple of lines are there
+ let found = []
+ for line in lines
+ 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'
+ call add(found, "--version")
+ endif
+ endfor
+ call assert_equal(['Readonly mode', '--version'], found)
+ endif
+ call delete('Xtestout')
+endfunc
+
+func Test_compatible_args()
+ throw "skipped: Nvim is always 'nocompatible'"
+ let after = [
+ \ 'call writefile([string(&compatible)], "Xtestout")',
+ \ 'set viminfo+=nviminfo',
+ \ 'quit',
+ \ ]
+ if RunVim([], after, '-C')
+ let lines = readfile('Xtestout')
+ call assert_equal('1', lines[0])
+ endif
+
+ if RunVim([], after, '-N')
+ let lines = readfile('Xtestout')
+ call assert_equal('0', lines[0])
+ endif
+
+ call delete('Xtestout')
+endfunc
+
+func Test_file_args()
+ let after = [
+ \ 'call writefile(argv(), "Xtestout")',
+ \ 'qall',
+ \ ]
+ if RunVim([], after, '')
+ let lines = readfile('Xtestout')
+ call assert_equal(0, len(lines))
+ endif
+
+ if RunVim([], after, 'one')
+ let lines = readfile('Xtestout')
+ call assert_equal(1, len(lines))
+ call assert_equal('one', lines[0])
+ endif
+
+ if RunVim([], after, 'one two three')
+ let lines = readfile('Xtestout')
+ call assert_equal(3, len(lines))
+ call assert_equal('one', lines[0])
+ call assert_equal('two', lines[1])
+ call assert_equal('three', lines[2])
+ endif
+
+ if RunVim([], after, 'one -c echo two')
+ let lines = readfile('Xtestout')
+ call assert_equal(2, len(lines))
+ call assert_equal('one', lines[0])
+ call assert_equal('two', lines[1])
+ endif
+
+ if RunVim([], after, 'one -- -c echo two')
+ let lines = readfile('Xtestout')
+ call assert_equal(4, len(lines))
+ call assert_equal('one', lines[0])
+ call assert_equal('-c', lines[1])
+ call assert_equal('echo', lines[2])
+ call assert_equal('two', lines[3])
+ endif
+
+ call delete('Xtestout')
+endfunc
+
+func Test_startuptime()
+ if !has('startuptime')
+ return
+ endif
+ let after = ['qall']
+ if RunVim([], after, '--startuptime Xtestout one')
+ let lines = readfile('Xtestout')
+ let expected = ['parsing arguments', 'inits 3', 'opening buffers']
+ let found = []
+ for line in lines
+ for exp in expected
+ if line =~ exp
+ call add(found, exp)
+ endif
+ endfor
+ endfor
+ call assert_equal(expected, found)
+ endif
+ call delete('Xtestout')
+endfunc
+
+func Test_read_stdin()
+ let after = [
+ \ 'write Xtestout',
+ \ 'quit!',
+ \ ]
+ if RunVimPiped([], after, '-', 'echo something | ')
+ let lines = readfile('Xtestout')
+ " MS-Windows adds a space after the word
+ call assert_equal(['something'], split(lines[0]))
+ endif
+ call delete('Xtestout')
+endfunc
+
+func Test_progpath()
+ " Tests normally run with "./vim" or "../vim", these must have been expanded
+ " to a full path.
+ if has('unix')
+ call assert_equal('/', v:progpath[0])
+ elseif has('win32')
+ call assert_equal(':', v:progpath[1])
+ call assert_match('[/\\]', v:progpath[2])
+ endif
+
+ " Only expect "vim" to appear in v:progname.
+ call assert_match('vim\c', v:progname)
+endfunc
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
new file mode 100644
index 0000000000..dee0d13e84
--- /dev/null
+++ b/src/nvim/testdir/test_stat.vim
@@ -0,0 +1,71 @@
+" Tests for stat functions and checktime
+
+func Test_existent_file()
+ let fname = 'Xtest.tmp'
+
+ let ts = localtime()
+ let fl = ['Hello World!']
+ call writefile(fl, fname)
+ let tf = getftime(fname)
+ let te = localtime()
+
+ 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])
+
+ call delete(fname)
+endfunc
+
+func Test_existent_directory()
+ let dname = '.'
+
+ call assert_equal(0, getfsize(dname))
+ call assert_equal('dir', getftype(dname))
+ call assert_equal('rwx', getfperm(dname)[0:2])
+endfunc
+
+func Test_checktime()
+ let fname = 'Xtest.tmp'
+
+ let fl = ['Hello World!']
+ call writefile(fl, fname)
+ set autoread
+ exec 'e' 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'
+
+ call delete(fname)
+ call assert_equal(-1, getftime(fname))
+ call assert_equal(-1, getfsize(fname))
+ call assert_equal('', getftype(fname))
+ call assert_equal('', getfperm(fname))
+endfunc
+
+func Test_win32_symlink_dir()
+ " On Windows, non-admin users cannot create symlinks.
+ " 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')
+ if match(res, '\C<SYMLINKD> *All Users') >= 0
+ " Get the filetype of the symlink.
+ call assert_equal('dir', getftype('C:\Users\All Users'))
+ endif
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
new file mode 100644
index 0000000000..e2b6de03c3
--- /dev/null
+++ b/src/nvim/testdir/test_substitute.vim
@@ -0,0 +1,41 @@
+" Tests for multi-line regexps with ":s".
+
+function! Test_multiline_subst()
+ enew!
+ call append(0, ["1 aa",
+ \ "bb",
+ \ "cc",
+ \ "2 dd",
+ \ "ee",
+ \ "3 ef",
+ \ "gh",
+ \ "4 ij",
+ \ "5 a8",
+ \ "8b c9",
+ \ "9d",
+ \ "6 e7",
+ \ "77f",
+ \ "xxxxx"])
+
+ 1
+ " test if replacing a line break works with a back reference
+ /^1/,/^2/s/\n\(.\)/ \1/
+ " test if inserting a line break works with a back reference
+ /^3/,/^4/s/\(.\)$/\r\1/
+ " test if replacing a line break with another line break works
+ /^5/,/^6/s/\(\_d\{3}\)/x\1x/
+ call assert_equal('1 aa bb cc 2 dd ee', getline(1))
+ call assert_equal('3 e', getline(2))
+ call assert_equal('f', getline(3))
+ call assert_equal('g', getline(4))
+ call assert_equal('h', getline(5))
+ call assert_equal('4 i', getline(6))
+ call assert_equal('j', getline(7))
+ call assert_equal('5 ax8', getline(8))
+ call assert_equal('8xb cx9', getline(9))
+ call assert_equal('9xd', getline(10))
+ call assert_equal('6 ex7', getline(11))
+ call assert_equal('7x7f', getline(12))
+ call assert_equal('xxxxx', getline(13))
+ enew!
+endfunction
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index af2cbbfe8e..6c084dd2a7 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -50,7 +50,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 +76,85 @@ 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', @:)
+
+ 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 \ No newline at end of file
diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim
index 7c3039ba24..33139fcda0 100644
--- a/src/nvim/testdir/test_tabpage.vim
+++ b/src/nvim/testdir/test_tabpage.vim
@@ -11,6 +11,7 @@ function Test_tabpage()
0tabnew
1tabnew
$tabnew
+ %del
tabdo call append(line('$'), tabpagenr())
tabclose! 2
tabrewind
@@ -93,10 +94,6 @@ function Test_tabpage()
call assert_equal(7, tabpagenr())
tabmove
call assert_equal(10, tabpagenr())
- tabmove -20
- call assert_equal(1, tabpagenr())
- tabmove +20
- call assert_equal(10, tabpagenr())
0tabmove
call assert_equal(1, tabpagenr())
$tabmove
@@ -109,7 +106,16 @@ function Test_tabpage()
call assert_equal(4, tabpagenr())
7tabmove 5
call assert_equal(5, tabpagenr())
+ call assert_fails("99tabmove", 'E16:')
+ call assert_fails("+99tabmove", 'E16:')
+ call assert_fails("-99tabmove", 'E16:')
call assert_fails("tabmove foo", 'E474:')
+ call assert_fails("tabmove 99", 'E474:')
+ call assert_fails("tabmove +99", 'E474:')
+ call assert_fails("tabmove -99", 'E474:')
+ call assert_fails("tabmove -3+", 'E474:')
+ call assert_fails("tabmove $3", 'E474:')
+ 1tabonly!
endfunc
" Test autocommands
@@ -117,7 +123,6 @@ function Test_tabpage_with_autocmd()
if !has('autocmd')
return
endif
- tabonly!
command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args>
augroup TestTabpageGroup
au!
@@ -182,8 +187,10 @@ function Test_tabpage_with_autocmd()
autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3
let s:li = []
- C tabnext 3
- call assert_equal(['=== tabnext 3 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ===', 'BufEnter', '=== tabclose 3 ==='], s:li)
+ call assert_equal(3, tabpagenr('$'))
+ C tabnext 2
+ call assert_equal(2, tabpagenr('$'))
+ call assert_equal(['=== tabnext 2 ===', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ==='], s:li)
call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')])
delcommand C
@@ -191,8 +198,7 @@ function Test_tabpage_with_autocmd()
augroup! TabDestructive
autocmd! TestTabpageGroup
augroup! TestTabpageGroup
- tabonly!
- bw!
+ 1tabonly!
endfunction
function Test_tabpage_with_tab_modifier()
@@ -204,7 +210,7 @@ function Test_tabpage_with_tab_modifier()
exec 'tabnext ' . a:pre_nr
exec a:cmd
call assert_equal(a:post_nr, tabpagenr())
- call assert_equal('help', &filetype)
+ call assert_equal('help', &buftype)
helpclose
endfunc
@@ -223,8 +229,223 @@ function Test_tabpage_with_tab_modifier()
call assert_fails('-99tab help', 'E16:')
delfunction s:check_tab
- tabonly!
- bw!
+ 1tabonly!
+endfunction
+
+function Check_tab_count(pre_nr, cmd, post_nr)
+ exec 'tabnext' a:pre_nr
+ normal! G
+ exec a:cmd
+ call assert_equal(a:post_nr, tabpagenr(), a:cmd)
+endfunc
+
+" Test for [count] of tabnext
+function Test_tabpage_with_tabnext()
+ for n in range(4)
+ tabedit
+ call setline(1, ['', '', '3'])
+ endfor
+
+ call Check_tab_count(1, 'tabnext', 2)
+ call Check_tab_count(1, '3tabnext', 3)
+ call Check_tab_count(1, '.tabnext', 1)
+ call Check_tab_count(1, '.+1tabnext', 2)
+ call Check_tab_count(2, '+tabnext', 3)
+ call Check_tab_count(2, '+2tabnext', 4)
+ call Check_tab_count(4, '-tabnext', 3)
+ call Check_tab_count(4, '-2tabnext', 2)
+ call Check_tab_count(3, '$tabnext', 5)
+ call assert_fails('0tabnext', 'E16:')
+ call assert_fails('99tabnext', 'E16:')
+ call assert_fails('+99tabnext', 'E16:')
+ call assert_fails('-99tabnext', 'E16:')
+ call Check_tab_count(1, 'tabnext 3', 3)
+ call Check_tab_count(2, 'tabnext +', 3)
+ call Check_tab_count(2, 'tabnext +2', 4)
+ call Check_tab_count(4, 'tabnext -', 3)
+ call Check_tab_count(4, 'tabnext -2', 2)
+ call Check_tab_count(3, 'tabnext $', 5)
+ call assert_fails('tabnext 0', 'E474:')
+ call assert_fails('tabnext .', 'E474:')
+ call assert_fails('tabnext -+', 'E474:')
+ call assert_fails('tabnext +2-', 'E474:')
+ call assert_fails('tabnext $3', 'E474:')
+ call assert_fails('tabnext 99', 'E474:')
+ call assert_fails('tabnext +99', 'E474:')
+ call assert_fails('tabnext -99', 'E474:')
+
+ 1tabonly!
+endfunction
+
+" Test for [count] of tabprevious
+function Test_tabpage_with_tabprevious()
+ for n in range(5)
+ tabedit
+ call setline(1, ['', '', '3'])
+ endfor
+
+ for cmd in ['tabNext', 'tabprevious']
+ call Check_tab_count(6, cmd, 5)
+ call Check_tab_count(6, '3' . cmd, 3)
+ call Check_tab_count(6, '8' . cmd, 4)
+ call Check_tab_count(6, cmd . ' 3', 3)
+ call Check_tab_count(6, cmd . ' 8', 4)
+ for n in range(2)
+ for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99']
+ if n == 0 " pre count
+ let entire_cmd = c . cmd
+ let err_code = 'E16:'
+ else
+ let entire_cmd = cmd . ' ' . c
+ let err_code = 'E474:'
+ endif
+ call assert_fails(entire_cmd, err_code)
+ endfor
+ endfor
+ endfor
+
+ 1tabonly!
+endfunction
+
+function s:reconstruct_tabpage_for_test(nr)
+ let n = (a:nr > 2) ? a:nr - 2 : 1
+ 1tabonly!
+ 0tabedit n0
+ for n in range(1, n)
+ exec '$tabedit n' . n
+ if n == 1
+ call setline(1, ['', '', '3'])
+ endif
+ endfor
+endfunc
+
+" Test for [count] of tabclose
+function Test_tabpage_with_tabclose()
+
+ " pre count
+ call s:reconstruct_tabpage_for_test(6)
+ call Check_tab_count(3, 'tabclose!', 3)
+ call Check_tab_count(1, '3tabclose', 1)
+ call Check_tab_count(4, '4tabclose', 3)
+ call Check_tab_count(3, '1tabclose', 2)
+ call Check_tab_count(2, 'tabclose', 1)
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal('', bufname(''))
+
+ call s:reconstruct_tabpage_for_test(6)
+ call Check_tab_count(2, '$tabclose', 2)
+ call Check_tab_count(4, '.tabclose', 4)
+ call Check_tab_count(3, '.+tabclose', 3)
+ call Check_tab_count(3, '.-2tabclose', 2)
+ call Check_tab_count(1, '.+1tabclose!', 1)
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal('', bufname(''))
+
+ " post count
+ call s:reconstruct_tabpage_for_test(6)
+ call Check_tab_count(3, 'tabclose!', 3)
+ call Check_tab_count(1, 'tabclose 3', 1)
+ call Check_tab_count(4, 'tabclose 4', 3)
+ call Check_tab_count(3, 'tabclose 1', 2)
+ call Check_tab_count(2, 'tabclose', 1)
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal('', bufname(''))
+
+ call s:reconstruct_tabpage_for_test(6)
+ call Check_tab_count(2, 'tabclose $', 2)
+ call Check_tab_count(4, 'tabclose', 4)
+ call Check_tab_count(3, 'tabclose +', 3)
+ call Check_tab_count(3, 'tabclose -2', 2)
+ call Check_tab_count(1, 'tabclose! +1', 1)
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal('', bufname(''))
+
+ call s:reconstruct_tabpage_for_test(6)
+ for n in range(2)
+ for c in ['0', '$3', '99', '+99', '-99']
+ if n == 0 " pre count
+ let entire_cmd = c . 'tabclose'
+ let err_code = 'E16:'
+ else
+ let entire_cmd = 'tabclose ' . c
+ let err_code = 'E474:'
+ endif
+ call assert_fails(entire_cmd, err_code)
+ call assert_equal(6, tabpagenr('$'))
+ endfor
+ endfor
+
+ call assert_fails('3tabclose', 'E37:')
+ call assert_fails('tabclose 3', 'E37:')
+ call assert_fails('tabclose -+', 'E474:')
+ call assert_fails('tabclose +2-', 'E474:')
+ call assert_equal(6, tabpagenr('$'))
+
+ 1tabonly!
+endfunction
+
+" Test for [count] of tabonly
+function Test_tabpage_with_tabonly()
+
+ " Test for the normal behavior (pre count only)
+ let tc = [ [4, '.', '!'], [2, '.+', ''], [3, '.-2', '!'], [1, '.+1', '!'] ]
+ for c in tc
+ call s:reconstruct_tabpage_for_test(6)
+ let entire_cmd = c[1] . 'tabonly' . c[2]
+ call Check_tab_count(c[0], entire_cmd, 1)
+ call assert_equal(1, tabpagenr('$'))
+ endfor
+
+ " Test for the normal behavior
+ let tc2 = [ [3, '', ''], [1, '3', ''], [4, '4', '!'], [3, '1', '!'],
+ \ [2, '', '!'],
+ \ [2, '$', '!'], [3, '+', '!'], [3, '-2', '!'], [3, '+1', '!']
+ \ ]
+ for n in range(2)
+ for c in tc2
+ call s:reconstruct_tabpage_for_test(6)
+ if n == 0 " pre count
+ let entire_cmd = c[1] . 'tabonly' . c[2]
+ else
+ let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
+ endif
+ call Check_tab_count(c[0], entire_cmd, 1)
+ call assert_equal(1, tabpagenr('$'))
+ endfor
+ endfor
+
+ " Test for the error behavior
+ for n in range(2)
+ for c in ['0', '$3', '99', '+99', '-99']
+ call s:reconstruct_tabpage_for_test(6)
+ if n == 0 " pre count
+ let entire_cmd = c . 'tabonly'
+ let err_code = 'E16:'
+ else
+ let entire_cmd = 'tabonly ' . c
+ let err_code = 'E474:'
+ endif
+ call assert_fails(entire_cmd, err_code)
+ call assert_equal(6, tabpagenr('$'))
+ endfor
+ endfor
+
+ " Test for the error behavior (post count only)
+ for c in tc
+ call s:reconstruct_tabpage_for_test(6)
+ let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
+ let err_code = 'E474:'
+ call assert_fails(entire_cmd, err_code)
+ call assert_equal(6, tabpagenr('$'))
+ endfor
+
+ call assert_fails('tabonly -+', 'E474:')
+ call assert_fails('tabonly +2-', 'E474:')
+ call assert_equal(6, tabpagenr('$'))
+
+ 1tabonly!
+ new
+ only!
endfunction
func Test_tabnext_on_buf_unload1()
diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim
index 678ad0ada8..0d697b3f3e 100644
--- a/src/nvim/testdir/test_tagjump.vim
+++ b/src/nvim/testdir/test_tagjump.vim
@@ -23,4 +23,76 @@ func Test_cancel_ptjump()
quit
endfunc
+func Test_static_tagjump()
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile1\t/^one/;\"\tf\tfile:\tsignature:(void)",
+ \ "word\tXfile2\tcmd2"],
+ \ 'Xtags')
+ new Xfile1
+ call setline(1, ['empty', 'one()', 'empty'])
+ write
+ tag one
+ call assert_equal(2, line('.'))
+
+ bwipe!
+ set tags&
+ call delete('Xtags')
+ call delete('Xfile1')
+endfunc
+
+func Test_duplicate_tagjump()
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile1\t1;\"\td\tfile:",
+ \ "thesame\tXfile1\t2;\"\td\tfile:",
+ \ "thesame\tXfile1\t3;\"\td\tfile:",
+ \ ],
+ \ 'Xtags')
+ new Xfile1
+ call setline(1, ['thesame one', 'thesame two', 'thesame three'])
+ write
+ tag thesame
+ call assert_equal(1, line('.'))
+ tnext
+ call assert_equal(2, line('.'))
+ tnext
+ call assert_equal(3, line('.'))
+
+ bwipe!
+ set tags&
+ call delete('Xtags')
+ call delete('Xfile1')
+endfunc
+
+" Tests for [ CTRL-I and CTRL-W CTRL-I commands
+function Test_keyword_jump()
+ call writefile(["#include Xinclude", "",
+ \ "",
+ \ "/* test text test tex start here",
+ \ " some text",
+ \ " test text",
+ \ " start OK if found this line",
+ \ " start found wrong line",
+ \ "test text"], 'Xtestfile')
+ call writefile(["/* test text test tex start here",
+ \ " some text",
+ \ " test text",
+ \ " start OK if found this line",
+ \ " start found wrong line",
+ \ "test text"], 'Xinclude')
+ new Xtestfile
+ call cursor(1,1)
+ call search("start")
+ exe "normal! 5[\<C-I>"
+ call assert_equal(" start OK if found this line", getline('.'))
+ call cursor(1,1)
+ call search("start")
+ exe "normal! 5\<C-W>\<C-I>"
+ call assert_equal(" start OK if found this line", getline('.'))
+ enew! | only
+ call delete('Xtestfile')
+ call delete('Xinclude')
+endfunction
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim
new file mode 100644
index 0000000000..2d1557ebd9
--- /dev/null
+++ b/src/nvim/testdir/test_taglist.vim
@@ -0,0 +1,58 @@
+" test 'taglist' function
+
+func Test_taglist()
+ call writefile([
+ \ "FFoo\tXfoo\t1",
+ \ "FBar\tXfoo\t2",
+ \ "BFoo\tXbar\t1",
+ \ "BBar\tXbar\t2"
+ \ ], 'Xtags')
+ set tags=Xtags
+ split Xtext
+
+ call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo"), {i, v -> v.name}))
+ call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xtext"), {i, v -> v.name}))
+ call assert_equal(['FFoo', 'BFoo'], map(taglist("Foo", "Xfoo"), {i, v -> v.name}))
+ call assert_equal(['BFoo', 'FFoo'], map(taglist("Foo", "Xbar"), {i, v -> v.name}))
+
+ call delete('Xtags')
+ bwipe
+endfunc
+
+func Test_taglist_native_etags()
+ if !has('emacs_tags')
+ return
+ endif
+ call writefile([
+ \ "\x0c",
+ \ "src/os_unix.c,13491",
+ \ "set_signals(\x7f1335,32699",
+ \ "reset_signals(\x7f1407,34136",
+ \ ], 'Xtags')
+
+ set tags=Xtags
+
+ call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']],
+ \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]}))
+
+ call delete('Xtags')
+endfunc
+
+func Test_taglist_ctags_etags()
+ if !has('emacs_tags')
+ return
+ endif
+ call writefile([
+ \ "\x0c",
+ \ "src/os_unix.c,13491",
+ \ "set_signals(void)\x7fset_signals\x011335,32699",
+ \ "reset_signals(void)\x7freset_signals\x011407,34136",
+ \ ], 'Xtags')
+
+ set tags=Xtags
+
+ call assert_equal([['set_signals', '1335,32699'], ['reset_signals', '1407,34136']],
+ \ map(taglist('set_signals'), {i, v -> [v.name, v.cmd]}))
+
+ call delete('Xtags')
+endfunc
diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim
index 56f9feef66..d377062780 100644
--- a/src/nvim/testdir/test_timers.vim
+++ b/src/nvim/testdir/test_timers.vim
@@ -4,8 +4,10 @@ if !has('timers')
finish
endif
+source shared.vim
+
func MyHandler(timer)
- let s:val += 1
+ let g:val += 1
endfunc
func MyHandlerWithLists(lists, timer)
@@ -13,44 +15,159 @@ func MyHandlerWithLists(lists, timer)
endfunc
func Test_oneshot()
- let s:val = 0
+ let g:val = 0
let timer = timer_start(50, 'MyHandler')
- sleep 200m
- call assert_equal(1, s:val)
+ let slept = WaitFor('g:val == 1')
+ call assert_equal(1, g:val)
+ if has('reltime')
+ call assert_inrange(40, 100, slept)
+ else
+ call assert_inrange(20, 100, slept)
+ endif
endfunc
func Test_repeat_three()
- let s:val = 0
+ let g:val = 0
let timer = timer_start(50, 'MyHandler', {'repeat': 3})
- sleep 500m
- call assert_equal(3, s:val)
+ let slept = WaitFor('g:val == 3')
+ call assert_equal(3, g:val)
+ if has('reltime')
+ call assert_inrange(120, 250, slept)
+ else
+ call assert_inrange(80, 200, slept)
+ endif
endfunc
func Test_repeat_many()
- let s:val = 0
+ let g:val = 0
let timer = timer_start(50, 'MyHandler', {'repeat': -1})
sleep 200m
call timer_stop(timer)
- call assert_true(s:val > 1)
- call assert_true(s:val < 5)
+ call assert_inrange(2, 4, g:val)
endfunc
func Test_with_partial_callback()
- let s:val = 0
- let s:meow = {}
- function s:meow.bite(...)
- let s:val += 1
+ let g:val = 0
+ let meow = {'one': 1}
+ function meow.bite(...)
+ let g:val += self.one
endfunction
- call timer_start(50, s:meow.bite)
- sleep 200m
- call assert_equal(1, s:val)
+ call timer_start(50, meow.bite)
+ let slept = WaitFor('g:val == 1')
+ call assert_equal(1, g:val)
+ if has('reltime')
+ call assert_inrange(40, 130, slept)
+ else
+ call assert_inrange(20, 100, slept)
+ endif
endfunc
func Test_retain_partial()
- call timer_start(100, function('MyHandlerWithLists', [['a']]))
+ call timer_start(50, function('MyHandlerWithLists', [['a']]))
call garbagecollect()
+ sleep 100m
+endfunc
+
+func Test_info()
+ let id = timer_start(1000, 'MyHandler')
+ let info = timer_info(id)
+ call assert_equal(id, info[0]['id'])
+ call assert_equal(1000, info[0]['time'])
+ call assert_equal("function('MyHandler')", string(info[0]['callback']))
+
+ let found = 0
+ for info in timer_info()
+ if info['id'] == id
+ let found += 1
+ endif
+ endfor
+ call assert_equal(1, found)
+
+ call timer_stop(id)
+ call assert_equal([], timer_info(id))
+endfunc
+
+func Test_stopall()
+ let id1 = timer_start(1000, 'MyHandler')
+ let id2 = timer_start(2000, 'MyHandler')
+ let info = timer_info()
+ call assert_equal(2, len(info))
+
+ call timer_stopall()
+ let info = timer_info()
+ call assert_equal(0, len(info))
+endfunc
+
+func Test_paused()
+ let g:val = 0
+
+ let id = timer_start(50, 'MyHandler')
+ let info = timer_info(id)
+ call assert_equal(0, info[0]['paused'])
+
+ call timer_pause(id, 1)
+ let info = timer_info(id)
+ call assert_equal(1, info[0]['paused'])
sleep 200m
+ call assert_equal(0, g:val)
+
+ call timer_pause(id, 0)
+ let info = timer_info(id)
+ call assert_equal(0, info[0]['paused'])
+
+ let slept = WaitFor('g:val == 1')
+ call assert_equal(1, g:val)
+ if has('reltime')
+ call assert_inrange(0, 60, slept)
+ else
+ call assert_inrange(0, 10, slept)
+ endif
endfunc
+func StopMyself(timer)
+ let g:called += 1
+ if g:called == 2
+ call timer_stop(a:timer)
+ endif
+endfunc
+
+func Test_delete_myself()
+ let g:called = 0
+ let t = timer_start(10, 'StopMyself', {'repeat': -1})
+ call WaitFor('g:called == 2')
+ call assert_equal(2, g:called)
+ call assert_equal([], timer_info(t))
+endfunc
+
+func StopTimer1(timer)
+ let g:timer2 = timer_start(10, 'StopTimer2')
+ " avoid maxfuncdepth error
+ call timer_pause(g:timer1, 1)
+ sleep 40m
+endfunc
+
+func StopTimer2(timer)
+ call timer_stop(g:timer1)
+endfunc
+
+func Test_stop_in_callback()
+ let g:timer1 = timer_start(10, 'StopTimer1')
+ sleep 40m
+endfunc
+
+func StopTimerAll(timer)
+ call timer_stopall()
+endfunc
+
+func Test_stop_all_in_callback()
+ let g:timer1 = timer_start(10, 'StopTimerAll')
+ let info = timer_info()
+ call assert_equal(1, len(info))
+ sleep 40m
+ let info = timer_info()
+ call assert_equal(0, len(info))
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_undo.vim b/src/nvim/testdir/test_undo.vim
index fc61d1f223..171618f6f7 100644
--- a/src/nvim/testdir/test_undo.vim
+++ b/src/nvim/testdir/test_undo.vim
@@ -131,6 +131,39 @@ func Test_undo_del_chars()
close!
endfunc
+func Test_undolist()
+ new
+ set ul=100
+
+ let a=execute('undolist')
+ call assert_equal("\nNothing to undo", a)
+
+ " 1 leaf (2 changes).
+ call feedkeys('achange1', 'xt')
+ call feedkeys('achange2', 'xt')
+ let a=execute('undolist')
+ call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a)
+
+ " 2 leaves.
+ call feedkeys('u', 'xt')
+ call feedkeys('achange3\<Esc>', 'xt')
+ let a=execute('undolist')
+ call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a)
+ close!
+endfunc
+
+func Test_U_command()
+ new
+ set ul=100
+ call feedkeys("achange1\<Esc>", 'xt')
+ call feedkeys("achange2\<Esc>", 'xt')
+ norm! U
+ call assert_equal('', getline(1))
+ norm! U
+ call assert_equal('change1change2', getline(1))
+ close!
+endfunc
+
func Test_undojoin()
new
call feedkeys("Goaaaa\<Esc>", 'xt')
@@ -204,3 +237,31 @@ 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
diff --git a/src/nvim/testdir/test_unlet.vim b/src/nvim/testdir/test_unlet.vim
index f6705997a9..96ba752d9f 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
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.vim b/src/nvim/testdir/test_utf8.vim
new file mode 100644
index 0000000000..24e3db86fb
--- /dev/null
+++ b/src/nvim/testdir/test_utf8.vim
@@ -0,0 +1,65 @@
+" Tests for Unicode manipulations
+if !has('multi_byte')
+ finish
+endif
+
+
+" Visual block Insert adjusts for multi-byte char
+func Test_visual_block_insert()
+ new
+ call setline(1, ["aaa", "あああ", "bbb"])
+ exe ":norm! gg0l\<C-V>jjIx\<Esc>"
+ call assert_equal(['axaa', 'xあああ', 'bxbb'], getline(1, '$'))
+ bwipeout!
+endfunc
+
+" Test for built-in function strchars()
+func Test_strchars()
+ let inp = ["a", "あいa", "A\u20dd", "A\u20dd\u20dd", "\u20dd"]
+ let exp = [[1, 1, 1], [3, 3, 3], [2, 2, 1], [3, 3, 1], [1, 1, 1]]
+ for i in range(len(inp))
+ call assert_equal(exp[i][0], strchars(inp[i]))
+ call assert_equal(exp[i][1], strchars(inp[i], 0))
+ call assert_equal(exp[i][2], strchars(inp[i], 1))
+ endfor
+endfunc
+
+" Test for customlist completion
+function! CustomComplete1(lead, line, pos)
+ return ['あ', 'い']
+endfunction
+
+function! CustomComplete2(lead, line, pos)
+ return ['あたし', 'あたま', 'あたりめ']
+endfunction
+
+function! CustomComplete3(lead, line, pos)
+ return ['Nこ', 'Nん', 'Nぶ']
+endfunction
+
+func Test_customlist_completion()
+ command -nargs=1 -complete=customlist,CustomComplete1 Test1 echo
+ call feedkeys(":Test1 \<C-L>\<C-B>\"\<CR>", 'itx')
+ call assert_equal('"Test1 ', getreg(':'))
+
+ command -nargs=1 -complete=customlist,CustomComplete2 Test2 echo
+ call feedkeys(":Test2 \<C-L>\<C-B>\"\<CR>", 'itx')
+ call assert_equal('"Test2 あた', getreg(':'))
+
+ command -nargs=1 -complete=customlist,CustomComplete3 Test3 echo
+ call feedkeys(":Test3 \<C-L>\<C-B>\"\<CR>", 'itx')
+ call assert_equal('"Test3 N', getreg(':'))
+
+ call garbagecollect(1)
+endfunc
+
+" Yank one 3 byte character and check the mark columns.
+func Test_getvcol()
+ new
+ call setline(1, "x\u2500x")
+ normal 0lvy
+ call assert_equal(2, col("'["))
+ call assert_equal(4, col("']"))
+ call assert_equal(2, virtcol("'["))
+ call assert_equal(2, virtcol("']"))
+endfunc
diff --git a/src/nvim/testdir/test_viml.vim b/src/nvim/testdir/test_vimscript.vim
index a2997b6d4d..4e0f1bbd2f 100644
--- a/src/nvim/testdir/test_viml.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1062,6 +1062,157 @@ func Test_echo_and_string()
call assert_equal(["{'a': [], 'b': []}",
\ "{'a': [], 'b': []}"], l)
+"-------------------------------------------------------------------------------
+" Test 94: 64-bit Numbers {{{1
+"-------------------------------------------------------------------------------
+
+func Test_num64()
+ if !has('num64')
+ return
+ endif
+
+ call assert_notequal( 4294967296, 0)
+ call assert_notequal(-4294967296, 0)
+ call assert_equal( 4294967296, 0xFFFFffff + 1)
+ call assert_equal(-4294967296, -0xFFFFffff - 1)
+
+ call assert_equal( 9223372036854775807, 1 / 0)
+ call assert_equal(-9223372036854775807, -1 / 0)
+ call assert_equal(-9223372036854775807 - 1, 0 / 0)
+
+ call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
+ call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
+
+ let rng = range(0xFFFFffff, 0x100000001)
+ call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
+ call assert_equal(0x100000001, max(rng))
+ call assert_equal(0xFFFFffff, min(rng))
+ call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 95: lines of :append, :change, :insert {{{1
+"-------------------------------------------------------------------------------
+
+function! DefineFunction(name, body)
+ let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
+ exec func
+endfunction
+
+func Test_script_lines()
+ " :append
+ try
+ call DefineFunction('T_Append', [
+ \ 'append',
+ \ 'py <<EOS',
+ \ '.',
+ \ ])
+ catch
+ call assert_report("Can't define function")
+ endtry
+ try
+ call DefineFunction('T_Append', [
+ \ 'append',
+ \ 'abc',
+ \ ])
+ call assert_report("Shouldn't be able to define function")
+ catch
+ call assert_exception('Vim(function):E126: Missing :endfunction')
+ endtry
+
+ " :change
+ try
+ call DefineFunction('T_Change', [
+ \ 'change',
+ \ 'py <<EOS',
+ \ '.',
+ \ ])
+ catch
+ call assert_report("Can't define function")
+ endtry
+ try
+ call DefineFunction('T_Change', [
+ \ 'change',
+ \ 'abc',
+ \ ])
+ call assert_report("Shouldn't be able to define function")
+ catch
+ call assert_exception('Vim(function):E126: Missing :endfunction')
+ endtry
+
+ " :insert
+ try
+ call DefineFunction('T_Insert', [
+ \ 'insert',
+ \ 'py <<EOS',
+ \ '.',
+ \ ])
+ catch
+ call assert_report("Can't define function")
+ endtry
+ try
+ call DefineFunction('T_Insert', [
+ \ 'insert',
+ \ 'abc',
+ \ ])
+ call assert_report("Shouldn't be able to define function")
+ catch
+ call assert_exception('Vim(function):E126: Missing :endfunction')
+ endtry
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 96: line continuation {{{1
+"
+" Undefined behavior was detected by ubsan with line continuation
+" after an empty line.
+"-------------------------------------------------------------------------------
+func Test_script_emty_line_continuation()
+
+ \
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 97: bitwise functions {{{1
+"-------------------------------------------------------------------------------
+func Test_bitwise_functions()
+ " and
+ call assert_equal(127, and(127, 127))
+ call assert_equal(16, and(127, 16))
+ call assert_equal(0, and(127, 128))
+ call assert_fails("call and(1.0, 1)", 'E805:')
+ call assert_fails("call and([], 1)", 'E745:')
+ call assert_fails("call and({}, 1)", 'E728:')
+ call assert_fails("call and(1, 1.0)", 'E805:')
+ call assert_fails("call and(1, [])", 'E745:')
+ call assert_fails("call and(1, {})", 'E728:')
+ " or
+ call assert_equal(23, or(16, 7))
+ call assert_equal(15, or(8, 7))
+ call assert_equal(123, or(0, 123))
+ call assert_fails("call or(1.0, 1)", 'E805:')
+ call assert_fails("call or([], 1)", 'E745:')
+ call assert_fails("call or({}, 1)", 'E728:')
+ call assert_fails("call or(1, 1.0)", 'E805:')
+ call assert_fails("call or(1, [])", 'E745:')
+ call assert_fails("call or(1, {})", 'E728:')
+ " xor
+ call assert_equal(0, xor(127, 127))
+ call assert_equal(111, xor(127, 16))
+ call assert_equal(255, xor(127, 128))
+ call assert_fails("call xor(1.0, 1)", 'E805:')
+ call assert_fails("call xor([], 1)", 'E745:')
+ call assert_fails("call xor({}, 1)", 'E728:')
+ call assert_fails("call xor(1, 1.0)", 'E805:')
+ call assert_fails("call xor(1, [])", 'E745:')
+ call assert_fails("call xor(1, {})", 'E728:')
+ " invert
+ call assert_equal(65408, and(invert(127), 65535))
+ call assert_equal(65519, and(invert(16), 65535))
+ call assert_equal(65407, and(invert(128), 65535))
+ call assert_fails("call invert(1.0)", 'E805:')
+ call assert_fails("call invert([])", 'E745:')
+ call assert_fails("call invert({})", 'E728:')
endfunc
"-------------------------------------------------------------------------------
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..1694adbd32 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -1,13 +1,13 @@
-" 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 +15,31 @@ 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
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index 569a78a0ed..9d61921988 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -67,4 +67,360 @@ function Test_window_cmd_wincmd_gf()
augroup! test_window_cmd_wincmd_gf
endfunc
+func Test_next_split_all()
+ " This was causing an illegal memory access.
+ n x
+ norm axxx
+ split
+ split
+ s/x
+ s/x
+ all
+ bwipe!
+endfunc
+
+func Test_window_quit()
+ e Xa
+ split Xb
+ call assert_equal(2, winnr('$'))
+ call assert_equal('Xb', bufname(winbufnr(1)))
+ call assert_equal('Xa', bufname(winbufnr(2)))
+
+ wincmd q
+ call assert_equal(1, winnr('$'))
+ call assert_equal('Xa', bufname(winbufnr(1)))
+
+ bw Xa Xb
+endfunc
+
+func Test_window_horizontal_split()
+ call assert_equal(1, winnr('$'))
+ 3wincmd s
+ call assert_equal(2, winnr('$'))
+ call assert_equal(3, winheight(0))
+ call assert_equal(winwidth(1), winwidth(2))
+
+ call assert_fails('botright topleft wincmd s', 'E442:')
+ bw
+endfunc
+
+func Test_window_vertical_split()
+ call assert_equal(1, winnr('$'))
+ 3wincmd v
+ call assert_equal(2, winnr('$'))
+ call assert_equal(3, winwidth(0))
+ call assert_equal(winheight(1), winheight(2))
+
+ call assert_fails('botright topleft wincmd v', 'E442:')
+ bw
+endfunc
+
+func Test_window_split_edit_alternate()
+ e Xa
+ e Xb
+
+ wincmd ^
+ call assert_equal('Xa', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+
+ bw Xa Xb
+endfunc
+
+func Test_window_preview()
+ " Open a preview window
+ pedit Xa
+ call assert_equal(2, winnr('$'))
+ call assert_equal(0, &previewwindow)
+
+ " Go to the preview window
+ wincmd P
+ call assert_equal(1, &previewwindow)
+
+ " Close preview window
+ wincmd z
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, &previewwindow)
+
+ call assert_fails('wincmd P', 'E441:')
+endfunc
+
+func Test_window_exchange()
+ e Xa
+
+ " Nothing happens with window exchange when there is 1 window
+ wincmd x
+ call assert_equal(1, winnr('$'))
+
+ split Xb
+ split Xc
+
+ call assert_equal('Xc', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+ call assert_equal('Xa', bufname(winbufnr(3)))
+
+ " Exchange current window 1 with window 3
+ 3wincmd x
+ call assert_equal('Xa', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+ call assert_equal('Xc', bufname(winbufnr(3)))
+
+ " Exchange window with next when at the top window
+ wincmd x
+ call assert_equal('Xb', bufname(winbufnr(1)))
+ call assert_equal('Xa', bufname(winbufnr(2)))
+ call assert_equal('Xc', bufname(winbufnr(3)))
+
+ " Exchange window with next when at the middle window
+ wincmd j
+ wincmd x
+ call assert_equal('Xb', bufname(winbufnr(1)))
+ call assert_equal('Xc', bufname(winbufnr(2)))
+ call assert_equal('Xa', bufname(winbufnr(3)))
+
+ " Exchange window with next when at the bottom window.
+ " When there is no next window, it exchanges with the previous window.
+ wincmd j
+ wincmd x
+ call assert_equal('Xb', bufname(winbufnr(1)))
+ call assert_equal('Xa', bufname(winbufnr(2)))
+ call assert_equal('Xc', bufname(winbufnr(3)))
+
+ bw Xa Xb Xc
+endfunc
+
+func Test_window_rotate()
+ e Xa
+ split Xb
+ split Xc
+ call assert_equal('Xc', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+ call assert_equal('Xa', bufname(winbufnr(3)))
+
+ " Rotate downwards
+ wincmd r
+ call assert_equal('Xa', bufname(winbufnr(1)))
+ call assert_equal('Xc', bufname(winbufnr(2)))
+ call assert_equal('Xb', bufname(winbufnr(3)))
+
+ 2wincmd r
+ call assert_equal('Xc', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+ call assert_equal('Xa', bufname(winbufnr(3)))
+
+ " Rotate upwards
+ wincmd R
+ call assert_equal('Xb', bufname(winbufnr(1)))
+ call assert_equal('Xa', bufname(winbufnr(2)))
+ call assert_equal('Xc', bufname(winbufnr(3)))
+
+ 2wincmd R
+ call assert_equal('Xc', bufname(winbufnr(1)))
+ call assert_equal('Xb', bufname(winbufnr(2)))
+ call assert_equal('Xa', bufname(winbufnr(3)))
+
+ bot vsplit
+ call assert_fails('wincmd R', 'E443:')
+
+ bw Xa Xb Xc
+endfunc
+
+func Test_window_height()
+ e Xa
+ split Xb
+
+ let [wh1, wh2] = [winheight(1), winheight(2)]
+ " Active window (1) should have the same height or 1 more
+ " than the other window.
+ call assert_inrange(wh2, wh2 + 1, wh1)
+
+ wincmd -
+ call assert_equal(wh1 - 1, winheight(1))
+ call assert_equal(wh2 + 1, winheight(2))
+
+ wincmd +
+ call assert_equal(wh1, winheight(1))
+ call assert_equal(wh2, winheight(2))
+
+ 2wincmd _
+ call assert_equal(2, winheight(1))
+ call assert_equal(wh1 + wh2 - 2, winheight(2))
+
+ wincmd =
+ call assert_equal(wh1, winheight(1))
+ call assert_equal(wh2, winheight(2))
+
+ 2wincmd _
+ set winfixheight
+ split Xc
+ let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
+ call assert_equal(2, winheight(2))
+ call assert_inrange(wh3, wh3 + 1, wh1)
+ 3wincmd +
+ call assert_equal(2, winheight(2))
+ call assert_equal(wh1 + 3, winheight(1))
+ call assert_equal(wh3 - 3, winheight(3))
+ wincmd =
+ call assert_equal(2, winheight(2))
+ call assert_equal(wh1, winheight(1))
+ call assert_equal(wh3, winheight(3))
+
+ wincmd j
+ set winfixheight&
+
+ wincmd =
+ let [wh1, wh2, wh3] = [winheight(1), winheight(2), winheight(3)]
+ " Current window (2) should have the same height or 1 more
+ " than the other windows.
+ call assert_inrange(wh1, wh1 + 1, wh2)
+ call assert_inrange(wh3, wh3 + 1, wh2)
+
+ bw Xa Xb Xc
+endfunc
+
+func Test_window_width()
+ e Xa
+ vsplit Xb
+
+ let [ww1, ww2] = [winwidth(1), winwidth(2)]
+ " Active window (1) should have the same width or 1 more
+ " than the other window.
+ call assert_inrange(ww2, ww2 + 1, ww1)
+
+ wincmd <
+ call assert_equal(ww1 - 1, winwidth(1))
+ call assert_equal(ww2 + 1, winwidth(2))
+
+ wincmd >
+ call assert_equal(ww1, winwidth(1))
+ call assert_equal(ww2, winwidth(2))
+
+ 2wincmd |
+ call assert_equal(2, winwidth(1))
+ call assert_equal(ww1 + ww2 - 2, winwidth(2))
+
+ wincmd =
+ call assert_equal(ww1, winwidth(1))
+ call assert_equal(ww2, winwidth(2))
+
+ 2wincmd |
+ 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_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(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(ww1, winwidth(1))
+ call assert_equal(ww3, winwidth(3))
+
+ wincmd l
+ set winfixwidth&
+
+ wincmd =
+ let [ww1, ww2, ww3] = [winwidth(1), winwidth(2), winwidth(3)]
+ " Current window (2) should have the same width or 1 more
+ " than the other windows.
+ call assert_inrange(ww1, ww1 + 1, ww2)
+ call assert_inrange(ww3, ww3 + 1, ww2)
+
+ 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
+ call assert_match('^|iccf|', getline('.'))
+ call assert_equal(2, winnr('$'))
+ 2wincmd }
+ call assert_equal(3, winnr('$'))
+ call assert_match('^|iccf|', getline('.'))
+ wincmd k
+ call assert_match('\*iccf\*', getline('.'))
+ call assert_equal(2, winheight(0))
+
+ wincmd z
+ set previewheight=4
+ help
+ /bugs
+ wincmd }
+ wincmd k
+ call assert_match('\*bugs\*', getline('.'))
+ call assert_equal(4, winheight(0))
+ set previewheight&
+
+ %bw!
+endfunc
+
+func Test_window_newtab()
+ e Xa
+
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal("\nAlready only one window", execute('wincmd T'))
+
+ split Xb
+ split Xc
+
+ wincmd T
+ call assert_equal(2, tabpagenr('$'))
+ call assert_equal(['Xb', 'Xa'], map(tabpagebuflist(1), 'bufname(v:val)'))
+ call assert_equal(['Xc' ], map(tabpagebuflist(2), 'bufname(v:val)'))
+
+ %bw!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim
index 66656e1d0a..b3b506d04d 100644
--- a/src/nvim/testdir/test_window_id.vim
+++ b/src/nvim/testdir/test_window_id.vim
@@ -92,3 +92,12 @@ func Test_win_getid()
only!
endfunc
+
+func Test_win_getid_curtab()
+ tabedit X
+ tabfirst
+ copen
+ only
+ call assert_equal(win_getid(1), win_getid(1, 1))
+ tabclose!
+endfunc
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