diff options
Diffstat (limited to 'src/testdir')
120 files changed, 3768 insertions, 210 deletions
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index e31d2b5..67ef641 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -20,7 +20,8 @@ SCRIPTS_TINY = \ test24 \ test25 \ test26 \ - test27 + test27 \ + test28 SCRIPTS_TINY_OUT = \ test10.out \ @@ -31,7 +32,8 @@ SCRIPTS_TINY_OUT = \ test24.out \ test25.out \ test26.out \ - test27.out + test27.out \ + test28.out # Tests for Vim9 script. TEST_VIM9 = \ @@ -161,6 +163,10 @@ NEW_TESTS = \ test_function_lists \ test_ga \ test_getcwd \ + test_gettext \ + test_gettext_cp1251 \ + test_gettext_utf8 \ + test_gettext_make \ test_getvar \ test_gf \ test_glob2regpat \ @@ -309,6 +315,7 @@ NEW_TESTS = \ test_textobjects \ test_textprop \ test_timers \ + test_tohtml \ test_true_false \ test_trycatch \ test_undo \ @@ -335,6 +342,7 @@ NEW_TESTS = \ test_writefile \ test_xdg \ test_xxd \ + test_zip_plugin \ test_alot_latin \ test_alot_utf8 \ test_alot @@ -420,6 +428,10 @@ NEW_TESTS_RES = \ test_functions.res \ test_function_lists.res \ test_getcwd.res \ + test_gettext.res \ + test_gettext_cp1251.res \ + test_gettext_utf8.res \ + test_gettext_make.res \ test_getvar.res \ test_gf.res \ test_gn.res \ @@ -550,6 +562,7 @@ NEW_TESTS_RES = \ test_textobjects.res \ test_textprop.res \ test_timers.res \ + test_tohtml.res \ test_true_false.res \ test_trycatch.res \ test_undo.res \ @@ -571,6 +584,7 @@ NEW_TESTS_RES = \ test_writefile.res \ test_xdg.res \ test_xxd.res \ + test_zip_plugin.res \ test_alot_latin.res \ test_alot_utf8.res \ test_alot.res diff --git a/src/testdir/Make_mvc.mak b/src/testdir/Make_mvc.mak index 318cd4a..1bf9eae 100644 --- a/src/testdir/Make_mvc.mak +++ b/src/testdir/Make_mvc.mak @@ -5,9 +5,9 @@ # Testing may be done with a debug build !IF EXIST(..\\vimd.exe) && !EXIST(..\\vim.exe) -VIMPROG = ..\\vimd +VIMPROG = ..\\vimd.exe !ELSE -VIMPROG = ..\\vim +VIMPROG = ..\\vim.exe !ENDIF @@ -42,7 +42,7 @@ report: else ( echo No failures reported > test_result.log ) $(VIMPROG) -u NONE $(COMMON_ARGS) -S summarize.vim messages -if exist starttime del starttime - @echo. + @echo: @echo Test results: @cmd /c type test_result.log @if exist test.log ( echo TEST FAILURE & exit /b 1 ) \ @@ -56,7 +56,7 @@ $(NEW_TESTS): -if exist test.log del test.log -if exist messages del messages -if exist starttime del starttime - @$(MAKE) -nologo -f Make_mvc.mak $@.res VIMPROG=$(VIMPROG) + @$(MAKE) -nologo -f Make_mvc.mak VIMPROG=$(VIMPROG) $@.res @type messages @if exist test.log exit 1 diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 4e476f9..7a4c4c4 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -84,7 +84,7 @@ test_vim9: RM_ON_RUN = test.out X* viminfo RM_ON_START = test.ok benchmark.out -RUN_VIM = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim $(NO_INITS) -s dotest.in +RUN_VIMPROG = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u unix.vim $(NO_INITS) -s dotest.in # Delete files that may interfere with running tests. This includes some files # that may result from working on the tests, not only from running them. @@ -114,7 +114,7 @@ tinytests: $(SCRIPTS_TINY_OUT) @# 200 msec is sufficient, but only modern sleep supports a fraction of @# a second, fall back to a second if it fails. @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1" - $(RUN_VIM) $*.in $(REDIR_TEST_TO_NULL) + $(RUN_VIMPROG) $*.in $(REDIR_TEST_TO_NULL) @# Check if the test.out file matches test.ok. @/bin/sh -c "if test -f test.out; then \ diff --git a/src/testdir/README.txt b/src/testdir/README.txt index f72bdbf..203c324 100644 --- a/src/testdir/README.txt +++ b/src/testdir/README.txt @@ -97,8 +97,7 @@ tests are successful, then this file will be an empty file. - To execute only specific test functions, add a second argument: - $ ../vim -u NONE -S runtest.vim test_channel.vim open_delay - + $ ../vim -u NONE -S runtest.vim test_channel.vim open_delay - To run all the tests: @@ -119,3 +118,83 @@ tests are successful, then this file will be an empty file. - To cleanup the temporary files after running the tests: $ make clean + + +VIEWING GENERATED SCREENDUMPS (local): + +You may also wish to look at the whole batch of failed screendumps after +running "make". Source the "viewdumps.vim" script for this task: + + $ ../vim -u NONE -S viewdumps.vim \ + [dumps/Test_xxd_*.dump ...] + +By default, all screendumps found in the "failed" directory will be added to +the argument list and then the first one will be loaded. Loaded screendumps +that bear filenames of screendumps found in the "dumps" directory will be +rendering the contents of any such pair of files and the difference between +them (:help term_dumpdiff()); otherwise, they will be rendering own contents +(:help term_dumpload()). Remember to execute :edit when occasionally you see +raw file contents instead of rendered. + +At any time, you can add, list, and abandon other screendumps: + + :$argedit dumps/Test_spell_*.dump + :args + :qall + +The listing of argument commands can be found under :help buffer-list. + + +VIEWING GENERATED SCREENDUMPS (from a CI-uploaded artifact): + +After you have downloaded an artifact archive containing failed screendumps +and extracted its files in a temporary directory, you need to set up a "dumps" +directory by creating a symlink: + + $ cd /path/to/fork + $ ln -s $(pwd)/src/testdir/dumps /tmp/src/testdir/dumps + +You can now examine the extracted screendumps: + + $ ./src/vim -u NONE -S src/testdir/viewdumps.vim \ + /tmp/src/testdir/failed/*.dump + + +VIEWING GENERATED SCREENDUMPS (submitted for a pull request): + +First, you need to check out the topic branch with the proposed changes and +write down a difference list between the HEAD commit (index) and its parent +commit with respect to the changed "dumps" filenames: + + $ cd /path/to/fork + $ git switch prs/1234 + $ git diff-index --relative=src/testdir/dumps/ \ + --name-only prs/1234~1 > /tmp/filelist + +Then, you need to check out the master branch, change the current working +directory to reconcile relative filepaths written in the filenames list, +possibly create an empty "failed" directory, copy in this directory the old +"dumps" files, whose names are on the same list, and follow it by checking out +the topic branch: + + $ git switch master + $ cd src/testdir/dumps + $ test -d ../failed || mkdir ../failed + $ cp -t ../failed $(cat /tmp/filelist) + $ git switch prs/1234 + +Make note of any missing new screendumps. Please remember about the +introduced INVERTED relation between "dumps" and "failed", i.e. the files to +be committed are in "dumps" already and their old versions are in "failed". +Therefore, you need to copy the missing new screendumps from "dumps" to +"failed": + + $ cp -t ../failed foo_10.dump foo_11.dump foo_12.dump + +After you have changed the current working directory to its parent directory, +you can now examine the screendumps from the "failed" directory (note that new +screendumps will be shown with no difference between their versions): + + $ cd .. + $ ../vim -u NONE -S viewdumps.vim + diff --git a/src/testdir/commondumps.vim b/src/testdir/commondumps.vim new file mode 100644 index 0000000..ed70280 --- /dev/null +++ b/src/testdir/commondumps.vim @@ -0,0 +1,76 @@ +vim9script + +# (Script-local.) +# +# Render a loaded screendump file or the difference of a loaded screendump +# file and its namesake file from the "dumps" directory. +def Render() + const failed_fname: string = bufname() + try + setlocal suffixesadd=.dump + const dumps_fname: string = findfile( + fnamemodify(failed_fname, ':p:t'), + fnamemodify(failed_fname, ':p:h:h') .. '/dumps') + if filereadable(dumps_fname) + term_dumpdiff(failed_fname, dumps_fname) + else + term_dumpload(failed_fname) + endif + finally + exec 'bwipeout ' .. failed_fname + endtry +enddef + +# Search for the "failed" directory in the passed _subtreedirname_ directories +# (usually "\<src\>" or "\<syntax\>") and, if found, select its passed _count_ +# occurence, add all its "*.dump" files to the argument list and list them; +# also define a BufRead autocommand that would invoke "Render()" for every +# "*.dump" file. +def g:Init(subtreedirname: string, count: number) + # Support sourcing this script from any directory in the direct path that + # leads to the project's root directory. + const failed_path: string = finddir('failed', getcwd() .. '/**', -1) + ->filter(((cwdpath: string, parentdirname: string) => + (_: number, dirpath: string) => + cwdpath =~ parentdirname || dirpath =~ parentdirname)( + getcwd(), + subtreedirname)) + ->get(count, '') .. '/' + var error: string = null_string + + if failed_path == '/' + error = 'No such directory: "failed"' + else + const failed_fnames: string = failed_path .. readdir(failed_path, + (fname: string) => fname =~ '^.\+\.dump$') + ->join(' ' .. failed_path) + + if failed_fnames =~ 'failed/$' + error = 'No such file: "*.dump"' + else + exec ':0argedit ' .. failed_fnames + buffers + endif + endif + + autocmd_add([{ + replace: true, + group: 'viewdumps', + event: 'BufRead', + pattern: '*.dump', + cmd: 'Render()', + }]) + + # Unconditionally help, in case a list of filenames is passed to the + # command, the first terminal window with its BufRead event. + silent doautocmd viewdumps BufRead + + if error != null_string + # Instead of sleeping, fill half a window with blanks and prompt + # hit-enter. + echom error .. repeat("\x20", + (winwidth(0) * (winheight(0) / 2) - strlen(error))) + endif +enddef + +# vim:fdm=syntax:sw=2:ts=8:noet:nolist:nosta: diff --git a/src/testdir/crash/dialog_changed_uaf b/src/testdir/crash/dialog_changed_uaf Binary files differnew file mode 100644 index 0000000..e37d18d --- /dev/null +++ b/src/testdir/crash/dialog_changed_uaf diff --git a/src/testdir/crash/double_free b/src/testdir/crash/double_free Binary files differnew file mode 100644 index 0000000..895c4a0 --- /dev/null +++ b/src/testdir/crash/double_free diff --git a/src/testdir/crash/heap_overflow3 b/src/testdir/crash/heap_overflow3 Binary files differnew file mode 100644 index 0000000..c40adbe --- /dev/null +++ b/src/testdir/crash/heap_overflow3 diff --git a/src/testdir/crash/nullpointer b/src/testdir/crash/nullpointer Binary files differnew file mode 100644 index 0000000..c8ff3a4 --- /dev/null +++ b/src/testdir/crash/nullpointer diff --git a/src/testdir/crash/reverse_text_overflow b/src/testdir/crash/reverse_text_overflow Binary files differnew file mode 100644 index 0000000..dfbfe2c --- /dev/null +++ b/src/testdir/crash/reverse_text_overflow diff --git a/src/testdir/dumps/Test_breakindent_with_double_width_wrap_1.dump b/src/testdir/dumps/Test_breakindent_with_double_width_wrap_1.dump new file mode 100644 index 0000000..7b761bc --- /dev/null +++ b/src/testdir/dumps/Test_breakindent_with_double_width_wrap_1.dump @@ -0,0 +1,6 @@ +| +0&#ffffff0@7|a@40|>+0#4040ff13& +| +0#0000000&@7>å£*&@2| +&@35 +|~+0#4040ff13&| @48 +|~| @48 +|~| @48 +| +0#0000000&@31|1|,|4|3|-|5|9| @6|A|l@1| diff --git a/src/testdir/dumps/Test_cmdwin_no_terminal.dump b/src/testdir/dumps/Test_cmdwin_no_terminal.dump index 97d8147..6de9879 100644 --- a/src/testdir/dumps/Test_cmdwin_no_terminal.dump +++ b/src/testdir/dumps/Test_cmdwin_no_terminal.dump @@ -1,6 +1,6 @@ | +0&#ffffff0@74 |[+1&&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 -|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|c+0#e000e06&|m|d|h|e|i|g|h|t|=+0#0000000&|2| @58 +|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|c+0#e000e06&|m|d|h|e|i|g|h|t|=+0#af5f00255&|2+0#0000000&| @58 |:+0#4040ff13&> +0#0000000&@73 |~+0#4040ff13&| @73 |~| @73 diff --git a/src/testdir/dumps/Test_matchparen_mbyte_1.dump b/src/testdir/dumps/Test_matchparen_mbyte_1.dump new file mode 100644 index 0000000..f5df150 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_1.dump @@ -0,0 +1,10 @@ +>a+0&#ffffff0@7|(*&| +&@64 +|b@3|)*&|c+&@1| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_2.dump b/src/testdir/dumps/Test_matchparen_mbyte_2.dump new file mode 100644 index 0000000..0e4e6e8 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_2.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7>(*0(ffff15| +0&#ffffff0@64 +|b@3|)*0(ffff15|c+0&#ffffff0@1| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|1|,|9| @10|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_3.dump b/src/testdir/dumps/Test_matchparen_mbyte_3.dump new file mode 100644 index 0000000..85c462a --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_3.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*&| +&@64 +|b@3|)*&|c+&>c| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|2|,|9|-|8| @8|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_4.dump b/src/testdir/dumps/Test_matchparen_mbyte_4.dump new file mode 100644 index 0000000..45f5d08 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_4.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*0(ffff15| +0&#ffffff0@64 +|b@3>)*0(ffff15|c+0&#ffffff0@1| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|2|,|5| @10|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_5.dump b/src/testdir/dumps/Test_matchparen_mbyte_5.dump new file mode 100644 index 0000000..45c3bfa --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_5.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*&| +&@64 +>b@3|)*&|c+&@1| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_6.dump b/src/testdir/dumps/Test_matchparen_mbyte_6.dump new file mode 100644 index 0000000..8064a98 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_6.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*0(ffff15> +0&#ffffff0@64 +|b@3|)*0(ffff15|c+0&#ffffff0@1| @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |I|N|S|E|R|T| |-@1| +0&&@44|1|,|1|2|-|1@1| @6|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_7.dump b/src/testdir/dumps/Test_matchparen_mbyte_7.dump new file mode 100644 index 0000000..4d8c647 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_7.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*&| +&@64 +|b@3|)*&|c+&@1> @66 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |I|N|S|E|R|T| |-@1| +0&&@44|2|,|1|0|-|9| @7|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_mbyte_8.dump b/src/testdir/dumps/Test_matchparen_mbyte_8.dump new file mode 100644 index 0000000..c3699fd --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_mbyte_8.dump @@ -0,0 +1,10 @@ +|a+0&#ffffff0@7|(*0(ffff15| +0&#ffffff0@64 +|b@3|)*0(ffff15> +0&#ffffff0@68 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |I|N|S|E|R|T| |-@1| +0&&@44|2|,|8|-|7| @8|A|l@1| diff --git a/src/testdir/dumps/Test_popup_setbuf_01.dump b/src/testdir/dumps/Test_popup_setbuf_01.dump new file mode 100644 index 0000000..14359ba --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_01.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_popup_setbuf_02.dump b/src/testdir/dumps/Test_popup_setbuf_02.dump new file mode 100644 index 0000000..5feb982 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_02.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t|b|u|f|(|p|,| |'|f|o@1|b|a|r|.|t|x|t|'|)| @21|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/dumps/Test_popup_setbuf_03.dump b/src/testdir/dumps/Test_popup_setbuf_03.dump new file mode 100644 index 0000000..2c49576 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_03.dump @@ -0,0 +1,10 @@ +|~+0#4040ff13#ffffff0| @73 +|~| @73 +|~| @73 +|~| @33|t+0#0000001#ffd7ff255|e|s|t| +0#4040ff13#ffffff0@35 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|E+0#ffffff16#e000002|1|2@1|0|:| |S|t|r|i|n|g| |o|r| |N|u|m|b|e|r| |r|e|q|u|i|r|e|d| |f|o|r| |a|r|g|u|m|e|n|t| |2| +0#0000000#ffffff0@27 +|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35 diff --git a/src/testdir/dumps/Test_popup_setbuf_04.dump b/src/testdir/dumps/Test_popup_setbuf_04.dump new file mode 100644 index 0000000..937fa7c --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_04.dump @@ -0,0 +1,10 @@ +>*+0#ffffff16#ffd7ff255|h+0#e000002&|e|l|p|.|t|x|t|*+0#ffffff16&| +0#0000001&@5|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000001&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @11| +0#0000000#0000001 +| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@23|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @29| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@72|k| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@5|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e|y|s|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @1| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255|l| @71| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@19|"|j|"| |t|o| |g|o| |d|o|w|n|,| |"|k|"| |t|o| |g|o| |u|p|,| |"|l|"| |t|o| |g|o| |r|i|g|h|t|.| @6|j| +0#0000000#a8a8a8255 +|C+0#0000001#ffd7ff255|l|o|s|e| |t|h|i|s| |w|i|n|d|o|w|:| @1|U|s|e| |"|:|q|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&|.| @37| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@2|G|e|t| |o|u|t| |o|f| |V|i|m|:| @1|U|s|e| |"|:|q|a|!|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&| |(|c|a|r|e|f|u|l|,| |a|l@1| |c|h|a|n|g|e|s| |a|r|e| |l|o|s|t|!|)|.| @2| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255 diff --git a/src/testdir/dumps/Test_popup_setbuf_05.dump b/src/testdir/dumps/Test_popup_setbuf_05.dump new file mode 100644 index 0000000..a13dfe3 --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_05.dump @@ -0,0 +1,10 @@ +>h+0#e000002#ffffff0|e|l|p|.|t|x|t| +0#0000000&@7|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000000&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @12 +@75 +@24|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @30 +@73|k| +@6|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e| +0#0000001#ffd7ff255|s+0#0000000#ffffff0|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @2 +|l| @73 +|h+3&&|e|l|p|.|t|x|t| |[|H|e|l|p|]|[|R|O|]| @37|1|,|1| @11|T|o|p +| +0&&@74 +|[+1&&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +| +0&&@74 diff --git a/src/testdir/dumps/Test_popup_setbuf_06.dump b/src/testdir/dumps/Test_popup_setbuf_06.dump new file mode 100644 index 0000000..937fa7c --- /dev/null +++ b/src/testdir/dumps/Test_popup_setbuf_06.dump @@ -0,0 +1,10 @@ +>*+0#ffffff16#ffd7ff255|h+0#e000002&|e|l|p|.|t|x|t|*+0#ffffff16&| +0#0000001&@5|F|o|r| |V+0#00e0e07&|i|m| |v|e|r|s|i|o|n| |9|.|1|.| +0#0000001&@1|L|a|s|t| |c|h|a|n|g|e|:| |2|0|2|4| |M|a|y| |2|7| @11| +0#0000000#0000001 +| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@23|V|I|M| |-| |m|a|i|n| |h|e|l|p| |f|i|l|e| @29| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@72|k| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@5|M|o|v|e| |a|r|o|u|n|d|:| @1|U|s|e| |t|h|e| |c|u|r|s|o|r| |k|e|y|s|,| |o|r| |"|h|"| |t|o| |g|o| |l|e|f|t|,| @11|h| @1| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255|l| @71| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@19|"|j|"| |t|o| |g|o| |d|o|w|n|,| |"|k|"| |t|o| |g|o| |u|p|,| |"|l|"| |t|o| |g|o| |r|i|g|h|t|.| @6|j| +0#0000000#a8a8a8255 +|C+0#0000001#ffd7ff255|l|o|s|e| |t|h|i|s| |w|i|n|d|o|w|:| @1|U|s|e| |"|:|q|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&|.| @37| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@2|G|e|t| |o|u|t| |o|f| |V|i|m|:| @1|U|s|e| |"|:|q|a|!|<+0#e000e06&|E|n|t|e|r|>|"+0#0000001&| |(|c|a|r|e|f|u|l|,| |a|l@1| |c|h|a|n|g|e|s| |a|r|e| |l|o|s|t|!|)|.| @2| +0#0000000#a8a8a8255 +| +0#0000001#ffd7ff255@73| +0#0000000#a8a8a8255 diff --git a/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_2.dump b/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_2.dump new file mode 100644 index 0000000..6022a16 --- /dev/null +++ b/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_2.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0@39|b+0#e000e06&@8|>+0#4040ff13& +>å£*0#0000000&|1+&|2|3|4|5| @42 +@32|1|,|4|1|-|5|1| @6|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_3.dump b/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_3.dump new file mode 100644 index 0000000..c033399 --- /dev/null +++ b/src/testdir/dumps/Test_prop_inserts_text_before_double_width_wrap_3.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0@39|b+0#e000e06&@8|>+0#4040ff13& +|+@2>å£*0#0000000&|1+&|2|3|4|5| @39 +|:|s|e|t| |s|h|o|w|b|r|e|a|k|=|+@2| @13|1|,|4|1|-|5|4| @6|A|l@1| diff --git a/src/testdir/dumps/Test_pum_highlights_10.dump b/src/testdir/dumps/Test_pum_highlights_10.dump new file mode 100644 index 0000000..790b028 --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_10.dump @@ -0,0 +1,20 @@ +| +0&#ffffff0|h|e|l@1|o| |h|e|l|i|o| |h|e|r|o| |h|e|l@1|o> @51 +|~+0#4040ff13&| @15| +0#0000001#ffd7ff255|h+0#0000e05&|e+0#0000001&|r|o| @10| +0#4040ff13#ffffff0@41 +|~| @15| +0#0000001#ffd7ff255|h+0#0000e05&|e+0#0000001&|l|i|o| @9| +0#4040ff13#ffffff0@41 +|~| @15| +0#0000001#e0e0e08|h+0#00e0e07&|e+0#0000001&|l@1|o| @9| +0#4040ff13#ffffff0@41 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |K|e|y|w|o|r|d| |L|o|c|a|l| |c|o|m|p|l|e|t|i|o|n| |(|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@27 diff --git a/src/testdir/dumps/Test_pum_highlights_11.dump b/src/testdir/dumps/Test_pum_highlights_11.dump new file mode 100644 index 0000000..ef75a89 --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_11.dump @@ -0,0 +1,20 @@ +| +0&#ffffff0|h|e|l@1|o| |h|e|l|i|o| |h|e|r|o| |h|e|l|i|o> @51 +|~+0#4040ff13&| @15| +0#0000001#ffd7ff255|h+0#0000e05&|e+0#0000001&|r|o| @10| +0#4040ff13#ffffff0@41 +|~| @15| +0#0000001#e0e0e08|h+0#00e0e07&|e+0#0000001&|l|i|o| @9| +0#4040ff13#ffffff0@41 +|~| @15| +0#0000001#ffd7ff255|h+0#0000e05&|e+0#0000001&|l@1|o| @9| +0#4040ff13#ffffff0@41 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |K|e|y|w|o|r|d| |L|o|c|a|l| |c|o|m|p|l|e|t|i|o|n| |(|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |2| |o|f| |3| +0#0000000&@27 diff --git a/src/testdir/dumps/Test_pum_highlights_12.dump b/src/testdir/dumps/Test_pum_highlights_12.dump new file mode 100644 index 0000000..a0d2b49 --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_12.dump @@ -0,0 +1,20 @@ +|a+0&#ffffff0|w|o|r|d|1> @68 +|a+0#ff404010#e0e0e08|w|o|r|d|1| |W| |e|x|t|r|a| |t|e|x|t| |1| | +0#4040ff13#ffffff0@52 +|a+0#0000001#ffd7ff255|w|o|r|d|2| |W| |e|x|t|r|a| |t|e|x|t| |2| | +0#4040ff13#ffffff0@52 +|ä½ *0#ff404010#ffd7ff255|好| +&@2|W| |e|x|t|r|a| |t|e|x|t| |3| | +0#4040ff13#ffffff0@52 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@26 diff --git a/src/testdir/dumps/Test_pum_highlights_13.dump b/src/testdir/dumps/Test_pum_highlights_13.dump new file mode 100644 index 0000000..34fde12 --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_13.dump @@ -0,0 +1,20 @@ +|a+0&#ffffff0|w|o|r|d|1> @68 +|a+8#ff404010#e0e0e08|w|o+0&&|r|d|1| |W| |e|x|t|r|a| |t|e|x|t| |1| | +0#4040ff13#ffffff0@52 +|a+8#0000e05#ffd7ff255|w|o+0#0000001&|r|d|2| |W| |e|x|t|r|a| |t|e|x|t| |2| | +0#4040ff13#ffffff0@52 +|ä½ *0#ff404010#ffd7ff255|好| +&@2|W| |e|x|t|r|a| |t|e|x|t| |3| | +0#4040ff13#ffffff0@52 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@26 diff --git a/src/testdir/dumps/Test_pum_highlights_14.dump b/src/testdir/dumps/Test_pum_highlights_14.dump new file mode 100644 index 0000000..f35b4cb --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_14.dump @@ -0,0 +1,20 @@ +|a+0&#ffffff0|w|o|r|d|2> @68 +|a+8#ff404010#ffd7ff255|w|o+0&&|r|d|1| |W| |e|x|t|r|a| |t|e|x|t| |1| | +0#4040ff13#ffffff0@52 +|a+8#00e0e07#e0e0e08|w|o+0#0000001&|r|d|2| |W| |e|x|t|r|a| |t|e|x|t| |2| | +0#4040ff13#ffffff0@52 +|ä½ *0#ff404010#ffd7ff255|好| +&@2|W| |e|x|t|r|a| |t|e|x|t| |3| | +0#4040ff13#ffffff0@52 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |2| |o|f| |3| +0#0000000&@26 diff --git a/src/testdir/dumps/Test_pum_highlights_15.dump b/src/testdir/dumps/Test_pum_highlights_15.dump new file mode 100644 index 0000000..e923b43 --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_15.dump @@ -0,0 +1,20 @@ +|/+0&#ffffff0|n|o|n|_|e|x|i|t|_|f|o|l|d|e|r> @58 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |F|i|l|e| |n|a|m|e| |c|o|m|p|l|e|t|i|o|n| |(|^|F|^|N|^|P|)| |P+0#ffffff16#e000002|a|t@1|e|r|n| |n|o|t| |f|o|u|n|d| +0#0000000#ffffff0@24 diff --git a/src/testdir/dumps/Test_pum_highlights_16.dump b/src/testdir/dumps/Test_pum_highlights_16.dump new file mode 100644 index 0000000..fe2b68d --- /dev/null +++ b/src/testdir/dumps/Test_pum_highlights_16.dump @@ -0,0 +1,20 @@ +|a+0&#ffffff0|w|o|r|d|1> @68 +|a+0#ff404010#e0e0e08|w|o|r|d|1| |v+0#ffff4012&|a|r|i|a|b|l|e| |e+0#ff404010&|x|t|r|a| |t|e|x|t| |1| | +0#4040ff13#ffffff0@45 +|a+0#0000001#ffd7ff255|w|o|r|d|2| |f+0#4040ff13&|u|n|c|t|i|o|n| |e+0#0000001&|x|t|r|a| |t|e|x|t| |2| | +0#4040ff13#ffffff0@45 +|ä½ *0#0000001#ffd7ff255|好| +&@2|c+0#40ff4011&|l|a|s@1| @3|e+0#0000001&|x|t|r|a| |t|e|x|t| |3| | +0#4040ff13#ffffff0@45 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|-+2#0000000&@1| |U|s|e|r| |d|e|f|i|n|e|d| |c|o|m|p|l|e|t|i|o|n| |(|^|U|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@26 diff --git a/src/testdir/dumps/Test_wildmenu_pum_11.dump b/src/testdir/dumps/Test_wildmenu_pum_11.dump index 4697c8a..a0ffc74 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_11.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_11.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @10| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@46 +|~| @10| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@46 |~| @10| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@46 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=> @55 diff --git a/src/testdir/dumps/Test_wildmenu_pum_12.dump b/src/testdir/dumps/Test_wildmenu_pum_12.dump index d93631d..12842c4 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_12.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_12.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @17| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@39 +|~| @17| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@39 |~| @17| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@39 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=| |c|u|l|h|l|=> @48 diff --git a/src/testdir/dumps/Test_wildmenu_pum_13.dump b/src/testdir/dumps/Test_wildmenu_pum_13.dump index b2b1424..94a8ccc 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_13.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_13.dump @@ -1,10 +1,10 @@ | +0&#ffffff0@74 |~+0#4040ff13&| @73 -|~| @73 |~| @24| +0#0000001#e0e0e08|c|u|l|h|l|=| @8| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|i|c|o|n|=| @9| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|l|i|n|e|h|l|=| @7| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|n|u|m|h|l|=| @8| +0#4040ff13#ffffff0@32 +|~| @24| +0#0000001#ffd7ff255|p|r|i|o|r|i|t|y|=| @5| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|t|e|x|t|=| @9| +0#4040ff13#ffffff0@32 |~| @24| +0#0000001#ffd7ff255|t|e|x|t|h|l|=| @7| +0#4040ff13#ffffff0@32 |:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |c|u|l|h|l|=| |c|u|l|h|l|=| |c|u|l|h|l|=> @41 diff --git a/src/testdir/dumps/Test_wildmenu_pum_22.dump b/src/testdir/dumps/Test_wildmenu_pum_22.dump index 3fd00ad..e774d5d 100644 --- a/src/testdir/dumps/Test_wildmenu_pum_22.dump +++ b/src/testdir/dumps/Test_wildmenu_pum_22.dump @@ -1,7 +1,7 @@ | +0&#ffffff0@74 |[+1&&|N|o| |N|a|m|e|]| @65 -|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|w+0#e000e06&|i|l|d|m|o|d|e|=+0#0000000&|l|o|n|g|e|s|t|,+0#af5f00255&|f+0#0000000&|u|l@1| @48 -|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|w+0#e000e06&|i|l|d|m|o|d|e|=+0#0000000&|f|u|l@1| @56 +|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|w+0#e000e06&|i|l|d|m|o|d|e|=+0#af5f00255&|l+0#0000000&|o|n|g|e|s|t|,+0#e000e06&|f+0#0000000&|u|l@1| @48 +|:+0#4040ff13&|s+0#af5f00255&|e|t| +0#0000000&|w+0#e000e06&|i|l|d|m|o|d|e|=+0#af5f00255&|f+0#0000000&|u|l@1| @56 |:+0#4040ff13&|s+0#af5f00255&|i|g|n| +0#0000000&|d|e|f|i|n|e| @62 |:+0#4040ff13&|s+0#af5f00255&|i|g|n| +0#0000000&|d|e|f|i|n|e> @62 |~+0#4040ff13&| @73 diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim index 8cca2b9..7674714 100644 --- a/src/testdir/gen_opt_test.vim +++ b/src/testdir/gen_opt_test.vim @@ -144,6 +144,7 @@ let test_values = { \ 'splitkeep': [['cursor', 'screen', 'topline'], ['xxx']], \ 'swapsync': [['', 'sync', 'fsync'], ['xxx']], \ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']], + \ 'tabclose': [['', 'left', 'left,uselast'], ['xxx']], \ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']], \ 'term': [[], []], \ 'termguicolors': [[], []], diff --git a/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo b/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo Binary files differnew file mode 100644 index 0000000..300eba2 --- /dev/null +++ b/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo diff --git a/src/testdir/samples/Test_tohtml_basic.c.html b/src/testdir/samples/Test_tohtml_basic.c.html new file mode 100644 index 0000000..d9467b5 --- /dev/null +++ b/src/testdir/samples/Test_tohtml_basic.c.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +<title>/home/jiangyinzuo/vim/src/testdir/Test_tohtml_basic.c.html</title> +<meta name="Generator" content="Vim/9.1"> +<meta name="plugin-version" content="vim9.0_v2"> +<meta name="syntax" content="none"> +<meta name="settings" content="use_css,no_foldcolumn,pre_wrap,prevent_copy=,use_input_for_pc=none"> +<meta name="colorscheme" content="none"> +<style> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; } +body { font-family: monospace; color: #000000; background-color: #ffffff; } +* { font-size: 1em; } +--> +</style> +</head> +<body> +<pre id='vimCodeElement'> +#include <stdio.h> +#include <stdlib.h> + +int isprime(int n) +{ + if (n <= 1) + return 0; + + for (int i = 2; i <= n / 2; i++) + if (n % i == 0) + return 0; + + return 1; +} + +int main(int argc, char *argv[]) +{ + int n = 7; + + printf("%d is %s prime\n", n, isprime(n) ? "a" : "not a"); + + return 0; +} +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/src/testdir/samples/Test_tohtml_basic_no_css.c.html b/src/testdir/samples/Test_tohtml_basic_no_css.c.html new file mode 100644 index 0000000..fcbcf5c --- /dev/null +++ b/src/testdir/samples/Test_tohtml_basic_no_css.c.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>/home/jiangyinzuo/vim/src/testdir/Test_tohtml_basic_no_css.c.html</title> +<meta name="Generator" content="Vim/9.1"> +<meta name="plugin-version" content="vim9.0_v2"> +<meta name="syntax" content="none"> +<meta name="settings" content="no_pre,no_foldcolumn,expand_tabs,prevent_copy=,use_input_for_pc=none"> +<meta name="colorscheme" content="none"> +</head> +<body bgcolor="#ffffff" text="#000000"> +<font face="monospace"> +#include <stdio.h><br> +#include <stdlib.h><br> +<br> +int isprime(int n)<br> +{<br> + if (n <= 1)<br> + return 0;<br> +<br> + for (int i = 2; i <= n / 2; i++)<br> + if (n % i == 0)<br> + return 0;<br> +<br> + return 1;<br> +}<br> +<br> +int main(int argc, char *argv[])<br> +{<br> + int n = 7;<br> +<br> + printf("%d is %s prime\n", n, isprime(n) ? "a" : "not a");<br> +<br> + return 0;<br> +}<br> +</font> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/src/testdir/samples/test.zip b/src/testdir/samples/test.zip Binary files differnew file mode 100644 index 0000000..6d34ac6 --- /dev/null +++ b/src/testdir/samples/test.zip diff --git a/src/testdir/samples/testa.zip b/src/testdir/samples/testa.zip Binary files differnew file mode 100644 index 0000000..10b0346 --- /dev/null +++ b/src/testdir/samples/testa.zip diff --git a/src/testdir/test28.in b/src/testdir/test28.in new file mode 100644 index 0000000..3d5289d --- /dev/null +++ b/src/testdir/test28.in @@ -0,0 +1,13 @@ +Test for using CTRL-A/CTRL-X in tiny mode + +STARTTEST +/12352 +/12354 +:/^STARTHERE/+,$w! test.out +:qa! +ENDTEST + +STARTHERE +12352 + +12354 diff --git a/src/testdir/test28.ok b/src/testdir/test28.ok new file mode 100644 index 0000000..085c133 --- /dev/null +++ b/src/testdir/test28.ok @@ -0,0 +1,3 @@ +12353 + +12353 diff --git a/src/testdir/test_arglist.vim b/src/testdir/test_arglist.vim index edc8b77..8d81a82 100644 --- a/src/testdir/test_arglist.vim +++ b/src/testdir/test_arglist.vim @@ -359,6 +359,7 @@ func Test_argv() call assert_equal('', argv(1, 100)) call assert_equal([], argv(-1, 100)) call assert_equal('', argv(10, -1)) + %argdelete endfunc " Test for the :argedit command @@ -744,4 +745,26 @@ func Test_all_command() %bw! endfunc +" Test for deleting buffer when creating an arglist. This was accessing freed +" memory +func Test_crash_arglist_uaf() + "%argdelete + new one + au BufAdd XUAFlocal :bw + "call assert_fails(':arglocal XUAFlocal', 'E163:') + arglocal XUAFlocal + au! BufAdd + bw! XUAFlocal + + au BufAdd XUAFlocal2 :bw + new two + new three + arglocal + argadd XUAFlocal2 Xfoobar + bw! XUAFlocal2 + bw! two + + au! BufAdd +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim index d143f19..15b18a4 100644 --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -48,10 +48,19 @@ func Test_assert_equal() call assert_match("Expected 'bar' but got 'foo'", v:errors[0]) call remove(v:errors, 0) + let s = 'αβγ' + call assert_equal(1, assert_equal('δεζ', s)) + call assert_match("Expected 'δεζ' but got 'αβγ'", v:errors[0]) + call remove(v:errors, 0) + call assert_equal('XxxxxxxxxxxxxxxxxxxxxxX', 'XyyyyyyyyyyyyyyyyyyyyyyyyyX') call assert_match("Expected 'X\\\\\\[x occurs 21 times]X' but got 'X\\\\\\[y occurs 25 times]X'", v:errors[0]) call remove(v:errors, 0) + call assert_equal('ΩωωωωωωωωωωωωωωωωωωωωωΩ', 'ΩψψψψψψψψψψψψψψψψψψψψψψψψψΩ') + call assert_match("Expected 'Ω\\\\\\[ω occurs 21 times]Ω' but got 'Ω\\\\\\[ψ occurs 25 times]Ω'", v:errors[0]) + call remove(v:errors, 0) + " special characters are escaped call assert_equal("\b\e\f\n\t\r\\\x01\x7f", 'x') call assert_match('Expected ''\\b\\e\\f\\n\\t\\r\\\\\\x01\\x7f'' but got ''x''', v:errors[0]) diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index c9f257a..5a91351 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -14,6 +14,13 @@ func s:cleanup_buffers() abort endfor endfunc +func CleanUpTestAuGroup() + augroup testing + au! + augroup END + augroup! testing +endfunc + func Test_vim_did_enter() call assert_false(v:vim_did_enter) @@ -269,6 +276,7 @@ endfunc func Test_win_tab_autocmd() let g:record = [] + defer CleanUpTestAuGroup() augroup testing au WinNewPre * call add(g:record, 'WinNewPre') au WinNew * call add(g:record, 'WinNew') @@ -288,7 +296,7 @@ func Test_win_tab_autocmd() call assert_equal([ \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', - \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter', \ 'WinLeave', 'WinClosed', 'WinEnter' \ ], g:record) @@ -299,7 +307,7 @@ func Test_win_tab_autocmd() bwipe somefile call assert_equal([ - \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', \ 'WinClosed', 'TabClosed' \ ], g:record) @@ -316,9 +324,6 @@ func Test_win_tab_autocmd() \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter' \ ], g:record) - augroup testing - au! - augroup END unlet g:record endfunc @@ -330,17 +335,15 @@ func Test_WinNewPre() au WinNewPre * call add(g:layouts_pre, winlayout()) au WinNew * call add(g:layouts_post, winlayout()) augroup END + defer CleanUpTestAuGroup() split call assert_notequal(g:layouts_pre[0], g:layouts_post[0]) split call assert_equal(g:layouts_pre[1], g:layouts_post[0]) call assert_notequal(g:layouts_pre[1], g:layouts_post[1]) + " not triggered for tabnew tabnew - call assert_notequal(g:layouts_pre[2], g:layouts_post[1]) - call assert_notequal(g:layouts_pre[2], g:layouts_post[2]) - augroup testing - au! - augroup END + call assert_equal(2, len(g:layouts_pre)) unlet g:layouts_pre unlet g:layouts_post @@ -383,9 +386,6 @@ func Test_WinNewPre() let g:caught += 1 endtry call assert_equal(4, g:caught) - augroup testing - au! - augroup END unlet g:caught endfunc @@ -2096,6 +2096,38 @@ func Test_Cmdline() au! CmdlineEnter au! CmdlineLeave let &shellslash = save_shellslash + + au! CursorMovedC : let g:pos += [getcmdpos()] + let g:pos = [] + call feedkeys(":foo bar baz\<C-W>\<C-W>\<C-W>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 9, 5, 1], g:pos) + let g:pos = [] + call feedkeys(":hello\<C-B>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 1], g:pos) + let g:pos = [] + call feedkeys(":hello\<C-U>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 1], g:pos) + let g:pos = [] + call feedkeys(":hello\<Left>\<C-R>=''\<CR>\<Left>\<Right>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 5, 4, 5], g:pos) + let g:pos = [] + call feedkeys(":12345678\<C-R>=setcmdpos(3)??''\<CR>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 3], g:pos) + let g:pos = [] + call feedkeys(":12345678\<C-R>=setcmdpos(3)??''\<CR>\<Left>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 3, 2], g:pos) + au! CursorMovedC + + " setcmdpos() is no-op inside an autocommand + au! CursorMovedC : let g:pos += [getcmdpos()] | call setcmdpos(1) + let g:pos = [] + call feedkeys(":hello\<Left>\<Left>\<Esc>", 'xt') + call assert_equal([2, 3, 4, 5, 6, 5, 4], g:pos) + au! CursorMovedC + + unlet g:entered + unlet g:left + unlet g:pos endfunc " Test for BufWritePre autocommand that deletes or unloads the buffer. @@ -2775,7 +2807,8 @@ endfunc func Test_autocmd_nested() let g:did_nested = 0 - augroup Testing + defer CleanUpTestAuGroup() + augroup testing au WinNew * edit somefile au BufNew * let g:did_nested = 1 augroup END @@ -2785,7 +2818,7 @@ func Test_autocmd_nested() bwipe! somefile " old nested argument still works - augroup Testing + augroup testing au! au WinNew * nested edit somefile au BufNew * let g:did_nested = 1 @@ -4720,4 +4753,115 @@ func Test_BufEnter_botline() set hidden&vim endfunc +func Test_KeyInputPre() + " Consume previous keys + call feedkeys('', 'ntx') + + " KeyInputPre can record input keys. + let s:keys = [] + au KeyInputPre n call add(s:keys, v:char) + + call feedkeys('jkjkjjj', 'ntx') + call assert_equal( + \ ['j', 'k', 'j', 'k', 'j', 'j', 'j'], + \ s:keys) + + unlet s:keys + au! KeyInputPre + + " KeyInputPre can handle multibyte. + let s:keys = [] + au KeyInputPre * call add(s:keys, v:char) + edit Xxx1 + + call feedkeys("iã‚\<ESC>", 'ntx') + call assert_equal(['i', "ã‚", "\<ESC>"], s:keys) + + bwipe! Xxx1 + unlet s:keys + au! KeyInputPre + + " KeyInputPre can change input keys. + au KeyInputPre i if v:char ==# 'a' | let v:char = 'b' | endif + edit Xxx1 + + call feedkeys("iaabb\<ESC>", 'ntx') + call assert_equal(getline('.'), 'bbbb') + + bwipe! Xxx1 + au! KeyInputPre + + " KeyInputPre returns multiple characters. + au KeyInputPre i if v:char ==# 'a' | let v:char = 'cccc' | endif + edit Xxx1 + + call feedkeys("iaabb\<ESC>", 'ntx') + call assert_equal(getline('.'), 'ccbb') + + bwipe! Xxx1 + au! KeyInputPre + + " KeyInputPre can use special keys. + au KeyInputPre i if v:char ==# 'a' | let v:char = "\<Ignore>" | endif + edit Xxx1 + + call feedkeys("iaabb\<ESC>", 'ntx') + call assert_equal(getline('.'), 'bb') + + bwipe! Xxx1 + au! KeyInputPre + + " Test for v:event.typed + au KeyInputPre n call assert_true(v:event.typed) + call feedkeys('j', 'ntx') + + au! KeyInputPre + + au KeyInputPre n call assert_false(v:event.typed) + call feedkeys('j', 'nx') + + au! KeyInputPre + + " Test for v:event.typedchar + nnoremap j k + au KeyInputPre n + \ call assert_equal(v:event.typedchar, 'j') + \ | call assert_equal(v:char, 'k') + call feedkeys('j', 'tx') + + au! KeyInputPre +endfunc + +" those commands caused null pointer access, see #15464 +func Test_WinNewPre_crash() + defer CleanUpTestAuGroup() + let _cmdheight=&cmdheight + augroup testing + au! + autocmd WinNewPre * redraw + augroup END + tabnew + tabclose + augroup testing + au! + autocmd WinNewPre * wincmd t + augroup END + tabnew + tabclose + augroup testing + au! + autocmd WinNewPre * wincmd b + augroup END + tabnew + tabclose + augroup testing + au! + autocmd WinNewPre * set cmdheight+=1 + augroup END + tabnew + tabclose + let &cmdheight=_cmdheight +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim index 96d91c9..b306c02 100644 --- a/src/testdir/test_breakindent.vim +++ b/src/testdir/test_breakindent.vim @@ -1165,4 +1165,15 @@ func Test_breakindent_min_with_signcol() call s:close_windows() endfunc +func Test_breakindent_with_double_width_wrap() + 50vnew + setlocal tabstop=8 breakindent nolist + call setline(1, "\t" .. repeat('a', winwidth(0) - 9) .. 'å£å£å£') + normal! $g0 + call assert_equal(2, winline()) + call assert_equal(9, wincol()) + + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim index de088bd..757ba05 100644 --- a/src/testdir/test_buffer.vim +++ b/src/testdir/test_buffer.vim @@ -126,6 +126,52 @@ func Test_buflist_browse() %bwipe! endfunc +" Test for :bnext and :bprev when called from help and non-help buffers. +func Test_bnext_bprev_help() + %bwipe! + + e XHelp1 | set bt=help + let b1 = bufnr() + e Xbuf1 + let b2 = bufnr() + + " There's only one buffer of each type. + b XHelp1 + bnext | call assert_equal(b1, bufnr()) + bprev | call assert_equal(b1, bufnr()) + b Xbuf1 + bnext | call assert_equal(b2, bufnr()) + bprev | call assert_equal(b2, bufnr()) + + " Add one more buffer of each type. + e XHelp2 | set bt=help + let b3 = bufnr() + e Xbuf2 + let b4 = bufnr() + + " Help buffer jumps to help buffer. + b XHelp1 + bnext | call assert_equal(b3, bufnr()) + bnext | call assert_equal(b1, bufnr()) + bprev | call assert_equal(b3, bufnr()) + bprev | call assert_equal(b1, bufnr()) + + " Regular buffer jumps to regular buffer. + b Xbuf1 + bnext | call assert_equal(b4, bufnr()) + bnext | call assert_equal(b2, bufnr()) + bprev | call assert_equal(b4, bufnr()) + bprev | call assert_equal(b2, bufnr()) + + " :brewind and :blast are not affected by the buffer type. + b Xbuf2 + brewind | call assert_equal(b1, bufnr()) + b XHelp1 + blast | call assert_equal(b4, bufnr()) + + %bwipe! +endfunc + " Test for :bdelete func Test_bdelete_cmd() %bwipe! diff --git a/src/testdir/test_cd.vim b/src/testdir/test_cd.vim index 9fb5958..13a3eba 100644 --- a/src/testdir/test_cd.vim +++ b/src/testdir/test_cd.vim @@ -200,12 +200,20 @@ endfunc func Test_cd_completion() call mkdir('XComplDir1', 'D') call mkdir('XComplDir2', 'D') + call mkdir('sub/XComplDir3', 'pD') call writefile([], 'XComplFile', 'D') for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/', @:) endfor + + set cdpath+=sub + for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] + call feedkeys(':' .. cmd .. " XCompl\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/ XComplDir3/', @:) + endfor + set cdpath& endfunc func Test_cd_unknown_dir() diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 8b7489e..3f6918a 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -658,7 +658,8 @@ func Test_getcompletion() unlet g:cmdline_compl_params " For others test if the name is recognized. - let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user'] + let names = ['buffer', 'environment', 'file_in_path', 'dir_in_path', 'mapping', 'tag', + \ 'tag_listfiles', 'user'] if has('cmdline_hist') call add(names, 'history') endif @@ -3612,7 +3613,7 @@ func Test_cmdline_complete_bang_cmd_argument() endfunc func Call_cmd_funcs() - return string([getcmdpos(), getcmdscreenpos(), getcmdcompltype()]) + return [getcmdpos(), getcmdscreenpos(), getcmdcompltype()] endfunc func Test_screenpos_and_completion() @@ -3620,13 +3621,24 @@ func Test_screenpos_and_completion() call assert_equal(0, getcmdscreenpos()) call assert_equal('', getcmdcompltype()) - cnoremap <expr> <F2> string([getcmdpos(), getcmdscreenpos(), getcmdcompltype()]) + cnoremap <expr> <F2> string(Call_cmd_funcs()) call feedkeys(":let a\<F2>\<C-B>\"\<CR>", "xt") call assert_equal("\"let a[6, 7, 'var']", @:) call feedkeys(":quit \<F2>\<C-B>\"\<CR>", "xt") call assert_equal("\"quit [6, 7, '']", @:) call feedkeys(":nosuchcommand \<F2>\<C-B>\"\<CR>", "xt") call assert_equal("\"nosuchcommand [15, 16, '']", @:) + + " Check that getcmdcompltype() doesn't interfere with cmdline completion. + let g:results = [] + cnoremap <F2> <Cmd>let g:results += [[getcmdline()] + Call_cmd_funcs()]<CR> + call feedkeys(":sign un\<Tab>\<F2>\<Tab>\<F2>\<Tab>\<F2>\<C-C>", "xt") + call assert_equal([ + \ ['sign undefine', 14, 15, 'sign'], + \ ['sign unplace', 13, 14, 'sign'], + \ ['sign un', 8, 9, 'sign']], g:results) + + unlet g:results cunmap <F2> endfunc @@ -3858,4 +3870,25 @@ func Test_term_option() let &cpo = _cpo endfunc +func Test_ex_command_completion() + " required for :* + set cpo+=* + let list = filter(getcompletion('', 'command'), 'exists(":" . v:val) == 0') + " :++ and :-- are only valid in Vim9 Script context, so they can be ignored + call assert_equal(['++', '--'], sort(list)) + call assert_equal(1, exists(':k')) + call assert_equal(0, exists(':ke')) + call assert_equal(1, exists(':kee')) + call assert_equal(1, exists(':keep')) + call assert_equal(1, exists(':keepm')) + call assert_equal(1, exists(':keepma')) + call assert_equal(1, exists(':keepmar')) + call assert_equal(1, exists(':keepmark')) + call assert_equal(2, exists(':keepmarks')) + call assert_equal(2, exists(':keepalt')) + call assert_equal(2, exists(':keepjumps')) + call assert_equal(2, exists(':keeppatterns')) + set cpo-=* +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_codestyle.vim b/src/testdir/test_codestyle.vim index a455264..83f52ef 100644 --- a/src/testdir/test_codestyle.vim +++ b/src/testdir/test_codestyle.vim @@ -28,6 +28,13 @@ def Test_source_files() g:ignoreSwapExists = 'e' exe 'edit ' .. fname + # Some files are generated files and may contain space errors. + if fname =~ 'dlldata.c' + || fname =~ 'if_ole.h' + || fname =~ 'iid_ole.c' + continue + endif + PerformCheck(fname, ' \t', 'space before Tab', '') PerformCheck(fname, '\s$', 'trailing white space', '') @@ -68,7 +75,8 @@ def Test_test_files() && fname !~ 'test_listchars.vim' && fname !~ 'test_visual.vim' cursor(1, 1) - var lnum = search(fname =~ "test_regexp_latin" ? '[^á] \t' : ' \t') + var skip = 'getline(".") =~ "codestyle: ignore"' + var lnum = search(fname =~ "test_regexp_latin" ? '[^á] \t' : ' \t', 'W', 0, 0, skip) ReportError('testdir/' .. fname, lnum, 'space before Tab') endif @@ -155,4 +163,4 @@ def Test_help_files() enddef -" vim: shiftwidth=2 sts=2 expandtab +" vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_cpoptions.vim b/src/testdir/test_cpoptions.vim index 6ff8301..7bfbcd1 100644 --- a/src/testdir/test_cpoptions.vim +++ b/src/testdir/test_cpoptions.vim @@ -19,7 +19,7 @@ func Test_cpo_a() set cpo+=a read XfileCpoA call assert_equal('XfileCpoA', @#) - close! + bw! let &cpo = save_cpo endfunc @@ -39,7 +39,7 @@ func Test_cpo_A() set cpo+=A write XcpoAfile2 call assert_equal('XcpoAfile2', @#) - close! + bw! call delete('XcpoAfile2') let &cpo = save_cpo endfunc @@ -81,7 +81,7 @@ func Test_cpo_B() call assert_equal('abd ', getline(1)) call feedkeys(":imap <buffer> x\<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"imap <buffer> x\k', @:) - close! + bw! let &cpo = save_cpo endfunc @@ -96,7 +96,7 @@ func Test_cpo_c() set cpo-=c exe "normal gg/abab\<CR>" call assert_equal(5, searchcount().total) - close! + bw! let &cpo = save_cpo endfunc @@ -143,7 +143,7 @@ func Test_cpo_D() exe "norm! 1gg0f\<c-k>!!" call assert_equal(1, col('.')) set cpo-=D - close! + bw! let &cpo = save_cpo endfunc @@ -183,7 +183,7 @@ func Test_cpo_E() call assert_beeps('exe "normal v\<C-A>"') call assert_beeps('exe "normal v\<C-X>"') set cpo-=E - close! + bw! endfunc " Test for the 'f' flag in 'cpo' (read in an empty buffer sets the file name) @@ -213,7 +213,7 @@ func Test_cpo_F() set cpo+=F write XfileCpoF call assert_equal('XfileCpoF', @%) - close! + bw! call delete('XfileCpoF') let &cpo = save_cpo endfunc @@ -229,7 +229,7 @@ func Test_cpo_g() set cpo+=g edit call assert_equal(1, line('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -245,7 +245,7 @@ func Test_cpo_H() call setline(1, ' ') normal! Ia call assert_equal(' a ', getline(1)) - close! + bw! let &cpo = save_cpo endfunc @@ -264,7 +264,7 @@ func Test_cpo_I() %d exe "normal i one\<CR>\<Up>" call assert_equal('', getline(2)) - close! + bw! let &cpo = save_cpo endfunc @@ -295,7 +295,7 @@ func Test_cpo_J() normal ( call assert_equal(colnr, col('.')) endfor - close! + bw! let &cpo = save_cpo endfunc @@ -317,7 +317,7 @@ func Test_cpo_l() set cpo+=l exe 'normal gg/[\t]' .. "\<CR>" call assert_equal([4, 10], [col('.'), virtcol('.')]) - close! + bw! let &cpo = save_cpo endfunc @@ -338,7 +338,7 @@ func Test_cpo_L() call setline(1, 'abcdefghijklmnopqr') exe "normal 0gR\<Tab>" call assert_equal("\<Tab>ijklmnopqr", getline(1)) - close! + bw! let &cpo = save_cpo endfunc @@ -376,7 +376,7 @@ func Test_cpo_M() call cursor(2, 1) call assert_beeps('normal %') - close! + bw! let &cpo = save_cpo endfunc @@ -392,7 +392,7 @@ func Test_cpo_n() set cpo+=n redraw! call assert_equal('aaaa', Screenline(2)) - close! + bw! let &cpo = save_cpo endfunc @@ -409,7 +409,7 @@ func Test_cpo_o() exe "normal /one/+2\<CR>" normal n call assert_equal(5, line('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -424,7 +424,7 @@ func Test_cpo_O() set cpo+=O write call assert_equal(['one'], readfile('XfileCpoO')) - close! + bw! let &cpo = save_cpo endfunc @@ -462,7 +462,7 @@ func Test_cpo_q() set cpo+=q normal gg4J call assert_equal(4, col('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -483,7 +483,7 @@ func Test_cpo_r() let @/ = 'three' normal 2G. call assert_equal('abc three four', getline(2)) - close! + bw! let &cpo = save_cpo endfunc @@ -503,7 +503,7 @@ func Test_cpo_R() 3mark r %!sort call assert_equal(0, line("'r")) - close! + bw! let &cpo = save_cpo endfunc @@ -530,8 +530,8 @@ func Test_cpo_S() wincmd p call assert_equal(0, &autoindent) wincmd t - close! - close! + bw! + bw! let &cpo = save_cpo endfunc @@ -550,7 +550,7 @@ func Test_cpo_u() exe "normal iabc\<C-G>udef\<C-G>ughi" normal uu call assert_equal('abcdefghi', getline(1)) - close! + bw! let &cpo = save_cpo endfunc @@ -574,7 +574,7 @@ func Test_cpo_w() call assert_equal('hereZZZare some words', getline('.')) norm! 1gg2elcWYYY call assert_equal('hereZZZare someYYYwords', getline('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -611,7 +611,7 @@ func Test_cpo_X() normal ggRy normal 4. call assert_equal('yyyyxxxaaaaa', getline(1)) - close! + bw! let &cpo = save_cpo endfunc @@ -630,7 +630,7 @@ func Test_cpo_y() normal ggyy normal 2G. call assert_equal("two\n", @") - close! + bw! let &cpo = save_cpo endfunc @@ -647,7 +647,7 @@ func Test_cpo_Z() setlocal readonly write! call assert_equal(1, &readonly) - close! + bw! let &cpo = save_cpo endfunc @@ -700,7 +700,7 @@ func Test_cpo_percent() call assert_equal(15, col('.')) normal 22|% call assert_equal(27, col('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -716,7 +716,7 @@ func Test_cpo_minus() call assert_beeps('normal 10k') call assert_equal(3, line('.')) call assert_fails(10, 'E16:') - close! + bw! let &cpo = save_cpo endfunc @@ -732,7 +732,7 @@ func Test_cpo_plus() set cpo+=+ write X2 call assert_equal(0, &modified) - close! + bw! call delete('X1') call delete('X2') let &cpo = save_cpo @@ -749,7 +749,7 @@ func Test_cpo_star() set cpo+=* *a call assert_equal(1, x) - close! + bw! let &cpo = save_cpo endfunc @@ -770,7 +770,7 @@ func Test_cpo_gt() normal gg"Rye normal "Rye call assert_equal("\none\none", @r) - close! + bw! let &cpo = save_cpo endfunc @@ -803,7 +803,7 @@ func Test_cpo_semicolon() call assert_equal('bbb y', getline(4)) call assert_equal('ccc', getline(5)) call assert_equal('ddd yee y', getline(6)) - close! + bw! let &cpo = save_cpo endfunc @@ -828,7 +828,7 @@ func Test_cpo_hash() call assert_equal(['', 'one', 'two', 'three'], getline(1, '$')) normal gg2Ozero call assert_equal(['zero', '', 'one', 'two', 'three'], getline(1, '$')) - close! + bw! let &cpo = save_cpo endfunc @@ -858,7 +858,7 @@ func Test_cpo_backslash() set cpo+=\ exe 'normal gg/[ \-]' .. "\<CR>n" call assert_equal(2, col('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -880,7 +880,7 @@ func Test_cpo_brace() call assert_equal(2, line('.')) normal G{ call assert_equal(2, line('.')) - close! + bw! let &cpo = save_cpo endfunc @@ -908,8 +908,53 @@ func Test_cpo_dot() call delete('Xfoo') set cpo& - close! + bw! let &cpo = save_cpo endfunc +" Test for the 'z' flag in 'cpo' (make cw and dw work similar and avoid +" inconsistencies, see :h cpo-z) +func Test_cpo_z() + let save_cpo = &cpo + new + " Test 1: dw behaves differently from cw + call setline(1, ['foo bar baz', 'one two three']) + call cursor(1, 1) + " dw does not delete the whitespace after the word + norm! wcwanother + set cpo-=z + " dw deletes the whitespace after the word + call cursor(2, 1) + norm! wcwfour + call assert_equal(['foo another baz', 'one fourthree'], getline(1, '$')) + " Test 2: d{motion} becomes linewise :h d-special + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + set cpo+=z + " delete operation becomes linewise + call feedkeys("fbd/e\\zs\<cr>", 'tnx') + call assert_equal(['one ', 'zwei'], getline(1, '$')) + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd2w", 'tnx') + call assert_equal(['one ', 'zwei'], getline(1, '$')) + + " delete operation does not become line wise + set cpo-=z + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd/e\\zs\<cr>", 'tnx') + call assert_equal(['one ', ' ', 'zwei'], getline(1, '$')) " codestyle: ignore + %d + call setline(1, ['one ', ' bar', ' e ', 'zwei']) + call cursor(2, 1) + call feedkeys("fbd2w", 'tnx') + call assert_equal(['one ', ' ', 'zwei'], getline(1, '$')) + + " clean up + bw! + let &cpo = save_cpo +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_crash.vim b/src/testdir/test_crash.vim index fd786e5..b334876 100644 --- a/src/testdir/test_crash.vim +++ b/src/testdir/test_crash.vim @@ -150,6 +150,13 @@ func Test_crash1_2() \ ' ; echo "crash 4: [OK]" >> '.. result .. "\<cr>") call TermWait(buf, 150) + let file = 'crash/reverse_text_overflow' + let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'" + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args .. + \ ' ; echo "crash 5: [OK]" >> '.. result .. "\<cr>") + call TermWait(buf, 150) + " clean up exe buf .. "bw!" exe "sp " .. result @@ -158,6 +165,7 @@ func Test_crash1_2() \ 'crash 2: [OK]', \ 'crash 3: [OK]', \ 'crash 4: [OK]', + \ 'crash 5: [OK]', \ ] call assert_equal(expected, getline(1, '$')) @@ -190,6 +198,31 @@ func Test_crash1_3() call term_sendkeys(buf, args) call TermWait(buf, 150) + let file = 'crash/double_free' + let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>" + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args) + call TermWait(buf, 50) + + let file = 'crash/dialog_changed_uaf' + let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>" + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args) + call TermWait(buf, 150) + + let file = 'crash/nullpointer' + let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>" + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args) + call TermWait(buf, 50) + + let file = 'crash/heap_overflow3' + let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'" + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args) + call TermWait(buf, 150) + + " clean up exe buf .. "bw!" bw! @@ -204,4 +237,11 @@ func Test_crash2() exe buf .. "bw!" endfunc +func TearDown() + " That file is created at Test_crash1_3() by dialog_changed_uaf + " but cleaning up in that test doesn't remove it. Let's try again at + " the end of this test script + call delete('Untitled') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index a346399..1b17108 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -2,6 +2,7 @@ source view_util.vim source shared.vim +import './vim9.vim' as v9 function s:foo() abort try @@ -126,7 +127,31 @@ func Test_for_invalid() call assert_fails("for x in 99", 'E1098:') call assert_fails("for x in function('winnr')", 'E1098:') call assert_fails("for x in {'a': 9}", 'E1098:') - call assert_fails("for v:maxcol in range(1)", 'E46:') + + let lines =<< trim END + for v:maxcol in range(5) + endfor + END + + let save_v_maxcol = v:maxcol + call v9.CheckLegacyAndVim9Failure(lines, 'E46:') + call assert_equal(save_v_maxcol, v:maxcol) + + let lines =<< trim END + for g:constvar in range(5) + endfor + END + + const g:constvar = 10 + call v9.CheckLegacyAndVim9Failure(lines, 'E741:') + call assert_equal(10, g:constvar) + unlet g:constvar + + let g:constvar = 10 + lockvar 0 g:constvar + call v9.CheckLegacyAndVim9Failure(lines, 'E1122:') + call assert_equal(10, g:constvar) + unlet g:constvar if 0 /1/5/2/s/\n diff --git a/src/testdir/test_ex_mode.vim b/src/testdir/test_ex_mode.vim index 59c28f3..aa94935 100644 --- a/src/testdir/test_ex_mode.vim +++ b/src/testdir/test_ex_mode.vim @@ -68,7 +68,7 @@ func Test_Ex_substitute() CheckRunVimInTerminal let buf = RunVimInTerminal('', {'rows': 6}) - call term_sendkeys(buf, ":call setline(1, ['foo foo', 'foo foo', 'foo foo'])\<CR>") + call term_sendkeys(buf, ":call setline(1, repeat(['foo foo'], 4))\<CR>") call term_sendkeys(buf, ":set number\<CR>") call term_sendkeys(buf, "gQ") call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000) @@ -90,8 +90,14 @@ func Test_Ex_substitute() " Pressing enter in ex mode should print the current line call term_sendkeys(buf, "\<CR>") - call WaitForAssert({-> assert_match(' 3 foo foo', - \ term_getline(buf, 5))}, 1000) + call WaitForAssert({-> assert_match(' 3 foo foo', term_getline(buf, 5))}, 1000) + call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000) + + " The printed line should overwrite the colon + call term_sendkeys(buf, "\<CR>") + call WaitForAssert({-> assert_match(' 3 foo foo', term_getline(buf, 4))}, 1000) + call WaitForAssert({-> assert_match(' 4 foo foo', term_getline(buf, 5))}, 1000) + call WaitForAssert({-> assert_match(':', term_getline(buf, 6))}, 1000) call term_sendkeys(buf, ":vi\<CR>") call WaitForAssert({-> assert_match('foo bar', term_getline(buf, 1))}, 1000) @@ -165,6 +171,37 @@ func Test_Ex_global() call assert_equal('bax', getline(3)) call assert_equal('bay', getline(5)) bwipe! + + new + call setline(1, ['foo', 'bar']) + call feedkeys("Qg/./i\\\na\\\n.\\\na\\\nb\\\n.", "xt") + call assert_equal(['a', 'b', 'foo', 'a', 'b', 'bar'], getline(1, '$')) + bwipe! +endfunc + +func Test_Ex_shell() + CheckUnix + + new + call feedkeys("Qr !echo foo\\\necho bar\n", 'xt') + call assert_equal(['', 'foo', 'bar'], getline(1, '$')) + bwipe! + + new + call feedkeys("Qr !echo foo\\\\\nbar\n", 'xt') + call assert_equal(['', 'foobar'], getline(1, '$')) + bwipe! + + new + call feedkeys("Qr !echo foo\\ \\\necho bar\n", 'xt') + call assert_equal(['', 'foo ', 'bar'], getline(1, '$')) + bwipe! + + new + call setline(1, ['bar', 'baz']) + call feedkeys("Qg/./!echo \\\ns/b/c/", "xt") + call assert_equal(['car', 'caz'], getline(1, '$')) + bwipe! endfunc " Test for pressing Ctrl-C in :append inside a loop in Ex mode @@ -204,18 +241,11 @@ func Test_Ex_append() call feedkeys("Qappend!\npqr\nxyz\n.\nvisual\n", 'xt') call assert_equal(["\t abc", "\t pqr", "\t xyz"], getline(1, '$')) close! -endfunc -" In Ex-mode, backslashes at the end of a command should be halved. -func Test_Ex_echo_backslash() - " This test works only when the language is English - CheckEnglish - let bsl = '\\\\' - let bsl2 = '\\\' - call assert_fails('call feedkeys("Qecho " .. bsl .. "\nvisual\n", "xt")', - \ 'E15: Invalid expression: "\\"') - call assert_fails('call feedkeys("Qecho " .. bsl2 .. "\nm\nvisual\n", "xt")', - \ "E15: Invalid expression: \"\\\nm\"") + new + call feedkeys("Qappend\na\\\n.", 'xt') + call assert_equal(['a\'], getline(1, '$')) + close! endfunc func Test_ex_mode_errors() @@ -314,5 +344,47 @@ func Test_empty_command_visual_mode() call delete('guidialogfile') endfunc +" Test using backslash in ex-mode +func Test_backslash_multiline() + new + call setline(1, 'enum') + call feedkeys('Qg/enum/i\
\
.', "xt") + call assert_equal(["", "enum"], getline(1, 2)) +endfunc + +" Test using backslash in ex-mode after patch 9.1.0535 +func Test_backslash_multiline2() + new + call feedkeys('Qa
X \\
Y
.', "xt") + call assert_equal(['X \\', "Y"], getline(1, 2)) +endfunc + +" Testing implicit print command +func Test_implicit_print() + new + call setline(1, ['one', 'two', 'three']) + call feedkeys('Q:let a=execute(":1,2")', 'xt') + call feedkeys('Q:let b=execute(":3")', 'xt') + call assert_equal('one two', a->split('\n')->join(' ')) + call assert_equal('three', b->split('\n')->join(' ')) + bw! +endfunc + +" Test inserting text after the trailing bar +func Test_insert_after_trailing_bar() + new + call feedkeys("Qi|\nfoo\n.\na|bar\nbar\n.\nc|baz\n.", "xt") + call assert_equal(['', 'foo', 'bar', 'baz'], getline(1, '$')) + bwipe! +endfunc + +" Test global insert of a newline without terminating period +func Test_global_insert_newline() + new + call setline(1, ['foo']) + call feedkeys("Qg/foo/i\\\n", "xt") + call assert_equal(['', 'foo'], getline(1, '$')) + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim index 221ceb0..3b7e489 100644 --- a/src/testdir/test_excmd.vim +++ b/src/testdir/test_excmd.vim @@ -703,6 +703,8 @@ func Test_address_line_overflow() call setline(1, range(100)) call assert_fails('|.44444444444444444444444', 'E1247:') call assert_fails('|.9223372036854775806', 'E1247:') + call assert_fails('.44444444444444444444444d', 'E1247:') + call assert_equal(range(100)->map('string(v:val)'), getline(1, '$')) $ yank 77777777777777777777 diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index d0a078f..1e6c39e 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -95,6 +95,7 @@ def s:GetFilenameChecks(): dict<list<string>> aml: ['file.aml'], ampl: ['file.run'], ant: ['build.xml'], + antlr4: ['parser.g4'], apache: ['.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config', '/etc/apache2/conf.file/file', '/etc/apache2/file.conf', '/etc/apache2/file.conf-file', '/etc/apache2/mods-file/file', '/etc/apache2/sites-file/file', '/etc/apache2/sites-file/file.com', '/etc/httpd/conf.d/file.conf', '/etc/httpd/conf.d/file.conf-file', 'access.conf', 'access.conf-file', 'any/etc/apache2/conf.file/file', 'any/etc/apache2/file.conf', 'any/etc/apache2/file.conf-file', 'any/etc/apache2/mods-file/file', 'any/etc/apache2/sites-file/file', 'any/etc/apache2/sites-file/file.com', 'any/etc/httpd/conf.d/file.conf', 'any/etc/httpd/conf.d/file.conf-file', 'any/etc/httpd/file.conf', 'apache.conf', 'apache.conf-file', 'apache2.conf', 'apache2.conf-file', 'httpd.conf', 'httpd.conf-file', 'srm.conf', 'srm.conf-file', '/etc/httpd/mods-some/file', '/etc/httpd/sites-some/file', '/etc/httpd/conf.file/conf'], apachestyle: ['/etc/proftpd/file.config,/etc/proftpd/conf.file/file', '/etc/proftpd/conf.file/file', '/etc/proftpd/file.conf', '/etc/proftpd/file.conf-file', 'any/etc/proftpd/conf.file/file', 'any/etc/proftpd/file.conf', 'any/etc/proftpd/file.conf-file', 'proftpd.conf', 'proftpd.conf-file'], applescript: ['file.scpt'], @@ -106,6 +107,7 @@ def s:GetFilenameChecks(): dict<list<string>> asn: ['file.asn', 'file.asn1'], asterisk: ['asterisk/file.conf', 'asterisk/file.conf-file', 'some-asterisk/file.conf', 'some-asterisk/file.conf-file'], astro: ['file.astro'], + asy: ['file.asy'], atlas: ['file.atl', 'file.as'], authzed: ['schema.zed'], autohotkey: ['file.ahk'], @@ -121,7 +123,7 @@ def s:GetFilenameChecks(): dict<list<string>> beancount: ['file.beancount'], bib: ['file.bib'], bicep: ['file.bicep', 'file.bicepparam'], - bindzone: ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'], + bindzone: ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file', 'foobar.zone'], bitbake: ['file.bb', 'file.bbappend', 'file.bbclass', 'build/conf/local.conf', 'meta/conf/layer.conf', 'build/conf/bbappend.conf', 'meta-layer/conf/distro/foo.conf'], blade: ['file.blade.php'], blank: ['file.bl'], @@ -142,6 +144,7 @@ def s:GetFilenameChecks(): dict<list<string>> cdl: ['file.cdl'], cdrdaoconf: ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao', 'any/etc/cdrdao.conf', 'any/etc/default/cdrdao', 'any/etc/defaults/cdrdao'], cdrtoc: ['file.toc'], + cedar: ['file.cedar'], cf: ['file.cfm', 'file.cfi', 'file.cfc'], cfengine: ['cfengine.conf'], cfg: ['file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], @@ -160,7 +163,7 @@ def s:GetFilenameChecks(): dict<list<string>> cmakecache: ['CMakeCache.txt'], cmod: ['file.cmod'], cmusrc: ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme', '/.cmus/autosave', '/.cmus/command-history', '/.cmus/file.theme', '/.cmus/rc', '/cmus/file.theme', '/cmus/rc'], - cobol: ['file.cbl', 'file.cob', 'file.lib'], + cobol: ['file.cbl', 'file.cob'], coco: ['file.atg'], conaryrecipe: ['file.recipe'], conf: ['auto.master', 'file.conf', 'texdoc.cnf', '.x11vncrc', '.chktexrc', '.ripgreprc', 'ripgreprc', 'file.ctags', '.mbsyncrc'], @@ -222,11 +225,11 @@ def s:GetFilenameChecks(): dict<list<string>> 'psprint.conf', 'sofficerc', 'any/.config/lxqt/globalkeyshortcuts.conf', 'any/.config/screengrab/screengrab.conf', 'any/.local/share/flatpak/repo/config', '.notmuch-config'], dot: ['file.dot', 'file.gv'], - dracula: ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], + dracula: ['file.drac', 'file.drc', 'file.lvs', 'file.lpe', 'drac.file'], dtd: ['file.dtd'], dtrace: ['/usr/lib/dtrace/io.d'], dts: ['file.dts', 'file.dtsi', 'file.dtso', 'file.its', 'file.keymap'], - dune: ['jbuild', 'dune', 'dune-project', 'dune-workspace'], + dune: ['jbuild', 'dune', 'dune-project', 'dune-workspace', 'dune-file'], dylan: ['file.dylan'], dylanintr: ['file.intr'], dylanlid: ['file.lid'], @@ -256,6 +259,7 @@ def s:GetFilenameChecks(): dict<list<string>> factor: ['file.factor'], falcon: ['file.fal'], fan: ['file.fan', 'file.fwt'], + faust: ['file.dsp', 'file.lib'], fennel: ['file.fnl'], fetchmail: ['.fetchmailrc'], fgl: ['file.4gl', 'file.4gh', 'file.m4gl'], @@ -285,17 +289,18 @@ def s:GetFilenameChecks(): dict<list<string>> gitattributes: ['file.git/info/attributes', '.gitattributes', '/.config/git/attributes', '/etc/gitattributes', '/usr/local/etc/gitattributes', 'some.git/info/attributes'] + WhenConfigHome('$XDG_CONFIG_HOME/git/attributes'), gitcommit: ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'], gitconfig: ['file.git/config', 'file.git/config.worktree', 'file.git/worktrees/x/config.worktree', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/usr/local/etc/gitconfig', '/etc/gitconfig.d/file', 'any/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'] + WhenConfigHome('$XDG_CONFIG_HOME/git/config'), - gitignore: ['file.git/info/exclude', '.gitignore', '/.config/git/ignore', 'some.git/info/exclude'] + WhenConfigHome('$XDG_CONFIG_HOME/git/ignore'), + gitignore: ['file.git/info/exclude', '.gitignore', '/.config/git/ignore', 'some.git/info/exclude'] + WhenConfigHome('$XDG_CONFIG_HOME/git/ignore') + ['.prettierignore'], gitolite: ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'], gitrebase: ['git-rebase-todo'], gitsendemail: ['.gitsendemail.msg.xxxxxx'], gkrellmrc: ['gkrellmrc', 'gkrellmrc_x'], gleam: ['file.gleam'], - glsl: ['file.glsl'], + glsl: ['file.glsl', 'file.vert', 'file.tesc', 'file.tese', 'file.geom', 'file.frag', 'file.comp', 'file.rgen', 'file.rmiss', 'file.rchit', 'file.rahit', 'file.rint', 'file.rcall'], gn: ['file.gn', 'file.gni'], gnash: ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], gnuplot: ['file.gpi', '.gnuplot', 'file.gnuplot', '.gnuplot_history'], go: ['file.go'], + goaccess: ['goaccess.conf'], gomod: ['go.mod'], gosum: ['go.sum', 'go.work.sum'], gowork: ['go.work'], @@ -332,6 +337,7 @@ def s:GetFilenameChecks(): dict<list<string>> hoon: ['file.hoon'], hostconf: ['/etc/host.conf', 'any/etc/host.conf'], hostsaccess: ['/etc/hosts.allow', '/etc/hosts.deny', 'any/etc/hosts.allow', 'any/etc/hosts.deny'], + # file.component.html should be HTML, not Angular, see #13594 html: ['file.html', 'file.htm', 'file.cshtml', 'file.component.html'], htmlm4: ['file.html.m4'], httest: ['file.htt', 'file.htb'], @@ -364,7 +370,9 @@ def s:GetFilenameChecks(): dict<list<string>> jq: ['file.jq'], jovial: ['file.jov', 'file.j73', 'file.jovial'], jproperties: ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'], - json: ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', 'file.jupyterlab-settings', '.prettierrc', '.firebaserc', '.stylelintrc', '.lintstagedrc', 'file.slnf', 'file.sublime-project', 'file.sublime-settings', 'file.sublime-workspace', 'file.bd', 'file.bda', 'file.xci', 'flake.lock'], + json: ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', 'file.jupyterlab-settings', + '.prettierrc', '.firebaserc', '.stylelintrc', '.lintstagedrc', 'file.slnf', 'file.sublime-project', 'file.sublime-settings', 'file.sublime-workspace', + 'file.bd', 'file.bda', 'file.xci', 'flake.lock', 'pack.mcmeta', 'deno.lock'], json5: ['file.json5'], jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.jscsrc', '.vsconfig', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], jsonl: ['file.jsonl'], @@ -383,6 +391,7 @@ def s:GetFilenameChecks(): dict<list<string>> lace: ['file.ace', 'file.ACE'], latte: ['file.latte', 'file.lte'], ld: ['file.ld', 'any/usr/lib/aarch64-xilinx-linux/ldscripts/aarch64elf32b.x'], + ldapconf: ['ldap.conf', '.ldaprc', 'ldaprc'], ldif: ['file.ldif'], lean: ['file.lean'], ledger: ['file.ldg', 'file.ledger', 'file.journal'], @@ -420,18 +429,19 @@ def s:GetFilenameChecks(): dict<list<string>> mail: ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml', 'reportbug-file'], mailaliases: ['/etc/mail/aliases', '/etc/aliases', 'any/etc/aliases', 'any/etc/mail/aliases'], mailcap: ['.mailcap', 'mailcap'], - make: ['file.mk', 'file.mak', 'file.dsp', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile', 'Kbuild'], + make: ['file.mk', 'file.mak', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile', 'Kbuild'], mallard: ['file.page'], man: ['file.man'], manconf: ['/etc/man.conf', 'man.config', 'any/etc/man.conf'], map: ['file.map'], maple: ['file.mv', 'file.mpl', 'file.mws'], markdown: ['file.markdown', 'file.mdown', 'file.mkd', 'file.mkdn', 'file.mdwn', 'file.md'], - mason: ['file.mason', 'file.mhtml', 'file.comp'], + mason: ['file.mason', 'file.mhtml'], master: ['file.mas', 'file.master'], matlab: ['file.m'], maxima: ['file.demo', 'file.dmt', 'file.dm1', 'file.dm2', 'file.dm3', 'file.wxm', 'maxima-init.mac'], + mediawiki: ['file.mw', 'file.wiki'], mel: ['file.mel'], mermaid: ['file.mmd', 'file.mmdc', 'file.mermaid'], meson: ['meson.build', 'meson.options', 'meson_options.txt'], @@ -466,7 +476,7 @@ def s:GetFilenameChecks(): dict<list<string>> mgp: ['file.mgp'], mib: ['file.mib', 'file.my'], mix: ['file.mix', 'file.mixal'], - mma: ['file.nb'], + mma: ['file.nb', 'file.wl'], mmp: ['file.mmp'], modconf: ['/etc/modules.conf', '/etc/modules', '/etc/conf.modules', '/etc/modprobe.file', 'any/etc/conf.modules', 'any/etc/modprobe.file', 'any/etc/modules', 'any/etc/modules.conf'], modula3: ['file.m3', 'file.mg', 'file.i3', 'file.ig', 'file.lm3'], @@ -522,7 +532,7 @@ def s:GetFilenameChecks(): dict<list<string>> odin: ['file.odin'], omnimark: ['file.xom', 'file.xin'], ondir: ['.ondirrc'], - opam: ['opam', 'file.opam', 'file.opam.template'], + opam: ['opam', 'file.opam', 'file.opam.template', 'opam.locked', 'file.opam.locked'], openroad: ['file.or'], openscad: ['file.scad'], openvpn: ['file.ovpn', '/etc/openvpn/client/client.conf', '/usr/share/openvpn/examples/server.conf'], @@ -645,7 +655,8 @@ def s:GetFilenameChecks(): dict<list<string>> sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '.bash_history', '.bash-history', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats', '.ash_history', 'any/etc/neofetch/config.conf', '.xprofile', - 'user-dirs.defaults', 'user-dirs.dirs', 'makepkg.conf', '.makepkg.conf', 'file.mdd', 'file.cygport'], + 'user-dirs.defaults', 'user-dirs.dirs', 'makepkg.conf', '.makepkg.conf', 'file.mdd', 'file.cygport', '.env', '.envrc', 'devscripts.conf', + '.devscripts'], sieve: ['file.siv', 'file.sieve'], sil: ['file.sil'], simula: ['file.sim'], @@ -759,7 +770,7 @@ def s:GetFilenameChecks(): dict<list<string>> teraterm: ['file.ttl'], terminfo: ['file.ti'], 'terraform-vars': ['file.tfvars'], - tex: ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl', 'any/.texlive/texmf-config/tex/latex/file/file.cfg', 'file.pgf', 'file.nlo', 'file.nls', 'file.thm', 'file.eps_tex', 'file.pygtex', 'file.pygstyle', 'file.clo', 'file.aux', 'file.brf', 'file.ind', 'file.lof', 'file.loe', 'file.nav', 'file.vrb', 'file.ins', 'file.tikz', 'file.bbx', 'file.cbx', 'file.beamer'], + tex: ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl', 'any/.texlive/texmf-config/tex/latex/file/file.cfg', 'file.pgf', 'file.nlo', 'file.nls', 'file.thm', 'file.eps_tex', 'file.pygtex', 'file.pygstyle', 'file.clo', 'file.aux', 'file.brf', 'file.ind', 'file.lof', 'file.loe', 'file.nav', 'file.vrb', 'file.ins', 'file.tikz', 'file.bbx', 'file.cbx', 'file.beamer', 'file.pdf_tex'], texinfo: ['file.texinfo', 'file.texi', 'file.txi'], texmf: ['texmf.cnf'], text: ['file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'], @@ -854,6 +865,8 @@ def s:GetFilenameChecks(): dict<list<string>> z8a: ['file.z8a'], zathurarc: ['zathurarc'], zig: ['file.zig', 'build.zig.zon'], + ziggy: ['file.ziggy'], + ziggy_schema: ['file.ziggy-schema'], zimbu: ['file.zu'], zimbutempl: ['file.zut'], zserio: ['file.zs'], @@ -1043,7 +1056,8 @@ func Test_emptybuf_ftdetect() call assert_equal('', &filetype) filetype detect call assert_equal('sh', &filetype) - close! + " close the swapfile + bw! endfunc " Test for ':filetype indent on' and ':filetype indent off' commands @@ -1567,6 +1581,73 @@ func Test_hook_file() filetype off endfunc +func Test_html_file() + filetype on + + " HTML Angular + let content = ['@for (item of items; track item.name) {', ' <li> {{ item.name }}</li>', '} @empty {', ' <li> There are no items.</li>', '}'] + call writefile(content, 'Xfile.html', 'D') + split Xfile.html + call assert_equal('htmlangular', &filetype) + bwipe! + + " Django Template + let content = ['{% if foobar %}', + \ ' <ul>', + \ ' {% for question in list %}', + \ ' <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>', + \ ' {% endfor %}', + \ ' </ul>', + \ '{% else %}', + \ ' <p>No polls are available.</p>', + \ '{% endif %}'] + call writefile(content, 'Xfile.html', 'D') + split Xfile.html + call assert_equal('htmldjango', &filetype) + bwipe! + + " Super html layout + let content = ['<extend template="base.shtml">', + \ '<title id="title" var="$page.title"></title>', + \ '<head id="head"></head>', + \ '<div id="content">', + \ '</div>'] + call writefile(content, 'Xfile.shtml', 'D') + split Xfile.shtml + call assert_equal('superhtml', &filetype) + bwipe! + + " Super html template + let content = ['<!DOCTYPE html>', + \ '<html>', + \ ' <head id="head">', + \ ' <title id="title">', + \ ' <super>', + \ ' suffix', + \ ' </title>', + \ ' <super>', + \ ' </head>', + \ ' <body>', + \ ' <div id="content">', + \ ' <super>', + \ ' </div>', + \ ' </body>', + \ '</html>'] + call writefile(content, 'Xfile.shtml', 'D') + split Xfile.shtml + call assert_equal('superhtml', &filetype) + bwipe! + + " regular HTML + let content = ['<!DOCTYPE html>', '<html>', ' <head>Foobar</head>', ' <body>Content', ' </body>', '</html>'] + call writefile(content, 'Xfile.html', 'D') + split Xfile.html + call assert_equal('html', &filetype) + bwipe! + + filetype off +endfunc + func Test_m_file() filetype on @@ -2401,6 +2482,32 @@ func Test_typ_file() filetype off endfunc +func Test_dsp_file() + filetype on + + " Microsoft Developer Studio Project file + + call writefile(['# Microsoft Developer Studio Project File'], 'Xfile.dsp', 'D') + split Xfile.dsp + call assert_equal('make', &filetype) + bwipe! + + let g:filetype_dsp = 'make' + split test.dsp + call assert_equal('make', &filetype) + bwipe! + unlet g:filetype_dsp + + " Faust + + call writefile(['this is a fallback'], 'Xfile.dsp') + split Xfile.dsp + call assert_equal('faust', &filetype) + bwipe! + + filetype off +endfunc + func Test_vba_file() filetype on @@ -2509,4 +2616,86 @@ func Test_uci_file() filetype off endfunc +func Test_pro_file() + filetype on + + "Prolog + call writefile([':-module(test/1,'], 'Xfile.pro', 'D') + split Xfile.pro + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['% comment'], 'Xfile.pro', 'D') + split Xfile.pro + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['/* multiline comment'], 'Xfile.pro', 'D') + split Xfile.pro + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['rule(test, 1.7).'], 'Xfile.pro', 'D') + split Xfile.pro + call assert_equal('prolog', &filetype) + bwipe! + + " IDL + call writefile(['x = findgen(100)/10'], 'Xfile.pro', 'D') + split Xfile.pro + call assert_equal('idlang', &filetype) + + filetype off +endfunc + + +func Test_pl_file() + filetype on + + "Prolog + call writefile([':-module(test/1,'], 'Xfile.pl', 'D') + split Xfile.pl + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['% comment'], 'Xfile.pl', 'D') + split Xfile.pl + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['/* multiline comment'], 'Xfile.pl', 'D') + split Xfile.pl + call assert_equal('prolog', &filetype) + bwipe! + + call writefile(['rule(test, 1.7).'], 'Xfile.pl', 'D') + split Xfile.pl + call assert_equal('prolog', &filetype) + bwipe! + + " Perl + call writefile(['%data = (1, 2, 3);'], 'Xfile.pl', 'D') + split Xfile.pl + call assert_equal('perl', &filetype) + + filetype off +endfunc + +func Test_make_file() + filetype on + + " Microsoft Makefile + call writefile(['# Makefile for Windows', '!if "$(VIMDLL)" == "yes"'], 'XMakefile.mak', 'D') + split XMakefile.mak + call assert_equal(1, get(b:, 'make_microsoft', 0)) + bwipe! + + call writefile(['# get the list of tests', 'include testdir/Make_all.mak'], 'XMakefile.mak', 'D') + split XMakefile.mak + call assert_equal(0, get(b:, 'make_microsoft', 0)) + bwipe! + + filetype off +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_findfile.vim b/src/testdir/test_findfile.vim index 20d5096..a5e18b9 100644 --- a/src/testdir/test_findfile.vim +++ b/src/testdir/test_findfile.vim @@ -98,14 +98,48 @@ func Test_findfile() " Test upwards search with stop-directory. cd Xdir2 + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3/', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';../', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';..', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/', -1) call assert_equal(1, len(l)) call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';../../', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';../..', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) let l = findfile('bar', ';' . save_dir . '/Xfinddir1/', -1) call assert_equal(2, len(l)) call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) call assert_match('.*/Xfinddir1/bar', l[1]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1', -1) + call assert_equal(2, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) + let l = findfile('bar', ';../../../', -1) + call assert_equal(2, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) + let l = findfile('bar', ';../../..', -1) + call assert_equal(2, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) " Test combined downwards and upwards search from Xdir2/. cd ../.. @@ -133,6 +167,7 @@ func Test_finddir() let save_shellslash = &shellslash let save_dir = getcwd() set path=,, + set shellslash call CreateFiles() cd Xfinddir1 diff --git a/src/testdir/test_fnamemodify.vim b/src/testdir/test_fnamemodify.vim index c19f464..4e61343 100644 --- a/src/testdir/test_fnamemodify.vim +++ b/src/testdir/test_fnamemodify.vim @@ -14,6 +14,8 @@ func Test_fnamemodify() call assert_equal($HOME .. "/foo" , fnamemodify('~/foo', ':p')) call assert_equal(fnamemodify('.', ':p:h:h:h') .. '/', fnamemodify($HOME .. '/../', ':p')) call assert_equal(fnamemodify('.', ':p:h:h:h') .. '/', fnamemodify($HOME .. '/..', ':p')) + call assert_equal(fnamemodify('.', ':p:h:h') .. '/', fnamemodify('../', ':p')) + call assert_equal(fnamemodify('.', ':p:h:h') .. '/', fnamemodify('..', ':p')) call assert_equal('test.out', fnamemodify('test.out', ':.')) call assert_equal('a', fnamemodify('../testdir/a', ':.')) call assert_equal('~/testdir/test.out', fnamemodify('test.out', ':~')) diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim index dedc4a2..17487a5 100644 --- a/src/testdir/test_fold.vim +++ b/src/testdir/test_fold.vim @@ -1914,4 +1914,39 @@ func Test_foldexpr_end_fold() bwipe! endfunc +" Test moving cursor down to or beyond start of folded end of buffer. +func Test_cursor_down_fold_eob() + call setline(1, range(1, 4)) + norm Gzf2kj + call assert_equal(2, line('.')) + norm zojzc + call assert_equal(3, line('.')) + norm j + call assert_equal(3, line('.')) + norm k2j + call assert_equal(4, line('.')) + bwipe! +endfunc + +" issue: #15455 +func Test_cursor_fold_marker_undo() + new + call setline(1, ['{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}']) + let &ul=&ul + setl foldmethod=marker + call cursor(2, 1) + norm! zo1vjdu + call assert_equal(1, foldlevel('.')) + bwipe! + new + call setline(1, ['', '{{{', '', 'This is a Line', '', 'This is a Line', '', '}}}']) + let &ul=&ul + setl foldmethod=marker + call cursor(3, 1) + norm! zo + norm! vjdu + call assert_equal(1, foldlevel('.')) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index acdb954..1021d05 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -923,6 +923,10 @@ func Test_mode() call feedkeys("gQ\<Insert>\<F2>vi\<CR>", 'xt') call assert_equal("c-cvr", g:current_modes) + " Commandline mode in Visual mode should return "c-c", never "v-v". + call feedkeys("v\<Cmd>call input('')\<CR>\<F2>\<CR>\<Esc>", 'xt') + call assert_equal("c-c", g:current_modes) + " Executing commands in Vim Ex mode should return "cv", never "cvr", " as Cmdline editing has already ended. call feedkeys("gQcall Save_mode()\<CR>vi\<CR>", 'xt') @@ -3822,6 +3826,29 @@ func Test_glob2() endif endfunc +func Test_glob_symlinks() + call writefile([], 'Xglob1') + + if has("win32") + silent !mklink XglobBad DoesNotExist + if v:shell_error + throw 'Skipped: cannot create symlinks' + endif + silent !mklink XglobOk Xglob1 + else + silent !ln -s DoesNotExist XglobBad + silent !ln -s Xglob1 XglobOk + endif + + " The broken symlink is excluded when alllinks is false. + call assert_equal(['Xglob1', 'XglobBad', 'XglobOk'], sort(glob('Xglob*', 0, 1, 1))) + call assert_equal(['Xglob1', 'XglobOk'], sort(glob('Xglob*', 0, 1, 0))) + + call delete('Xglob1') + call delete('XglobBad') + call delete('XglobOk') +endfunc + " Test for browse() func Test_browse() CheckFeature browse @@ -3842,11 +3869,6 @@ func Test_default_arg_value() call assert_equal('msg', HasDefault()) endfunc -" Test for gettext() -func Test_gettext() - call assert_fails('call gettext(1)', 'E1174:') -endfunc - func Test_builtin_check() call assert_fails('let g:["trim"] = {x -> " " .. x}', 'E704:') call assert_fails('let g:.trim = {x -> " " .. x}', 'E704:') diff --git a/src/testdir/test_gettext.vim b/src/testdir/test_gettext.vim new file mode 100644 index 0000000..a990121 --- /dev/null +++ b/src/testdir/test_gettext.vim @@ -0,0 +1,18 @@ +source check.vim + +CheckFeature gettext + +" Test for gettext() +func Test_gettext() + call assert_fails('call bindtextdomain("test")', 'E119:') + call assert_fails('call bindtextdomain("vim", "test")', 'E475:') + + call assert_fails('call gettext(1)', 'E1174:') + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx")) + + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx", "vim")) + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx", "__PACKAGE__")) + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_gettext_cp1251.vim b/src/testdir/test_gettext_cp1251.vim new file mode 100644 index 0000000..69d2bbf --- /dev/null +++ b/src/testdir/test_gettext_cp1251.vim @@ -0,0 +1,35 @@ +source check.vim +" This fail on CI MacOS 14 because bindtextdomain() is not available there +" (missing library?) +CheckNotMac +CheckFeature gettext + +" Test for gettext() +func Test_gettext() + set encoding=cp1251 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + + try + call assert_true(bindtextdomain("__PACKAGE__", getcwd())) + + try + language messages ru_RU + call assert_equal('ÎØÈÁÊÀ: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to ru (missing?)" + endtry + + try + language messages en_GB.UTF-8 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to en (missing?)" + endtry + + catch /^Vim\%((\a\+)\)\=:E342:/ + throw "Skipped: out of memory executing bindtextdomain()" + endtry + set encoding& +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_gettext_make.vim b/src/testdir/test_gettext_make.vim new file mode 100644 index 0000000..1242fa4 --- /dev/null +++ b/src/testdir/test_gettext_make.vim @@ -0,0 +1,72 @@ +source check.vim +CheckNotMac +CheckFeature gettext + +" Test for package translation Makefile +func Test_gettext_makefile() + cd ../po + if has('win32') + if getenv('GETTEXT_PATH') == v:null + throw 'Skipped: %GETTEXT_PATH% is not set.' + endif + call system('nmake.exe -f Make_mvc.mak "VIMPROG=' .. getenv('VIMPROG') .. + \ '" "GETTEXT_PATH=' .. getenv('GETTEXT_PATH') .. + \ '" PLUGPACKAGE=test_gettext + \ "PO_PLUG_INPUTLIST=..\testdir\test_gettext_makefile_in1.vim + \ ..\testdir\test_gettext_makefile_in2.vim + \ ..\testdir\test_gettext_makefile_in3.vim + \ ..\testdir\test_gettext_makefile_in4.vim" test_gettext.pot') + else +" Will it work on macOS? + call system("make -f Makefile PLUGPACKAGE=test_gettext + \ PO_PLUG_INPUTLIST=\"../testdir/test_gettext_makefile_in1.vim + \ ../testdir/test_gettext_makefile_in2.vim + \ ../testdir/test_gettext_makefile_in3.vim + \ ../testdir/test_gettext_makefile_in4.vim\" test_gettext.pot") + endif + if v:shell_error != 0 + throw 'Fail to create test_gettext.pot. Error code: ' .. v:shell_error + endif + let expected =<< trim END + # SOME DESCRIPTIVE TITLE. + # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER + # This file is distributed under the same license as the test_gettext package. + # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. + # + #, fuzzy + msgid "" + msgstr "" + "Project-Id-Version: test_gettext\n" + "Report-Msgid-Bugs-To: \n" + "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" + "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" + "Language-Team: LANGUAGE <LL@li.org>\n" + "Language: \n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=CHARSET\n" + "Content-Transfer-Encoding: 8bit\n" + + #: ../testdir/test_gettext_makefile_in1.vim:4 ../testdir/test_gettext_makefile_in1.vim:6 + #: ../testdir/test_gettext_makefile_in2.vim:5 ../testdir/test_gettext_makefile_in4.vim:4 + msgid "This is a test" + msgstr "" + + #: ../testdir/test_gettext_makefile_in1.vim:5 + msgid "This is another test" + msgstr "" + + #: ../testdir/test_gettext_makefile_in2.vim:4 + msgid "This is a test from the second file" + msgstr "" + + #: ../testdir/test_gettext_makefile_in4.vim:5 + msgid "This is a fourth test" + msgstr "" + END + let potfile = filter(readfile("test_gettext.pot"), 'v:val !~ "POT-Creation-Date"') + call assert_equal(expected, potfile) + call delete('test_gettext.pot') + cd - +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_gettext_makefile_in1.vim b/src/testdir/test_gettext_makefile_in1.vim new file mode 100644 index 0000000..cbe1159 --- /dev/null +++ b/src/testdir/test_gettext_makefile_in1.vim @@ -0,0 +1,7 @@ +" Test file for gettext() package makefile +" Last Change: 2024 Jun 01 + +echo gettext("This is a test", "test_gettext") +echo gettext("This is another test", "test_gettext") +echo gettext("This is a test", "test_gettext") +" vim: ts=8 diff --git a/src/testdir/test_gettext_makefile_in2.vim b/src/testdir/test_gettext_makefile_in2.vim new file mode 100644 index 0000000..86d3dd9 --- /dev/null +++ b/src/testdir/test_gettext_makefile_in2.vim @@ -0,0 +1,6 @@ +" Test file for gettext() package makefile +" Last Change: 2024 Jun 01 + +echo gettext("This is a test from the second file", "test_gettext") +echo gettext("This is a test", "test_gettext") +" vim: ts=8 diff --git a/src/testdir/test_gettext_makefile_in3.vim b/src/testdir/test_gettext_makefile_in3.vim new file mode 100644 index 0000000..f4cf93d --- /dev/null +++ b/src/testdir/test_gettext_makefile_in3.vim @@ -0,0 +1,4 @@ +" Test file for gettext() package makefile +" Last Change: 2024 Jun 01 + +" vim: ts=8 diff --git a/src/testdir/test_gettext_makefile_in4.vim b/src/testdir/test_gettext_makefile_in4.vim new file mode 100644 index 0000000..7f9f3f7 --- /dev/null +++ b/src/testdir/test_gettext_makefile_in4.vim @@ -0,0 +1,6 @@ +" Test file for gettext() package makefile +" Last Change: 2024 Jun 01 + +echo gettext("This is a test", "test_gettext") +echo gettext("This is a fourth test", "test_gettext") +" vim: ts=8 diff --git a/src/testdir/test_gettext_utf8.vim b/src/testdir/test_gettext_utf8.vim new file mode 100644 index 0000000..b96f8ea --- /dev/null +++ b/src/testdir/test_gettext_utf8.vim @@ -0,0 +1,35 @@ +source check.vim +" This fail on CI MacOS 14 because bindtextdomain() is not available there +" (missing library?) +CheckNotMac +CheckFeature gettext + +" Test for gettext() +func Test_gettext() + set encoding=utf-8 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + + try + call assert_true(bindtextdomain("__PACKAGE__", getcwd())) + + try + language messages ru_RU + call assert_equal('ОШИБКÐ: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to ru (missing?)" + endtry + + try + language messages en_GB.UTF-8 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to en (missing?)" + endtry + + catch /^Vim\%((\a\+)\)\=:E342:/ + throw "Skipped: out of memory executing bindtextdomain()" + endtry + set encoding& +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_getvar.vim b/src/testdir/test_getvar.vim index 2065186..6efb192 100644 --- a/src/testdir/test_getvar.vim +++ b/src/testdir/test_getvar.vim @@ -142,20 +142,28 @@ func Test_get_func() let l:F = function('tr') call assert_equal('tr', get(l:F, 'name')) call assert_equal(l:F, get(l:F, 'func')) + call assert_equal({'required': 3, 'optional': 0, 'varargs': v:false}, + \ get(l:F, 'arity')) let Fb_func = function('s:FooBar') call assert_match('<SNR>\d\+_FooBar', get(Fb_func, 'name')) + call assert_equal({'required': 0, 'optional': 0, 'varargs': v:false}, + \ get(Fb_func, 'arity')) let Fb_ref = funcref('s:FooBar') call assert_match('<SNR>\d\+_FooBar', get(Fb_ref, 'name')) + call assert_equal({'required': 0, 'optional': 0, 'varargs': v:false}, + \ get(Fb_ref, 'arity')) call assert_equal({'func has': 'no dict'}, get(l:F, 'dict', {'func has': 'no dict'})) call assert_equal(0, get(l:F, 'dict')) call assert_equal([], get(l:F, 'args')) + let NF = test_null_function() call assert_equal('', get(NF, 'name')) call assert_equal(NF, get(NF, 'func')) call assert_equal(0, get(NF, 'dict')) call assert_equal([], get(NF, 'args')) + call assert_equal({'required': 0, 'optional': 0, 'varargs': v:false}, get(NF, 'arity')) endfunc " get({partial}, {what} [, {default}]) - in test_partial.vim diff --git a/src/testdir/test_goto.vim b/src/testdir/test_goto.vim index 357a8d2..b6a6695 100644 --- a/src/testdir/test_goto.vim +++ b/src/testdir/test_goto.vim @@ -296,6 +296,7 @@ func Test_gd_string() return x; } [CODE] + call XTest_goto_decl('gd', lines, 4, 7) endfunc @@ -320,14 +321,16 @@ func Test_set_options_keep_col() let pos = getcurpos() normal j set invhlsearch spell spelllang=en,cjk spelloptions=camel textwidth=80 - set cursorline cursorcolumn cursorlineopt=line colorcolumn=+1 + set cursorline cursorcolumn cursorlineopt=line colorcolumn=+1 winfixbuf + set comments=:# commentstring=#%s define=function set background=dark set background=light normal k call assert_equal(pos, getcurpos()) bwipe! set hlsearch& spell& spelllang& spelloptions& textwidth& - set cursorline& cursorcolumn& cursorlineopt& colorcolumn& + set cursorline& cursorcolumn& cursorlineopt& colorcolumn& winfixbuf& + set comments& commentstring& define& set background& endfunc diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index d53750f..ae65310 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -1708,7 +1708,8 @@ func Test_gui_lowlevel_keyevent() new " Test for <Ctrl-A> to <Ctrl-Z> keys - for kc in range(65, 90) + " FIXME: <Ctrl-C> is excluded for now. It makes the test flaky. + for kc in range(65, 66) + range(68, 90) call SendKeys([0x11, kc]) try let ch = getcharstr() diff --git a/src/testdir/test_increment.vim b/src/testdir/test_increment.vim index fdd7c0c..3a5f5ee 100644 --- a/src/testdir/test_increment.vim +++ b/src/testdir/test_increment.vim @@ -840,6 +840,44 @@ func Test_increment_unsigned() set nrformats-=unsigned endfunc +" Try incrementing/decrementing a number when nrformats contains blank +func Test_increment_blank() + set nrformats+=blank + + " Signed + call setline(1, '0') + exec "norm! gg0\<C-X>" + call assert_equal('-1', getline(1)) + + call setline(1, '3') + exec "norm! gg010\<C-X>" + call assert_equal('-7', getline(1)) + + call setline(1, '-0') + exec "norm! gg0\<C-X>" + call assert_equal("-1", getline(1)) + + " Unsigned + " NOTE: 18446744073709551615 == 2^64 - 1 + call setline(1, 'a-18446744073709551615') + exec "norm! gg0\<C-A>" + call assert_equal('a-18446744073709551615', getline(1)) + + call setline(1, 'a-18446744073709551615') + exec "norm! gg0\<C-A>" + call assert_equal('a-18446744073709551615', getline(1)) + + call setline(1, 'a-18446744073709551614') + exec "norm! gg08\<C-A>" + call assert_equal('a-18446744073709551615', getline(1)) + + call setline(1, 'a-1') + exec "norm! gg0\<C-A>" + call assert_equal('a-2', getline(1)) + + set nrformats-=blank +endfunc + func Test_in_decrement_large_number() " NOTE: 18446744073709551616 == 2^64 call setline(1, '18446744073709551616') diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 48589ce..aee3393 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -2586,9 +2586,85 @@ func Test_complete_fuzzy_match() call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') call assert_equal('hello help hero h', getline('.')) + set completeopt-=noinsert + call setline(1, ['xyz yxz x']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('xyz yxz xyz', getline('.')) + " can fuzzy get yxz when use Ctrl-N twice + call setline(1, ['xyz yxz x']) + call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') + call assert_equal('xyz yxz yxz', getline('.')) + + call setline(1, ['ä½ å¥½ ä½ ']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('ä½ å¥½ ä½ å¥½', getline('.')) + call setline(1, ['ä½ çš„ 我的 çš„']) + call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('ä½ çš„ 我的 ä½ çš„', getline('.')) + " can fuzzy get multiple-byte word when use Ctrl-N twice + call setline(1, ['ä½ çš„ 我的 çš„']) + call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') + call assert_equal('ä½ çš„ 我的 我的', getline('.')) + + " respect wrapscan + set nowrapscan + call setline(1, ["xyz", "yxz", ""]) + call cursor(3, 1) + call feedkeys("Sy\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('y', getline('.')) + set wrapscan + call feedkeys("Sy\<C-X>\<C-N>\<Esc>0", 'tx!') + call assert_equal('xyz', getline('.')) + + " fuzzy on file + call writefile([''], 'fobar', 'D') + call writefile([''], 'foobar', 'D') + call setline(1, ['fob']) + call cursor(1, 1) + call feedkeys("A\<C-X>\<C-f>\<Esc>0", 'tx!') + call assert_equal('fobar', getline('.')) + call feedkeys("Sfob\<C-X>\<C-f>\<C-N>\<Esc>0", 'tx!') + call assert_equal('foobar', getline('.')) + call feedkeys("S../\<C-X>\<C-f>\<Esc>0", 'tx!') + call assert_match('../*', getline('.')) + call feedkeys("S../td\<C-X>\<C-f>\<Esc>0", 'tx!') + call assert_match('../testdir', getline('.')) + + " can get completion from other buffer + set completeopt=fuzzy,menu,menuone + vnew + call setline(1, ["completeness,", "compatibility", "Composite", "Omnipotent"]) + wincmd p + call feedkeys("Somp\<C-N>\<Esc>0", 'tx!') + call assert_equal('completeness', getline('.')) + call feedkeys("Somp\<C-N>\<C-N>\<Esc>0", 'tx!') + call assert_equal('compatibility', getline('.')) + call feedkeys("Somp\<C-P>\<Esc>0", 'tx!') + call assert_equal('Omnipotent', getline('.')) + call feedkeys("Somp\<C-P>\<C-P>\<Esc>0", 'tx!') + call assert_equal('Composite', getline('.')) + call feedkeys("S omp\<C-N>\<Esc>0", 'tx!') + call assert_equal(' completeness', getline('.')) + + " fuzzy on whole line completion + call setline(1, ["world is on fire", "no one can save me but you", 'user can execute', '']) + call cursor(4, 1) + call feedkeys("Swio\<C-X>\<C-L>\<Esc>0", 'tx!') + call assert_equal('world is on fire', getline('.')) + call feedkeys("Su\<C-X>\<C-L>\<C-P>\<Esc>0", 'tx!') + call assert_equal('no one can save me but you', getline('.')) + + " issue #15526 + set completeopt=fuzzy,menuone,menu,noselect + call setline(1, ['Text', 'ToText', '']) + call cursor(2, 1) + call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!') + call assert_equal('Tex', getline('.')) + " clean up set omnifunc= bw! + bw! set complete& completeopt& autocmd! AAAAA_Group augroup! AAAAA_Group @@ -2599,6 +2675,38 @@ func Test_complete_fuzzy_match() unlet g:word endfunc +func Test_complete_fuzzy_with_completeslash() + CheckMSWindows + + call writefile([''], 'fobar', 'D') + let orig_shellslash = &shellslash + set cpt& + new + set completeopt+=fuzzy + set noshellslash + + " Test with completeslash unset + set completeslash= + call setline(1, ['.\fob']) + call feedkeys("A\<C-X>\<C-F>\<Esc>0", 'tx!') + call assert_equal('.\fobar', getline('.')) + + " Test with completeslash=backslash + set completeslash=backslash + call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!') + call assert_equal('.\fobar', getline('.')) + + " Test with completeslash=slash + set completeslash=slash + call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!') + call assert_equal('./fobar', getline('.')) + + " Reset and clean up + let &shellslash = orig_shellslash + set completeslash= + %bw! +endfunc + " Check that tie breaking is stable for completeopt+=fuzzy (which should " behave the same on different platforms). func Test_complete_fuzzy_match_tie() @@ -2619,4 +2727,14 @@ func Test_complete_fuzzy_match_tie() set completeopt& endfunc +func Test_complete_backwards_default() + new + call append(1, ['foobar', 'foobaz']) + new + call feedkeys("i\<c-p>", 'tx') + call assert_equal('foobaz', getline('.')) + bw! + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_jumplist.vim b/src/testdir/test_jumplist.vim index 8fbf39f..4b9fcee 100644 --- a/src/testdir/test_jumplist.vim +++ b/src/testdir/test_jumplist.vim @@ -59,29 +59,63 @@ func Test_getjumplist() call assert_equal(4, l[1]) endfunc -func Test_jumplist_invalid() +func Test_jumplist_wipe_buf() new clearjumps - " put some randome text - put ='a' - let prev = bufnr('%') + " Put some random text and fill the jump list. + call setline(1, ['foo', 'bar', 'baz']) + normal G + normal gg setl nomodified bufhidden=wipe e XXJumpListBuffer - let bnr = bufnr('%') - " 1) empty jumplist - let expected = [[ - \ {'lnum': 2, 'bufnr': prev, 'col': 0, 'coladd': 0}], 1] - call assert_equal(expected, getjumplist()) + " The jump list is empty as the buffer was wiped out. + call assert_equal([[], 0], getjumplist()) let jumps = execute(':jumps') call assert_equal('>', jumps[-1:]) - " now jump back - exe ":norm! \<c-o>" - let expected = [[ - \ {'lnum': 2, 'bufnr': prev, 'col': 0, 'coladd': 0}, - \ {'lnum': 1, 'bufnr': bnr, 'col': 0, 'coladd': 0}], 0] - call assert_equal(expected, getjumplist()) - let jumps = execute(':jumps') - call assert_match('> 0 2 0 -invalid-', jumps) + + " Put some random text and fill the jump list. + call setline(1, ['foo', 'bar', 'baz']) + setl bufhidden=hide + + " References to wiped buffer are deleted with multiple tabpages. + let [w1, t1] = [win_getid(), tabpagenr()] + clearjumps + normal G + normal gg + enew + + split XXJumpListBuffer + let [w2, t2] = [win_getid(), tabpagenr()] + clearjumps + normal G + normal gg + enew + + tabnew XXJumpListBuffer + let [w3, t3] = [win_getid(), tabpagenr()] + clearjumps + normal G + normal gg + enew + + split XXJumpListBuffer + let [w4, t4] = [win_getid(), tabpagenr()] + clearjumps + normal G + normal gg + enew + + for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]] + call assert_equal(2, len(getjumplist(w, t)[0])) + endfor + + bwipe! XXJumpListBuffer + + for [w, t] in [[w1, t1], [w2, t2], [w3, t3], [w4, t4]] + call assert_equal(0, len(getjumplist(w, t)[0])) + endfor + + %bwipe! endfunc " Test for '' mark in an empty buffer diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index 12a6dd4..48217cf 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -1147,6 +1147,19 @@ func Test_listdict_compare() call assert_fails('echo {} =~ {}', 'E736:') endfunc +func Test_recursive_listdict_compare() + let l1 = [0, 1] + let l1[0] = l1 + let l2 = [0, 1] + let l2[0] = l2 + call assert_true(l1 == l2) + let d1 = {0: 0, 1: 1} + let d1[0] = d1 + let d2 = {0: 0, 1: 1} + let d2[0] = d2 + call assert_true(d1 == d2) +endfunc + " compare complex recursively linked list and dict func Test_listdict_compare_complex() let lines =<< trim END @@ -1557,4 +1570,83 @@ func Test_extendnew_leak() for i in range(100) | silent! call extendnew({}, {}, {}) | endfor endfunc +" Test for comparing deeply nested List/Dict values +func Test_deep_nested_listdict_compare() + let lines =<< trim END + def GetNestedList(sz: number): list<any> + var l: list<any> = [] + var x: list<any> = l + for i in range(sz) + var y: list<any> = [1] + add(x, y) + x = y + endfor + return l + enddef + + VAR l1 = GetNestedList(1000) + VAR l2 = GetNestedList(999) + call assert_false(l1 == l2) + + #" after 1000 nested items, the lists are considered to be equal + VAR l3 = GetNestedList(1001) + VAR l4 = GetNestedList(1002) + call assert_true(l3 == l4) + END + call v9.CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + def GetNestedDict(sz: number): dict<any> + var d: dict<any> = {} + var x: dict<any> = d + for i in range(sz) + var y: dict<any> = {} + x['a'] = y + x = y + endfor + return d + enddef + + VAR d1 = GetNestedDict(1000) + VAR d2 = GetNestedDict(999) + call assert_false(d1 == d2) + + #" after 1000 nested items, the Dicts are considered to be equal + VAR d3 = GetNestedDict(1001) + VAR d4 = GetNestedDict(1002) + call assert_true(d3 == d4) + END + call v9.CheckLegacyAndVim9Success(lines) +endfunc + +" Test for using id() +def Test_id_with_dict() + # demonstate a way that "id(item)" differs from "string(item)" + var d1 = {one: 1} + var d2 = {one: 1} + var d3 = {one: 1} + var idDict: dict<any> + idDict[id(d1)] = d1 + idDict[id(d2)] = d2 + idDict[id(d3)] = d3 + assert_equal(3, idDict->len()) + + var stringDict: dict<any> + stringDict[string(d1)] = d1 + stringDict[string(d2)] = d2 + stringDict[string(d3)] = d3 + assert_equal(1, stringDict->len()) + + assert_equal('', id(3)) + + assert_equal('', id(null)) + assert_equal('', id(null_blob)) + assert_equal('', id(null_dict)) + assert_equal('', id(null_function)) + assert_equal('', id(null_list)) + assert_equal('', id(null_partial)) + assert_equal('', id(null_string)) + assert_equal('', id(null_channel)) + assert_equal('', id(null_job)) +enddef " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_listlbr_utf8.vim b/src/testdir/test_listlbr_utf8.vim index 313ff30..693f201 100644 --- a/src/testdir/test_listlbr_utf8.vim +++ b/src/testdir/test_listlbr_utf8.vim @@ -280,6 +280,9 @@ func Test_chinese_char_on_wrap_column() call s:compare_lines(expect, lines) call assert_equal(len(expect), winline()) call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol()) + norm! g0 + call assert_equal(len(expect), winline()) + call assert_equal(1, wincol()) call s:close_windows() endfunc @@ -315,6 +318,9 @@ func Test_chinese_char_on_wrap_column_sbr() call s:compare_lines(expect, lines) call assert_equal(len(expect), winline()) call assert_equal(strwidth(trim(expect[-1], ' ', 2)), wincol()) + norm! g0 + call assert_equal(len(expect), winline()) + call assert_equal(4, wincol()) call s:close_windows() endfunc diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 1175310..064f8ac 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -1767,6 +1767,49 @@ func Test_unmap_simplifiable() unmap <C-I> endfunc +" Test that the first byte of rhs is not remapped if rhs starts with lhs. +func Test_map_rhs_starts_with_lhs() + new + func MapExpr() + return "\<C-R>\<C-P>" + endfunc + + for expr in [v:false, v:true] + if expr + imap <buffer><expr> <C-R> MapExpr() + else + imap <buffer> <C-R> <C-R><C-P> + endif + + for restore in [v:false, v:true] + if restore + let saved = maparg('<C-R>', 'i', v:false, v:true) + iunmap <buffer> <C-R> + call mapset(saved) + endif + + let @a = 'foo' + call assert_nobeep('call feedkeys("S\<C-R>a", "tx")') + call assert_equal('foo', getline('.')) + + let @a = 'bar' + call assert_nobeep('call feedkeys("S\<*C-R>a", "tx")') + call assert_equal('bar', getline('.')) + endfor + endfor + + " When two mappings are used for <C-I> and <Tab>, remapping should work. + imap <buffer> <C-I> <Tab>bar + imap <buffer> <Tab> foo + call feedkeys("S\<Tab>", 'xt') + call assert_equal('foo', getline('.')) + call feedkeys("S\<*C-I>", 'xt') + call assert_equal('foobar', getline('.')) + + delfunc MapExpr + bwipe! +endfunc + func Test_expr_map_escape_special() nnoremap … <Cmd>let g:got_ellipsis += 1<CR> func Func() diff --git a/src/testdir/test_matchparen.vim b/src/testdir/test_matchparen.vim index 70aa38f..49d3510 100644 --- a/src/testdir/test_matchparen.vim +++ b/src/testdir/test_matchparen.vim @@ -108,5 +108,35 @@ func Test_matchparen_pum_clear() call StopVimInTerminal(buf) endfunc +" Test that matchparen works with multibyte chars in 'matchpairs' +func Test_matchparen_mbyte() + CheckScreendump + + let lines =<< trim END + source $VIMRUNTIME/plugin/matchparen.vim + call setline(1, ['aaaaaaaa(', 'bbbb)cc']) + set matchpairs+=(:) + END + + call writefile(lines, 'XmatchparenMbyte', 'D') + let buf = RunVimInTerminal('-S XmatchparenMbyte', #{rows: 10}) + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_1', {}) + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_2', {}) + call term_sendkeys(buf, "j") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_3', {}) + call term_sendkeys(buf, "2h") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_4', {}) + call term_sendkeys(buf, "0") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_5', {}) + call term_sendkeys(buf, "kA") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_6', {}) + call term_sendkeys(buf, "\<Down>") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_7', {}) + call term_sendkeys(buf, "\<C-W>") + call VerifyScreenDump(buf, 'Test_matchparen_mbyte_8', {}) + + call StopVimInTerminal(buf) +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_menu.vim b/src/testdir/test_menu.vim index 2229228..40fec40 100644 --- a/src/testdir/test_menu.vim +++ b/src/testdir/test_menu.vim @@ -481,13 +481,48 @@ func Test_popup_menu() unmenu PopUp endfunc +func Test_popup_menu_truncated() + CheckNotGui + + set mouse=a mousemodel=popup + aunmenu PopUp + for i in range(2 * &lines) + exe $'menu PopUp.{i} <Cmd>let g:res = {i}<CR>' + endfor + + func LeftClickExpr(row, col) + call test_setmouse(a:row, a:col) + return "\<LeftMouse>" + endfunc + + " Clicking at the bottom should place popup menu above click position. + " <RightRelease> should not select an item immediately. + let g:res = -1 + call test_setmouse(&lines, 1) + nnoremap <expr><F2> LeftClickExpr(4, 1) + call feedkeys("\<RightMouse>\<RightRelease>\<F2>", 'tx') + call assert_equal(3, g:res) + + " Clicking at the top should place popup menu below click position. + let g:res = -1 + call test_setmouse(1, 1) + nnoremap <expr><F2> LeftClickExpr(5, 1) + call feedkeys("\<RightMouse>\<RightRelease>\<F2>", 'tx') + call assert_equal(3, g:res) + + nunmap <F2> + delfunc LeftClickExpr + unlet g:res + aunmenu PopUp + set mouse& mousemodel& +endfunc + " Test for MenuPopup autocommand func Test_autocmd_MenuPopup() CheckNotGui - set mouse=a - set mousemodel=popup - aunmenu * + set mouse=a mousemodel=popup + aunmenu PopUp autocmd MenuPopup * exe printf( \ 'anoremenu PopUp.Foo <Cmd>let g:res = ["%s", "%s"]<CR>', \ expand('<afile>'), expand('<amatch>')) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 83594d2..398bf29 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -4257,6 +4257,9 @@ func Test_page_cursor_topbot() call assert_equal(18, line('.')) exe "norm! \<C-B>\<C-F>" call assert_equal(9, line('.')) + " Not when already at the start of the buffer. + exe "norm! ggj\<C-B>" + call assert_equal(2, line('.')) bwipe! endfunc diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index fbfbaae..94c98fe 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -548,6 +548,9 @@ func Test_set_completion_string_values() call assert_equal('sync', getcompletion('set swapsync=', 'cmdline')[1]) call assert_equal('usetab', getcompletion('set switchbuf=', 'cmdline')[1]) call assert_equal('ignore', getcompletion('set tagcase=', 'cmdline')[1]) + if exists('+tabclose') + call assert_equal('left uselast', join(sort(getcompletion('set tabclose=', 'cmdline'))), ' ') + endif if exists('+termwintype') call assert_equal('conpty', getcompletion('set termwintype=', 'cmdline')[1]) endif @@ -1407,7 +1410,8 @@ func Test_write() set nowrite call assert_fails('write Xwrfile', 'E142:') set write - close! + " close swapfile + bw! endfunc " Test for 'buftype' option @@ -1724,7 +1728,7 @@ func Test_VIM_POSIX() qall [CODE] if RunVim([], after, '') - call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>#{|&/\.;', + call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\.;', \ 'AS'], readfile('X_VIM_POSIX')) endif @@ -1734,7 +1738,7 @@ func Test_VIM_POSIX() qall [CODE] if RunVim([], after, '') - call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZ$!%*-+<>;', + call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>;', \ 'S'], readfile('X_VIM_POSIX')) endif diff --git a/src/testdir/test_partial.vim b/src/testdir/test_partial.vim index b5a58f6..acc8b73 100644 --- a/src/testdir/test_partial.vim +++ b/src/testdir/test_partial.vim @@ -311,6 +311,11 @@ func Test_auto_partial_rebind() endfunc func Test_get_partial_items() + func s:Qux(x, y, z=3, w=1, ...) + endfunc + func s:Qux1(x, y) + endfunc + let dict = {'name': 'hello'} let args = ["foo", "bar"] let Func = function('MyDictFunc') @@ -331,6 +336,23 @@ func Test_get_partial_items() let dict = {'partial has': 'no dict'} call assert_equal(dict, get(P, 'dict', dict)) call assert_equal(0, get(l:P, 'dict')) + + call assert_equal({'required': 2, 'optional': 2, 'varargs': v:true}, + \ get(funcref('s:Qux', []), 'arity')) + call assert_equal({'required': 1, 'optional': 2, 'varargs': v:true}, + \ get(funcref('s:Qux', [1]), 'arity')) + call assert_equal({'required': 0, 'optional': 2, 'varargs': v:true}, + \ get(funcref('s:Qux', [1, 2]), 'arity')) + call assert_equal({'required': 0, 'optional': 1, 'varargs': v:true}, + \ get(funcref('s:Qux', [1, 2, 3]), 'arity')) + call assert_equal({'required': 0, 'optional': 0, 'varargs': v:true}, + \ get(funcref('s:Qux', [1, 2, 3, 4]), 'arity')) + " More args than expected is not an error + call assert_equal({'required': 0, 'optional': 0, 'varargs': v:false}, + \ get(funcref('s:Qux1', [1, 2, 3, 4]), 'arity')) + + delfunc s:Qux + delfunc s:Qux1 endfunc func Test_compare_partials() diff --git a/src/testdir/test_paste.vim b/src/testdir/test_paste.vim index d079f48..b35fc81 100644 --- a/src/testdir/test_paste.vim +++ b/src/testdir/test_paste.vim @@ -93,7 +93,7 @@ func Test_paste_ex_mode() call assert_equal("foo\rbar", foo) " pasting more than 40 bytes - exe "norm Q\<PasteStart>0000000000000000000000000000000000000000000000000000000000000000000000\<C-C>" + exe "norm Q\<PasteStart>s/.*/0000000000000000000000000000000000000000000000000000000000000000/\<C-C>" endfunc func Test_paste_onechar() diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index dd01a57..fe958da 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -1482,8 +1482,101 @@ func Test_pum_highlights_match() call term_sendkeys(buf, "o\<BS>\<C-R>=Comp()\<CR>") call VerifyScreenDump(buf, 'Test_pum_highlights_09', {}) + " issue #15095 wrong select + call term_sendkeys(buf, "\<ESC>:set completeopt=fuzzy,menu\<CR>") + call TermWait(buf) + call term_sendkeys(buf, "S hello helio hero h\<C-X>\<C-P>") + call TermWait(buf, 50) + call VerifyScreenDump(buf, 'Test_pum_highlights_10', {}) + + call term_sendkeys(buf, "\<ESC>S hello helio hero h\<C-X>\<C-P>\<C-P>") + call TermWait(buf, 50) + call VerifyScreenDump(buf, 'Test_pum_highlights_11', {}) + + " issue #15357 + call term_sendkeys(buf, "\<ESC>S/non_exit_folder\<C-X>\<C-F>") + call TermWait(buf, 50) + call VerifyScreenDump(buf, 'Test_pum_highlights_15', {}) + + call term_sendkeys(buf, "\<C-E>\<Esc>") + call TermWait(buf) + + call StopVimInTerminal(buf) +endfunc + +func Test_pum_user_hl_group() + CheckScreendump + let lines =<< trim END + func CompleteFunc( findstart, base ) + if a:findstart + return 0 + endif + return { + \ 'words': [ + \ { 'word': 'aword1', 'menu': 'extra text 1', 'kind': 'W', 'hl_group': 'StrikeFake' }, + \ { 'word': 'aword2', 'menu': 'extra text 2', 'kind': 'W', }, + \ { 'word': 'ä½ å¥½', 'menu': 'extra text 3', 'kind': 'W', 'hl_group': 'StrikeFake' }, + \]} + endfunc + set completeopt=menu + set completefunc=CompleteFunc + + hi StrikeFake ctermfg=9 + func HlMatch() + hi PmenuMatchSel ctermfg=6 ctermbg=7 cterm=underline + hi PmenuMatch ctermfg=4 ctermbg=225 cterm=underline + endfunc + END + call writefile(lines, 'Xscript', 'D') + let buf = RunVimInTerminal('-S Xscript', {}) + + call TermWait(buf) + call term_sendkeys(buf, "Saw\<C-X>\<C-U>") + call VerifyScreenDump(buf, 'Test_pum_highlights_12', {}) + call term_sendkeys(buf, "\<C-E>\<Esc>") + + call TermWait(buf) + call term_sendkeys(buf, ":call HlMatch()\<CR>") + + call TermWait(buf) + call term_sendkeys(buf, "Saw\<C-X>\<C-U>") + call VerifyScreenDump(buf, 'Test_pum_highlights_13', {}) + call term_sendkeys(buf, "\<C-N>") + call VerifyScreenDump(buf, 'Test_pum_highlights_14', {}) call term_sendkeys(buf, "\<C-E>\<Esc>") + + call StopVimInTerminal(buf) +endfunc + +func Test_pum_user_kind_hlgroup() + CheckScreendump + let lines =<< trim END + func CompleteFunc( findstart, base ) + if a:findstart + return 0 + endif + return { + \ 'words': [ + \ { 'word': 'aword1', 'menu': 'extra text 1', 'kind': 'variable', 'kind_hlgroup': 'KindVar', 'hl_group': 'StrikeFake' }, + \ { 'word': 'aword2', 'menu': 'extra text 2', 'kind': 'function', 'kind_hlgroup': 'KindFunc' }, + \ { 'word': 'ä½ å¥½', 'menu': 'extra text 3', 'kind': 'class', 'kind_hlgroup': 'KindClass' }, + \]} + endfunc + set completeopt=menu + set completefunc=CompleteFunc + + hi StrikeFake ctermfg=9 + hi KindVar ctermfg=yellow + hi KindFunc ctermfg=blue + hi KindClass ctermfg=green + END + call writefile(lines, 'Xscript', 'D') + let buf = RunVimInTerminal('-S Xscript', {}) + call TermWait(buf) + call term_sendkeys(buf, "S\<C-X>\<C-U>") + call VerifyScreenDump(buf, 'Test_pum_highlights_16', {}) + call term_sendkeys(buf, "\<C-E>\<Esc>") call StopVimInTerminal(buf) endfunc diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index a397f70..64aa654 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2499,6 +2499,88 @@ func Test_popup_settext_null() call popup_close(id) endfunc +func Test_popup_setbuf() + CheckScreendump + + let lines =<< trim END + let opts = #{wrap: 0} + let p = popup_create('test', opts) + let buf = bufnr('%') + END + + call writefile(lines, 'XtestPopupSetBuf', 'D') + let buf = RunVimInTerminal('-S XtestPopupSetBuf', #{rows: 10}) + call VerifyScreenDump(buf, 'Test_popup_setbuf_01', {}) + + " Setting to an non-existing buffer doesn't do anything + call term_sendkeys(buf, ":call popup_setbuf(p, 'foobar.txt')\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_02', {}) + + " Error + call term_sendkeys(buf, ":call popup_setbuf(p, ['a','b','c'])\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_03', {}) + + " Set to help window + call term_sendkeys(buf, ":help\<CR>") + call term_sendkeys(buf, ":call popup_setbuf(p, 'help.txt')\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_04', {}) + + " Setting back to original buffer + call term_sendkeys(buf, ":call popup_setbuf(p, buf)\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_05', {}) + + " use method + call term_sendkeys(buf, ":echo p->popup_setbuf('help.txt')\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_06', {}) + + call term_sendkeys(buf, ":echo p->popup_setbuf(buf)\<CR>") + call VerifyScreenDump(buf, 'Test_popup_setbuf_05', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_popup_setbuf_terminal() + CheckFeature terminal + + " Check Terminal Feature + let termbuf = term_start(&shell, #{hidden: 1}) + " Wait for shell to start + call WaitForAssert({-> assert_equal("run", job_status(term_getjob(termbuf)))}) + + let popup = popup_create('test', {}) + call assert_true(popup->popup_setbuf(termbuf)) + call popup_close(popup) + + let popup1 = popup_create(termbuf, #{minwidth: 40, minheight: 10, border: []}) + + let popup = popup_create('test', {}) + try + call assert_fails(call popup_setbuf(popup, termbuf)) + catch + endtry + call popup_close(popup) + call popup_close(popup1) + call assert_equal([], popup_list()) + " Close the terminal + call term_sendkeys(termbuf, "exit\<CR>") + " Wait for shell to exit + call WaitForAssert({-> assert_equal("dead", job_status(term_getjob(termbuf)))}) +endfunc + +func Test_popup_setbuf_null() + let id = popup_create('', {}) + call assert_false(popup_setbuf(id, -1)) + call popup_close(id) + + let id = popup_create('', {}) + call assert_true(popup_setbuf(id, test_null_string())) + call assert_true(popup_setbuf(id, '')) + call popup_close(id) + + call assert_false(popup_setbuf(id, 0)) +endfunc + func Test_popup_hidden() new diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim index 69c2943..94e4f47 100644 --- a/src/testdir/test_put.vim +++ b/src/testdir/test_put.vim @@ -168,10 +168,6 @@ func Test_very_large_count() endfunc func Test_very_large_count_64bit() - if v:sizeoflong < 8 - throw 'Skipped: only works with 64 bit long ints' - endif - new let @" = repeat('x', 100) call assert_fails('norm 999999999p', 'E1240:') @@ -188,10 +184,6 @@ func Test_very_large_count_block() endfunc func Test_very_large_count_block_64bit() - if v:sizeoflong < 8 - throw 'Skipped: only works with 64 bit long ints' - endif - new call setline(1, repeat('x', 100)) exe "norm \<C-V>$y" diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 0b61815..47b9b47 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -893,7 +893,7 @@ func Test_helpgrep() endfunc def Test_helpgrep_vim9_restore_cpo() - assert_equal('aABceFs', &cpo) + assert_equal('aABceFsz', &cpo) var rtp_save = &rtp var dir = 'Xruntime/after' @@ -905,7 +905,7 @@ def Test_helpgrep_vim9_restore_cpo() cwindow silent helpgrep grail - assert_equal('aABceFs', &cpo) + assert_equal('aABceFsz', &cpo) &rtp = rtp_save cclose helpclose diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim index bc70544..51c0984 100644 --- a/src/testdir/test_regexp_utf8.vim +++ b/src/testdir/test_regexp_utf8.vim @@ -587,4 +587,36 @@ func Test_combining_chars_in_collection() bw! endfunc +func Test_search_multibyte_match_ascii() + new + " Match single 'Å¿' and 's' + call setline(1, 'das abc heraus abc Å¿ich abc Å¿ind') + for i in range(0, 2) + exe "set re="..i + let ic_match = matchbufline('%', '\c\%u17f', 1, '$')->mapnew({idx, val -> val.text}) + let noic_match = matchbufline('%', '\C\%u17f', 1, '$')->mapnew({idx, val -> val.text}) + call assert_equal(['s', 's', 'Å¿','Å¿'], ic_match, "Ignorecase Regex-engine: " .. &re) + call assert_equal(['Å¿','Å¿'], noic_match, "No-Ignorecase Regex-engine: " .. &re) + endfor + " Match several 'Å¿Å¿' and 'ss' + call setline(1, 'das abc herauss abc Å¿Å¿ich abc Å¿ind') + for i in range(0, 2) + exe "set re="..i + let ic_match = matchbufline('%', '\c\%u17f\%u17f', 1, '$')->mapnew({idx, val -> val.text}) + let noic_match = matchbufline('%', '\C\%u17f\%u17f', 1, '$')->mapnew({idx, val -> val.text}) + let ic_match2 = matchbufline('%', '\c\%u17f\+', 1, '$')->mapnew({idx, val -> val.text}) + let noic_match2 = matchbufline('%', '\C\%u17f\+', 1, '$')->mapnew({idx, val -> val.text}) + let ic_match3 = matchbufline('%', '\c[\u17f]\+', 1, '$')->mapnew({idx, val -> val.text}) + let noic_match3 = matchbufline('%', '\C[\u17f]\+', 1, '$')->mapnew({idx, val -> val.text}) + + call assert_equal(['ss', 'Å¿Å¿'], ic_match, "Ignorecase Regex-engine: " .. &re) + call assert_equal(['Å¿Å¿'], noic_match, "No-Ignorecase Regex-engine: " .. &re) + call assert_equal(['s', 'ss', 'Å¿Å¿', 'Å¿'], ic_match2, "Ignorecase Regex-engine: " .. &re) + call assert_equal(['Å¿Å¿','Å¿'], noic_match2, "No-Ignorecase Regex-engine: " .. &re) + call assert_equal(['s', 'ss', 'Å¿Å¿', 'Å¿'], ic_match3, "Ignorecase Collection Regex-engine: " .. &re) + call assert_equal(['Å¿Å¿','Å¿'], noic_match3, "No-Ignorecase Collection Regex-engine: " .. &re) + endfor + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index 1a9f49b..708aca2 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -1747,6 +1747,37 @@ func Test_search_with_no_last_pat() call delete('Xresult') endfunc +" Test for using the last substitute pattern without last search pattern. +func Test_search_with_last_substitute_pat() + let lines =<< trim [SCRIPT] + new + set shortmess+=S + call setline(1, repeat(['foofoo'], 3)) + %s/foo/bar/ + call assert_equal(repeat(['barfoo'], 3), getline(1, '$')) + + call cursor(1, 1) + call assert_equal("/foo", execute('call feedkeys("/\r", "tx")', '')->trim()) + call assert_equal([0, 1, 4, 0], getpos('.')) + + if has('rightleft') + set rightleft rightleftcmd=search + call cursor(1, 1) + call assert_equal("oof/", execute('call feedkeys("/\r", "tx")', '')->trim()) + call assert_equal([0, 1, 4, 0], getpos('.')) + endif + + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript', 'D') + + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xresult') +endfunc + " Test for using tilde (~) atom in search. This should use the last used " substitute pattern func Test_search_tilde_pat() diff --git a/src/testdir/test_selectmode.vim b/src/testdir/test_selectmode.vim index bf1b52b..63aa0b9 100644 --- a/src/testdir/test_selectmode.vim +++ b/src/testdir/test_selectmode.vim @@ -321,4 +321,20 @@ func Test_ins_ctrl_o_in_insert_mode_resets_selectmode() bwipe! endfunc +" Test that an :lmap mapping for a printable keypad key is applied when typing +" it in Select mode. +func Test_selectmode_keypad_lmap() + new + lnoremap <buffer> <kPoint> ??? + lnoremap <buffer> <kEnter> !!! + setlocal iminsert=1 + call setline(1, 'abcdef') + call feedkeys("gH\<kPoint>\<Esc>", 'tx') + call assert_equal(['???'], getline(1, '$')) + call feedkeys("gH\<kEnter>\<Esc>", 'tx') + call assert_equal(['!!!'], getline(1, '$')) + + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index 0d76d7a..7f53d62 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -245,7 +245,7 @@ func Test_sign_completion() call assert_equal('"sign define jump list place undefine unplace', @:) call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx') - call assert_equal('"sign define Sign culhl= icon= linehl= numhl= text= texthl=', @:) + call assert_equal('"sign define Sign culhl= icon= linehl= numhl= priority= text= texthl=', @:) for hl in ['culhl', 'linehl', 'numhl', 'texthl'] call feedkeys(":sign define Sign "..hl.."=Spell\<C-A>\<C-B>\"\<CR>", 'tx') @@ -1231,6 +1231,25 @@ func Test_sign_priority() call sign_define("sign1", attr) call sign_define("sign2", attr) call sign_define("sign3", attr) + let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Search', 'priority': 60} + call sign_define("sign4", attr) + + " Test for :sign list + let a = execute('sign list') + call assert_equal("\nsign sign1 text==> linehl=Search texthl=Search\n" . + \ "sign sign2 text==> linehl=Search texthl=Search\n" . + \ "sign sign3 text==> linehl=Search texthl=Search\n" . + \ "sign sign4 text==> priority=60 linehl=Search texthl=Search", a) + + " Test for sign_getdefined() + let s = sign_getdefined() + call assert_equal([ + \ {'name': 'sign1', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'}, + \ {'name': 'sign2', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'}, + \ {'name': 'sign3', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'}, + \ {'name': 'sign4', 'priority': 60, 'texthl': 'Search', 'linehl': 'Search', + \ 'text': '=>'}], + \ s) " Place three signs with different priority in the same line call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D') @@ -1586,6 +1605,25 @@ func Test_sign_priority() \ " line=10 id=5 group=g1 name=sign1 priority=20\n", a) call sign_unplace('*') + + " Test for sign with default priority. + call sign_place(1, 'g1', 'sign4', 'Xsign', {'lnum' : 3}) + sign place 2 line=5 name=sign4 group=g1 file=Xsign + + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign4', 'lnum' : 3, 'group' : 'g1', + \ 'priority' : 60}, + \ {'id' : 2, 'name' : 'sign4', 'lnum' : 5, 'group' : 'g1', + \ 'priority' : 60}], + \ s[0].signs) + + let a = execute('sign place group=g1') + call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . + \ " line=3 id=1 group=g1 name=sign4 priority=60\n" . + \ " line=5 id=2 group=g1 name=sign4 priority=60\n", a) + + call sign_unplace('*') call sign_undefine() enew | only endfunc diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim index 1ddcd83..692e191 100644 --- a/src/testdir/test_spell.vim +++ b/src/testdir/test_spell.vim @@ -5,6 +5,7 @@ source check.vim CheckFeature spell source screendump.vim +source view_util.vim func TearDown() set nospell @@ -300,6 +301,20 @@ func Test_compl_with_CTRL_X_CTRL_K_using_spell() set spell& spelllang& dictionary& ignorecase& endfunc +func Test_compl_with_CTRL_X_s() + new + set spell spelllang=en_us showmode + inoremap <buffer><F2> <Cmd>let g:msg = Screenline(&lines)<CR> + + call feedkeys("STheatre\<C-X>s\<F2>\<C-Y>\<Esc>", 'tx') + call assert_equal(['Theater'], getline(1, '$')) + call assert_match('(^S^N^P)', g:msg) + + bwipe! + set spell& spelllang& showmode& + unlet g:msg +endfunc + func Test_spellrepall() new set spell diff --git a/src/testdir/test_spellfile.vim b/src/testdir/test_spellfile.vim index d8d954b..8abb680 100644 --- a/src/testdir/test_spellfile.vim +++ b/src/testdir/test_spellfile.vim @@ -845,6 +845,22 @@ func Test_spell_add_word() %bw! endfunc +func Test_spell_add_long_word() + set spell spellfile=./Xspellfile.add spelllang=en + + let word = repeat('a', 9000) + let v:errmsg = '' + " Spell checking doesn't really work for such a long word, + " but this should not cause an E1510 error. + exe 'spellgood ' .. word + call assert_equal('', v:errmsg) + call assert_equal([word], readfile('./Xspellfile.add')) + + set spell& spellfile= spelllang& encoding=utf-8 + call delete('./Xspellfile.add') + call delete('./Xspellfile.add.spl') +endfunc + func Test_spellfile_verbose() call writefile(['1', 'one'], 'XtestVerbose.dic', 'D') call writefile([], 'XtestVerbose.aff', 'D') diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim index afdc104..b25cd60 100644 --- a/src/testdir/test_substitute.vim +++ b/src/testdir/test_substitute.vim @@ -806,7 +806,7 @@ func Test_replace_keeppatterns() a foobar -substitute foo asdf +substitute foo asdf foo one two . @@ -815,21 +815,26 @@ one two /^substitute s/foo/bar/ call assert_equal('foo', @/) - call assert_equal('substitute bar asdf', getline('.')) + call assert_equal('substitute bar asdf foo', getline('.')) /^substitute keeppatterns s/asdf/xyz/ call assert_equal('^substitute', @/) - call assert_equal('substitute bar xyz', getline('.')) + call assert_equal('substitute bar xyz foo', getline('.')) + + /^substitute + & + call assert_equal('^substitute', @/) + call assert_equal('substitute bar xyz bar', getline('.')) exe "normal /bar /e\<CR>" call assert_equal(15, col('.')) normal - keeppatterns /xyz call assert_equal('bar ', @/) - call assert_equal('substitute bar xyz', getline('.')) + call assert_equal('substitute bar xyz bar', getline('.')) exe "normal 0dn" - call assert_equal('xyz', getline('.')) + call assert_equal('xyz bar', getline('.')) close! endfunc diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 3624790..1a40567 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -965,6 +965,64 @@ func Test_tabpage_alloc_failure() call assert_equal(1, tabpagenr('$')) endfunc +func Test_tabpage_tabclose() + " Default behaviour, move to the right. + call s:reconstruct_tabpage_for_test(6) + norm! 4gt + setl tcl= + tabclose + call assert_equal("n3", bufname()) + + " Move to the left. + call s:reconstruct_tabpage_for_test(6) + norm! 4gt + setl tcl=left + tabclose + call assert_equal("n1", bufname()) + + " Move to the last used tab page. + call s:reconstruct_tabpage_for_test(6) + norm! 5gt + norm! 2gt + setl tcl=uselast + tabclose + call assert_equal("n3", bufname()) + + " Same, but the last used tab page is invalid. Move to the right. + call s:reconstruct_tabpage_for_test(6) + norm! 5gt + norm! 3gt + setl tcl=uselast + tabclose 5 + tabclose! + call assert_equal("n2", bufname()) + + " Same, but the last used tab page is invalid. Move to the left. + call s:reconstruct_tabpage_for_test(6) + norm! 5gt + norm! 3gt + setl tcl=uselast,left + tabclose 5 + tabclose! + call assert_equal("n0", bufname()) + + " Move left when moving right is not possible. + call s:reconstruct_tabpage_for_test(6) + setl tcl= + norm! 6gt + tabclose + call assert_equal("n3", bufname()) + + " Move right when moving left is not possible. + call s:reconstruct_tabpage_for_test(6) + setl tcl=left + norm! 1gt + tabclose + call assert_equal("n0", bufname()) + + setl tcl& +endfunc + " this was giving ml_get errors func Test_tabpage_last_line() enew diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 432906e..c241937 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -958,8 +958,63 @@ func Test_tag_stack() call settagstack(1, {'items' : []}) call assert_fails('pop', 'E73:') + " References to wiped buffer are deleted. + for i in range(10, 20) + edit Xtest + exe "tag var" .. i + endfor + edit Xtest + + let t = gettagstack() + call assert_equal(11, t.length) + call assert_equal(12, t.curidx) + + bwipe! + + let t = gettagstack() + call assert_equal(0, t.length) + call assert_equal(1, t.curidx) + + " References to wiped buffer are deleted with multiple tabpages. + let w1 = win_getid() + call settagstack(1, {'items' : []}) + for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor + enew + + new + let w2 = win_getid() + call settagstack(1, {'items' : []}) + for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor + enew + + tabnew + let w3 = win_getid() + call settagstack(1, {'items' : []}) + for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor + enew + + new + let w4 = win_getid() + call settagstack(1, {'items' : []}) + for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor + enew + + for w in [w1, w2, w3, w4] + let t = gettagstack(w) + call assert_equal(11, t.length) + call assert_equal(12, t.curidx) + endfor + + bwipe! Xtest + + for w in [w1, w2, w3, w4] + let t = gettagstack(w) + call assert_equal(0, t.length) + call assert_equal(1, t.curidx) + endfor + + %bwipe! set tags& - %bwipe endfunc " Test for browsing multiple matching tags diff --git a/src/testdir/test_taglist.vim b/src/testdir/test_taglist.vim index 2dd2366..c5c7df2 100644 --- a/src/testdir/test_taglist.vim +++ b/src/testdir/test_taglist.vim @@ -100,9 +100,9 @@ func Test_tagfiles() help let tf = tagfiles() - " if 'helplang includes another language, then we may find - " 2 tagfiles (e.g.: for EN and RU) - " we may need to adjust this, if further translated help files are included + " If 'helplang' includes another language, then we may find 2 tagfiles + " (e.g.: for EN and RU). + " We may need to adjust this, if further translated help files are included. call assert_inrange(1, 2, len(tf)) call assert_equal(fnamemodify(expand('$VIMRUNTIME/doc/tags'), ':p:gs?\\?/?'), \ fnamemodify(tf[0], ':p:gs?\\?/?')) @@ -127,6 +127,47 @@ func Test_tagsfile_without_trailing_newline() set tags& endfunc +" Check that specifying a stop directory in 'tags' works properly. +func Test_tagfiles_stopdir() + let save_cwd = getcwd() + + call mkdir('Xtagsdir1/Xtagsdir2/Xtagsdir3', 'pR') + call writefile([], 'Xtagsdir1/Xtags', 'D') + + cd Xtagsdir1/ + let &tags = './Xtags;' .. fnamemodify('..', ':p') + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir2/ + let &tags = './Xtags;' .. fnamemodify('..', ':p') + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir3/ + let &tags = './Xtags;' .. fnamemodify('..', ':p') + call assert_equal(0, len(tagfiles())) + + let &tags = './Xtags;../' + call assert_equal(0, len(tagfiles())) + + cd .. + call assert_equal(1, len(tagfiles())) + + cd .. + call assert_equal(1, len(tagfiles())) + + let &tags = './Xtags;..' + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir2/ + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir3/ + call assert_equal(0, len(tagfiles())) + + set tags& + call chdir(save_cwd) +endfunc + " Test for ignoring comments in a tags file func Test_tagfile_ignore_comments() call writefile([ diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index 7e450d9..507753c 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -2256,6 +2256,17 @@ func Test_modifyOtherKeys_mapped() iunmap ' iunmap <C-W><C-A> + + " clean buffer + %d _ + imap B b + imap BBB blimp + let input = repeat(GetEscCodeCSI27('B', 2), 3) + call feedkeys("a" .. input .. "\<Esc>", 'Lx!') + call assert_equal('blimp', getline(1)) + " cleanup + iunmap BBB + iunmap B set timeoutlen& endfunc diff --git a/src/testdir/test_termdebug.vim b/src/testdir/test_termdebug.vim index a9762df..b5c12ae 100644 --- a/src/testdir/test_termdebug.vim +++ b/src/testdir/test_termdebug.vim @@ -63,6 +63,7 @@ func Test_termdebug_basic() edit XTD_basic.c Termdebug ./XTD_basic + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) let gdb_buf = winbufnr(1) wincmd b @@ -123,13 +124,13 @@ func Test_termdebug_basic() " 60 is approx spaceBuffer * 3 if winwidth(0) <= 78 + 60 Var - call assert_equal(winnr(), winnr('$')) - call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]]) + call assert_equal(winnr('$'), winnr()) + call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]], winlayout()) let cn += 1 bw! Asm - call assert_equal(winnr(), winnr('$')) - call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]]) + call assert_equal(winnr('$'), winnr()) + call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['leaf', 1000], ['leaf', 1003 + cn]]], winlayout()) let cn += 1 bw! endif @@ -138,16 +139,16 @@ func Test_termdebug_basic() let winw = winwidth(0) Var if winwidth(0) < winw - call assert_equal(winnr(), winnr('$') - 1) - call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]]) + call assert_equal(winnr('$') - 1, winnr()) + call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]], winlayout()) let cn += 1 bw! endif let winw = winwidth(0) Asm if winwidth(0) < winw - call assert_equal(winnr(), winnr('$') - 1) - call assert_equal(winlayout(), ['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]]) + call assert_equal(winnr('$') - 1, winnr()) + call assert_equal(['col', [['leaf', 1002], ['leaf', 1001], ['row', [['leaf', 1003 + cn], ['leaf', 1000]]]]], winlayout()) let cn += 1 bw! endif @@ -160,6 +161,19 @@ func Test_termdebug_basic() call WaitForAssert({-> assert_equal(1, winnr('$'))}) call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs) + for use_prompt in [v:true, v:false] + let g:termdebug_config = {} + let g:termdebug_config['use_prompt'] = use_prompt + TermdebugCommand ./XTD_basic arg args + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) + call WaitForAssert({-> assert_equal(3, winnr('$'))}) + wincmd t + quit! + redraw! + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + unlet g:termdebug_config + endfor + call s:cleanup_files(bin_name) %bw! endfunc @@ -174,6 +188,7 @@ func Test_termdebug_tbreak() execute 'edit ' .. src_name execute 'Termdebug ./' .. bin_name + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) let gdb_buf = winbufnr(1) wincmd b @@ -234,6 +249,7 @@ func Test_termdebug_mapping() call assert_true(maparg('-', 'n', 0, 1)->empty()) call assert_true(maparg('+', 'n', 0, 1)->empty()) Termdebug + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b call assert_false(maparg('K', 'n', 0, 1)->empty()) @@ -256,6 +272,7 @@ func Test_termdebug_mapping() nnoremap - :echom "-"<cr> nnoremap + :echom "+"<cr> Termdebug + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b call assert_false(maparg('K', 'n', 0, 1)->empty()) @@ -278,76 +295,184 @@ func Test_termdebug_mapping() call assert_equal(':echom "K"<cr>', maparg('K', 'n', 0, 1).rhs) %bw! + + " -- Test that local-buffer mappings are restored in the correct buffers -- + " local mappings for foo + file foo nnoremap <buffer> K :echom "bK"<cr> nnoremap <buffer> - :echom "b-"<cr> nnoremap <buffer> + :echom "b+"<cr> + + " no mappings for 'bar' + enew + file bar + + " Start termdebug from foo + buffer foo Termdebug + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) wincmd b call assert_true(maparg('K', 'n', 0, 1).buffer) call assert_true(maparg('-', 'n', 0, 1).buffer) call assert_true(maparg('+', 'n', 0, 1).buffer) call assert_equal(maparg('K', 'n', 0, 1).rhs, ':echom "bK"<cr>') + + Source + buffer bar + call assert_false(maparg('K', 'n', 0, 1)->empty()) + call assert_false(maparg('-', 'n', 0, 1)->empty()) + call assert_false(maparg('+', 'n', 0, 1)->empty()) + call assert_true(maparg('K', 'n', 0, 1).buffer->empty()) + call assert_true(maparg('-', 'n', 0, 1).buffer->empty()) + call assert_true(maparg('+', 'n', 0, 1).buffer->empty()) wincmd t quit! redraw! call WaitForAssert({-> assert_equal(1, winnr('$'))}) + + " Termdebug session ended. Buffer 'bar' shall have no mappings + call assert_true(bufname() ==# 'bar') + call assert_false(maparg('K', 'n', 0, 1)->empty()) + call assert_false(maparg('-', 'n', 0, 1)->empty()) + call assert_false(maparg('+', 'n', 0, 1)->empty()) + call assert_true(maparg('K', 'n', 0, 1).buffer->empty()) + call assert_true(maparg('-', 'n', 0, 1).buffer->empty()) + call assert_true(maparg('+', 'n', 0, 1).buffer->empty()) + + " Buffer 'foo' shall have the same mapping as before running the termdebug + " session + buffer foo + call assert_true(bufname() ==# 'foo') call assert_true(maparg('K', 'n', 0, 1).buffer) call assert_true(maparg('-', 'n', 0, 1).buffer) call assert_true(maparg('+', 'n', 0, 1).buffer) call assert_equal(':echom "bK"<cr>', maparg('K', 'n', 0, 1).rhs) + nunmap K + nunmap + + nunmap - %bw! endfunc -func Test_termdebug_bufnames() - " Test if user has filename/folders named gdb, Termdebug-gdb-console, - " etc. in the current directory +function Test_termdebug_save_restore_variables() + " saved mousemodel + let &mousemodel='' + + " saved keys + nnoremap K :echo "hello world!"<cr> + let expected_map_K = maparg('K', 'n', 0 , 1) + nnoremap + :echo "hello plus!"<cr> + let expected_map_plus = maparg('+', 'n', 0 , 1) + let expected_map_minus = {} + + " saved &columns + let expected_columns = &columns + + " We want termdebug to overwrite 'K' map but not '+' map. let g:termdebug_config = {} - let g:termdebug_config['use_prompt'] = 1 - let filename = 'gdb' - let replacement_filename = 'Termdebug-gdb-console' + let g:termdebug_config['map_K'] = v:true - call writefile(['This', 'is', 'a', 'test'], filename, 'D') - " Throw away the file once the test has done. Termdebug - " Once termdebug has completed the startup you should have 3 windows on screen + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) - " A file named filename already exists in the working directory, - " hence you must call the newly created buffer differently - call WaitForAssert({-> assert_false(bufexists(filename))}) - call WaitForAssert({-> assert_true(bufexists(replacement_filename))}) + call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')}) + wincmd t quit! call WaitForAssert({-> assert_equal(1, winnr('$'))}) - " Check if error message is in :message - let g:termdebug_config['disasm_window'] = 1 - let filename = 'Termdebug-asm-listing' - call writefile(['This', 'is', 'a', 'test'], filename, 'D') - " Check only the head of the error message - let error_message = "You have a file/folder named '" .. filename .. "'" - Termdebug - " Once termdebug has completed the startup you should have 4 windows on screen - call WaitForAssert({-> assert_equal(4, winnr('$'))}) - call WaitForAssert({-> assert_notequal(-1, stridx(execute('messages'), error_message))}) - quit! - wincmd b - wincmd q - call WaitForAssert({-> assert_equal(1, winnr('$'))}) + call assert_true(empty(&mousemodel)) + call assert_true(empty(expected_map_minus)) + call assert_equal(expected_map_K.rhs, maparg('K', 'n', 0, 1).rhs) + call assert_equal(expected_map_plus.rhs, maparg('+', 'n', 0, 1).rhs) + + call assert_equal(expected_columns, &columns) + + nunmap K + nunmap + unlet g:termdebug_config -endfunc +endfunction -function Test_termdebug_save_restore_variables() - let &mousemodel='' +function Test_termdebug_sanity_check() + " Test if user has filename/folders with wrong names + let g:termdebug_config = {} + let s:dict = {'disasm_window': 'Termdebug-asm-listing', 'use_prompt': 'gdb', 'variables_window': 'Termdebug-variables-listing'} + + for key in keys(s:dict) + let s:filename = s:dict[key] + let g:termdebug_config[key] = v:true + let s:error_message = "You have a file/folder named '" .. s:filename .. "'" + + " Write dummy file with bad name + call writefile(['This', 'is', 'a', 'test'], s:filename, 'D') + Termdebug + call WaitForAssert({-> assert_true(execute('messages') =~ s:error_message)}) + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + + call delete(s:filename) + call remove(g:termdebug_config, key) + endfor + + unlet g:termdebug_config +endfunction + +function Test_termdebug_double_termdebug_instances() + let s:error_message = 'Terminal debugger already running, cannot run two' Termdebug + call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))}) call WaitForAssert({-> assert_equal(3, winnr('$'))}) - call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')}) + Termdebug + call WaitForAssert({-> assert_true(execute('messages') =~ s:error_message)}) wincmd t quit! call WaitForAssert({-> assert_equal(1, winnr('$'))}) - call WaitForAssert({-> assert_true(empty(&mousemodel))}) + :%bw! endfunction +function Test_termdebug_config_types() + " TODO Remove the deprecated features after 1 Jan 2025. + let g:termdebug_config = {} + let s:error_message = 'Deprecation Warning:' + call assert_true(maparg('K', 'n', 0, 1)->empty()) + + for key in ['disasm_window', 'variables_window', 'map_K'] + for val in [0, 1, v:true, v:false] + let g:termdebug_config[key] = val + Termdebug + + " Type check: warning is displayed + if typename(val) == 'number' + call WaitForAssert({-> assert_true(execute('messages') =~ s:error_message)}) + endif + + " Test on g:termdebug_config keys + if val && key != 'map_K' + call WaitForAssert({-> assert_equal(4, winnr('$'))}) + call remove(g:termdebug_config, key) + else + call WaitForAssert({-> assert_equal(3, winnr('$'))}) + endif + + " Test on mapping + if key == 'map_K' + if val + call assert_equal(':Evaluate<CR>', maparg('K', 'n', 0, 1).rhs) + else + call assert_true(maparg('K', 'n', 0, 1)->empty()) + endif + endif + + " Shutoff termdebug + wincmd t + quit! + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + :%bw! + + endfor + endfor + + unlet g:termdebug_config +endfunction " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_textobjects.vim b/src/testdir/test_textobjects.vim index d5e772d..2622b06 100644 --- a/src/testdir/test_textobjects.vim +++ b/src/testdir/test_textobjects.vim @@ -201,6 +201,18 @@ func Test_string_html_objects() normal! 2k0vaty call assert_equal("<div><div\nattr=\"attr\"\n></div></div>", @", e) + " tag, that includes a > in some attribute + let t = "<div attr=\"attr >> foo >> bar \">Hello</div>" + $put =t + normal! fHyit + call assert_equal("Hello", @", e) + + " tag, that includes a > in some attribute + let t = "<div attr='attr >> foo >> bar '>Hello 123</div>" + $put =t + normal! fHyit + call assert_equal("Hello 123", @", e) + set quoteescape& " this was going beyond the end of the line diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index 2bf2834..57277f7 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -2901,6 +2901,10 @@ func Test_prop_inserts_text_before_double_width_wrap() call writefile(lines, 'XscriptPropsBeforeDoubleWidthWrap', 'D') let buf = RunVimInTerminal('-S XscriptPropsBeforeDoubleWidthWrap', #{rows: 3, cols: 50}) call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_double_width_wrap_1', {}) + call term_sendkeys(buf, 'g0') + call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_double_width_wrap_2', {}) + call term_sendkeys(buf, ":set showbreak=+++\<CR>") + call VerifyScreenDump(buf, 'Test_prop_inserts_text_before_double_width_wrap_3', {}) call StopVimInTerminal(buf) endfunc diff --git a/src/testdir/test_tohtml.vim b/src/testdir/test_tohtml.vim new file mode 100644 index 0000000..a1c8572 --- /dev/null +++ b/src/testdir/test_tohtml.vim @@ -0,0 +1,72 @@ +" Tests for Vim :TOhtml + +source check.vim + +func s:setup_basic(src_name) + let lines =<< trim END + #include <stdio.h> + #include <stdlib.h> + + int isprime(int n) + { + if (n <= 1) + return 0; + + for (int i = 2; i <= n / 2; i++) + if (n % i == 0) + return 0; + + return 1; + } + + int main(int argc, char *argv[]) + { + int n = 7; + + printf("%d is %s prime\n", n, isprime(n) ? "a" : "not a"); + + return 0; + } + END + call writefile(lines, a:src_name) + exe 'edit ' . a:src_name + TOhtml + write +endfunc + +func s:cleanup_basic(src_name) + call delete(a:src_name) + call delete(a:src_name . ".html") +endfunc + +source $VIMRUNTIME/plugin/tohtml.vim + +func Test_tohtml_basic() + let src_name = "Test_tohtml_basic.c" + call s:setup_basic(src_name) + let expected = readfile("samples/" . src_name . ".html") + let actual = readfile(src_name . ".html") + call assert_equal(expected[0:3], actual[0:3]) + " Ignore the title + call assert_equal(expected[5:11], actual[5:11]) + " Ignore pre and body css + call assert_equal(expected[14:], actual[14:]) + call s:cleanup_basic(src_name) +endfunc + +func Test_tohtml_basic_no_css() + let g:html_use_css = 0 + let src_name = "Test_tohtml_basic_no_css.c" + call s:setup_basic(src_name) + let expected = readfile("samples/" . src_name . ".html") + let actual = readfile(src_name . ".html") + call assert_equal(expected[0:3], actual[0:3]) + " Ignore the title + call assert_equal(expected[5:10], actual[5:10]) + " Ignore body's inline css + call assert_equal(expected[12:], actual[12:]) + call s:cleanup_basic(src_name) + unlet g:html_use_css +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_usercommands.vim b/src/testdir/test_usercommands.vim index e161ee6..fe08b95 100644 --- a/src/testdir/test_usercommands.vim +++ b/src/testdir/test_usercommands.vim @@ -133,6 +133,10 @@ function Test_cmdmods() \ 'silent verbose aboveleft belowright botright tab topleft vertical', \ g:mods) + kee keep keepm keepma keepmar keepmarks keepa keepalt keepj keepjumps + \ keepp keeppatterns MyCmd + call assert_equal('keepalt keepjumps keepmarks keeppatterns', g:mods) + let g:mods = '' command! -nargs=* MyQCmd let g:mods .= '<q-mods> ' diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 6b1a50d..7ed9123 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -497,6 +497,56 @@ def Test_call_call() v9.CheckSourceDefAndScriptFailure(['call("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) enddef +def Test_call_imports() + # Use call with an imported function + var lines =<< trim END + vim9script + + export const foo = 'foo' + + export def Imported() + enddef + + var count: number + export def ImportedListArg(l: list<number>) + count += 1 + l[0] += count + enddef + END + writefile(lines, 'Test_call_imports_importme', 'D') + lines =<< trim END + vim9script + import './Test_call_imports_importme' as i_imp + + var l = [12] + call('i_imp.ImportedListArg', [l]) + assert_equal(13, l[0]) + const ImportedListArg = i_imp.ImportedListArg + call('ImportedListArg', [l]) + assert_equal(15, l[0]) + const Imported = i_imp.Imported + call("Imported", []) + + assert_equal('foo', i_imp.foo) + const foo = i_imp.foo + assert_equal('foo', foo) + END + v9.CheckSourceScriptSuccess(lines) + + # A few error cases + lines =<< trim END + vim9script + import './Test_call_imports_importme' as i_imp + const Imported = i_imp.Imported + const foo = i_imp.foo + + assert_fails('call("i_imp.foo", [])', 'E117:') # foo is not a function + assert_fails('call("foo", [])', 'E117:') # foo is not a function + assert_fails('call("i_xxx.foo", [])', 'E117:') # i_xxx not imported file + END + v9.CheckSourceScriptSuccess(lines) +enddef + def Test_ch_canread() if !has('channel') CheckFeature channel @@ -1969,6 +2019,17 @@ def Test_getreginfo() getreginfo('').regcontents->assert_equal(['D1E2F3']) enddef +def Test_getregionpos() + var lines =<< trim END + cursor(1, 1) + var pos = getregionpos(getpos('.'), getpos('$')) + for p in pos + assert_equal(bufnr('%'), p[0][0]) + endfor + END + v9.CheckSourceDefSuccess(lines) +enddef + def Test_getregtype() var lines = ['aaa', 'bbb', 'ccc'] setreg('a', lines) @@ -3152,6 +3213,11 @@ def Test_popup_settext() v9.CheckSourceDefAndScriptFailure(['popup_settext(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2']) enddef +def Test_popup_setbuf() + v9.CheckSourceDefAndScriptFailure(['popup_setbuf([], "abc")'], ['E1013: Argument 1: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_setbuf(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) +enddef + def Test_popup_show() v9.CheckSourceDefAndScriptFailure(['popup_show("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) v9.CheckSourceDefAndScriptFailure(['popup_show(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index e92fcc5..8791a52 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -661,6 +661,44 @@ def Test_object_not_set() Func() END v9.CheckSourceFailure(lines, 'E1363: Incomplete type', 1) + + # Reference a object variable through a null class object which is stored in a + # variable of type "any". + lines =<< trim END + vim9script + + def Z() + var o: any = null_object + o.v = 4 + enddef + Z() + END + v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2) + + # Do "echom" of a null object variable. + lines =<< trim END + vim9script + + def X() + var x = null_object + echom x + enddef + X() + END + v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 2) + + # Use a null object variable that vim wants to force to number. + lines =<< trim END + vim9script + + def X() + var o = null_object + var l = [ 1, o] + sort(l, 'N') + enddef + X() + END + v9.CheckSourceFailure(lines, 'E1324: Using an Object as a String', 3) enddef " Null object assignment and comparison @@ -2246,6 +2284,47 @@ def Test_class_object_to_string() assert_equal("object of TextPosition {lnum: 1, col: 22}", string(pos)) END v9.CheckSourceSuccess(lines) + + # check string() with object nesting + lines =<< trim END + vim9script + class C + var nest1: C + var nest2: C + def Init(n1: C, n2: C) + this.nest1 = n1 + this.nest2 = n2 + enddef + endclass + + var o1 = C.new() + var o2 = C.new() + o1.Init(o1, o2) + o2.Init(o2, o1) + + # The following previously put's vim into an infinite loop. + + var expect = "object of C {nest1: object of C {...}, nest2: object of C {nest1: object of C {...}, nest2: object of C {...}}}" + assert_equal(expect, string(o1)) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + + class B + endclass + + class C + var b: B + var c: C + endclass + + var o1 = C.new(B.new(), C.new(B.new())) + var expect = "object of C {b: object of B {}, c: object of C {b: object of B {}, c: object of [unknown]}}" + assert_equal(expect, string(o1)) + END + v9.CheckSourceSuccess(lines) enddef def Test_interface_basics() @@ -3173,6 +3252,141 @@ def Test_using_base_class() v9.CheckSourceSuccess(lines) enddef +def Test_super_dispatch() + # See #15448 and #15463 + var lines =<< trim END + vim9script + + class A + def String(): string + return 'A' + enddef + endclass + + class B extends A + def String(): string + return super.String() + enddef + endclass + + class C extends B + endclass + + assert_equal('A', C.new().String()) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + + class A + def F(): string + return 'AA' + enddef + endclass + + class B extends A + def F(): string + return 'BB' + enddef + def S(): string + return super.F() + enddef + def S0(): string + return this.S() + enddef + endclass + + class C extends B + def F(): string + return 'CC' + enddef + def ToB(): string + return super.F() + enddef + endclass + + assert_equal('AA', B.new().S()) + assert_equal('AA', C.new().S()) + assert_equal('AA', B.new().S0()) + assert_equal('AA', C.new().S0()) + + assert_equal('BB', C.new().ToB()) + + assert_equal('CC', C.new().F()) + assert_equal('BB', B.new().F()) + assert_equal('AA', A.new().F()) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + + var call_chain: list<string> + + abstract class A + abstract def _G(): string + + def F(): string + call_chain->add('A.F()') + return this._G() + enddef + def _H(): string + call_chain->add('A._H()') + return this.F() + enddef + endclass + + class B extends A + def _G(): string + call_chain->add('B.G()') + return 'BBB' + enddef + def SF(): string + call_chain->add('B.SF()') + return super._H() + enddef + endclass + + class C extends B + endclass + + class D extends C + def SF(): string + call_chain->add('D.SF()') + return super.SF() + enddef + endclass + + class E extends D + def SF(): string + call_chain->add('E.SF()') + return super.SF() + enddef + endclass + + class F extends E + def _G(): string + call_chain->add('F._G()') + return 'FFF' + enddef + endclass + + # E.new() -> A.F() -> B._G() + call_chain = [] + var o1 = E.new() + assert_equal('BBB', o1.F()) + assert_equal(['A.F()', 'B.G()'], call_chain) + + # F.new() -> E.SF() -> D.SF() -> B.SF() -> A._H() -> A.F() -> F._G() + call_chain = [] + var o2 = F.new() + assert_equal('FFF', o2.SF()) + assert_equal(['E.SF()', 'D.SF()', 'B.SF()', 'A._H()', 'A.F()', 'F._G()'], call_chain) + END + v9.CheckSourceSuccess(lines) +enddef + def Test_class_import() var lines =<< trim END vim9script @@ -7162,6 +7376,47 @@ def Test_null_object_method_call() T() END v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2) + + # Calling an object method defined in a class that is extended. This differs + # from the previous by invoking ISN_METHODCALL instead of ISN_DCALL. + lines =<< trim END + vim9script + + class C0 + def F() + enddef + endclass + + class C extends C0 + endclass + + def X() + var o: C0 = null_object + o.F() + enddef + X() + END + v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2) + + # Getting a function ref an object method. + lines =<< trim END + vim9script + + class C0 + def F() + enddef + endclass + + class C extends C0 + endclass + + def X() + var o: C0 = null_object + var XXX = o.F + enddef + X() + END + v9.CheckSourceFailure(lines, 'E1360: Using a null object', 2) enddef " Test for using a dict as an object member @@ -10425,6 +10680,20 @@ func Test_object_string() call v9.CheckSourceSuccess(lines) endfunc +" Test for using the string() builtin method with an object's method +def Test_method_string() + var lines =<< trim END + vim9script + class A + def F() + enddef + endclass + assert_match('function(''<SNR>\d\+_A\.F'')', string(A.new().F)) + END + v9.CheckScriptSuccess(lines) +enddef + + " Test for using a class in the class definition def Test_Ref_Class_Within_Same_Class() var lines =<< trim END @@ -10486,6 +10755,156 @@ def Test_Ref_Class_Within_Same_Class() v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3) enddef +" Test for comparing a class referencing itself +def Test_Object_Compare_With_Recursive_Class_Ref() + var lines =<< trim END + vim9script + + class C + public var nest: C + endclass + + var o1 = C.new() + o1.nest = o1 + + var result = o1 == o1 + assert_equal(true, result) + END + v9.CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + + class C + public var nest: C + endclass + var o1 = C.new() + var o2 = C.new(C.new()) + + var result = o1 == o2 + assert_equal(false, result) + END + v9.CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + class C + var nest1: C + var nest2: C + def Init(n1: C, n2: C) + this.nest1 = n1 + this.nest2 = n2 + enddef + endclass + + var o1 = C.new() + var o2 = C.new() + o1.Init(o1, o2) + o2.Init(o2, o1) + + var result = o1 == o2 + assert_equal(true, result) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for comparing a class with nesting objects +def Test_Object_Compare_With_Nesting_Objects() + # On a compare, after vim equal recurses 1000 times, not finding an unequal, + # return the compare is equal. + # Test that limit + + var lines =<< trim END + vim9script + class C + public var n: number + public var nest: C + + # Create a "C" that chains/nests to indicated depth. + # return {head: firstC, tail: lastC} + static def CreateNested(depth: number): dict<C> + var first = C.new(1, null_object) + var last = first + for i in range(2, depth) + last.nest = C.new(i, null_object) + last = last.nest + endfor + return {head: first, tail: last} + enddef + + # Return pointer to nth item in chain. + def GetLink(depth: number): C + var count = 1 + var p: C = this + while count < depth + p = p.nest + if p == null + throw "too deep" + endif + count += 1 + endwhile + return p + enddef + + # Return the length of the chain + def len(): number + var count = 1 + var p: C = this + while p.nest != null + p = p.nest + count += 1 + endwhile + return count + enddef + endclass + + var chain = C.CreateNested(3) + var s = "object of C {n: 1, nest: object of C {n: 2, nest: object of C {n: 3, nest: object of [unknown]}}}" + assert_equal(s, string(chain.head)) + assert_equal(3, chain.head->len()) + + var chain1 = C.CreateNested(100) + var chain2 = C.CreateNested(100) + assert_true(chain1.head == chain2.head) + + # modify the tail of chain2, compare not equal + chain2.tail.n = 123456 + assert_true(chain1.head != chain2.head) + + # a tail of a different length compares not equal + chain2 = C.CreateNested(101) + assert_true(chain1.head != chain2.head) + + chain1 = C.CreateNested(1000) + chain2 = C.CreateNested(1000) + assert_true(chain1.head == chain2.head) + + # modify the tail of chain2, compare not equal + chain2.tail.n = 123456 + assert_true(chain1.head != chain2.head) + + # try a chain longer that the limit + chain1 = C.CreateNested(1001) + chain2 = C.CreateNested(1001) + assert_true(chain1.head == chain2.head) + + # modify the tail, but still equal + chain2.tail.n = 123456 + assert_true(chain1.head == chain2.head) + + # remove 2 items from front, shorten the chain by two. + chain1.head = chain1.head.GetLink(3) + chain2.head = chain2.head.GetLink(3) + assert_equal(3, chain1.head.n) + assert_equal(3, chain2.head.n) + assert_equal(999, chain1.head->len()) + assert_equal(999, chain2.head->len()) + # Now less than the limit, compare not equal + assert_true(chain1.head != chain2.head) + END + v9.CheckScriptSuccess(lines) +enddef + " Test for using a compound operator from a lambda function in an object method def Test_compound_op_in_objmethod_lambda() # Test using the "+=" operator @@ -10744,4 +11163,54 @@ def Test_class_object_index() v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5) enddef +def Test_class_member_init_typecheck() + # Ensure the class member is assigned its declared type. + var lines =<< trim END + vim9script + class S + static var l: list<string> = [] + endclass + S.l->add(123) + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5) + + # Ensure the initializer value and the declared type match. + lines =<< trim END + vim9script + class S + var l: list<string> = [1, 2, 3] + endclass + var o = S.new() + END + v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>') + + # Ensure the class member is assigned its declared type. + lines =<< trim END + vim9script + class S + var l: list<string> = [] + endclass + var o = S.new() + o.l->add(123) + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6) +enddef + +def Test_class_cast() + var lines =<< trim END + vim9script + class A + endclass + class B extends A + var mylen: number + endclass + def F(o: A): number + return (<B>o).mylen + enddef + + defcompile F + END + v9.CheckScriptSuccess(lines) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index a9e10e7..51ae7e6 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -2036,6 +2036,14 @@ def Test_no_space_after_command() v9.CheckDefExecAndScriptFailure(lines, 'E486:', 1) enddef +def Test_lambda_crash() + # This used to crash Vim + var lines =<< trim END + vim9 () => super => { + END + v9.CheckScriptFailureList(lines, ["E1356:", "E1405:"]) +enddef + " Test for the 'previewpopup' option def Test_previewpopup() set previewpopup=height:10,width:60 @@ -2044,6 +2052,7 @@ def Test_previewpopup() assert_notequal(id, 0) assert_match('Xppfile', popup_getoptions(id).title) popup_clear() + bw Xppfile set previewpopup& enddef diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index c74cce4..7746b23 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1761,6 +1761,74 @@ def Test_disassemble_typecast() instr) enddef +def Test_disassemble_object_cast() + # Downcasting. + var lines =<< trim END + vim9script + class A + endclass + class B extends A + var mylen: number + endclass + def F(o: A): number + return (<B>o).mylen + enddef + + g:instr = execute('disassemble F') + END + v9.CheckScriptSuccess(lines) + assert_match('\<SNR>\d*_F\_s*' .. + 'return (<B>o).mylen\_s*' .. + '0 LOAD arg\[-1\]\_s*' .. + '1 CHECKTYPE object<B> stack\[-1\]\_s*' .. + '2 OBJ_MEMBER 0\_s*' .. + '3 RETURN\_s*', + g:instr) + + # Upcasting. + lines =<< trim END + vim9script + class A + var mylen: number + endclass + class B extends A + endclass + def F(o: B): number + return (<A>o).mylen + enddef + + g:instr = execute('disassemble F') + END + v9.CheckScriptSuccess(lines) + assert_match('\<SNR>\d*_F\_s*' .. + 'return (<A>o).mylen\_s*' .. + '0 LOAD arg\[-1\]\_s*' .. + '1 OBJ_MEMBER 0\_s*' .. + '2 RETURN\_s*', + g:instr) + + # Casting, type is not statically known. + lines =<< trim END + vim9script + class A + endclass + class B extends A + endclass + def F(o: any): any + return <A>o + enddef + + g:instr = execute('disassemble F') + END + v9.CheckScriptSuccess(lines) + assert_match('\<SNR>\d*_F\_s*' .. + 'return <A>o\_s*' .. + '0 LOAD arg\[-1\]\_s*' .. + '1 CHECKTYPE object<A> stack\[-1\]\_s*' .. + '2 RETURN\_s*', + g:instr) +enddef + def s:Computing() var nr = 3 var nrres = nr + 7 @@ -3496,4 +3564,26 @@ def Test_disassemble_compound_op_in_closure() unlet g:instr enddef +def Test_disassemble_member_initializer() + var lines =<< trim END + vim9script + class A + var l: list<string> = [] + var d: dict<string> = {} + endclass + g:instr = execute('disassemble A.new') + END + v9.CheckScriptSuccess(lines) + # Ensure SETTYPE is emitted and that matches the declared type. + assert_match('new\_s*' .. + '0 NEW A size \d\+\_s*' .. + '1 NEWLIST size 0\_s*' .. + '2 SETTYPE list<string>\_s*' .. + '3 STORE_THIS 0\_s*' .. + '4 NEWDICT size 0\_s*' .. + '5 SETTYPE dict<string>\_s*' .. + '6 STORE_THIS 1', g:instr) + unlet g:instr +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index d07bbfb..030ff83 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -164,6 +164,16 @@ def Test_wrong_function_name() END v9.CheckScriptFailure(lines, 'E1182:') delfunc g:Define + + lines =<< trim END + vim9script + var F1_ref: func + def Start() + F1_ref() + enddef + Start() + END + v9.CheckScriptFailure(lines, 'E117:') enddef " Check that in a legacy script a :def accesses the correct script variables. diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 0b17150..bcb590d 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -4007,7 +4007,7 @@ def Test_restoring_cpo() edit XanotherScript so % assert_equal('aABceFsMny>', &cpo) - assert_equal('aABceFs', g:cpoval) + assert_equal('aABceFsz', g:cpoval) :1del setline(1, 'let g:cpoval = &cpo') w @@ -4048,10 +4048,10 @@ def Test_restoring_cpo() exe "silent !" .. cmd assert_equal([ - 'before: aABceFs', - 'after: aABceFsM', - 'later: aABceFsM', - 'vim9: aABceFs'], readfile('Xrporesult')) + 'before: aABceFsz', + 'after: aABceFszM', + 'later: aABceFszM', + 'vim9: aABceFsz'], readfile('Xrporesult')) $HOME = save_HOME delete('Xrporesult') @@ -5085,15 +5085,19 @@ def Test_null_values() var nullValues = [ [null, 1, 'null', 7, 'special'], [null_blob, 1, '0z', 10, 'blob'], - [null_channel, 1, 'channel fail', 9, 'channel'], [null_dict, 1, '{}', 4, 'dict<any>'], [null_function, 1, "function('')", 2, 'func(...): unknown'], - [null_job, 1, 'no process', 8, 'job'], [null_list, 1, '[]', 3, 'list<any>'], [null_object, 1, 'object of [unknown]', 13, 'object<Unknown>'], [null_partial, 1, "function('')", 2, 'func(...): unknown'], [null_string, 1, "''", 1, 'string'] ] + if has('channel') + nullValues->add([null_channel, 1, 'channel fail', 9, 'channel']) + endif + if has('job') + nullValues->add([null_job, 1, 'no process', 8, 'job']) + endif for [Val, emptyExp, stringExp, typeExp, typenameExp] in nullValues assert_equal(emptyExp, empty(Val)) diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index 8976779..21f894e 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -7536,6 +7536,31 @@ func Test_deeply_nested_source() call system(cmd) endfunc +func Test_exception_silent() + XpathINIT + let lines =<< trim END + func Throw() + Xpath 'a' + throw "Uncaught" + " This line is not executed. + Xpath 'b' + endfunc + " The exception is suppressed due to the presence of silent!. + silent! call Throw() + try + call DoesNotExist() + catch /E117:/ + Xpath 'c' + endtry + Xpath 'd' + END + let verify =<< trim END + call assert_equal('acd', g:Xpath) + END + + call RunInNewVim(lines, verify) +endfunc + "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_winfixbuf.vim b/src/testdir/test_winfixbuf.vim index f800338..3cec4ed 100644 --- a/src/testdir/test_winfixbuf.vim +++ b/src/testdir/test_winfixbuf.vim @@ -2934,6 +2934,7 @@ func Test_tfirst() \ "Xtags", 'D') call writefile(["one", "two", "three"], "Xfile", 'D') call writefile(["one"], "Xother", 'D') + tag one edit Xother set winfixbuf diff --git a/src/testdir/test_xxd.vim b/src/testdir/test_xxd.vim index a91a1fc..99e4998 100644 --- a/src/testdir/test_xxd.vim +++ b/src/testdir/test_xxd.vim @@ -73,21 +73,21 @@ func Test_xxd() exe '0r! ' . s:xxd_cmd . ' -l 120 -ps -c20 ' . man_copy $d let expected = [ - \ '2e54482058584420312022417567757374203139', - \ '39362220224d616e75616c207061676520666f72', - \ '20787864220a2e5c220a2e5c222032317374204d', - \ '617920313939360a2e5c22204d616e2070616765', - \ '20617574686f723a0a2e5c2220202020546f6e79', - \ '204e7567656e74203c746f6e79407363746e7567'] + \ '2e544820585844203120224d6179203230323422', + \ '20224d616e75616c207061676520666f72207878', + \ '64220a2e5c220a2e5c222032317374204d617920', + \ '313939360a2e5c22204d616e2070616765206175', + \ '74686f723a0a2e5c2220202020546f6e79204e75', + \ '67656e74203c746f6e79407363746e7567656e2e'] call assert_equal(expected, getline(1,'$'), s:Mess(s:test)) " Test 6: Print the date from xxd.1 let s:test += 1 for arg in ['-l 13', '-l13', '-len 13'] %d - exe '0r! ' . s:xxd_cmd . ' -s 0x36 ' . arg . ' -cols 13 ' . man_copy + exe '0r! ' . s:xxd_cmd . ' -s 0x33 ' . arg . ' -cols 13 ' . man_copy $d - call assert_equal('00000036: 3231 7374 204d 6179 2031 3939 36 21st May 1996', getline(1), s:Mess(s:test)) + call assert_equal('00000033: 3231 7374 204d 6179 2031 3939 36 21st May 1996', getline(1), s:Mess(s:test)) endfor " Cleanup after tests 5 and 6 diff --git a/src/testdir/test_zip_plugin.vim b/src/testdir/test_zip_plugin.vim new file mode 100644 index 0000000..e831f26 --- /dev/null +++ b/src/testdir/test_zip_plugin.vim @@ -0,0 +1,237 @@ +so check.vim + +CheckExecutable unzip + +if 0 " Find uncovered line + profile start zip_profile + profile! file */zip*.vim +endif + +runtime plugin/zipPlugin.vim + +def Test_zip_basic() + + ### get our zip file + if !filecopy("samples/test.zip", "X.zip") + assert_report("Can't copy samples/test.zip") + return + endif + defer delete("X.zip") + + e X.zip + + ### Check header + assert_match('^" zip\.vim version v\d\+', getline(1)) + assert_match('^" Browsing zipfile .*/X.zip', getline(2)) + assert_match('^" Select a file with cursor and press ENTER', getline(3)) + assert_match('^$', getline(4)) + + ### Check files listing + assert_equal(["Xzip/", "Xzip/dir/", "Xzip/file.txt"], getline(5, 7)) + + ### Check ENTER on header + :1 + exe ":normal \<cr>" + assert_equal("X.zip", @%) + + ### Check ENTER on directory + :1|:/^$//dir/ + assert_match('Please specify a file, not a directory', + execute("normal \<CR>")) + + ### Check ENTER on file + :1 + search('file.txt') + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::Xzip/file.txt', @%) + assert_equal('one', getline(1)) + + ### Check editing file + if executable("zip") + s/one/two/ + assert_equal("two", getline(1)) + w + bw|bw + e X.zip + + :1|:/^$//file/ + exe "normal \<cr>" + assert_equal("two", getline(1)) + endif + + only + e X.zip + + ### Check extracting file + :1|:/^$//file/ + normal x + assert_true(filereadable("Xzip/file.txt")) + + ## Check not overwriting existing file + assert_match('<Xzip/file.txt> .* not overwriting!', execute("normal x")) + + delete("Xzip", "rf") + + ### Check extracting directory + :1|:/^$//dir/ + assert_match('Please specify a file, not a directory', execute("normal x")) + assert_equal("X.zip", @%) + + ### Check "x" on header + :1 + normal x + assert_equal("X.zip", @%) + bw + + ### Check opening zip when "unzip" program is missing + var save_zip_unzipcmd = g:zip_unzipcmd + g:zip_unzipcmd = "/" + assert_match('unzip not available on your system', execute("e X.zip")) + + ### Check when "unzip" don't work + if executable("false") + g:zip_unzipcmd = "false" + assert_match('X\.zip is not a zip file', execute("e X.zip")) + endif + bw + + g:zip_unzipcmd = save_zip_unzipcmd + e X.zip + + ### Check opening file when "unzip" is missing + g:zip_unzipcmd = "/" + assert_match('sorry, your system doesn''t appear to have the / program', + execute("normal \<CR>")) + + bw|bw + g:zip_unzipcmd = save_zip_unzipcmd + e X.zip + + ### Check :write when "zip" program is missing + :1|:/^$//file/ + exe "normal \<cr>Goanother\<esc>" + var save_zip_zipcmd = g:zip_zipcmd + g:zip_zipcmd = "/" + assert_match('sorry, your system doesn''t appear to have the / program', + execute("write")) + + ### Check when "zip" report failure + if executable("false") + g:zip_zipcmd = "false" + assert_match('sorry, unable to update .*/X.zip with Xzip/file.txt', + execute("write")) + endif + bw!|bw + + g:zip_zipcmd = save_zip_zipcmd + + ### Check opening an no zipfile + writefile(["qsdf"], "Xcorupt.zip", "D") + e! Xcorupt.zip + assert_equal("qsdf", getline(1)) + + bw + + ### Check no existing zipfile + assert_match('File not readable', execute("e Xnot_exists.zip")) + + bw +enddef + +def Test_zip_glob_fname() + CheckNotMSWindows + # does not work on Windows, why? + + ### copy sample zip file + if !filecopy("samples/testa.zip", "X.zip") + assert_report("Can't copy samples/testa.zip") + return + endif + defer delete("X.zip") + defer delete('zipglob', 'rf') + + e X.zip + + ### 1) Check extracting strange files + :1 + var fname = 'a[a].txt' + search('\V' .. fname) + normal x + assert_true(filereadable('zipglob/' .. fname)) + delete('zipglob', 'rf') + + :1 + fname = 'a*.txt' + search('\V' .. fname) + normal x + assert_true(filereadable('zipglob/' .. fname)) + delete('zipglob', 'rf') + + :1 + fname = 'a?.txt' + search('\V' .. fname) + normal x + assert_true(filereadable('zipglob/' .. fname)) + delete('zipglob', 'rf') + + :1 + fname = 'a\.txt' + search('\V' .. escape(fname, '\\')) + normal x + assert_true(filereadable('zipglob/' .. fname)) + delete('zipglob', 'rf') + + :1 + fname = 'a\\.txt' + search('\V' .. escape(fname, '\\')) + normal x + assert_true(filereadable('zipglob/' .. fname)) + delete('zipglob', 'rf') + + ### 2) Check entering strange file names + :1 + fname = 'a[a].txt' + search('\V' .. fname) + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::zipglob/a\[a\].txt', @%) + assert_equal('a test file with []', getline(1)) + bw + + e X.zip + :1 + fname = 'a*.txt' + search('\V' .. fname) + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::zipglob/a\*.txt', @%) + assert_equal('a test file with a*', getline(1)) + bw + + e X.zip + :1 + fname = 'a?.txt' + search('\V' .. fname) + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::zipglob/a?.txt', @%) + assert_equal('a test file with a?', getline(1)) + bw + + e X.zip + :1 + fname = 'a\.txt' + search('\V' .. escape(fname, '\\')) + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::zipglob/a\\.txt', @%) + assert_equal('a test file with a\', getline(1)) + bw + + e X.zip + :1 + fname = 'a\\.txt' + search('\V' .. escape(fname, '\\')) + exe ":normal \<cr>" + assert_match('zipfile://.*/X.zip::zipglob/a\\\\.txt', @%) + assert_equal('a test file with a double \', getline(1)) + bw + + bw +enddef diff --git a/src/testdir/view_util.vim b/src/testdir/view_util.vim index 71cb071..161c8b2 100644 --- a/src/testdir/view_util.vim +++ b/src/testdir/view_util.vim @@ -71,7 +71,7 @@ endfunc " than the raw code. " Return the modifyOtherKeys level 2 encoding for "key" with "modifier" -" (number value, e.g. CTRL is 5). +" (number value, e.g. CTRL is 5, Shift is 2, Alt is 3). func GetEscCodeCSI27(key, modifier) let key = printf("%d", char2nr(a:key)) let mod = printf("%d", a:modifier) diff --git a/src/testdir/viewdumps.vim b/src/testdir/viewdumps.vim new file mode 100644 index 0000000..62f7bbe --- /dev/null +++ b/src/testdir/viewdumps.vim @@ -0,0 +1,11 @@ +vim9script + +exec 'source ' .. (((cwdpath: string) => cwdpath + ->strpart(0, cwdpath->strridx('/vim')))(getcwd())) + .. '/vim/src/testdir/commondumps.vim' +g:Init('\<src\>', 0) + +# Match ":language" of runtest.vim. +language messages C + +# vim:fdm=syntax:sw=2:ts=8:noet:nolist:nosta: |