diff options
Diffstat (limited to 'src/testdir')
159 files changed, 8167 insertions, 549 deletions
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 1614cf0..c4403e6 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -248,6 +248,7 @@ NEW_TESTS = \ test_regexp_utf8 \ test_registers \ test_reltime \ + test_remote \ test_rename \ test_restricted \ test_retab \ @@ -324,6 +325,7 @@ NEW_TESTS = \ test_window_cmd \ test_window_id \ test_windows_home \ + test_winfixbuf \ test_wnext \ test_wordcount \ test_writefile \ @@ -492,6 +494,7 @@ NEW_TESTS_RES = \ test_recover.res \ test_regex_char_classes.res \ test_registers.res \ + test_remote.res \ test_rename.res \ test_restricted.res \ test_retab.res \ @@ -555,6 +558,7 @@ NEW_TESTS_RES = \ test_window_cmd.res \ test_window_id.res \ test_windows_home.res \ + test_winfixbuf.res \ test_wordcount.res \ test_writefile.res \ test_xxd.res \ diff --git a/src/testdir/check.vim b/src/testdir/check.vim index 82abb64..e67d39a 100644 --- a/src/testdir/check.vim +++ b/src/testdir/check.vim @@ -160,6 +160,14 @@ func CheckEnv(name) endif endfunc +" Command to Check for pure X11 (no Wayland) +command -nargs=0 CheckX11 call CheckX11() +func CheckX11() + if !empty($WAYLAND_DISPLAY) || empty($DISPLAY) + throw 'Skipped: not pure X11 environment' + endif +endfunc + " Command to check that we are using the GUI command CheckGui call CheckGui() func CheckGui() diff --git a/src/testdir/dumps/Test_balloon_eval_term_02.dump b/src/testdir/dumps/Test_balloon_eval_term_02.dump index 51c5e32..f3bd633 100644 --- a/src/testdir/dumps/Test_balloon_eval_term_02.dump +++ b/src/testdir/dumps/Test_balloon_eval_term_02.dump @@ -1,6 +1,6 @@ |o+0&#ffffff0|n|e| |o|n|e| |o|n|e| @38 |t|w|o| |t|X|o| |t|w|o| @38 -|t|h|r|e|e+0&#e0e0e08| |t|h>r+0&#ffffff0|e@1| |t|h|r|e@1| @32 +|t|h|r|e|e+0#0000001#a8a8a8255| |t|h>r+0#0000000#ffffff0|e@1| |t|h|r|e@1| @32 |~+0#4040ff13&| @2| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@27 |~| @2| +0#0000001#ffd7ff255|l|i|n|e| |3| |c|o|l|u|m|n| |5|:| | +0#4040ff13#ffffff0@27 |~| @2| +0#0000001#ffd7ff255|e| |t|h|r|<| @10| +0#4040ff13#ffffff0@27 diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_01.dump b/src/testdir/dumps/Test_conceal_cul_wcr_01.dump new file mode 100644 index 0000000..9cb27c8 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_01.dump @@ -0,0 +1,4 @@ +|o+8&#ffffff0|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7 +@1|o|n|e| |o|n|e| |o|n|e| @27 +|~+0#4040ff13&| @38 +| +0#0000000&@21|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_02.dump b/src/testdir/dumps/Test_conceal_cul_wcr_02.dump new file mode 100644 index 0000000..668e1af --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_02.dump @@ -0,0 +1,4 @@ +|o+8#ffffff16#e000002|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7 +@1|o|n|e| |o|n|e| |o|n|e| @27 +|~+0#4040ff13&| @38 +|:+0#0000000#ffffff0|s|e|t| |w|i|n|c|o|l|o|r|=|E|r@1|o|r|M|s|g|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_03.dump b/src/testdir/dumps/Test_conceal_cul_wcr_03.dump new file mode 100644 index 0000000..965e9f5 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_03.dump @@ -0,0 +1,4 @@ +|o+0#ffffff16#e000002|n|e| |o|n|e| |o|n|e| @1|o|n|e| |o|n|e| |o|n|e| |o|n|e| |o|n>e| @7 +@1|o|n|e| |o|n|e| |o|n|e| @27 +|~+0#4040ff13&| @38 +|:+0#0000000#ffffff0|s|e|t| |n|o|c|u|r|s|o|r|l|i|n|e| @4|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump new file mode 100644 index 0000000..d1a31a6 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_01.dump @@ -0,0 +1,4 @@ +| +8&#ffffff0@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o +| @27|e|n|o| |e|n|o| |e|n|o| +| +0#4040ff13&@38|~ +| +0#0000000&@21|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump new file mode 100644 index 0000000..21809e9 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_02.dump @@ -0,0 +1,4 @@ +| +8#ffffff16#e000002@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o +| @27|e|n|o| |e|n|o| |e|n|o| +| +0#4040ff13&@38|~ +|:+0#0000000#ffffff0|s|e|t| |w|i|n|c|o|l|o|r|=|E|r@1|o|r|M|s|g|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump b/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump new file mode 100644 index 0000000..0eeb739 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_cul_wcr_rl_03.dump @@ -0,0 +1,4 @@ +| +0#ffffff16#e000002@7>e|n|o| |e|n|o| |e|n|o| |e|n|o| |e|n|o| @1|e|n|o| |e|n|o| |e|n|o +| @27|e|n|o| |e|n|o| |e|n|o| +| +0#4040ff13&@38|~ +|:+0#0000000#ffffff0|s|e|t| |n|o|c|u|r|s|o|r|l|i|n|e| @4|1|,|4|0| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_double_width_1.dump b/src/testdir/dumps/Test_conceal_double_width_1.dump new file mode 100644 index 0000000..57353bb --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_1.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@4|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@3>c| @11| +0&#ffd7d7255| +0&#ffffff0@44 +|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|9|-|2|5| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_double_width_2.dump b/src/testdir/dumps/Test_conceal_double_width_2.dump new file mode 100644 index 0000000..782db47 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_2.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@4|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@1>b@2|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@4| @11| +0&#ffd7d7255| +0&#ffffff0@44 +|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|1|5|-|1|3| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_double_width_3.dump b/src/testdir/dumps/Test_conceal_double_width_3.dump new file mode 100644 index 0000000..5102c7b --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_3.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@4|b@1>b@2|c@4| @13| +0&#ffd7d7255| +0&#ffffff0@44 +|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44 +|~+0#4040ff13&| @73 +|:+0#0000000&|s|e|t| |c|o|n|c|e|a|l@1|e|v|e|l|=|3| @37|1|,|1|5|-|1|3| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_double_width_4.dump b/src/testdir/dumps/Test_conceal_double_width_4.dump new file mode 100644 index 0000000..8ef8b96 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_4.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@4|b@4|c@3>c| @13| +0&#ffd7d7255| +0&#ffffff0@44 +|f|o@1|b|a|r| @22| +0&#ffd7d7255| +0&#ffffff0@44 +|~+0#4040ff13&| @73 +|:+0#0000000&|s|e|t| |c|o|n|c|e|a|l@1|e|v|e|l|=|3| @37|1|,|2|9|-|2|5| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump new file mode 100644 index 0000000..e794b7c --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_wrap_1.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@9|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4| @3 +|b@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@8>c| @3 +|~+0#4040ff13&| @18 +| +0#0000000&@9|1|,|4@1|-|4|0| @2 diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump new file mode 100644 index 0000000..36e64fc --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_wrap_2.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@9|β+0#e0e0e08#6c6c6c255|b+0#0000000#ffffff0@4| @3 +>b@4|β+0#e0e0e08#6c6c6c255|c+0#0000000#ffffff0@9| @3 +|~+0#4040ff13&| @18 +| +0#0000000&@9|1|,|2|3|-|2|1| @2 diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump new file mode 100644 index 0000000..ba6c835 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_wrap_3.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@9|b@4| @4 +>b@4|c@9| @4 +|~+0#4040ff13&| @18 +|:+0#0000000&|s|e|t| |c|o|n|c|e|1|,|2|3|-|2|1| @2 diff --git a/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump b/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump new file mode 100644 index 0000000..8997e98 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_double_width_wrap_4.dump @@ -0,0 +1,4 @@ +|a+0&#ffffff0@9|b@4| @4 +|b@4|c@8>c| @4 +|~+0#4040ff13&| @18 +|:+0#0000000&| @8|1|,|4@1|-|4|0| @2 diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump new file mode 100644 index 0000000..635c6db --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_1.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o>p| @57 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|5| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump new file mode 100644 index 0000000..ecdc5a3 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_2.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p> @57 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|6| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump new file mode 100644 index 0000000..5eff9fa --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_3.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| > @56 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|6|-|2|7| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump new file mode 100644 index 0000000..0b2120a --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_4.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| @1> @55 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|6|-|2|8| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump new file mode 100644 index 0000000..2aa8644 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_5.dump @@ -0,0 +1,3 @@ +|a+0&#ffffff0|b|c|d|e|f|g|h|i|j|k|l|m|n|p|o|p| @1>r| @54 +|~+0#4040ff13&| @73 +| +0#0000000&@56|1|,|2|8| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump new file mode 100644 index 0000000..840e19b --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_1.dump @@ -0,0 +1,3 @@ +| +0&#ffffff0@57>p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a +| +0#4040ff13&@73|~ +| +0#0000000&@56|1|,|2|5| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump new file mode 100644 index 0000000..c4b0190 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_2.dump @@ -0,0 +1,3 @@ +| +0&#ffffff0@56> |p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a +| +0#4040ff13&@73|~ +| +0#0000000&@56|1|,|2|6| @9|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump new file mode 100644 index 0000000..e4a05f7 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_3.dump @@ -0,0 +1,3 @@ +| +0&#ffffff0@55> @1|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a +| +0#4040ff13&@73|~ +| +0#0000000&@56|1|,|2|6|-|2|7| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump new file mode 100644 index 0000000..9f21657 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_4.dump @@ -0,0 +1,3 @@ +| +0&#ffffff0@54> @2|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a +| +0#4040ff13&@73|~ +| +0#0000000&@56|1|,|2|6|-|2|8| @6|A|l@1| diff --git a/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump new file mode 100644 index 0000000..7d2dad6 --- /dev/null +++ b/src/testdir/dumps/Test_conceal_ve_after_eol_rl_5.dump @@ -0,0 +1,3 @@ +| +0&#ffffff0@54>r| @1|p|o|p|n|m|l|k|j|i|h|g|f|e|d|c|b|a +| +0#4040ff13&@73|~ +| +0#0000000&@56|1|,|2|8| @9|A|l@1| diff --git a/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump b/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump index b6e20b7..326abac 100644 --- a/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump +++ b/src/testdir/dumps/Test_cursorline_with_visualmode_01.dump @@ -1,9 +1,9 @@ -|a+0&#e0e0e08|b|c| | +0&#ffffff0@70 -|a+0&#e0e0e08|b|c| | +0&#ffffff0@70 -|a+0&#e0e0e08|b|c| | +0&#ffffff0@70 -|a+0&#e0e0e08|b|c| | +0&#ffffff0@70 -|a+0&#e0e0e08|b|c| | +0&#ffffff0@70 ->a|b+0&#e0e0e08|c| | +0&#ffffff0@70 +|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70 +|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70 +|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70 +|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70 +|a+0#0000001#a8a8a8255|b|c| | +0#0000000#ffffff0@70 +>a|b+0#0000001#a8a8a8255|c| | +0#0000000#ffffff0@70 |a|b|c| @71 |a|b|c| @71 |a|b|c| @71 diff --git a/src/testdir/dumps/Test_difffunc_diffexpr_1.dump b/src/testdir/dumps/Test_difffunc_diffexpr_1.dump new file mode 100644 index 0000000..b103cc8 --- /dev/null +++ b/src/testdir/dumps/Test_difffunc_diffexpr_1.dump @@ -0,0 +1,12 @@ +| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|z+0#0000000#5fd7ff255|e|r|o| @30 +| +0#0000e05#a8a8a8255@1>o+0#0000000#ffffff0|n|e| @31||+1&&| +0#0000e05#a8a8a8255@1|o+0#0000000#ffffff0|n|e| @31 +| +0#0000e05#a8a8a8255@1|t+0#0000000#ffd7ff255|w|o|x+2&#ff404010| +0&#ffd7ff255@30||+1&#ffffff0| +0#0000e05#a8a8a8255@1|t+0#0000000#ffd7ff255|w|o| @31 +| +0#0000e05#a8a8a8255@1|t+0#0000000#ffffff0|h|r|e@1| @29||+1&&| +0#0000e05#a8a8a8255@1|t+0#0000000#ffffff0|h|r|e@1| @29 +| +0#0000e05#a8a8a8255@1|f+0#0000000#5fd7ff255|o|u|r| @30||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34 +|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|X+3#0000000&|d|i|f@2|u|n|c|2|.|t|x|t| @4|1|,|1| @11|A|l@1| |X+1&&|d|i|f@2|u|n|c|1|.|t|x|t| @4|1|,|1| @11|A|l@1 +|"+0&&|X|d|i|f@2|u|n|c|2|.|t|x|t|"| |4|L|,| |2|0|B| @50 diff --git a/src/testdir/dumps/Test_display_scroll_update_visual.dump b/src/testdir/dumps/Test_display_scroll_update_visual.dump index c174390..4b17a3b 100644 --- a/src/testdir/dumps/Test_display_scroll_update_visual.dump +++ b/src/testdir/dumps/Test_display_scroll_update_visual.dump @@ -1,4 +1,4 @@ -| +0#0000e05#a8a8a8255@1>f+0#0000000#ffffff0|o+0&#e0e0e08@1| | +0&#ffffff0@53 +| +0#0000e05#a8a8a8255@1>f+0#0000000#ffffff0|o+0#0000001#a8a8a8255@1| | +0#0000000#ffffff0@53 | +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54 | +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54 | +0#0000e05#a8a8a8255@1|f+0#0000000#ffffff0|o@1| @54 diff --git a/src/testdir/dumps/Test_drop_modified_1.dump b/src/testdir/dumps/Test_drop_modified_1.dump new file mode 100644 index 0000000..bbd60c0 --- /dev/null +++ b/src/testdir/dumps/Test_drop_modified_1.dump @@ -0,0 +1,10 @@ +>T+0&#ffffff0|h|e| |q|u|i|c|k| |b|r|o|w|n| |f|o|x| |j|u|m|p|e|d| |o|v|e|r| |t|h|e| |l|a|z|y| |d|o|g|s| @29 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|:+0#0000000&|d|r|o|p| |X|d|r|o|p|_|m|o|d|i|f|i|e|d|.|t|x|t| @32|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_echowin_showmode.dump b/src/testdir/dumps/Test_echowin_showmode.dump index 24eb4d0..9a73bbf 100644 --- a/src/testdir/dumps/Test_echowin_showmode.dump +++ b/src/testdir/dumps/Test_echowin_showmode.dump @@ -1,4 +1,4 @@ ->o+0&#ffffff0|n+0&#e0e0e08|e| | +0&#ffffff0@70 +>o+0&#ffffff0|n+0#0000001#a8a8a8255|e| | +0#0000000#ffffff0@70 |t|w|o| @71 |~+0#4040ff13&| @73 |~| @73 diff --git a/src/testdir/dumps/Test_hlsearch_visual_1.dump b/src/testdir/dumps/Test_hlsearch_visual_1.dump index 99150db..e65d567 100644 --- a/src/testdir/dumps/Test_hlsearch_visual_1.dump +++ b/src/testdir/dumps/Test_hlsearch_visual_1.dump @@ -1,6 +1,6 @@ -|x+0&#ffffff0@2| |y+2&#ffff4012|y+2&#e0e0e08@1| +0&&|z@2| | +0&#ffffff0@27 -|x+0&#e0e0e08@2| |y+2&&@2| +0&&|z@2| | +0&#ffffff0@27 -|x+0&#e0e0e08@2| |y+2&&>y+2&#ffff4012@1| +0&#ffffff0|z@2| @28 +|x+0&#ffffff0@2| |y+2&#ffff4012|y+2#0000001#a8a8a8255@1| +0&&|z@2| | +0#0000000#ffffff0@27 +|x+0#0000001#a8a8a8255@2| |y+2&&@2| +0&&|z@2| | +0#0000000#ffffff0@27 +|x+0#0000001#a8a8a8255@2| |y+2&&>y+2#0000000#ffff4012@1| +0&#ffffff0|z@2| @28 |~+0#4040ff13&| @38 |~| @38 |-+2#0000000&@1| |V|I|S|U|A|L| |-@1|3+0&&| @8|3|,|6| @10|A|l@1| diff --git a/src/testdir/dumps/Test_matchparen_win_execute_1.dump b/src/testdir/dumps/Test_matchparen_win_execute_1.dump new file mode 100644 index 0000000..75ab210 --- /dev/null +++ b/src/testdir/dumps/Test_matchparen_win_execute_1.dump @@ -0,0 +1,5 @@ +>{+0(ffff15|}| +0&#ffffff0@72 +|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|A|l@1 +|{+0&&|}| @72 +|[+1&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|1| @11|A|l@1 +| +0&&@74 diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_1.dump b/src/testdir/dumps/Test_number_insert_delete_lines_1.dump new file mode 100644 index 0000000..5aecb46 --- /dev/null +++ b/src/testdir/dumps/Test_number_insert_delete_lines_1.dump @@ -0,0 +1,8 @@ +| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69 +| +0#af5f00255&@1|2| >2+0#0000000&| @69 +| +0#af5f00255&@1|3| |3+0#0000000&| @69 +| +0#af5f00255&@1|4| |4+0#0000000&| @69 +| +0#af5f00255&@1|5| |5+0#0000000&| @69 +| +0#af5f00255&@1|6| |6+0#0000000&| @69 +| +0#af5f00255&@1|7| |7+0#0000000&| @69 +@57|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_2.dump b/src/testdir/dumps/Test_number_insert_delete_lines_2.dump new file mode 100644 index 0000000..dea68e8 --- /dev/null +++ b/src/testdir/dumps/Test_number_insert_delete_lines_2.dump @@ -0,0 +1,8 @@ +| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69 +| +0#af5f00255&@1|2| >3+0#0000000&| @69 +| +0#af5f00255&@1|3| |4+0#0000000&| @69 +| +0#af5f00255&@1|4| |5+0#0000000&| @69 +| +0#af5f00255&@1|5| |6+0#0000000&| @69 +| +0#af5f00255&@1|6| |7+0#0000000&| @69 +|~+0#4040ff13&| @73 +| +0#0000000&@56|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_number_insert_delete_lines_3.dump b/src/testdir/dumps/Test_number_insert_delete_lines_3.dump new file mode 100644 index 0000000..fff3297 --- /dev/null +++ b/src/testdir/dumps/Test_number_insert_delete_lines_3.dump @@ -0,0 +1,8 @@ +| +0#af5f00255#ffffff0@1|1| |1+0#0000000&| @69 +| +0#af5f00255&@1|2| >4+0#0000000&| @69 +| +0#af5f00255&@1|3| |5+0#0000000&| @69 +| +0#af5f00255&@1|4| |6+0#0000000&| @69 +| +0#af5f00255&@1|5| |7+0#0000000&| @69 +|~+0#4040ff13&| @73 +|~| @73 +| +0#0000000&@56|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_popup_command_03.dump b/src/testdir/dumps/Test_popup_command_03.dump index fa2ac70..2a0c5af 100644 --- a/src/testdir/dumps/Test_popup_command_03.dump +++ b/src/testdir/dumps/Test_popup_command_03.dump @@ -1,5 +1,5 @@ |o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @51 -|a|n|d| |o|n|e| |t|w|o| |X+0&#e0e0e08|t|h|r|e@1> +0&#ffffff0|f|o|u|r| |f|i|v|e| @46 +|a|n|d| |o|n|e| |t|w|o| |X+0#0000001#a8a8a8255|t|h|r|e@1> +0#0000000#ffffff0|f|o|u|r| |f|i|v|e| @46 |o|n|e| |m|o|r|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @46 |~+0#4040ff13&| @73 |~| @73 diff --git a/src/testdir/dumps/Test_prop_above_below_empty_1.dump b/src/testdir/dumps/Test_prop_above_below_empty_1.dump index f470016..1cc6d01 100644 --- a/src/testdir/dumps/Test_prop_above_below_empty_1.dump +++ b/src/testdir/dumps/Test_prop_above_below_empty_1.dump @@ -1,16 +1,16 @@ -| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| |1+0#0000000&@7| @47 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|3| |3+0#0000000&@8| @46 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|4| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|5| >5+0#0000000&@10| @44 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 @42|5|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_above_below_empty_2.dump b/src/testdir/dumps/Test_prop_above_below_empty_2.dump index 3954a4b..db11724 100644 --- a/src/testdir/dumps/Test_prop_above_below_empty_2.dump +++ b/src/testdir/dumps/Test_prop_above_below_empty_2.dump @@ -1,16 +1,16 @@ -| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| |1+0#0000000&@7|$+0#4040ff13&| +0#0000000&@46 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| |$+0#4040ff13&| +0#0000000&@54 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|3| |3+0#0000000&@8|$+0#4040ff13&| +0#0000000&@45 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|4| |$+0#4040ff13&| +0#0000000&@54 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|5| >5+0#0000000&@10|$+0#4040ff13&| +0#0000000&@43 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 |:|s|e|t| |l|i|s|t| @32|5|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_above_below_empty_3.dump b/src/testdir/dumps/Test_prop_above_below_empty_3.dump index 27f9eec..78f30b7 100644 --- a/src/testdir/dumps/Test_prop_above_below_empty_3.dump +++ b/src/testdir/dumps/Test_prop_above_below_empty_3.dump @@ -1,16 +1,16 @@ -| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| |1+0#0000000&@7| | +0&#ffd7d7255| +0&#ffffff0@45 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|3| |3+0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|4| | +0#0000000&@8| +0&#ffd7d7255| +0&#ffffff0@45 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|5| >5+0#0000000&@8|5+0&#ffd7d7255|5+0&#ffffff0| @44 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 |:| @40|5|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_above_below_empty_4.dump b/src/testdir/dumps/Test_prop_above_below_empty_4.dump index cc3c27d..2c7bf4d 100644 --- a/src/testdir/dumps/Test_prop_above_below_empty_4.dump +++ b/src/testdir/dumps/Test_prop_above_below_empty_4.dump @@ -1,16 +1,16 @@ -| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|4| |1+0#0000000&@7| @47 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|3| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| |3+0#0000000&@8| @46 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 |5+0#af5f00255&| @2>5+0#0000000&@10| @44 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 |:| @40|5|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_above_below_empty_5.dump b/src/testdir/dumps/Test_prop_above_below_empty_5.dump index 5ee4d80..1928ea2 100644 --- a/src/testdir/dumps/Test_prop_above_below_empty_5.dump +++ b/src/testdir/dumps/Test_prop_above_below_empty_5.dump @@ -1,16 +1,16 @@ -| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| |1+0#0000000&@7| @47 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 |3+0#af5f00255&| @2>3+0#0000000&@8| @46 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|1| | +0#0000000&@55 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 -| +0#af5f00255&@3|-+0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 | +0#af5f00255&@1|2| |5+0#0000000&@10| @44 -| +0#af5f00255&@3|++0#0000001#ffff4012@2| +0#0000000#ffffff0@52 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 |:| @40|3|,|1|-|5|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_above_below_empty_6.dump b/src/testdir/dumps/Test_prop_above_below_empty_6.dump new file mode 100644 index 0000000..5013643 --- /dev/null +++ b/src/testdir/dumps/Test_prop_above_below_empty_6.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|1| |1+0#0000000&@7| @47 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 +|2+0#af5f00255&| @2> +0#0000000&@55 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|1| |3+0#0000000&@8| @46 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@1|2| | +0#0000000&@55 +| +0#af5f00255&@3|++0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|-+0#0000001#ffff4012| +0#0000000#ffffff0@54 +| +0#af5f00255&@3|!+0#0000001#ffff4012| +0#0000000#ffffff0@54 +|@+0#4040ff13&@2| @56 +|:+0#0000000&|c|a|l@1| |A|d@1|M|o|r|e|(|)| @26|2|,|0|-|5|7| @7|T|o|p| diff --git a/src/testdir/dumps/Test_prop_inserts_text_1.dump b/src/testdir/dumps/Test_prop_inserts_text_1.dump index 7d1b102..7a51c12 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_1.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_1.dump @@ -1,6 +1,6 @@ |i+0&#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| |s|o |m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @27 -|p|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @40 +|p|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @40 |F|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @34 |e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@49 |l|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @42 diff --git a/src/testdir/dumps/Test_prop_inserts_text_2.dump b/src/testdir/dumps/Test_prop_inserts_text_2.dump index 2a5b2f3..c9c325f 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_2.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_2.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n>g| @23 -| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38 | +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32 | +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47 | +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40 diff --git a/src/testdir/dumps/Test_prop_inserts_text_3.dump b/src/testdir/dumps/Test_prop_inserts_text_3.dump index 36a4b8c..2b93554 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_3.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_3.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23 -| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s>t| @38 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s>t| @38 | +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32 | +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47 | +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40 diff --git a/src/testdir/dumps/Test_prop_inserts_text_4.dump b/src/testdir/dumps/Test_prop_inserts_text_4.dump index 8bb637a..83e656a 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_4.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_4.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23 -| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38 | +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=>1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32 | +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47 | +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40 diff --git a/src/testdir/dumps/Test_prop_inserts_text_5.dump b/src/testdir/dumps/Test_prop_inserts_text_5.dump index 75194f6..2885d4d 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_5.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_5.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23 -| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38 | +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=>2+0#0000000&| |}|;| @32 | +0#0000e05#a8a8a8255@1|e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47 | +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40 diff --git a/src/testdir/dumps/Test_prop_inserts_text_6.dump b/src/testdir/dumps/Test_prop_inserts_text_6.dump index fb25ddf..5aeddb4 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_6.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_6.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1|i+0#0000000#ffffff0|n|s|e|r|t| |s|o|m|e| |t|e|x|t| |S+0#ffffff16#e000002|O|M|E| |h+0#0000000#ffffff0|e|r|e| |a|n|d| |o|t|h|e|r| |t|e|x|t| |O+0&#ffff4012|T|H|E|R| |t+0&#ffffff0|h|e|r|e| |a|n|d| | +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e| |m|o|r|e| |t|e|x|t| |a|f|t|e|r| |M+0fd7ff255|O|R|E| |w+0&#ffffff0|r|a|p@1|i|n|g| @23 -| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0&#e0e0e08|ö|m|e|和*&|平|t+&|é|x|t|p+0&#ffffff0|o|s|t| @38 +| +0#0000e05#a8a8a8255@1|p+0#0000000#ffffff0|r|e|s+0#0000001#a8a8a8255|ö|m|e|和*&|平|t+&|é|x|t|p+0#0000000#ffffff0|o|s|t| @38 | +0#0000e05#a8a8a8255@1|F+0#0000000#ffffff0|o@1| |f|o@1| |=| |{| |.+0#0000e05&|x|=|1+0#0000000&|,| |.+0#0000e05&|y|=|2+0#0000000&| |}|;| @32 | +0#0000e05#a8a8a8255@1>e+0#ffffff16#e000002|m|p|t|y| |l|i|n|e| +0#0000000#ffffff0@47 | +0#0000e05#a8a8a8255@1|l+0#0000000#ffffff0|o@1|k| |n|o| |h|i|g|h|l|i|g|h|t| @40 diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump index 2383b4a..48d8ebc 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_2.dump @@ -1,6 +1,6 @@ -|1+0&#e0e0e08|2|3+0&#ffffff0|4|5|6|7|8|9| @50 -|1+0&#e0e0e08|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46 -|1+0&#e0e0e08|2|口*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48 -|1+0&#e0e0e08>2+0&#ffffff0|3|4|5|6|7|8|9| @50 +|1+0#0000001#a8a8a8255|2|3+0#0000000#ffffff0|4|5|6|7|8|9| @50 +|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46 +|1+0#0000001#a8a8a8255|2|口*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48 +|1+0#0000001#a8a8a8255>2+0#0000000#ffffff0|3|4|5|6|7|8|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|2| @6|4|,|2| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump index 920cb1d..0234ba4 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_3.dump @@ -1,6 +1,6 @@ -|1+0&#e0e0e08|2|3|4+0&#ffffff0|5|6|7|8|9| @50 -|1+0&#e0e0e08|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46 -|1+0&#e0e0e08|2|口*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48 -|1+0&#e0e0e08|2>3+0&#ffffff0|4|5|6|7|8|9| @50 +|1+0#0000001#a8a8a8255|2|3|4+0#0000000#ffffff0|5|6|7|8|9| @50 +|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000000&|3|4|5|6|7|8|9| @46 +|1+0#0000001#a8a8a8255|2|口*0#e000e06#ffffff0|3+0#0000000&|4|5|6|7|8|9| @48 +|1+0#0000001#a8a8a8255|2>3+0#0000000#ffffff0|4|5|6|7|8|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|3| @6|4|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump index 0017f02..ff5af3a 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_4.dump @@ -1,6 +1,6 @@ -|1+0&#e0e0e08|2|3|4|5|6|7|8+0&#ffffff0|9| @50 -|1+0&#e0e0e08|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46 -|1+0&#e0e0e08|2|口*0#e000e06#ffffff0|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48 -|1+0&#e0e0e08|2|3|4|5|6>7+0&#ffffff0|8|9| @50 +|1+0#0000001#a8a8a8255|2|3|4|5|6|7|8+0#0000000#ffffff0|9| @50 +|1+0#0000001#a8a8a8255|-+0#e000e06#ffffff0|口*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46 +|1+0#0000001#a8a8a8255|2|口*0#e000e06#ffffff0|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48 +|1+0#0000001#a8a8a8255|2|3|4|5|6>7+0#0000000#ffffff0|8|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|7| @6|4|,|7| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump index cb7e0c9..496eee9 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_5.dump @@ -1,6 +1,6 @@ -|1+0&#ffffff0|2+0&#e0e0e08|3|4|5|6|7|8+0&#ffffff0|9| @50 -|1|-+0#e000e06&|口*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46 -|1|2+0&#e0e0e08|口*0#e000e06#ffffff0|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48 -|1>2|3+0&#e0e0e08|4|5|6|7|8+0&#ffffff0|9| @50 +|1+0&#ffffff0|2+0#0000001#a8a8a8255|3|4|5|6|7|8+0#0000000#ffffff0|9| @50 +|1|-+0#e000e06&|口*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46 +|1|2+0#0000001#a8a8a8255|口*0#e000e06#ffffff0|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48 +|1>2|3+0#0000001#a8a8a8255|4|5|6|7|8+0#0000000#ffffff0|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|6| @6|4|,|2| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump index c4be65f..8630777 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_6.dump @@ -1,6 +1,6 @@ -|1+0&#ffffff0|2|3+0&#e0e0e08|4|5|6|7|8+0&#ffffff0|9| @50 -|1|-+0#e000e06&|口*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46 -|1|2|口*0#e000e06&|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48 -|1|2>3|4+0&#e0e0e08|5|6|7|8+0&#ffffff0|9| @50 +|1+0&#ffffff0|2|3+0#0000001#a8a8a8255|4|5|6|7|8+0#0000000#ffffff0|9| @50 +|1|-+0#e000e06&|口*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46 +|1|2|口*0#e000e06&|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48 +|1|2>3|4+0#0000001#a8a8a8255|5|6|7|8+0#0000000#ffffff0|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|5| @6|4|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump b/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump index 54c7fde..bcc9101 100644 --- a/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump +++ b/src/testdir/dumps/Test_prop_inserts_text_visual_block_7.dump @@ -1,6 +1,6 @@ -|1+0&#ffffff0|2|3|4+0&#e0e0e08|5|6|7|8+0&#ffffff0|9| @50 -|1|-+0#e000e06&|口*&|-+&|2+0#0000000#e0e0e08|3|4+0&#ffffff0|5|6|7|8|9| @46 -|1|2|口*0#e000e06&|3+0#0000000#e0e0e08|4|5|6+0&#ffffff0|7|8|9| @48 -|1|2|3>4|5+0&#e0e0e08|6|7|8+0&#ffffff0|9| @50 +|1+0&#ffffff0|2|3|4+0#0000001#a8a8a8255|5|6|7|8+0#0000000#ffffff0|9| @50 +|1|-+0#e000e06&|口*&|-+&|2+0#0000001#a8a8a8255|3|4+0#0000000#ffffff0|5|6|7|8|9| @46 +|1|2|口*0#e000e06&|3+0#0000001#a8a8a8255|4|5|6+0#0000000#ffffff0|7|8|9| @48 +|1|2|3>4|5+0#0000001#a8a8a8255|6|7|8+0#0000000#ffffff0|9| @50 |~+0#4040ff13&| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|4|x|4| @6|4|,|4| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_1.dump b/src/testdir/dumps/Test_prop_wincolor_1.dump new file mode 100644 index 0000000..d8a6226 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_1.dump @@ -0,0 +1,8 @@ +>s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @45 +@3|B+0fd7ff255|E|L|O|W| +0&#ffd7ff255@51 +|s|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @33 +|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@37 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_2.dump b/src/testdir/dumps/Test_prop_wincolor_2.dump new file mode 100644 index 0000000..6e5126c --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_2.dump @@ -0,0 +1,8 @@ +>s+8&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @45 +@3|B+8fd7ff255|E|L|O|W| +8&#ffd7ff255@51 +|s+0&&|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @33 +|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@37 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_3.dump b/src/testdir/dumps/Test_prop_wincolor_3.dump new file mode 100644 index 0000000..f77c274 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_3.dump @@ -0,0 +1,8 @@ +>s+8&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @14| +8&#ffd7d7255| +8&#ffd7ff255@29 +@3|B+8fd7ff255|E|L|O|W| +8&#ffd7ff255@51 +|s+0&&|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29 +|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_4.dump b/src/testdir/dumps/Test_prop_wincolor_4.dump new file mode 100644 index 0000000..06d6b0f --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_4.dump @@ -0,0 +1,8 @@ +>s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r|e| @14| +8&#ffd7d7255| +8&#af5f00255@29 +@3|B+8fd7ff255|E|L|O|W| +8&#af5f00255@51 +|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29 +|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_5.dump b/src/testdir/dumps/Test_prop_wincolor_5.dump new file mode 100644 index 0000000..0c062b4 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_5.dump @@ -0,0 +1,8 @@ +|s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r>e| @14| +8&#ffd7d7255| +8&#af5f00255@29 +@3|B+8fd7ff255|E|L|O|W| +8&#af5f00255@51 +|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g+0&#e0e0e08|e+0&#ffd7ff255|r| |t|e|x|t| |h|e|r|e| @2| +0&#ffd7d7255| +0&#ffd7ff255@29 +|m|o|r|e| |t|e|x|t| |h|e|r|e+0&#e0e0e08| +0&#ffd7ff255@2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@6| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1|4| @9|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_6.dump b/src/testdir/dumps/Test_prop_wincolor_6.dump new file mode 100644 index 0000000..e07b3e6 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_6.dump @@ -0,0 +1,8 @@ +|s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @10| +0&#e0e0e08| +0&#ffd7ff255@2| +0&#ffd7d7255| +0&#ffd7ff255@29 +@3|B+0fd7ff255|E|L|O|W| +0&#ffd7ff255@51 +|s+8&#af5f00255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r>e| @2| +8&#ffd7d7255| +8&#af5f00255@29 +|m+0&#ffd7ff255|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@2| +0&#e0e0e08| +0&#ffd7ff255@2| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|2|,|2|6| @9|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_7.dump b/src/testdir/dumps/Test_prop_wincolor_7.dump new file mode 100644 index 0000000..9412811 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_7.dump @@ -0,0 +1,8 @@ +|s+0&#ffd7ff255|o|m|e| |t|e|x|t| |h|e|r|e| @11| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29 +@3|B+0fd7ff255|E|L|O|W| +0&#ffd7ff255@51 +|s+8&#af5f00255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e> @2| +8&#ffd7d7255| +8&#af5f00255@29 +|m+0&#ffd7ff255|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@3| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|2|,|2|7| @9|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_8.dump b/src/testdir/dumps/Test_prop_wincolor_8.dump new file mode 100644 index 0000000..9df69ec --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_8.dump @@ -0,0 +1,8 @@ +|s+8&#af5f00255|o|m|e| |t|e|x|t| |h|e|r|e| @11> @2| +8&#ffd7d7255| +8&#af5f00255@29 +@3|B+8fd7ff255|E|L|O|W| +8&#af5f00255@51 +|s+0&#ffd7ff255|o|m|e| |m|u|c|h| |l|o|n|g|e|r| |t|e|x|t| |h|e|r|e| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29 +|m|o|r|e| |t|e|x|t| |h|e|r|e| @2|A+0&#ffff4012|F|T|E|R| +0&#ffd7ff255@3| +0&#e0e0e08| +0&#ffd7ff255@1| +0&#ffd7d7255| +0&#ffd7ff255@29 +|~+0#4040ff13&| @58 +|~| @58 +|~| @58 +|:+0#0000000#ffffff0| @40|1|,|1|5|-|2|7| @6|A|l@1| diff --git a/src/testdir/dumps/Test_prop_wincolor_9.dump b/src/testdir/dumps/Test_prop_wincolor_9.dump new file mode 100644 index 0000000..7b26974 --- /dev/null +++ b/src/testdir/dumps/Test_prop_wincolor_9.dump @@ -0,0 +1,8 @@ +| +8&#af5f00255@29| +8&#ffd7d7255| +8&#af5f00255@1> @12|e|r|e|h| |t|x|e|t| |e|m|o|s +| @51|W+8fd7ff255|O|L|E|B| +8&#af5f00255@2 +| +0&#ffd7ff255@29| +0&#ffd7d7255| +0&#ffd7ff255@1| +0&#e0e0e08|e+0&#ffd7ff255|r|e|h| |t|x|e|t| |r|e|g|n|o|l| |h|c|u|m| |e|m|o|s +| @29| +0&#ffd7d7255| +0&#ffd7ff255@1| +0&#e0e0e08| +0&#ffd7ff255@3|R+0&#ffff4012|E|T|F|A| +0&#ffd7ff255@2|e|r|e|h| |t|x|e|t| |e|r|o|m +| +0#4040ff13&@58|~ +| @58|~ +| @58|~ +|:+0#0000000#ffffff0| @40|1|,|1|5|-|2|7| @6|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_above_6.dump b/src/testdir/dumps/Test_prop_with_text_above_6.dump index da28228..0aa04b5 100644 --- a/src/testdir/dumps/Test_prop_with_text_above_6.dump +++ b/src/testdir/dumps/Test_prop_with_text_above_6.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|f+0#0000000#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@36 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|s+0#0000000#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@35 -| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000000#e0e0e08|n|s|e|r|t|e>d+0&#ffffff0| |o|n|e| |t|w|o| @37 +| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000001#a8a8a8255|n|s|e|r|t|e>d+0#0000000#ffffff0| |o|n|e| |t|w|o| @37 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|b+0#0000000#5fd7ff255|e|l|o|w| +0&#ffffff0@48 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|2| |t+0#0000000&|h|r|e@1| |f|o|u|r| @43 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3| +0#0000000&@2|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| +0&#ffffff0@37 diff --git a/src/testdir/dumps/Test_prop_with_text_above_7.dump b/src/testdir/dumps/Test_prop_with_text_above_7.dump index c50749b..b675ed9 100644 --- a/src/testdir/dumps/Test_prop_with_text_above_7.dump +++ b/src/testdir/dumps/Test_prop_with_text_above_7.dump @@ -1,6 +1,6 @@ | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|f+0#0000000#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@36 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|s+0#0000000#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| +0&#ffffff0@35 -| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000000#e0e0e08|n|s|e|r|t|e>d+0&#ffffff0| +0&#e0e0e08|o|n|e| |t|w|o| +0&#ffffff0@37 +| +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|1| |i+0#0000001#a8a8a8255|n|s|e|r|t|e>d+0#0000000#ffffff0| +0#0000001#a8a8a8255|o|n|e| |t|w|o| +0#0000000#ffffff0@37 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3|b+0#0000000#5fd7ff255|e|l|o|w| +0#4040ff13#ffffff0| +0#0000000&@47 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@1|2| |t+0#0000000&|h|r|e@1| |f|o|u|r| @43 | +0#0000e05#a8a8a8255@1| +0#af5f00255#ffffff0@3| +0#0000000&@2|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| +0&#ffffff0@37 diff --git a/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump b/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump index 1bc9903..d9a055e 100644 --- a/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump +++ b/src/testdir/dumps/Test_prop_with_text_empty_line_6.dump @@ -1,8 +1,8 @@ |X+0&#ffff4012@59 -|a+0&#e0e0e08@1>a+0&#ffffff0| @56 +|a+0#0000001#a8a8a8255@1>a+0#0000000#ffffff0| @56 |X+0&#ffff4012@59 @1| +0&#ffffff0@58 -|b+0&#e0e0e08@2|b+0&#ffffff0@2| @53 +|b+0#0000001#a8a8a8255@2|b+0#0000000#ffffff0@2| @53 |~+0#4040ff13&| @58 |~| @58 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@13|3|x|3| @6|2|,|3| @10|A|l@1| diff --git a/src/testdir/dumps/Test_prop_with_text_override_2.dump b/src/testdir/dumps/Test_prop_with_text_override_2.dump index 334929e..5311cd7 100644 --- a/src/testdir/dumps/Test_prop_with_text_override_2.dump +++ b/src/testdir/dumps/Test_prop_with_text_override_2.dump @@ -1,4 +1,4 @@ -|s+0&#ffffff0|o|m+0&#e0e0e08|e| | +0#4040ff13#40ffff15|i|n|s|e|r|t|e|d| |t+0#0000000#e0e0e08|e|x|t| |h|e>r+0&#ffffff0|e| @35 +|s+0&#ffffff0|o|m+0#0000001#a8a8a8255|e| | +0#4040ff13#40ffff15|i|n|s|e|r|t|e|d| |t+0#0000001#a8a8a8255|e|x|t| |h|e>r+0#0000000#ffffff0|e| @35 |~+0#4040ff13&| @58 |~| @58 |~| @58 diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump new file mode 100644 index 0000000..a0a269f --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_wrapped_1.dump @@ -0,0 +1,20 @@ +| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0 +| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17 +| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0 +| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17 +|1+0#0000001#ff404010@2| >1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1 +| +0#0000001#ff404010@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1 +| +0#0000001#ff404010@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17 +| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@45 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@45 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@27| @17 +| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1 +| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17 +| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1 +| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17 +| +0#0000001#40ff4011@1|4| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2 +| +0#0000000&@31|1@2|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump new file mode 100644 index 0000000..1f2df5e --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_wrapped_2.dump @@ -0,0 +1,20 @@ +| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0 +| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17 +|1+0#0000001#ff404010@1|0| >1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1 +| +0#0000001#ff404010@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0 +| +0#0000001#ff404010@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17 +| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1 +| +0#0000001#40ff4011@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17 +| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@45 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@45 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0@27| @17 +| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1 +| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17 +| +0#0000001#40ff4011@1|4| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1 +| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17 +| +0#0000001#40ff4011@1|5| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2 +| +0#0000000&@31|1@1|0|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump new file mode 100644 index 0000000..b6f6c60 --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_wrapped_3.dump @@ -0,0 +1,20 @@ +| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0 +| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17 +| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0 +| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17 +| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17 +|1+0#0000001#ff404010@1|2| >1+0#0000000#ffffff0@45 +| +0#0000001#ff404010@3|1+0#0000000#ffffff0@45 +| +0#0000001#ff404010@3|1+0#0000000#ffffff0@27| @17 +| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1 +| +0#0000001#40ff4011@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17 +| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1 +| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17 +| +0#0000001#40ff4011@1|3| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2 +| +0#0000000&@31|1@1|2|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump new file mode 100644 index 0000000..b838950 --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_wrapped_4.dump @@ -0,0 +1,20 @@ +| +0#0000001#4040ff13@1|5| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0 +| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17 +| +0#0000001#4040ff13@1|4| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0 +| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17 +| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17 +| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0@45 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@45 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@27| @17 +| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1 +| +0#0000001#4040ff13@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17 +|1+0#0000001#ff404010@1|4| >1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1 +| +0#0000001#ff404010@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1 +| +0#0000001#ff404010@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17 +| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2 +| +0#0000000&@31|1@1|4|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump b/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump new file mode 100644 index 0000000..549275a --- /dev/null +++ b/src/testdir/dumps/Test_relnr_colors_wrapped_5.dump @@ -0,0 +1,20 @@ +| +0#0000001#4040ff13@1|4| |1+0#0000000#ffffff0|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0 +| +0#0000001#4040ff13@3|8+0#0000000#ffffff0|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8|1|0|8| @17 +| +0#0000001#4040ff13@1|3| |1+0#0000000#ffffff0|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0 +| +0#0000001#4040ff13@3|9+0#0000000#ffffff0|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9|1|0|9| @17 +| +0#0000001#4040ff13@1|2| |1+0#0000000#ffffff0@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1 +| +0#0000001#4040ff13@3|0+0#0000000#ffffff0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0|1@1|0| @17 +| +0#0000001#4040ff13@1|1| |1+0#0000000#ffffff0@45 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@45 +| +0#0000001#4040ff13@3|1+0#0000000#ffffff0@27| @17 +|1+0#0000001#ff404010@1|3| >1+0#0000000#ffffff0@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1 +| +0#0000001#ff404010@3|1+0#0000000#ffffff0|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1 +| +0#0000001#ff404010@3|2+0#0000000#ffffff0|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2|1@1|2| @17 +| +0#0000001#40ff4011@1|1| |1+0#0000000#ffffff0@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1 +| +0#0000001#40ff4011@3|1+0#0000000#ffffff0|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1 +| +0#0000001#40ff4011@3|3+0#0000000#ffffff0|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3|1@1|3| @17 +| +0#0000001#40ff4011@1|2| |1+0#0000000#ffffff0@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1@1|4|1|@+0#4040ff13&@2 +| +0#0000000&@31|1@1|3|,|1| @8|5@1|%| diff --git a/src/testdir/dumps/Test_statusline_showcmd_3.dump b/src/testdir/dumps/Test_statusline_showcmd_3.dump index 049e0f7..d2b2158 100644 --- a/src/testdir/dumps/Test_statusline_showcmd_3.dump +++ b/src/testdir/dumps/Test_statusline_showcmd_3.dump @@ -1,6 +1,6 @@ -|a+0&#e0e0e08| +0&#ffffff0@73 -|b+0&#e0e0e08| +0&#ffffff0@73 -|c+0&#e0e0e08> +0&#ffffff0@73 +|a+0#0000001#a8a8a8255| +0#0000000#ffffff0@73 +|b+0#0000001#a8a8a8255| +0#0000000#ffffff0@73 +|c+0#0000001#a8a8a8255> +0#0000000#ffffff0@73 |~+0#4040ff13&| @73 |3+3#0000000&|x|2| @71 |-+2&&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@56 diff --git a/src/testdir/dumps/Test_syntax_c_01.dump b/src/testdir/dumps/Test_syntax_c_01.dump index 7224216..bd2ec04 100644 --- a/src/testdir/dumps/Test_syntax_c_01.dump +++ b/src/testdir/dumps/Test_syntax_c_01.dump @@ -4,8 +4,8 @@ | +0#0000e05&@2|i|n|t| @2|n|o|t|_|u|s|e|d|;| +0#0000000&@56 |#+0#e000e06&|e|l|s|e| +0#0000000&@69 @3|i+0#00e0003&|n|t| +0#0000000&@2|u|s|e|d|;| @60 -|#+0#e000e06&|e+0&#e0e0e08|n|d|i|f| +0#0000000&| +0&#ffffff0@67 -| +0&#e0e0e08@2|p|r|i|n|t|f|(|"+0#e000002&|J|u|s|t| |a|n| |e|x|a|m|p|l|e| |p|i|e|c|e| |o|f| >C+0&#ffffff0| |c|o|d|e|\+0#e000e06&|n|"+0#e000002&|)+0#0000000&|;| @27 +|#+0#e000e06&|e+0#0000001#a8a8a8255|n|d|i|f| | +0#0000000#ffffff0@67 +| +0#0000001#a8a8a8255@2|p|r|i|n|t|f|(|"|J|u|s|t| |a|n| |e|x|a|m|p|l|e| |p|i|e|c|e| |o|f| >C+0#e000002#ffffff0| |c|o|d|e|\+0#e000e06&|n|"+0#e000002&|)+0#0000000&|;| @27 @3|r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|x|0|f@1|;+0#0000000&| @58 |}| @73 | +0#ffffff16#ff404010@16| +0#0000000#ffffff0@57 diff --git a/src/testdir/dumps/Test_tabline_showcmd_3.dump b/src/testdir/dumps/Test_tabline_showcmd_3.dump index 3e29cda..21a66a3 100644 --- a/src/testdir/dumps/Test_tabline_showcmd_3.dump +++ b/src/testdir/dumps/Test_tabline_showcmd_3.dump @@ -1,6 +1,6 @@ |3+1&#ffffff0|x|2| @71 -|a+0&#e0e0e08| +0&#ffffff0@73 -|b+0&#e0e0e08| +0&#ffffff0@73 -|c+0&#e0e0e08> +0&#ffffff0@73 +|a+0#0000001#a8a8a8255| +0#0000000#ffffff0@73 +|b+0#0000001#a8a8a8255| +0#0000000#ffffff0@73 +|c+0#0000001#a8a8a8255> +0#0000000#ffffff0@73 |~+0#4040ff13&| @73 |-+2#0000000&@1| |V|I|S|U|A|L| |B|L|O|C|K| |-@1| +0&&@38|3|,|2| @10|A|l@1| diff --git a/src/testdir/dumps/Test_terminal_popup_7.dump b/src/testdir/dumps/Test_terminal_popup_7.dump index e7e5aae..0b14d27 100644 --- a/src/testdir/dumps/Test_terminal_popup_7.dump +++ b/src/testdir/dumps/Test_terminal_popup_7.dump @@ -4,7 +4,7 @@ |3| @12|╔+0#0000001#ffd7ff255|═@44|╗| +0#0000000#ffffff0@13 |4| @12|║+0#0000001#ffd7ff255|s|o|m|e| |t|e|x|t| @35|║| +0#0000000#ffffff0@13 |5| @12|║+0#0000001#ffd7ff255|t|o| |e+0&#ffff4012|d|i|t| +0&#ffd7ff255@37|║| +0#0000000#ffffff0@13 -|6| @12|║+0#0000001#ffd7ff255|i+0&#e0e0e08|n| |a| >p+0&#ffd7ff255|o|p|u|p| |w|i|n|d|o|w| @27|║| +0#0000000#ffffff0@13 +|6| @12|║+0#0000001#ffd7ff255|i+0&#a8a8a8255|n| |a| >p+0&#ffd7ff255|o|p|u|p| |w|i|n|d|o|w| @27|║| +0#0000000#ffffff0@13 |7| @12|║+0#0000001#ffd7ff255|~+0#4040ff13&| @43|║+0#0000001&| +0#0000000#ffffff0@13 |8| @12|║+0#0000001#ffd7ff255|~+0#4040ff13&| @43|║+0#0000001&| +0#0000000#ffffff0@13 |9| @12|║+0#0000001#ffd7ff255|~+0#4040ff13&| @43|║+0#0000001&| +0#0000000#ffffff0@13 diff --git a/src/testdir/dumps/Test_textprop_hl_override_2.dump b/src/testdir/dumps/Test_textprop_hl_override_2.dump index 187233d..9e677f8 100644 --- a/src/testdir/dumps/Test_textprop_hl_override_2.dump +++ b/src/testdir/dumps/Test_textprop_hl_override_2.dump @@ -1,6 +1,6 @@ |O+0&#ffffff0|n|e| |o+0#4040ff13#ffff4012|n|e| |o+0#0000000#ffffff0|n|e| |o+0#4040ff13#ffff4012|n|e| |o+0#0000000#ffffff0|n|e| @55 |T|w|o| |t+0#4040ff13#ffff4012|w|o| |t+0#0000000#ffffff0|w|o| |t+0#4040ff13#ffff4012|w|o| |t+0#0000000#ffffff0|w|o| @55 -|T|h|r+0&#e0e0e08|e|e+0#4040ff13&| |t|h|r+0#0000000&|e@1| |t+0#4040ff13#ffff4012|h|r|e|e+0#0000000#e0e0e08| |t|h|r>e+0&#ffffff0@1| @51 +|T|h|r+0#0000001#a8a8a8255|e@1| |t|h|r|e@1| |t+0#4040ff13#ffff4012|h|r|e|e+0#0000001#a8a8a8255| |t|h|r>e+0#0000000#ffffff0@1| @51 |~+0#4040ff13&| @73 |~| @73 |~| @73 diff --git a/src/testdir/dumps/Test_vim9_no_redraw.dump b/src/testdir/dumps/Test_vim9_no_redraw.dump index 1d77a08..2f02082 100644 --- a/src/testdir/dumps/Test_vim9_no_redraw.dump +++ b/src/testdir/dumps/Test_vim9_no_redraw.dump @@ -1,4 +1,4 @@ -|s+0&#ffffff0|o+0&#e0e0e08|m|e| |t|e|x|t| | +0&#ffffff0@64 +|s+0&#ffffff0|o+0#0000001#a8a8a8255|m|e| |t|e|x|t| | +0#0000000#ffffff0@64 |~+0#4040ff13&| @73 |~| @73 |~| @73 diff --git a/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump b/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump new file mode 100644 index 0000000..d81456f --- /dev/null +++ b/src/testdir/dumps/Test_virtual_text_overlap_with_highlight_1.dump @@ -0,0 +1,8 @@ +| +0#af5f00255#ffffff0@1|1| |o+0#0000000&|n|e| @52 +| +0#af5f00255&@1|2| |t+0#0000000&|w|o| @52 +| +0#af5f00255&@3|s+0#ffffff16#ff404010|y|n|t|a|x| |e|r@1|o|r| +0#0000000#ffffff0@43 +| +0#af5f00255&@1|3| >t+0#0000000&|h|r|e@1| @50 +| +0#af5f00255&@1|4| |f+0#0000000&|o|u|r+0#e000002&| +0#0000000&@40|o+0#ffffff16#ff404010|t|h|e|r| |e|r@1|o|r +| +0#af5f00255#ffffff0@1|5| |f+0#e000002&|i+0#0000000&|v|e| @51 +|~+0#4040ff13&| @58 +| +0#0000000&@41|3|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_visual_block_with_virtualedit.dump b/src/testdir/dumps/Test_visual_block_with_virtualedit.dump index 2991a63..7a24250 100644 --- a/src/testdir/dumps/Test_visual_block_with_virtualedit.dump +++ b/src/testdir/dumps/Test_visual_block_with_virtualedit.dump @@ -1,6 +1,6 @@ -|a+0&#e0e0e08@5> +0&#ffffff0@43 -|b+0&#e0e0e08@3| @2| +0&#ffffff0@42 -|c+0&#e0e0e08@1| @4| +0&#ffffff0@42 +|a+0#0000001#a8a8a8255@5> +0#0000000#ffffff0@43 +|b+0#0000001#a8a8a8255@3| @2| +0#0000000#ffffff0@42 +|c+0#0000001#a8a8a8255@1| @4| +0#0000000#ffffff0@42 |~+0#4040ff13&| @48 |~| @48 |~| @48 diff --git a/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump b/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump index 3c62156..e68df74 100644 --- a/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump +++ b/src/testdir/dumps/Test_visual_block_with_virtualedit2.dump @@ -1,6 +1,6 @@ -|a+0&#e0e0e08@5| | +0&#ffffff0@42 -|b+0&#e0e0e08@3| @2| +0&#ffffff0@42 -|c+0&#e0e0e08@1> +0&#ffffff0| +0&#e0e0e08@3| +0&#ffffff0@42 +|a+0#0000001#a8a8a8255@5| | +0#0000000#ffffff0@42 +|b+0#0000001#a8a8a8255@3| @2| +0#0000000#ffffff0@42 +|c+0#0000001#a8a8a8255@1> +0#0000000#ffffff0| +0#0000001#a8a8a8255@3| +0#0000000#ffffff0@42 |~+0#4040ff13&| @48 |~| @48 |~| @48 diff --git a/src/testdir/dumps/Test_visual_ends_before_showbreak.dump b/src/testdir/dumps/Test_visual_ends_before_showbreak.dump new file mode 100644 index 0000000..ee809ba --- /dev/null +++ b/src/testdir/dumps/Test_visual_ends_before_showbreak.dump @@ -0,0 +1,6 @@ +|x+0&#ffffff0@4| @69 +|↪+0#4040ff13&| |y+0#0000001#a8a8a8255@68> +0#0000000#ffffff0| +0#0000001#a8a8a8255@2 +|↪+0#4040ff13#ffffff0| |z+0#0000000&@3| @68 +|~+0#4040ff13&| @73 +|~| @73 +|-+2#0000000&@1| |V|I|S|U|A|L| |-@1| +0&&@34|7|0| @7|1|,|7|6|-|1|4|7| @5|A|l@1| diff --git a/src/testdir/dumps/Test_visual_hl_with_showbreak.dump b/src/testdir/dumps/Test_visual_hl_with_showbreak.dump index fa0b2dc..0bd83b0 100644 --- a/src/testdir/dumps/Test_visual_hl_with_showbreak.dump +++ b/src/testdir/dumps/Test_visual_hl_with_showbreak.dump @@ -1,5 +1,5 @@ |a+0&#ffffff0@48>a -|++0#4040ff13&|a+0#0000000#e0e0e08@3|a+0&#ffffff0@5| @38 +|++0#4040ff13&|a+0#0000001#a8a8a8255@3|a+0#0000000#ffffff0@5| @38 |~+0#4040ff13&| @48 |~| @48 |~| @48 diff --git a/src/testdir/dumps/Test_visual_sbr_1.dump b/src/testdir/dumps/Test_visual_sbr_1.dump index 0a9511d..3c167ec 100644 --- a/src/testdir/dumps/Test_visual_sbr_1.dump +++ b/src/testdir/dumps/Test_visual_sbr_1.dump @@ -1,4 +1,4 @@ -|>+0#4040ff13#ffffff0| +0#0000000#e0e0e08|k|a|s|d| |g|u|b|e|r|g|r|e|n|,| |n|o| |s|e|a| |t|a|k|i|m|a|t|a| |s|a|n|c|t|u|s| |e|s|t| |L|o|r|e|m| |i|p|s|u|m| |d|o|l|o|r| |s|i|t| |a|m|e|t|.> +0&#ffffff0@1 +|>+0#4040ff13#ffffff0| +0#0000001#a8a8a8255|k|a|s|d| |g|u|b|e|r|g|r|e|n|,| |n|o| |s|e|a| |t|a|k|i|m|a|t|a| |s|a|n|c|t|u|s| |e|s|t| |L|o|r|e|m| |i|p|s|u|m| |d|o|l|o|r| |s|i|t| |a|m|e|t|.> +0#0000000#ffffff0@1 @75 @75 @75 diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump index f61440a..4cbf8d0 100644 --- a/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump +++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_1.dump @@ -1,4 +1,4 @@ -|<+0#4040ff13#ffffff0@2| +0#0000000&@4| +0&#e0e0e08|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@45 +|<+0#4040ff13#ffffff0@2| +0#0000000&@4| +0#0000001#a8a8a8255|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@45 |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3@1|0| @5|A|l@1 | +0&&@74 |~+0#4040ff13&| @73 diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump index 1f10940..a6df79e 100644 --- a/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump +++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_2.dump @@ -1,4 +1,4 @@ -| +0&#ffffff0@7|++0#4040ff13&@2| +0#0000000#e0e0e08|9|0| |9|1| |9|2| |9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@33 +| +0&#ffffff0@7|++0#4040ff13&@2| +0#0000001#a8a8a8255|9|0| |9|1| |9|2| |9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@33 |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3|4|2| @5|A|l@1 | +0&&@74 |~+0#4040ff13&| @73 diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump index d36d675..77ef541 100644 --- a/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump +++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_3.dump @@ -1,4 +1,4 @@ -|++0#4040ff13#ffffff0@2| +0#0000000&@4| +0&#e0e0e08|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0&#ffffff0@45 +|++0#4040ff13#ffffff0@2| +0#0000000&@4| +0#0000001#a8a8a8255|9|3| |9|4| |9|5| |9|6| |9|7| |9|8| |9@1> +0#0000000#ffffff0@45 |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3@1|0| @5|A|l@1 | +0&&@74 |~+0#4040ff13&| @73 diff --git a/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump b/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump index 101352e..0abcc3c 100644 --- a/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump +++ b/src/testdir/dumps/Test_visual_starts_before_skipcol_4.dump @@ -1,4 +1,4 @@ -|++0#4040ff13#ffffff0@2| +0#0000000#e0e0e08|9|8| |9@1> +0&#ffffff0@65 +|++0#4040ff13#ffffff0@2| +0#0000001#a8a8a8255|9|8| |9@1> +0#0000000#ffffff0@65 |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @43|1|,|2|9|1|-|3|1|0| @5|A|l@1 | +0&&@74 |~+0#4040ff13&| @73 diff --git a/src/testdir/dumps/Test_win_gotoid_2.dump b/src/testdir/dumps/Test_win_gotoid_2.dump index 7a778f5..8573fbe 100644 --- a/src/testdir/dumps/Test_win_gotoid_2.dump +++ b/src/testdir/dumps/Test_win_gotoid_2.dump @@ -6,7 +6,7 @@ |[+1&&|N|o| |N|a|m|e|]| @47|1|,|1| @11|T|o|p |2+0&&|1| @72 |2@1| @72 -|2+0&#e0e0e08>3+0&#ffffff0| @72 +|2+0#0000001#a8a8a8255>3+0#0000000#ffffff0| @72 |2|4| @72 |2|5| @72 |2|6| @72 diff --git a/src/testdir/dumps/Test_wincolor_01.dump b/src/testdir/dumps/Test_wincolor_01.dump index 5a5ccf5..c8578b2 100644 --- a/src/testdir/dumps/Test_wincolor_01.dump +++ b/src/testdir/dumps/Test_wincolor_01.dump @@ -1,6 +1,6 @@ | +0#af5f00255#ffd7ff255@1|2| | +0#0000001&@4| +0&#e0e0e08| +0&#ffd7ff255@64 -| +0#af5f00255&@1|1| |1+0#0000001&@4|1+0&#e0e0e08@4| | +0&#ffd7ff255@59 -| +8#af5f00255&@1|0| |2+0#0000001#e0e0e08@4>2+0&#ffd7ff255@5| +8&&@59 +| +0#af5f00255&@1|1| |1+0#0000001&@4|1+0&#a8a8a8255@4| | +0&#ffd7ff255@59 +| +8#af5f00255&@1|0| |2+0#0000001#a8a8a8255@4>2+0&#ffd7ff255@5| +8&&@59 | +0#af5f00255&@1|1| |3+0#0000001&| |h|e|r|e+0&#e0e0e08| +0&#ffd7ff255|3| @62 | +0#af5f00255&@1|2| | +0#0000001&@4| +0&#e0e0e08| +0&#ffd7ff255@64 | +0#af5f00255&@1|3| |t+0#40ff4011&|h|e| |c|a+0&#e0e0e08|t+0&#ffd7ff255| |i|s| |o+1&&|u|t| +0&&|o|f| |t|h|e| |b|a|g| +0#0000001&@45 diff --git a/src/testdir/shared.vim b/src/testdir/shared.vim index 4d008a0..dd2f012 100644 --- a/src/testdir/shared.vim +++ b/src/testdir/shared.vim @@ -300,7 +300,8 @@ func GetVimCommand(...) endif let cmd .= ' --not-a-term' let cmd .= ' --gui-dialog-file guidialogfile' - let cmd = substitute(cmd, 'VIMRUNTIME=\S\+', '', '') + " remove any environment variables + let cmd = substitute(cmd, '[A-Z_]\+=\S\+ *', '', 'g') " If using valgrind, make sure every run uses a different log file. if cmd =~ 'valgrind.*--log-file=' @@ -363,7 +364,7 @@ func RunVimPiped(before, after, arguments, pipecmd) " Optionally run Vim under valgrind " let cmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind ' . cmd - exe "silent !" . a:pipecmd . cmd . args . ' ' . a:arguments + exe "silent !" .. a:pipecmd .. ' ' .. cmd .. args .. ' ' .. a:arguments if len(a:before) > 0 call delete('Xbefore.vim') diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index cecb55a..564d568 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -270,6 +270,7 @@ func Test_win_tab_autocmd() let g:record = [] augroup testing + au WinNewPre * call add(g:record, 'WinNewPre') au WinNew * call add(g:record, 'WinNew') au WinClosed * call add(g:record, 'WinClosed') au WinEnter * call add(g:record, 'WinEnter') @@ -286,8 +287,8 @@ func Test_win_tab_autocmd() close call assert_equal([ - \ 'WinLeave', 'WinNew', 'WinEnter', - \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', + \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter', \ 'WinLeave', 'WinClosed', 'WinEnter' \ ], g:record) @@ -298,17 +299,96 @@ func Test_win_tab_autocmd() bwipe somefile call assert_equal([ - \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', + \ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', \ 'WinClosed', 'TabClosed' \ ], g:record) + let g:record = [] + copen + help + tabnext + vnew + + call assert_equal([ + \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', + \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', + \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter' + \ ], g:record) + augroup testing au! augroup END unlet g:record endfunc +func Test_WinNewPre() + " Test that the old window layout can be accessed before a new window is created. + let g:layouts_pre = [] + let g:layouts_post = [] + augroup testing + au WinNewPre * call add(g:layouts_pre, winlayout()) + au WinNew * call add(g:layouts_post, winlayout()) + augroup END + 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]) + 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 + unlet g:layouts_pre + unlet g:layouts_post + + " Test modifying window layout during WinNewPre throws. + let g:caught = 0 + augroup testing + au! + au WinNewPre * split + augroup END + try + vnew + catch + let g:caught += 1 + endtry + augroup testing + au! + au WinNewPre * tabnew + augroup END + try + vnew + catch + let g:caught += 1 + endtry + augroup testing + au! + au WinNewPre * close + augroup END + try + vnew + catch + let g:caught += 1 + endtry + augroup testing + au! + au WinNewPre * tabclose + augroup END + try + vnew + catch + let g:caught += 1 + endtry + call assert_equal(4, g:caught) + augroup testing + au! + augroup END + unlet g:caught +endfunc + func Test_WinResized() CheckRunVimInTerminal @@ -739,6 +819,27 @@ func Test_WinClosed_switch_tab() %bwipe! endfunc +" This used to trigger WinClosed twice for the same window, and the window's +" buffer was NULL in the second autocommand. +func Test_WinClosed_BufUnload_close_other() + tabnew + let g:tab = tabpagenr() + let g:buf = bufnr() + new + setlocal bufhidden=wipe + augroup test-WinClosed + autocmd BufUnload * ++once exe g:buf .. 'bwipe!' + autocmd WinClosed * call tabpagebuflist(g:tab) + augroup END + close + + unlet g:tab + unlet g:buf + autocmd! test-WinClosed + augroup! test-WinClosed + %bwipe! +endfunc + func s:AddAnAutocmd() augroup vimBarTest au BufReadCmd * echo 'hello' @@ -2626,6 +2727,24 @@ func Test_TextChangedI_with_setline() bwipe! endfunc +func Test_TextChanged_with_norm() + " For unknown reason this fails on MS-Windows + CheckNotMSWindows + CheckFeature terminal + let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) + call assert_equal('running', term_getstatus(buf)) + call term_sendkeys(buf, ":let g:a=0\<cr>") + call term_wait(buf, 50) + call term_sendkeys(buf, ":au! TextChanged * :let g:a+=1\<cr>") + call term_wait(buf, 50) + call term_sendkeys(buf, ":norm! ia\<cr>") + call term_wait(buf, 50) + call term_sendkeys(buf, ":echo g:a\<cr>") + call term_wait(buf, 50) + call WaitForAssert({-> assert_match('^1.*$', term_getline(buf, 3))}) + bwipe! +endfunc + func Test_Changed_FirstTime() CheckFeature terminal CheckNotGui @@ -4315,4 +4434,44 @@ func Test_autocmd_shortmess() delfunc SetupVimTest_shm endfunc +func Test_autocmd_invalidates_undo_on_textchanged() + CheckRunVimInTerminal + let script =<< trim END + set hidden + " create quickfix list (at least 2 lines to move line) + vimgrep /u/j % + + " enter quickfix window + cwindow + + " set modifiable + setlocal modifiable + + " set autocmd to clear quickfix list + + autocmd! TextChanged <buffer> call setqflist([]) + " move line + move+1 + END + call writefile(script, 'XTest_autocmd_invalidates_undo_on_textchanged', 'D') + let buf = RunVimInTerminal('XTest_autocmd_invalidates_undo_on_textchanged', {'rows': 20}) + call term_sendkeys(buf, ":so %\<cr>") + call term_sendkeys(buf, "G") + call WaitForAssert({-> assert_match('^XTest_autocmd_invalidates_undo_on_textchanged\s*$', term_getline(buf, 20))}, 1000) + + call StopVimInTerminal(buf) +endfunc + +func Test_autocmd_creates_new_buffer_on_bufleave() + e a.txt + e b.txt + setlocal bufhidden=wipe + autocmd BufLeave <buffer> diffsplit c.txt + bn + call assert_equal(1, winnr('$')) + call assert_equal('a.txt', bufname('%')) + bw a.txt + bw c.txt +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim index ee05548..96d91c9 100644 --- a/src/testdir/test_breakindent.vim +++ b/src/testdir/test_breakindent.vim @@ -424,7 +424,7 @@ func Test_breakindent12() \ "~ ", \ ] call s:compare_lines(expect, lines) - call s:close_windows('set nuw=4 listchars=') + call s:close_windows('set nuw=4 listchars&') endfunc func Test_breakindent12_vartabs() @@ -439,7 +439,7 @@ func Test_breakindent12_vartabs() \ "~ ", \ ] call s:compare_lines(expect, lines) - call s:close_windows('set nuw=4 listchars= vts&') + call s:close_windows('set nuw=4 listchars& vts&') endfunc func Test_breakindent13() @@ -733,7 +733,7 @@ func Test_breakindent20_list() \ "shall make no law ", \ ] call s:compare_lines(expect, lines) - " set minimum indent + " set minimum text width setl briopt=min:5 redraw! let lines = s:screen_lines2(1, 6, 20) @@ -1086,5 +1086,83 @@ func Test_linebreak_list() bwipe! endfunc +func Test_breakindent_change_display_uhex() + call s:test_windows('setl briopt=min:0 list listchars=eol:$') + redraw! + let lines = s:screen_lines(line('.'), 20) + let expect = [ + \ "^Iabcdefghijklmnopqr", + \ " stuvwxyzABCDEFGHIJ", + \ " KLMNOP$ " + \ ] + call s:compare_lines(expect, lines) + set display+=uhex + redraw! + let lines = s:screen_lines(line('.'), 20) + let expect = [ + \ "<09>abcdefghijklmnop", + \ " qrstuvwxyzABCDEF", + \ " GHIJKLMNOP$ " + \ ] + call s:compare_lines(expect, lines) + set display& + + call s:close_windows() +endfunc + +func Test_breakindent_list_split() + 10new + 61vsplit + setlocal tabstop=8 breakindent list listchars=tab:<->,eol:$ + put =s:input + 30vsplit + setlocal listchars=eol:$ + let expect = [ + \ "^IabcdefghijklmnopqrstuvwxyzAB|<------>abcdefghijklmnopqrstuv", + \ " CDEFGHIJKLMNOP$ | wxyzABCDEFGHIJKLMNOP$ ", + \ "~ |~ " + \ ] + redraw! + let lines = s:screen_lines(line('.'), 61) + call s:compare_lines(expect, lines) + wincmd p + redraw! + let lines = s:screen_lines(line('.'), 61) + call s:compare_lines(expect, lines) + + bwipe! +endfunc + +func Test_breakindent_min_with_signcol() + call s:test_windows('setl briopt=min:15 signcolumn=yes') + redraw! + let expect = [ + \ " abcdefghijklmn", + \ " opqrstuvwxyzABC", + \ " DEFGHIJKLMNOP " + \ ] + let lines = s:screen_lines(line('.'), 20) + call s:compare_lines(expect, lines) + setl briopt=min:17 + redraw! + let expect = [ + \ " abcdefghijklmn", + \ " opqrstuvwxyzABCDE", + \ " FGHIJKLMNOP " + \ ] + let lines = s:screen_lines(line('.'), 20) + call s:compare_lines(expect, lines) + setl briopt=min:19 + redraw! + let expect = [ + \ " abcdefghijklmn", + \ " opqrstuvwxyzABCDEF", + \ " GHIJKLMNOP " + \ ] + let lines = s:screen_lines(line('.'), 20) + call s:compare_lines(expect, lines) + + call s:close_windows() +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim index 53947f4..8be521b 100644 --- a/src/testdir/test_clientserver.vim +++ b/src/testdir/test_clientserver.vim @@ -13,7 +13,7 @@ source shared.vim func Check_X11_Connection() if has('x11') - CheckEnv DISPLAY + CheckX11 try call remote_send('xxx', '') catch diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 4554712..7c86bcd 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -691,7 +691,7 @@ func Test_getcompletion() bw Xtest\ endif - call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') + call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E866:') call assert_fails('call getcompletion("", "burp")', 'E475:') call assert_fails('call getcompletion("abc", [])', 'E1174:') endfunc @@ -917,6 +917,26 @@ func Test_cmdline_remove_char() let &encoding = encoding_save endfunc +func Test_cmdline_del_utf8() + let @s = '⒌' + call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx') + call assert_equal('",,', @:) + + let @s = 'a̳' + call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx') + call assert_equal('",,', @:) + + let @s = 'β̳' + call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx') + call assert_equal('",,', @:) + + if has('arabic') + let @s = 'لا' + call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx') + call assert_equal('",,', @:) + endif +endfunc + func Test_cmdline_keymap_ctrl_hat() CheckFeature keymap @@ -3742,4 +3762,34 @@ func Test_custom_completion_with_glob() delfunc TestGlobComplete endfunc +func Test_window_size_stays_same_after_changing_cmdheight() + set laststatus=2 + let expected = winheight(0) + function! Function_name() abort + call feedkeys(":"..repeat('x', &columns), 'x') + let &cmdheight=2 + let &cmdheight=1 + redraw + endfunction + call Function_name() + call assert_equal(expected, winheight(0)) +endfunc + +" verify that buffer-completion finds all buffer names matching a pattern +func Test_buffer_completion() + " should return empty list + call assert_equal([], getcompletion('', 'buffer')) + + call mkdir('Xbuf_complete', 'R') + e Xbuf_complete/Foobar.c + e Xbuf_complete/MyFoobar.c + e AFoobar.h + let expected = ["Xbuf_complete/Foobar.c", "Xbuf_complete/MyFoobar.c", "AFoobar.h"] + + call assert_equal(3, len(getcompletion('Foo', 'buffer'))) + call assert_equal(expected, getcompletion('Foo', 'buffer')) + call feedkeys(":b Foo\<C-A>\<C-B>\"\<CR>", 'xt') + call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim index 5ba16db..33a2662 100644 --- a/src/testdir/test_cmdwin.vim +++ b/src/testdir/test_cmdwin.vim @@ -188,7 +188,7 @@ func Test_cmdwin_tabpage() tabclose! endfunc -func Test_cmdwin_interrupted() +func Test_cmdwin_interrupted_more_prompt() CheckScreendump " aborting the :smile output caused the cmdline window to use the current @@ -470,4 +470,117 @@ func Test_cmdwin_restore_heights() set cmdheight& showtabline& laststatus& endfunc +func Test_cmdwin_temp_curwin() + func CheckWraps(expect_wrap) + setlocal textwidth=0 wrapmargin=1 + + call deletebufline('', 1, '$') + let as = repeat('a', winwidth(0) - 2 - &wrapmargin) + call setline(1, as .. ' b') + normal! gww + + setlocal textwidth& wrapmargin& + call assert_equal(a:expect_wrap ? [as, 'b'] : [as .. ' b'], getline(1, '$')) + endfunc + + func CheckCmdWin() + call assert_equal('command', win_gettype()) + " textoff and &wrapmargin formatting considers the cmdwin_type char. + call assert_equal(1, getwininfo(win_getid())[0].textoff) + call CheckWraps(1) + endfunc + + func CheckOtherWin() + call assert_equal('', win_gettype()) + call assert_equal(0, getwininfo(win_getid())[0].textoff) + call CheckWraps(0) + endfunc + + call feedkeys("q::call CheckCmdWin()\<CR>:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\<CR>:q<CR>", 'ntx') + + %bwipe! + delfunc CheckWraps + delfunc CheckCmdWin + delfunc CheckOtherWin +endfunc + +func Test_cmdwin_interrupted() + func CheckInterrupted() + call feedkeys("q::call assert_equal('', getcmdwintype())\<CR>:call assert_equal('', getcmdtype())\<CR>:q<CR>", 'ntx') + endfunc + + augroup CmdWin + + " While opening the cmdwin's split: + " Close the cmdwin's window. + au WinEnter * ++once quit + call CheckInterrupted() + + " Close the old window. + au WinEnter * ++once execute winnr('#') 'quit' + call CheckInterrupted() + + " Switch back to the old window. + au WinEnter * ++once wincmd p + call CheckInterrupted() + + " Change the old window's buffer. + au WinEnter * ++once call win_execute(win_getid(winnr('#')), 'enew') + call CheckInterrupted() + + " Using BufLeave autocmds as cmdwin restrictions do not apply to them when + " fired from opening the cmdwin... + " After opening the cmdwin's split, while creating the cmdwin's buffer: + " Delete the cmdwin's buffer. + au BufLeave * ++once bwipe + call CheckInterrupted() + + " Close the cmdwin's window. + au BufLeave * ++once quit + call CheckInterrupted() + + " Close the old window. + au BufLeave * ++once execute winnr('#') 'quit' + call CheckInterrupted() + + " Switch to a different window. + au BufLeave * ++once split + call CheckInterrupted() + + " Change the old window's buffer. + au BufLeave * ++once call win_execute(win_getid(winnr('#')), 'enew') + call CheckInterrupted() + + " However, changing the current buffer is OK and does not interrupt. + au BufLeave * ++once edit other + call feedkeys("q::let t=getcmdwintype()\<CR>:let b=bufnr()\<CR>:clo<CR>", 'ntx') + call assert_equal(':', t) + call assert_equal(1, bufloaded('other')) + call assert_notequal(b, bufnr('other')) + + augroup END + + " No autocmds should remain, but clear the augroup to be sure. + augroup CmdWin + au! + augroup END + + %bwipe! + delfunc CheckInterrupted +endfunc + +func Test_cmdwin_existing_bufname() + func CheckName() + call assert_equal(1, getbufinfo('')[0].command) + call assert_equal(0, getbufinfo('[Command Line]')[0].command) + call assert_match('#a\s*"\[Command Line\]"', execute('ls')) + call assert_match('%a\s*"\[Command Line\]"', execute('ls')) + endfunc + + file [Command Line] + call feedkeys("q::call CheckName()\<CR>:q\<CR>", 'ntx') + 0file + delfunc CheckName +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_comments.vim b/src/testdir/test_comments.vim index c34b85c..67454f4 100644 --- a/src/testdir/test_comments.vim +++ b/src/testdir/test_comments.vim @@ -237,6 +237,12 @@ func Test_comment_autoformat() call feedkeys("aone\ntwo\n", 'xt') call assert_equal(['one', 'two', ''], getline(1, '$')) + set backspace=indent,eol,start + %d + call feedkeys("aone \n\<BS>", 'xt') + call assert_equal(['one'], getline(1, '$')) + set backspace& + close! endfunc diff --git a/src/testdir/test_conceal.vim b/src/testdir/test_conceal.vim index e977921..355817d 100644 --- a/src/testdir/test_conceal.vim +++ b/src/testdir/test_conceal.vim @@ -171,6 +171,57 @@ func Test_conceal_with_cursorcolumn() call StopVimInTerminal(buf) endfunc +" Check that 'cursorline' and 'wincolor' apply to the whole line in presence +" of wrapped lines containing concealed text. +func Test_conceal_wrapped_cursorline_wincolor() + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline + normal! g$ + [CODE] + + call writefile(code, 'XTest_conceal_cul_wcr', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr', {'rows': 4, 'cols': 40}) + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_01', {}) + + call term_sendkeys(buf, ":set wincolor=ErrorMsg\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_02', {}) + + call term_sendkeys(buf, ":set nocursorline\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_03', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +" Same as Test_conceal_wrapped_cursorline_wincolor(), but with 'rightleft'. +func Test_conceal_wrapped_cursorline_wincolor_rightleft() + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'one one one |hidden| one one one one one one one one') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n cursorline rightleft + normal! g$ + [CODE] + + call writefile(code, 'XTest_conceal_cul_wcr_rl', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_cul_wcr_rl', {'rows': 4, 'cols': 40}) + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_01', {}) + + call term_sendkeys(buf, ":set wincolor=ErrorMsg\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_02', {}) + + call term_sendkeys(buf, ":set nocursorline\n") + call VerifyScreenDump(buf, 'Test_conceal_cul_wcr_rl_03', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + func Test_conceal_resize_term() CheckScreendump @@ -338,77 +389,290 @@ func Test_conceal_eol() endfunc func Test_conceal_mouse_click() - enew! + call NewWindow(10, 40) set mouse=a setlocal conceallevel=2 concealcursor=nc syn match Concealed "this" conceal hi link Concealed Search - call setline(1, 'conceal this click here') - redraw - call assert_equal(['conceal click here '], ScreenLines(1, 20)) - - " click on the space between "this" and "click" puts cursor there - call test_setmouse(1, 9) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 13, 0, 13], getcurpos()) - " click on 'h' of "here" puts cursor there - call test_setmouse(1, 16) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 20, 0, 20], getcurpos()) - " click on 'e' of "here" puts cursor there - call test_setmouse(1, 19) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 23], getcurpos()) - " click after end of line puts cursor on 'e' without 'virtualedit' - call test_setmouse(1, 20) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 24], getcurpos()) - call test_setmouse(1, 21) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 25], getcurpos()) - call test_setmouse(1, 22) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 26], getcurpos()) - call test_setmouse(1, 31) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 35], getcurpos()) - call test_setmouse(1, 32) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 36], getcurpos()) - - set virtualedit=all - redraw - " click on the space between "this" and "click" puts cursor there - call test_setmouse(1, 9) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 13, 0, 13], getcurpos()) - " click on 'h' of "here" puts cursor there - call test_setmouse(1, 16) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 20, 0, 20], getcurpos()) - " click on 'e' of "here" puts cursor there - call test_setmouse(1, 19) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 23, 0, 23], getcurpos()) - " click after end of line puts cursor there without 'virtualedit' - call test_setmouse(1, 20) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 0, 24], getcurpos()) - call test_setmouse(1, 21) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 1, 25], getcurpos()) - call test_setmouse(1, 22) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 2, 26], getcurpos()) - call test_setmouse(1, 31) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 11, 35], getcurpos()) - call test_setmouse(1, 32) - call feedkeys("\<LeftMouse>", "tx") - call assert_equal([0, 1, 24, 12, 36], getcurpos()) - - bwipe! - set mouse& virtualedit& + + " Test with both 'nocursorline' and 'cursorline', as they use two different + " code paths to set virtual columns for the cells to clear. + for cul in [v:false, v:true] + let &l:cursorline = cul + + call setline(1, 'conceal this click here') + call assert_equal([ + \ 'conceal click here ', + \ ], ScreenLines(1, 40)) + + " Click on the space between "this" and "click" puts cursor there. + call test_setmouse(1, 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call test_setmouse(1, 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call test_setmouse(1, 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor on 'e' without 'virtualedit'. + call test_setmouse(1, 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 24], getcurpos()) + call test_setmouse(1, 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 25], getcurpos()) + call test_setmouse(1, 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 26], getcurpos()) + call test_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 35], getcurpos()) + call test_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 36], getcurpos()) + + set virtualedit=all + redraw + " Click on the space between "this" and "click" puts cursor there. + call test_setmouse(1, 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call test_setmouse(1, 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call test_setmouse(1, 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor there with 'virtualedit'. + call test_setmouse(1, 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 0, 24], getcurpos()) + call test_setmouse(1, 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 1, 25], getcurpos()) + call test_setmouse(1, 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 2, 26], getcurpos()) + call test_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call test_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + " Behavior should also be the same with 'colorcolumn'. + setlocal colorcolumn=30 + redraw + call test_setmouse(1, 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call test_setmouse(1, 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + setlocal colorcolumn& + + if has('rightleft') + setlocal rightleft + call assert_equal([ + \ ' ereh kcilc laecnoc', + \ ], ScreenLines(1, 40)) + " Click on the space between "this" and "click" puts cursor there. + call test_setmouse(1, 41 - 9) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 13, 0, 13], getcurpos()) + " Click on 'h' of "here" puts cursor there. + call test_setmouse(1, 41 - 16) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 20, 0, 20], getcurpos()) + " Click on 'e' of "here" puts cursor there. + call test_setmouse(1, 41 - 19) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 23, 0, 23], getcurpos()) + " Click after end of line puts cursor there with 'virtualedit'. + call test_setmouse(1, 41 - 20) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 0, 24], getcurpos()) + call test_setmouse(1, 41 - 21) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 1, 25], getcurpos()) + call test_setmouse(1, 41 - 22) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 2, 26], getcurpos()) + call test_setmouse(1, 41 - 31) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 11, 35], getcurpos()) + call test_setmouse(1, 41 - 32) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 24, 12, 36], getcurpos()) + setlocal rightleft& + endif + + set virtualedit& + + " Test with a wrapped line. + call setline(1, ['conceal this click here']->repeat(3)->join()) + call assert_equal([ + \ 'conceal click here conceal cli ', + \ 'ck here conceal click here ', + \ ], ScreenLines([1, 2], 40)) + " Click on boguscols puts cursor on the last char of a screen line. + for col in range(33, 40) + call test_setmouse(1, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 40, 0, 40], getcurpos()) + endfor + + " Also test with the last char of a screen line concealed. + setlocal number signcolumn=yes + call assert_equal([ + \ ' 1 conceal click here conceal ', + \ ' click here conceal click h ', + \ ' ere ', + \ ], ScreenLines([1, 3], 40)) + call test_setmouse(1, 34) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 32, 0, 32], getcurpos()) + call test_setmouse(2, 7) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 37, 0, 37], getcurpos()) + " Click on boguscols puts cursor on the last char of a screen line. + for col in range(35, 40) + call test_setmouse(1, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 34, 0, 34], getcurpos()) + call test_setmouse(2, col) + call feedkeys("\<LeftMouse>", "tx") + call assert_equal([0, 1, 68, 0, 68], getcurpos()) + endfor + setlocal number& signcolumn& + endfor + + call CloseWindow() + set mouse& +endfunc + +" Test that cursor is drawn at the correct column when it is after end of the +" line with 'virtualedit' and concealing. +func Run_test_conceal_virtualedit_after_eol(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_ve_after_eol', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol', {'rows': 3}) + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_1', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_2', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_3', {}) + call term_sendkeys(buf, "l") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_4', {}) + call term_sendkeys(buf, "rr") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_5', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_virtualedit_after_eol() + CheckScreendump + + call Run_test_conceal_virtualedit_after_eol(1) + call Run_test_conceal_virtualedit_after_eol(0) +endfunc + +" Same as Run_test_conceal_virtualedit_after_eol(), but with 'rightleft'. +func Run_test_conceal_virtualedit_after_eol_rightleft(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, 'abcdefgh|hidden|ijklmnpop') + syntax match test /|hidden|/ conceal + set conceallevel=2 concealcursor=n virtualedit=all rightleft + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_ve_after_eol_rl', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_ve_after_eol_rl', {'rows': 3}) + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_1', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_2', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_3', {}) + call term_sendkeys(buf, "h") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_4', {}) + call term_sendkeys(buf, "rr") + call VerifyScreenDump(buf, 'Test_conceal_ve_after_eol_rl_5', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_virtualedit_after_eol_rightleft() + CheckFeature rightleft + CheckScreendump + + call Run_test_conceal_virtualedit_after_eol_rightleft(1) + call Run_test_conceal_virtualedit_after_eol_rightleft(0) +endfunc + +" Test that cursor position is correct when double-width chars are concealed. +func Run_test_conceal_double_width(wrap) + let code =<< trim eval [CODE] + let &wrap = {a:wrap} + call setline(1, ['aaaaa口=口bbbbb口=口ccccc', 'foobar']) + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n colorcolumn=30 + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_double_width', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_double_width', {'rows': 4}) + call VerifyScreenDump(buf, 'Test_conceal_double_width_1', {}) + call term_sendkeys(buf, "gM") + call VerifyScreenDump(buf, 'Test_conceal_double_width_2', {}) + call term_sendkeys(buf, ":set conceallevel=3\<CR>") + call VerifyScreenDump(buf, 'Test_conceal_double_width_3', {}) + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_conceal_double_width_4', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + +func Test_conceal_double_width() + CheckScreendump + + call Run_test_conceal_double_width(1) + call Run_test_conceal_double_width(0) +endfunc + +" Test that line wrapping is correct when double-width chars are concealed. +func Test_conceal_double_width_wrap() + CheckScreendump + + let code =<< trim [CODE] + call setline(1, 'aaaaaaaaaa口=口bbbbbbbbbb口=口cccccccccc') + syntax match test /口=口/ conceal cchar=β + set conceallevel=2 concealcursor=n + normal! $ + [CODE] + call writefile(code, 'XTest_conceal_double_width_wrap', 'D') + let buf = RunVimInTerminal('-S XTest_conceal_double_width_wrap', {'rows': 4, 'cols': 20}) + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_1', {}) + call term_sendkeys(buf, "gM") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_2', {}) + call term_sendkeys(buf, ":set conceallevel=3\<CR>") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_3', {}) + call term_sendkeys(buf, "$") + call VerifyScreenDump(buf, 'Test_conceal_double_width_wrap_4', {}) + + " clean up + call StopVimInTerminal(buf) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index 930fd7b..7602bd3 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -3,6 +3,7 @@ source shared.vim source screendump.vim source check.vim +source view_util.vim func Test_diff_fold_sync() enew! @@ -871,6 +872,10 @@ func VerifyInternal(buf, dumpfile, extra) endfunc func Test_diff_screen() + if has('osxdarwin') && system('diff --version') =~ '^Apple diff' + throw 'Skipped: unified diff does not work properly on this macOS version' + endif + let g:test_is_flaky = 1 CheckScreendump CheckFeature menu @@ -1129,7 +1134,7 @@ func Test_diff_breakindent_after_filler() CheckScreendump let lines =<< trim END - set laststatus=0 diffopt+=followwrap breakindent + set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0 call setline(1, ['a', ' ' .. repeat('c', 50)]) vnew call setline(1, ['a', 'b', ' ' .. repeat('c', 50)]) @@ -1712,5 +1717,307 @@ func Test_diff_put_and_undo() set nodiff endfunc +" Test for the diff() function +def Test_diff_func() + # string is added/removed/modified at the beginning + assert_equal("@@ -0,0 +1 @@\n+abc\n", + diff(['def'], ['abc', 'def'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}], + diff(['def'], ['abc', 'def'], {output: 'indices'})) + assert_equal("@@ -1 +0,0 @@\n-abc\n", + diff(['abc', 'def'], ['def'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}], + diff(['abc', 'def'], ['def'], {output: 'indices'})) + assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", + diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'})) + + # string is added/removed/modified at the end + assert_equal("@@ -1,0 +2 @@\n+def\n", + diff(['abc'], ['abc', 'def'], {output: 'unified'})) + assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}], + diff(['abc'], ['abc', 'def'], {output: 'indices'})) + assert_equal("@@ -2 +1,0 @@\n-def\n", + diff(['abc', 'def'], ['abc'], {output: 'unified'})) + assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}], + diff(['abc', 'def'], ['abc'], {output: 'indices'})) + assert_equal("@@ -2 +2 @@\n-def\n+xef\n", + diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'})) + assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}], + diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'})) + + # string is added/removed/modified in the middle + assert_equal("@@ -2,0 +3 @@\n+xxx\n", + diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'})) + assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}], + diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'})) + assert_equal("@@ -3 +2,0 @@\n-333\n", + diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'})) + assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}], + diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'})) + assert_equal("@@ -3 +3 @@\n-333\n+xxx\n", + diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'})) + assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}], + diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'})) + + # new strings are added to an empty List + assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n", + diff([], ['abc', 'def'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}], + diff([], ['abc', 'def'], {output: 'indices'})) + + # all the strings are removed from a List + assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n", + diff(['abc', 'def'], [], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}], + diff(['abc', 'def'], [], {output: 'indices'})) + + # First character is added/removed/different + assert_equal("@@ -1 +1 @@\n-abc\n+bc\n", + diff(['abc'], ['bc'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['abc'], ['bc'], {output: 'indices'})) + assert_equal("@@ -1 +1 @@\n-bc\n+abc\n", + diff(['bc'], ['abc'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['bc'], ['abc'], {output: 'indices'})) + assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n", + diff(['abc'], ['xbc'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['abc'], ['xbc'], {output: 'indices'})) + + # Last character is added/removed/different + assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n", + diff(['abc'], ['abcd'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['abc'], ['abcd'], {output: 'indices'})) + assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n", + diff(['abcd'], ['abc'], {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff(['abcd'], ['abc'], {output: 'indices'})) + var diff_unified: string = diff(['abc'], ['abx'], {output: 'unified'}) + assert_equal("@@ -1 +1 @@\n-abc\n+abx\n", diff_unified) + var diff_indices: list<dict<number>> = + diff(['abc'], ['abx'], {output: 'indices'}) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff_indices) + + # partial string modification at the start and at the end. + var fromlist =<< trim END + one two + three four + five six + END + var tolist =<< trim END + one + six + END + assert_equal("@@ -1,3 +1,2 @@\n-one two\n-three four\n-five six\n+one\n+six\n", diff(fromlist, tolist, {output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}], + diff(fromlist, tolist, {output: 'indices'})) + + # non-contiguous modifications + fromlist =<< trim END + one two + three four + five abc six + END + tolist =<< trim END + one abc two + three four + five six + END + assert_equal("@@ -1 +1 @@\n-one two\n+one abc two\n@@ -3 +3 @@\n-five abc six\n+five six\n", + diff(fromlist, tolist, {output: 'unified'})) + assert_equal([{'from_count': 1, 'to_idx': 0, 'to_count': 1, 'from_idx': 0}, + {'from_count': 1, 'to_idx': 2, 'to_count': 1, 'from_idx': 2}], + diff(fromlist, tolist, {output: 'indices'})) + + # add/remove blank lines + assert_equal("@@ -2,2 +1,0 @@\n-\n-\n", + diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'})) + assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}], + diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'})) + assert_equal("@@ -1,0 +2,2 @@\n+\n+\n", + diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'})) + assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}], + diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'})) + + # diff ignoring case + assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'})) + assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'})) + + # diff ignoring all whitespace changes except leading whitespace changes + assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true})) + assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true})) + assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false})) + assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true})) + assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false})) + + # diff ignoring all whitespace changes + assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true})) + assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true})) + assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false})) + + # diff ignoring trailing whitespace changes + assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true})) + + # diff ignoring blank lines + assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true})) + assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true})) + + # same string + assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi'])) + assert_equal('', diff([''], [''])) + assert_equal('', diff([], [])) + + # different xdiff algorithms + for algo in ['myers', 'minimal', 'patience', 'histogram'] + assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", + diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'})) + endfor + assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", + diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'})) + assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}], + diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'})) + + # identical strings + assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'})) + assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'})) + assert_equal('', diff([], [], {output: 'unified'})) + assert_equal([], diff([], [], {output: 'indices'})) + + # If 'diffexpr' is set, it should not be used for diff() + def MyDiffExpr() + enddef + var save_diffexpr = &diffexpr + :set diffexpr=MyDiffExpr() + assert_equal("@@ -1 +1 @@\n-abc\n+\n", + diff(['abc'], [''], {output: 'unified'})) + assert_equal([{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}], + diff(['abc'], [''], {output: 'indices'})) + assert_equal('MyDiffExpr()', &diffexpr) + &diffexpr = save_diffexpr + + # try different values for unified diff 'context' + assert_equal("@@ -0,0 +1 @@\n+x\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'])) + assert_equal("@@ -0,0 +1 @@\n+x\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 0})) + assert_equal("@@ -1 +1,2 @@\n+x\n a\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 1})) + assert_equal("@@ -1,2 +1,3 @@\n+x\n a\n b\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 2})) + assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 3})) + assert_equal("@@ -1,3 +1,4 @@\n+x\n a\n b\n c\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: 4})) + assert_equal("@@ -0,0 +1 @@\n+x\n", + diff(['a', 'b', 'c'], ['x', 'a', 'b', 'c'], {context: -1})) + + # Error cases + assert_fails('call diff({}, ["a"])', 'E1211:') + assert_fails('call diff(["a"], {})', 'E1211:') + assert_fails('call diff(["a"], ["a"], [])', 'E1206:') + assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz') + assert_fails('call diff(["a"], ["a"], {context: []})', 'E745: Using a List as a Number') +enddef + +" Test for using the diff() function with 'diffexpr' +func Test_diffexpr_with_diff_func() + CheckScreendump + + let lines =<< trim END + def DiffFuncExpr() + var in: list<string> = readfile(v:fname_in) + var new: list<string> = readfile(v:fname_new) + var out: string = diff(in, new) + writefile(split(out, "\n"), v:fname_out) + enddef + set diffexpr=DiffFuncExpr() + + edit Xdifffunc1.txt + diffthis + vert split Xdifffunc2.txt + diffthis + END + call writefile(lines, 'XsetupDiffFunc.vim', 'D') + + call writefile(['zero', 'one', 'two', 'three'], 'Xdifffunc1.txt', 'D') + call writefile(['one', 'twox', 'three', 'four'], 'Xdifffunc2.txt', 'D') + + let buf = RunVimInTerminal('-S XsetupDiffFunc.vim', {'rows': 12}) + call VerifyScreenDump(buf, 'Test_difffunc_diffexpr_1', {}) + call StopVimInTerminal(buf) +endfunc + +func Test_diff_toggle_wrap_skipcol_leftcol() + 61vnew + call setline(1, 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.') + 30vnew + call setline(1, 'ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.') + let win1 = win_getid() + setlocal smoothscroll + exe "normal! $\<C-E>" + wincmd l + let win2 = win_getid() + setlocal smoothscroll + exe "normal! $\<C-E>" + call assert_equal([ + \ '<<<sadipscing elitr, sed diam |<<<tetur sadipscing elitr, sed|', + \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|', + \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|', + \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|', + \ '~ |ptua. |', + \ ], ScreenLines([1, 5], 62)) + call assert_equal({'col': 29, 'row': 4, 'endcol': 29, 'curscol': 29}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 36, 'row': 5, 'endcol': 36, 'curscol': 36}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + wincmd h + diffthis + wincmd l + diffthis + normal! 0 + call assert_equal([ + \ ' ipsum dolor sit amet, conset| Lorem ipsum dolor sit amet, |', + \ '~ |~ |', + \ ], ScreenLines([1, 2], 62)) + call assert_equal({'col': 3, 'row': 1, 'endcol': 3, 'curscol': 3}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 34, 'row': 1, 'endcol': 34, 'curscol': 34}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + normal! $ + call assert_equal([ + \ ' voluptua. | diam voluptua. |', + \ '~ |~ |', + \ ], ScreenLines([1, 2], 62)) + call assert_equal({'col': 11, 'row': 1, 'endcol': 11, 'curscol': 11}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 48, 'row': 1, 'endcol': 48, 'curscol': 48}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + diffoff! + call assert_equal([ + \ 'ipsum dolor sit amet, consetet|Lorem ipsum dolor sit amet, co|', + \ 'ur sadipscing elitr, sed diam |nsetetur sadipscing elitr, sed|', + \ 'nonumy eirmod tempor invidunt | diam nonumy eirmod tempor inv|', + \ 'ut labore et dolore magna aliq|idunt ut labore et dolore magn|', + \ 'uyam erat, sed diam voluptua. |a aliquyam erat, sed diam volu|', + \ '~ |ptua. |', + \ ], ScreenLines([1, 6], 62)) + call assert_equal({'col': 29, 'row': 5, 'endcol': 29, 'curscol': 29}, + \ screenpos(win1, line('.', win1), col('.', win1))) + call assert_equal({'col': 36, 'row': 6, 'endcol': 36, 'curscol': 36}, + \ screenpos(win2, line('.', win2), col('.', win2))) + + bwipe! + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_display.vim b/src/testdir/test_display.vim index 5e0f86a..86e400e 100644 --- a/src/testdir/test_display.vim +++ b/src/testdir/test_display.vim @@ -252,12 +252,12 @@ func Test_eob_fillchars() " default value call assert_match('eob:\~', &fillchars) " invalid values - call assert_fails(':set fillchars=eob:', 'E474:') - call assert_fails(':set fillchars=eob:xy', 'E474:') - call assert_fails(':set fillchars=eob:\255', 'E474:') - call assert_fails(':set fillchars=eob:<ff>', 'E474:') - call assert_fails(":set fillchars=eob:\x01", 'E474:') - call assert_fails(':set fillchars=eob:\\x01', 'E474:') + call assert_fails(':set fillchars=eob:', 'E1511:') + call assert_fails(':set fillchars=eob:xy', 'E1511:') + call assert_fails(':set fillchars=eob:\255', 'E1511:') + call assert_fails(':set fillchars=eob:<ff>', 'E1511:') + call assert_fails(":set fillchars=eob:\x01", 'E1512:') + call assert_fails(':set fillchars=eob:\\x01', 'E1512:') " default is ~ new redraw @@ -411,14 +411,16 @@ func Run_Test_display_lastline(euro) call StopVimInTerminal(buf) endfunc -func Test_display_lastline() +func Test_display_lastline_dump() CheckScreendump call Run_Test_display_lastline('') call Run_Test_display_lastline('euro_') +endfunc - call assert_fails(':set fillchars=lastline:', 'E474:') - call assert_fails(':set fillchars=lastline:〇', 'E474:') +func Test_display_lastline_fails() + call assert_fails(':set fillchars=lastline:', 'E1511:') + call assert_fails(':set fillchars=lastline:〇', 'E1512:') endfunc func Test_display_long_lastline() diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim index d662f4a..36e0525 100644 --- a/src/testdir/test_edit.vim +++ b/src/testdir/test_edit.vim @@ -2123,4 +2123,39 @@ func Test_edit_shift_bs() call StopVimInTerminal(buf) endfunc +func Test_edit_Ctrl_RSB() + new + let g:triggered = [] + autocmd InsertCharPre <buffer> let g:triggered += [v:char] + + " i_CTRL-] should not trigger InsertCharPre + exe "normal! A\<C-]>" + call assert_equal([], g:triggered) + + " i_CTRL-] should expand abbreviations but not trigger InsertCharPre + inoreabbr <buffer> f foo + exe "normal! Af\<C-]>a" + call assert_equal(['f', 'f', 'o', 'o', 'a'], g:triggered) + call assert_equal('fooa', getline(1)) + + " CTRL-] followed by i_CTRL-V should not expand abbreviations + " i_CTRL-V doesn't trigger InsertCharPre + call setline(1, '') + exe "normal! Af\<C-V>\<C-]>" + call assert_equal("f\<C-]>", getline(1)) + + let g:triggered = [] + call setline(1, '') + + " Also test assigning to v:char + autocmd InsertCharPre <buffer> let v:char = 'f' + exe "normal! Ag\<C-]>h" + call assert_equal(['g', 'f', 'o', 'o', 'h'], g:triggered) + call assert_equal('ffff', getline(1)) + + autocmd! InsertCharPre + unlet g:triggered + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim index 47fc267..221ceb0 100644 --- a/src/testdir/test_excmd.vim +++ b/src/testdir/test_excmd.vim @@ -3,6 +3,7 @@ source check.vim source shared.vim source term_util.vim +source screendump.vim func Test_ex_delete() new @@ -84,18 +85,27 @@ endfunc " Test for the :drop command func Test_drop_cmd() call writefile(['L1', 'L2'], 'Xdropfile', 'D') + " Test for reusing the current buffer enew | only + let expected_nr = bufnr() drop Xdropfile + call assert_equal(expected_nr, bufnr()) call assert_equal('L2', getline(2)) " Test for switching to an existing window below new drop Xdropfile call assert_equal(1, winnr()) - " Test for splitting the current window + " Test for splitting the current window (set nohidden) enew | only set modified drop Xdropfile call assert_equal(2, winnr('$')) + " Not splitting the current window even if modified (set hidden) + set hidden + enew | only + set modified + drop Xdropfile + call assert_equal(1, winnr('$')) " Check for setting the argument list call assert_equal(['Xdropfile'], argv()) enew | only! @@ -729,4 +739,19 @@ func Test_ex_address_range_overflow() call assert_fails(':--+foobar', 'E492:') endfunc +func Test_drop_modified_file() + CheckScreendump + let lines =<< trim END + call setline(1, 'The quick brown fox jumped over the lazy dogs') + END + call writefile([''], 'Xdrop_modified.txt', 'D') + call writefile(lines, 'Xtest_drop_modified', 'D') + let buf = RunVimInTerminal('-S Xtest_drop_modified Xdrop_modified.txt', {'rows': 10,'columns': 40}) + call term_sendkeys(buf, ":drop Xdrop_modified.txt\<CR>") + call VerifyScreenDump(buf, 'Test_drop_modified_1', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_execute_func.vim b/src/testdir/test_execute_func.vim index 09b976b..faaace0 100644 --- a/src/testdir/test_execute_func.vim +++ b/src/testdir/test_execute_func.vim @@ -204,4 +204,28 @@ func Test_execute_func_with_null() endif endfunc +func Test_win_execute_tabpagewinnr() + belowright split + tab split + belowright split + call assert_equal(2, tabpagewinnr(1)) + + tabprevious + wincmd p + call assert_equal(1, tabpagenr()) + call assert_equal(1, tabpagewinnr(1)) + call assert_equal(2, tabpagewinnr(2)) + + call win_execute(win_getid(1, 2), + \ 'call assert_equal(2, tabpagenr())' + \ .. '| call assert_equal(1, tabpagewinnr(1))' + \ .. '| call assert_equal(1, tabpagewinnr(2))') + + call assert_equal(1, tabpagenr()) + call assert_equal(1, tabpagewinnr(1)) + call assert_equal(2, tabpagewinnr(2)) + + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_exists.vim b/src/testdir/test_exists.vim index a735a7d..9cdb3fb 100644 --- a/src/testdir/test_exists.vim +++ b/src/testdir/test_exists.vim @@ -1,5 +1,7 @@ " Tests for the exists() function +import './vim9.vim' as v9 + func Test_exists() augroup myagroup autocmd! BufEnter *.my echo "myfile edited" @@ -334,4 +336,51 @@ func Test_exists_funcarg() call FuncArg_Tests("arg1", "arg2") endfunc +" Test for using exists() with class and object variables and methods. +func Test_exists_class_object() + let lines =<< trim END + vim9script + class A + var var1: number = 10 + static var var2: number = 10 + static def Foo() + enddef + def Bar() + enddef + endclass + + assert_equal(1, exists("A")) + var a = A.new() + assert_equal(1, exists("a")) + + assert_equal(1, exists("a.var1")) + assert_fails('exists("a.var2")', 'E1375: Class variable "var2" accessible only using class "A"') + assert_fails('exists("a.var3")', 'E1326: Variable "var3" not found in object "A"') + assert_equal(1, exists("A.var2")) + assert_fails('exists("A.var1")', 'E1376: Object variable "var1" accessible only using class "A" object') + assert_fails('exists("A.var3")', 'E1337: Class variable "var3" not found in class "A"') + + assert_equal(1, exists("a.Bar")) + assert_fails('exists("a.Barz")', 'E1326: Variable "Barz" not found in object "A"') + assert_fails('exists("a.Foo")', 'E1326: Variable "Foo" not found in object "A"') + assert_equal(1, exists("A.Foo")) + assert_fails('exists("A.Bar")', 'E1337: Class variable "Bar" not found in class "A"') + assert_fails('exists("A.Barz")', 'E1337: Class variable "Barz" not found in class "A"') + + def Baz() + assert_equal(1, exists("A")) + var aa = A.new() + assert_equal(1, exists("A.var2")) + assert_fails('exists("A.var1")', 'E1376: Object variable "var1" accessible only using class "A" object') + assert_fails('exists("A.var3")', 'E1337: Class variable "var3" not found in class "A"') + + assert_equal(1, exists("A.Foo")) + assert_fails('exists("A.Bar")', 'E1337: Class variable "Bar" not found in class "A"') + assert_fails('exists("A.Barz")', 'E1337: Class variable "Barz" not found in class "A"') + enddef + Baz() + END + call v9.CheckSourceSuccess(lines) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_expand.vim b/src/testdir/test_expand.vim index d7c393a..bebe138 100644 --- a/src/testdir/test_expand.vim +++ b/src/testdir/test_expand.vim @@ -51,6 +51,19 @@ func Test_expand_tilde_filename() bwipe! endfunc +func Test_expand_env_pathsep() + let $FOO = './foo' + call assert_equal('./foo/bar', expand('$FOO/bar')) + let $FOO = './foo/' + call assert_equal('./foo/bar', expand('$FOO/bar')) + let $FOO = 'C:' + call assert_equal('C:/bar', expand('$FOO/bar')) + let $FOO = 'C:/' + call assert_equal('C:/bar', expand('$FOO/bar')) + + unlet $FOO +endfunc + func Test_expandcmd() let $FOO = 'Test' call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y')) diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 6913eec..d77e5e0 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -150,6 +150,7 @@ def s:GetFilenameChecks(): dict<list<string>> chatito: ['file.chatito'], chill: ['file..ch'], chordpro: ['file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'], + chuck: ['file.ck'], cl: ['file.eni'], clean: ['file.dcl', 'file.icl'], clojure: ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'], @@ -188,6 +189,7 @@ def s:GetFilenameChecks(): dict<list<string>> cynpp: ['file.cyn'], cypher: ['file.cypher'], d: ['file.d'], + dafny: ['file.dfy'], dart: ['file.dart', 'file.drt'], datascript: ['file.ds'], dcd: ['file.dcd'], @@ -213,7 +215,7 @@ def s:GetFilenameChecks(): dict<list<string>> dracula: ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], dtd: ['file.dtd'], dtrace: ['/usr/lib/dtrace/io.d'], - dts: ['file.dts', 'file.dtsi'], + dts: ['file.dts', 'file.dtsi', 'file.dtso', 'file.its'], dune: ['jbuild', 'dune', 'dune-project', 'dune-workspace'], dylan: ['file.dylan'], dylanintr: ['file.intr'], @@ -281,7 +283,7 @@ def s:GetFilenameChecks(): dict<list<string>> glsl: ['file.glsl'], gn: ['file.gn', 'file.gni'], gnash: ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], - gnuplot: ['file.gpi', '.gnuplot'], + gnuplot: ['file.gpi', '.gnuplot', 'file.gnuplot'], go: ['file.go'], gomod: ['go.mod'], gosum: ['go.sum', 'go.work.sum'], @@ -350,13 +352,13 @@ def s:GetFilenameChecks(): dict<list<string>> 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', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'], json5: ['file.json5'], - jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'], + jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], jsonl: ['file.jsonl'], jsonnet: ['file.jsonnet', 'file.libsonnet'], jsp: ['file.jsp'], julia: ['file.jl'], just: ['justfile', 'Justfile', '.justfile', 'config.just'], - kconfig: ['Kconfig', 'Kconfig.debug', 'Kconfig.file'], + kconfig: ['Kconfig', 'Kconfig.debug', 'Kconfig.file', 'Config.in', 'Config.in.host'], kdl: ['file.kdl'], kivy: ['file.kv'], kix: ['file.kix'], @@ -620,7 +622,7 @@ def s:GetFilenameChecks(): dict<list<string>> services: ['/etc/services', 'any/etc/services'], setserial: ['/etc/serial.conf', 'any/etc/serial.conf'], sexplib: ['file.sexp'], - sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/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'], + sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/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'], sieve: ['file.siv', 'file.sieve'], sil: ['file.sil'], simula: ['file.sim'], @@ -777,6 +779,7 @@ def s:GetFilenameChecks(): dict<list<string>> vdmpp: ['file.vpp', 'file.vdmpp'], vdmrt: ['file.vdmrt'], vdmsl: ['file.vdm', 'file.vdmsl'], + vento: ['file.vto'], vera: ['file.vr', 'file.vri', 'file.vrh'], verilogams: ['file.va', 'file.vams'], vgrindefs: ['vgrindefs'], @@ -1602,82 +1605,89 @@ func Test_mod_file() filetype on " *.mod defaults to Modsim III - call writefile(['locks like Modsim III'], 'modfile.mod') - split modfile.mod + call writefile(['locks like Modsim III'], 'Xfile.mod', 'D') + split Xfile.mod call assert_equal('modsim3', &filetype) bwipe! " Users preference set by g:filetype_mod let g:filetype_mod = 'lprolog' - split modfile.mod + split Xfile.mod call assert_equal('lprolog', &filetype) unlet g:filetype_mod bwipe! + " LambdaProlog module + call writefile(['module lpromod.'], 'Xfile.mod') + split Xfile.mod + call assert_equal('lprolog', &filetype) + bwipe! + + " LambdaProlog with comment and empty lines prior module + call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'Xfile.mod') + split Xfile.mod + call assert_equal('lprolog', &filetype) + bwipe! + " RAPID header start with a line containing only "%%%", " but is not always present. - call writefile(['%%%'], 'modfile.mod') - split modfile.mod + call writefile(['%%%'], 'Xfile.mod') + split Xfile.mod call assert_equal('rapid', &filetype) bwipe! - call delete('modfile.mod') " RAPID supports umlauts in module names, leading spaces, " the .mod extension is not case sensitive. - call writefile([' module ÜmlautModule'], 'modfile.Mod') - split modfile.Mod + call writefile([' module ÜmlautModule'], 'Xfile.Mod', 'D') + split Xfile.Mod call assert_equal('rapid', &filetype) bwipe! - call delete('modfile.Mod') " RAPID is not case sensitive, embedded spaces, sysmodule, " file starts with empty line(s). - call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD') - split modfile.MOD + call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'Xfile.MOD', 'D') + split Xfile.MOD call assert_equal('rapid', &filetype) bwipe! " Modula-2 MODULE not start of line - call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'modfile.MOD') - split modfile.MOD + call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'Xfile.mod') + split Xfile.mod call assert_equal('modula2', &filetype) call assert_equal('pim', b:modula2.dialect) bwipe! " Modula-2 with comment and empty lines prior MODULE - call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'modfile.MOD') - split modfile.MOD + call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'Xfile.mod') + split Xfile.mod call assert_equal('modula2', &filetype) call assert_equal('pim', b:modula2.dialect) bwipe! - call delete('modfile.MOD') - - " LambdaProlog module - call writefile(['module lpromod.'], 'modfile.mod') - split modfile.mod - call assert_equal('lprolog', &filetype) + " Modula-2 program MODULE with priorty (and uppercase extension) + call writefile(['MODULE Module2Mod [42];'], 'Xfile.MOD') + split Xfile.MOD + call assert_equal('modula2', &filetype) + call assert_equal('pim', b:modula2.dialect) bwipe! - " LambdaProlog with comment and empty lines prior module - call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'modfile.mod') - split modfile.mod - call assert_equal('lprolog', &filetype) + " Modula-2 implementation MODULE with priorty (and uppercase extension) + call writefile(['IMPLEMENTATION MODULE Module2Mod [42];'], 'Xfile.MOD') + split Xfile.MOD + call assert_equal('modula2', &filetype) + call assert_equal('pim', b:modula2.dialect) bwipe! - call delete('modfile.mod') " go.mod - call writefile(['module example.com/M'], 'go.mod') + call writefile(['module example.com/M'], 'go.mod', 'D') split go.mod call assert_equal('gomod', &filetype) bwipe! - call delete('go.mod') call writefile(['module M'], 'go.mod') split go.mod call assert_equal('gomod', &filetype) bwipe! - call delete('go.mod') filetype off endfunc diff --git a/src/testdir/test_filter_map.vim b/src/testdir/test_filter_map.vim index 6a07bec..37ebe84 100644 --- a/src/testdir/test_filter_map.vim +++ b/src/testdir/test_filter_map.vim @@ -14,6 +14,18 @@ func Test_filter_map_list_expr_string() call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2')) call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9)) call assert_equal([7, 7, 7], map([1, 2, 3], ' 7 ')) + + " foreach() + let list01 = [1, 2, 3, 4] + let list02 = [] + call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:val * 2)')) + call assert_equal([2, 4, 6, 8], list02) + let list02 = [] + call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:key * 2)')) + call assert_equal([0, 2, 4, 6], list02) + let list02 = [] + call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, 9)')) + call assert_equal([9, 9, 9, 9], list02) endfunc " dict with expression string @@ -29,6 +41,14 @@ func Test_filter_map_dict_expr_string() call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2')) call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]')) call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9)) + + " foreach() + let dict01 = {} + call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:val * 2')) + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, dict01) + let dict01 = {} + call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:key[0]')) + call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, dict01) endfunc " list with funcref @@ -54,6 +74,16 @@ func Test_filter_map_list_expr_funcref() return a:index * 2 endfunc call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4'))) + + " foreach() + func! s:foreach1(index, val) abort + call add(g:test_variable, a:val + 1) + return [ 11, 12, 13, 14 ] + endfunc + let g:test_variable = [] + call assert_equal([0, 1, 2, 3, 4], foreach(range(5), function('s:foreach1'))) + call assert_equal([1, 2, 3, 4, 5], g:test_variable) + call remove(g:, 'test_variable') endfunc func Test_filter_map_nested() @@ -90,11 +120,46 @@ func Test_filter_map_dict_expr_funcref() return a:key[0] endfunc call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4'))) + + " foreach() + func! s:foreach1(key, val) abort + call extend(g:test_variable, {a:key: a:val * 2}) + return [ 11, 12, 13, 14 ] + endfunc + let g:test_variable = {} + call assert_equal(dict, foreach(copy(dict), function('s:foreach1'))) + call assert_equal({"foo": 2, "bar": 4, "baz": 6}, g:test_variable) + call remove(g:, 'test_variable') +endfunc + +func Test_map_filter_locked() + let list01 = [1, 2, 3, 4] + lockvar 1 list01 + call assert_fails('call filter(list01, "v:val > 1")', 'E741:') + call assert_equal([2, 4, 6, 8], map(list01, 'v:val * 2')) + call assert_equal([1, 2, 3, 4], map(list01, 'v:val / 2')) + call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2')) + let g:test_variable = [] + call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)')) + call remove(g:, 'test_variable') + call assert_fails('call filter(list01, "v:val > 1")', 'E741:') + unlockvar 1 list01 + lockvar! list01 + call assert_fails('call filter(list01, "v:val > 1")', 'E741:') + call assert_fails('call map(list01, "v:val * 2")', 'E741:') + call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2')) + let g:test_variable = [] + call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)')) + call assert_fails('call foreach(list01, "let list01[0] = -1")', 'E741:') + call assert_fails('call filter(list01, "v:val > 1")', 'E741:') + call remove(g:, 'test_variable') + unlockvar! list01 endfunc func Test_map_filter_fails() call assert_fails('call map([1], "42 +")', 'E15:') call assert_fails('call filter([1], "42 +")', 'E15:') + call assert_fails('call foreach([1], "let a = }")', 'E15:') call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:') call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:') call assert_fails("let l = filter([1, 2], {})", 'E731:') @@ -106,6 +171,8 @@ func Test_map_filter_fails() call assert_fails("let l = filter([1, 2], function('min'))", 'E118:') call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_partial())) call assert_fails("let l = filter([1, 2], {a, b, c -> 1})", 'E119:') + call assert_fails('call foreach([1], "xyzzy")', 'E492:') + call assert_fails('call foreach([1], "let a = foo")', 'E121:') endfunc func Test_map_and_modify() @@ -123,7 +190,7 @@ endfunc func Test_filter_and_modify() let l = [0] - " cannot change the list halfway a map() + " cannot change the list halfway thru filter() call assert_fails('call filter(l, "remove(l, 0)")', 'E741:') let d = #{a: 0, b: 0, c: 0} @@ -133,6 +200,18 @@ func Test_filter_and_modify() call assert_fails('call filter(b, "remove(b, 0)")', 'E741:') endfunc +func Test_foreach_and_modify() + let l = [0] + " cannot change the list halfway thru foreach() + call assert_fails('call foreach(l, "let a = remove(l, 0)")', 'E741:') + + let d = #{a: 0, b: 0, c: 0} + call assert_fails('call foreach(d, "let a = remove(d, v:key)")', 'E741:') + + let b = 0z1234 + call assert_fails('call foreach(b, "let a = remove(b, 0)")', 'E741:') +endfunc + func Test_mapnew_dict() let din = #{one: 1, two: 2} let dout = mapnew(din, {k, v -> string(v)}) @@ -160,6 +239,36 @@ func Test_mapnew_blob() call assert_equal(0z129956, bout) endfunc +func Test_foreach_blob() + let lines =<< trim END + LET g:test_variable = [] + call assert_equal(0z0001020304, foreach(0z0001020304, 'call add(g:test_variable, v:val)')) + call assert_equal([0, 1, 2, 3, 4], g:test_variable) + END + call v9.CheckLegacyAndVim9Success(lines) + + func! s:foreach1(index, val) abort + call add(g:test_variable, a:val) + return [ 11, 12, 13, 14 ] + endfunc + let g:test_variable = [] + call assert_equal(0z0001020304, foreach(0z0001020304, function('s:foreach1'))) + call assert_equal([0, 1, 2, 3, 4], g:test_variable) + + let lines =<< trim END + def Foreach1(_, val: any): list<number> + add(g:test_variable, val) + return [ 11, 12, 13, 14 ] + enddef + g:test_variable = [] + assert_equal(0z0001020304, foreach(0z0001020304, Foreach1)) + assert_equal([0, 1, 2, 3, 4], g:test_variable) + END + call v9.CheckDefSuccess(lines) + + call remove(g:, 'test_variable') +endfunc + " Test for using map(), filter() and mapnew() with a string func Test_filter_map_string() " filter() @@ -219,6 +328,37 @@ func Test_filter_map_string() END call v9.CheckLegacyAndVim9Success(lines) + " foreach() + let lines =<< trim END + VAR s = "abc" + LET g:test_variable = [] + call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)')) + call assert_equal(['a', 'b', 'c'], g:test_variable) + LET g:test_variable = [] + LET s = 'あiうえお' + call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)')) + call assert_equal(['あ', 'i', 'う', 'え', 'お'], g:test_variable) + END + call v9.CheckLegacyAndVim9Success(lines) + func! s:foreach1(index, val) abort + call add(g:test_variable, a:val) + return [ 11, 12, 13, 14 ] + endfunc + let g:test_variable = [] + call assert_equal('abcd', foreach('abcd', function('s:foreach1'))) + call assert_equal(['a', 'b', 'c', 'd'], g:test_variable) + let lines =<< trim END + def Foreach1(_, val: string): list<number> + add(g:test_variable, val) + return [ 11, 12, 13, 14 ] + enddef + g:test_variable = [] + assert_equal('abcd', foreach('abcd', Foreach1)) + assert_equal(['a', 'b', 'c', 'd'], g:test_variable) + END + call v9.CheckDefSuccess(lines) + call remove(g:, 'test_variable') + let lines =<< trim END #" map() and filter() call assert_equal('[あ][⁈][a][😊][⁉][💕][💕][b][💕]', map(filter('あx⁈ax😊x⁉💕💕b💕x', '"x" != v:val'), '"[" .. v:val .. "]"')) diff --git a/src/testdir/test_format.vim b/src/testdir/test_format.vim index af364c2..785348b 100644 --- a/src/testdir/test_format.vim +++ b/src/testdir/test_format.vim @@ -105,67 +105,6 @@ func Test_printf_pos_misc() END call v9.CheckLegacyAndVim9Success(lines) - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:") endfunc func Test_printf_pos_float() @@ -287,8 +226,6 @@ func Test_printf_pos_float() call assert_equal('nan', printf('%1$S', -0.0 / 0.0)) END call v9.CheckLegacyAndVim9Success(lines) - - call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') endfunc func Test_printf_pos_errors() @@ -299,6 +236,111 @@ func Test_printf_pos_errors() call v9.CheckLegacyAndVim9Failure(['echo printf("%1$s")'], 'E1503:') call v9.CheckLegacyAndVim9Failure(['echo printf("%1$d", 1.2)'], 'E805:') call v9.CheckLegacyAndVim9Failure(['echo printf("%1$f")'], 'E1503:') + + call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.987654321d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.987654321d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.987654321d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.987654321d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.*123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*987654321$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*987654321$d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*987654321$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*987654321$d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*1$d', 5, 9999)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*2$d', 5, 9999)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*3$.*1$d', 5, 9123, 9321)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*3$d', 5, 9123, 9321)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$.*3$d', 5, 9123, 9312)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$d', 5, 9999)"], "E1510:") endfunc func Test_printf_pos_64bit() diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 85ccc78..fecebc4 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3953,4 +3953,55 @@ func Test_glob_extended_mswin() call delete('Xtestglob', 'rf') endfunc +" Tests for the slice() function. +func Test_slice() + let lines =<< trim END + call assert_equal([1, 2, 3, 4, 5], slice(range(6), 1)) + call assert_equal([2, 3, 4, 5], slice(range(6), 2)) + call assert_equal([2, 3], slice(range(6), 2, 4)) + call assert_equal([0, 1, 2, 3], slice(range(6), 0, 4)) + call assert_equal([1, 2, 3], slice(range(6), 1, 4)) + call assert_equal([1, 2, 3, 4], slice(range(6), 1, -1)) + call assert_equal([1, 2], slice(range(6), 1, -3)) + call assert_equal([1], slice(range(6), 1, -4)) + call assert_equal([], slice(range(6), 1, -5)) + call assert_equal([], slice(range(6), 1, -6)) + + call assert_equal(0z1122334455, slice(0z001122334455, 1)) + call assert_equal(0z22334455, slice(0z001122334455, 2)) + call assert_equal(0z2233, slice(0z001122334455, 2, 4)) + call assert_equal(0z00112233, slice(0z001122334455, 0, 4)) + call assert_equal(0z112233, slice(0z001122334455, 1, 4)) + call assert_equal(0z11223344, slice(0z001122334455, 1, -1)) + call assert_equal(0z1122, slice(0z001122334455, 1, -3)) + call assert_equal(0z11, slice(0z001122334455, 1, -4)) + call assert_equal(0z, slice(0z001122334455, 1, -5)) + call assert_equal(0z, slice(0z001122334455, 1, -6)) + + call assert_equal('12345', slice('012345', 1)) + call assert_equal('2345', slice('012345', 2)) + call assert_equal('23', slice('012345', 2, 4)) + call assert_equal('0123', slice('012345', 0, 4)) + call assert_equal('123', slice('012345', 1, 4)) + call assert_equal('1234', slice('012345', 1, -1)) + call assert_equal('12', slice('012345', 1, -3)) + call assert_equal('1', slice('012345', 1, -4)) + call assert_equal('', slice('012345', 1, -5)) + call assert_equal('', slice('012345', 1, -6)) + + #" Composing chars are treated as a part of the preceding base char. + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1)) + call assert_equal('γ̳̂δ̳̃ε̳̄ζ̳̅', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2)) + call assert_equal('γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(2, 4)) + call assert_equal('ὰ̳β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(0, 4)) + call assert_equal('β̳́γ̳̂δ̳̃', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, 4)) + call assert_equal('β̳́γ̳̂δ̳̃ε̳̄', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -1)) + call assert_equal('β̳́γ̳̂', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -3)) + call assert_equal('β̳́', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -4)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -5)) + call assert_equal('', 'ὰ̳β̳́γ̳̂δ̳̃ε̳̄ζ̳̅'->slice(1, -6)) + END + call v9.CheckLegacyAndVim9Success(lines) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_goto.vim b/src/testdir/test_goto.vim index 85c156a..357a8d2 100644 --- a/src/testdir/test_goto.vim +++ b/src/testdir/test_goto.vim @@ -312,18 +312,23 @@ func Test_gd_string_only() call XTest_goto_decl('gd', lines, 5, 10) endfunc -" Check that setting 'cursorline' does not change curswant -func Test_cursorline_keep_col() +" Check that setting some options does not change curswant +func Test_set_options_keep_col() new call setline(1, ['long long long line', 'short line']) normal ggfi let pos = getcurpos() normal j - set cursorline + set invhlsearch spell spelllang=en,cjk spelloptions=camel textwidth=80 + set cursorline cursorcolumn cursorlineopt=line colorcolumn=+1 + set background=dark + set background=light normal k call assert_equal(pos, getcurpos()) bwipe! - set nocursorline + set hlsearch& spell& spelllang& spelloptions& textwidth& + set cursorline& cursorcolumn& cursorlineopt& colorcolumn& + set background& endfunc func Test_gd_local_block() diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index e7f7c6d..2ff8d34 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -111,6 +111,8 @@ func Test_getfontname_without_arg() endfunc func Test_getwinpos() + CheckX11 + call assert_match('Window position: X \d\+, Y \d\+', execute('winpos')) call assert_true(getwinposx() >= 0) call assert_true(getwinposy() >= 0) @@ -633,7 +635,7 @@ endfunc func Test_set_guiligatures() CheckX11BasedGui - if has('gui_gtk') || has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3') + if has('gui_gtk') || has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3') || has('win32') " Try correct value set guiligatures=<>=ab call assert_equal("<>=ab", &guiligatures) @@ -897,7 +899,7 @@ func Test_set_term() endfunc func Test_windowid_variable() - if g:x11_based_gui || has('win32') + if (g:x11_based_gui && empty($WAYLAND_DISPLAY)) || has('win32') call assert_true(v:windowid > 0) else call assert_equal(0, v:windowid) @@ -1708,7 +1710,11 @@ func Test_gui_lowlevel_keyevent() " Test for <Ctrl-A> to <Ctrl-Z> keys for kc in range(65, 90) call SendKeys([0x11, kc]) - let ch = getcharstr() + try + let ch = getcharstr() + catch /^Vim:Interrupt$/ + let ch = "\<c-c>" + endtry call assert_equal(nr2char(kc - 64), ch) endfor diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index af60503..d6c9f50 100644 --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -557,22 +557,23 @@ func Test_cursorline_after_yank() call StopVimInTerminal(buf) endfunc -" test for issue #4862 +" Test for issue #4862: pasting above 'cursorline' redraws properly. func Test_put_before_cursorline() new only! - call setline(1, 'A') + call setline(1, ['A', 'B', 'C']) + call cursor(2, 1) redraw - let std_attr = screenattr(1, 1) + let std_attr = screenattr(2, 1) set cursorline redraw - let cul_attr = screenattr(1, 1) + let cul_attr = screenattr(2, 1) normal yyP redraw - " Line 1 has cursor so it should be highlighted with CursorLine. - call assert_equal(cul_attr, screenattr(1, 1)) - " And CursorLine highlighting from the second line should be gone. - call assert_equal(std_attr, screenattr(2, 1)) + " Line 2 has cursor so it should be highlighted with CursorLine. + call assert_equal(cul_attr, screenattr(2, 1)) + " And CursorLine highlighting from line 3 should be gone. + call assert_equal(std_attr, screenattr(3, 1)) set nocursorline bwipe! endfunc @@ -888,6 +889,16 @@ func Test_highlight_ctermul() highlight Normal ctermul=NONE endfunc +" Test for 'ctermfont' in a highlight group +func Test_highlight_ctermfont() + CheckNotGui + call assert_notmatch('ctermfont=', HighlightArgs('Normal')) + highlight Normal ctermfont=3 + call assert_match('ctermfont=3', HighlightArgs('Normal')) + call assert_equal('3', synIDattr(synIDtrans(hlID('Normal')), 'font')) + highlight Normal ctermfont=NONE +endfunc + " Test for specifying 'start' and 'stop' in a highlight group func Test_highlight_start_stop() hi HlGrp1 start=<Esc>[27h;<Esc>[<Space>r; @@ -1314,6 +1325,7 @@ func Test_hlset() call hlset([{'name': 'hlg11', 'ctermfg': ''}]) call hlset([{'name': 'hlg11', 'ctermbg': ''}]) call hlset([{'name': 'hlg11', 'ctermul': ''}]) + call hlset([{'name': 'hlg11', 'ctermfont': ''}]) call hlset([{'name': 'hlg11', 'font': ''}]) call hlset([{'name': 'hlg11', 'gui': {}}]) call hlset([{'name': 'hlg11', 'guifg': ''}]) diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 61ddcd3..52306e8 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -412,6 +412,62 @@ func Test_completefunc_info() set completefunc& endfunc +func CompleteInfoUserDefinedFn(findstart, query) + " User defined function (i_CTRL-X_CTRL-U) + if a:findstart + return col('.') + endif + return [{'word': 'foo'}, {'word': 'bar'}, {'word': 'baz'}, {'word': 'qux'}] +endfunc + +func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect) + new + if a:noselect + set completeopt=menuone,popup,noinsert,noselect + else + set completeopt=menu,preview + endif + set completefunc=CompleteInfoUserDefinedFn + call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") + let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : '' + call assert_equal(completed. "{'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': [" . + \ "{'word': 'foo', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'bar', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'baz', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . + \ "{'word': 'qux', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}" . + \ "]}", getline(1)) + bwipe! + set completeopt& + set completefunc& +endfunc + +func Test_complete_info_user_defined_fn() + " forward + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 2, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>", -1, v:false) + " backward + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>", -1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 2, v:false) + " forward backward + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 1, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 0, v:true) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 2, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 1, v:false) + " backward forward + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 0, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 2, v:true) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 1, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 3, v:false) + call CompleteInfoTestUserDefinedFn("\<C-P>\<C-N>\<C-N>", 1, v:false) +endfunc + " Test that mouse scrolling/movement should not interrupt completion. func Test_mouse_scroll_move_during_completion() new @@ -2345,7 +2401,7 @@ func Test_complete_info_index() call assert_equal(-1, g:compl_info['selected']) call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx') - call assert_equal(0, g:compl_info['selected']) + call assert_equal(5, g:compl_info['selected']) call assert_equal(6 , len(g:compl_info['items'])) call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') @@ -2359,4 +2415,18 @@ func Test_complete_info_index() bwipe! endfunc -" vim: shiftwidth=2 sts=2 expandtab +func Test_complete_changed_complete_info() + CheckRunVimInTerminal + " this used to crash vim, see #13929 + let lines =<< trim END + set completeopt=menuone + autocmd CompleteChanged * call complete_info(['items']) + call feedkeys("iii\<cr>\<c-p>") + END + call writefile(lines, 'Xsegfault', 'D') + let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5}) + call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000) + call StopVimInTerminal(buf) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_listchars.vim b/src/testdir/test_listchars.vim index 57ddcda..46e96de 100644 --- a/src/testdir/test_listchars.vim +++ b/src/testdir/test_listchars.vim @@ -429,52 +429,52 @@ func Test_listchars_invalid() call assert_fails('set listchars=leadmultispace', 'E474:') " Too short - call assert_fails('set listchars=space:', 'E474:') - call assert_fails('set listchars=tab:x', 'E474:') - call assert_fails('set listchars=multispace:', 'E474:') - call assert_fails('set listchars=leadmultispace:', 'E474:') + call assert_fails('set listchars=space:', 'E1511:') + call assert_fails('set listchars=tab:x', 'E1511:') + call assert_fails('set listchars=multispace:', 'E1511:') + call assert_fails('set listchars=leadmultispace:', 'E1511:') " One occurrence too short - call assert_fails('set listchars=space:,space:x', 'E474:') - call assert_fails('set listchars=space:x,space:', 'E474:') - call assert_fails('set listchars=tab:x,tab:xx', 'E474:') - call assert_fails('set listchars=tab:xx,tab:x', 'E474:') - call assert_fails('set listchars=multispace:,multispace:x', 'E474:') - call assert_fails('set listchars=multispace:x,multispace:', 'E474:') - call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E474:') - call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E474:') + call assert_fails('set listchars=space:x,space:', 'E1511:') + call assert_fails('set listchars=space:,space:x', 'E1511:') + call assert_fails('set listchars=tab:xx,tab:x', 'E1511:') + call assert_fails('set listchars=tab:x,tab:xx', 'E1511:') + call assert_fails('set listchars=multispace:,multispace:x', 'E1511:') + call assert_fails('set listchars=multispace:x,multispace:', 'E1511:') + call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E1511:') + call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E1511:') " Too long - call assert_fails('set listchars=space:xx', 'E474:') - call assert_fails('set listchars=tab:xxxx', 'E474:') + call assert_fails('set listchars=space:xx', 'E1511:') + call assert_fails('set listchars=tab:xxxx', 'E1511:') " Has double-width character - call assert_fails('set listchars=space:·', 'E474:') - call assert_fails('set listchars=tab:·x', 'E474:') - call assert_fails('set listchars=tab:x·', 'E474:') - call assert_fails('set listchars=tab:xx·', 'E474:') - call assert_fails('set listchars=multispace:·', 'E474:') - call assert_fails('set listchars=multispace:xxx·', 'E474:') - call assert_fails('set listchars=leadmultispace:·', 'E474:') - call assert_fails('set listchars=leadmultispace:xxx·', 'E474:') + call assert_fails('set listchars=space:·', 'E1512:') + call assert_fails('set listchars=tab:·x', 'E1512:') + call assert_fails('set listchars=tab:x·', 'E1512:') + call assert_fails('set listchars=tab:xx·', 'E1512:') + call assert_fails('set listchars=multispace:·', 'E1512:') + call assert_fails('set listchars=multispace:xxx·', 'E1512:') + call assert_fails('set listchars=leadmultispace:·', 'E1512:') + call assert_fails('set listchars=leadmultispace:xxx·', 'E1512:') " Has control character - call assert_fails("set listchars=space:\x01", 'E474:') - call assert_fails("set listchars=tab:\x01x", 'E474:') - call assert_fails("set listchars=tab:x\x01", 'E474:') - call assert_fails("set listchars=tab:xx\x01", 'E474:') - call assert_fails("set listchars=multispace:\x01", 'E474:') - call assert_fails("set listchars=multispace:xxx\x01", 'E474:') - call assert_fails('set listchars=space:\\x01', 'E474:') - call assert_fails('set listchars=tab:\\x01x', 'E474:') - call assert_fails('set listchars=tab:x\\x01', 'E474:') - call assert_fails('set listchars=tab:xx\\x01', 'E474:') - call assert_fails('set listchars=multispace:\\x01', 'E474:') - call assert_fails('set listchars=multispace:xxx\\x01', 'E474:') - call assert_fails("set listchars=leadmultispace:\x01", 'E474:') - call assert_fails('set listchars=leadmultispace:\\x01', 'E474:') - call assert_fails("set listchars=leadmultispace:xxx\x01", 'E474:') - call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E474:') + call assert_fails("set listchars=space:\x01", 'E1512:') + call assert_fails("set listchars=tab:\x01x", 'E1512:') + call assert_fails("set listchars=tab:x\x01", 'E1512:') + call assert_fails("set listchars=tab:xx\x01", 'E1512:') + call assert_fails("set listchars=multispace:\x01", 'E1512:') + call assert_fails("set listchars=multispace:xxx\x01", 'E1512:') + call assert_fails('set listchars=space:\\x01', 'E1512:') + call assert_fails('set listchars=tab:\\x01x', 'E1512:') + call assert_fails('set listchars=tab:x\\x01', 'E1512:') + call assert_fails('set listchars=tab:xx\\x01', 'E1512:') + call assert_fails('set listchars=multispace:\\x01', 'E1512:') + call assert_fails('set listchars=multispace:xxx\\x01', 'E1512:') + call assert_fails("set listchars=leadmultispace:\x01", 'E1512:') + call assert_fails('set listchars=leadmultispace:\\x01', 'E1512:') + call assert_fails("set listchars=leadmultispace:xxx\x01", 'E1512:') + call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E1512:') enew! set ambiwidth& listchars& ff& diff --git a/src/testdir/test_listlbr.vim b/src/testdir/test_listlbr.vim index bcbd886..68bf948 100644 --- a/src/testdir/test_listlbr.vim +++ b/src/testdir/test_listlbr.vim @@ -374,13 +374,13 @@ endfunc func Test_linebreak_no_break_after_whitespace_only() call s:test_windows('setl ts=4 linebreak wrap') - call setline(1, "\tabcdefghijklmnopqrstuvwxyz" .. + call setline(1, "\t abcdefghijklmnopqrstuvwxyz" .. \ "abcdefghijklmnopqrstuvwxyz") let lines = s:screen_lines([1, 4], winwidth(0)) let expect = [ -\ " abcdefghijklmnop", -\ "qrstuvwxyzabcdefghij", -\ "klmnopqrstuvwxyz ", +\ " abcdefghijklmn", +\ "opqrstuvwxyzabcdefgh", +\ "ijklmnopqrstuvwxyz ", \ "~ ", \ ] call s:compare_lines(expect, lines) diff --git a/src/testdir/test_listlbr_utf8.vim b/src/testdir/test_listlbr_utf8.vim index 1bbbd2d..313ff30 100644 --- a/src/testdir/test_listlbr_utf8.vim +++ b/src/testdir/test_listlbr_utf8.vim @@ -9,6 +9,7 @@ CheckFeature conceal CheckFeature signs source view_util.vim +source screendump.vim func s:screen_lines(lnum, width) abort return ScreenLines(a:lnum, a:width) @@ -358,4 +359,24 @@ func Test_unprintable_char_on_wrap_column() call s:close_windows() endfunc +" Test that Visual selection is drawn correctly when 'linebreak' is set and +" selection ends before multibyte 'showbreak'. +func Test_visual_ends_before_showbreak() + CheckScreendump + + let lines =<< trim END + vim9script + &wrap = true + &linebreak = true + &showbreak = '↪ ' + ['xxxxx ' .. 'y'->repeat(&columns - 6) .. ' zzzz']->setline(1) + normal! wvel + END + call writefile(lines, 'XvisualEndsBeforeShowbreak', 'D') + let buf = RunVimInTerminal('-S XvisualEndsBeforeShowbreak', #{rows: 6}) + call VerifyScreenDump(buf, 'Test_visual_ends_before_showbreak', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_lua.vim b/src/testdir/test_lua.vim index 7e72728..a99affc 100644 --- a/src/testdir/test_lua.vim +++ b/src/testdir/test_lua.vim @@ -28,21 +28,37 @@ func TearDown() endfunc " Check that switching to another buffer does not trigger ml_get error. -func Test_lua_command_new_no_ml_get_error() +func Test_lua_luado_change_buffer() new + let wincount = winnr('$') call setline(1, ['one', 'two', 'three']) luado vim.command("new") call assert_equal(wincount + 1, winnr('$')) + %bwipe! endfunc -" Test vim.command() -func Test_lua_command() +" Check that :luado deleting lines does not trigger ml_get error. +func Test_lua_luado_delete_lines() new + + call setline(1, ['one', 'two', 'three']) + luado vim.command("%d_") + call assert_equal([''], getline(1, '$')) + call setline(1, ['one', 'two', 'three']) luado vim.command("1,2d_") call assert_equal(['three'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + luado vim.command("2,3d_"); return "REPLACED" + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3luado vim.command("1,2d_"); return "REPLACED" + call assert_equal(['three'], getline(1, '$')) + bwipe! endfunc diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index e81173d..71d9046 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -120,7 +120,7 @@ func Test_map_langmap() unmap x bwipe! - " 'langnoremap' follows 'langremap' and vise versa + " 'langnoremap' follows 'langremap' and vice versa set langremap set langnoremap call assert_equal(0, &langremap) @@ -247,6 +247,24 @@ func Test_map_meta_multibyte() iunmap <M-á> endfunc +func Test_map_super_quotes() + if has('gui_gtk') || has('gui_gtk3') || has("macos") + imap <D-"> foo + call feedkeys("Go-\<*D-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <D-"> + endif +endfunc + +func Test_map_super_multibyte() + if has('gui_gtk') || has('gui_gtk3') || has("macos") + imap <D-á> foo + call assert_match('i <D-á>\s*foo', execute('imap')) + iunmap <D-á> + endif +endfunc + func Test_abbr_after_line_join() new abbr foo bar diff --git a/src/testdir/test_matchparen.vim b/src/testdir/test_matchparen.vim index 6d09b6f..70aa38f 100644 --- a/src/testdir/test_matchparen.vim +++ b/src/testdir/test_matchparen.vim @@ -61,6 +61,31 @@ func Test_matchparen_clear_highlight() call StopVimInTerminal(buf) endfunc +" Test for matchparen highlight when switching buffer in win_execute() +func Test_matchparen_win_execute() + CheckScreendump + + let lines =<< trim END + source $VIMRUNTIME/plugin/matchparen.vim + let s:win = win_getid() + call setline(1, '{}') + split + + func SwitchBuf() + call win_execute(s:win, 'enew | buffer #') + endfunc + END + call writefile(lines, 'XMatchparenWinExecute', 'D') + let buf = RunVimInTerminal('-S XMatchparenWinExecute', #{rows: 5}) + call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {}) + + " Switching buffer away and back shouldn't change matchparen highlight. + call term_sendkeys(buf, ":call SwitchBuf()\<CR>:\<Esc>") + call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {}) + + call StopVimInTerminal(buf) +endfunc + " Test for scrolling that modifies buffer during visual block func Test_matchparen_pum_clear() CheckScreendump diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 48f1bab..46f3368 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -162,8 +162,18 @@ func Test_echospace() call assert_equal(&columns - 12, v:echospace) set showcmd ruler call assert_equal(&columns - 29, v:echospace) + set showcmdloc=statusline + call assert_equal(&columns - 19, v:echospace) + set showcmdloc=tabline + call assert_equal(&columns - 19, v:echospace) + call assert_fails('set showcmdloc=leap', 'E474:') + call assert_equal(&columns - 19, v:echospace) + set showcmdloc=last + call assert_equal(&columns - 29, v:echospace) + call assert_fails('set showcmdloc=jump', 'E474:') + call assert_equal(&columns - 29, v:echospace) - set ruler& showcmd& + set ruler& showcmd& showcmdloc& endfunc func Test_warning_scroll() diff --git a/src/testdir/test_mswin_event.vim b/src/testdir/test_mswin_event.vim index 4de0169..3b7b3c7 100644 --- a/src/testdir/test_mswin_event.vim +++ b/src/testdir/test_mswin_event.vim @@ -36,6 +36,17 @@ func SendKey(key) call SendKeyWithModifiers(a:key, 0) endfunc +" getcharstr(0) but catch Vim:Interrupt +func Getcharstr() + try + let ch = getcharstr(0) + catch /^Vim:Interrupt$/ + let ch = "\<c-c>" + endtry + return ch +endfunc + + " Send a string of individual key-press events, without modifiers. func SendKeyStr(keystring) for k in a:keystring @@ -347,7 +358,7 @@ func s:LoopTestKeyArray(arr) for [kcodes, kstr] in a:arr " Send as a sequence of key presses. call SendKeyGroup(kcodes) - let ch = getcharstr(0) + let ch = Getcharstr() " need to deal a bit differently with the non-printable ascii chars < 0x20 if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0 call assert_equal(nr2char(kstr), $"{ch}") @@ -374,7 +385,7 @@ func s:LoopTestKeyArray(arr) endif endfor call SendKeyWithModifiers(key, modifiers) - let ch = getcharstr(0) + let ch = Getcharstr() " need to deal a bit differently with the non-printable ascii chars < 0x20 if kstr < 0x20 && index([s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL], kcodes[0]) >= 0 call assert_equal(nr2char(kstr), $"{ch}") @@ -408,10 +419,10 @@ func Test_mswin_event_character_keys() " (0x30 - 0x39) : VK_0 - VK_9 are the same as ASCII '0' - '9' for kc in range(48, 57) call SendKey(kc) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc), ch) call SendKeyWithModifiers(kc, 0) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc), ch) endfor @@ -437,10 +448,10 @@ func Test_mswin_event_character_keys() " numbered 32 higher than their uppercase versions. for kc in range(65, 90) call SendKey(kc) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc + 32), ch) call SendKeyWithModifiers(kc, 0) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc + 32), ch) endfor @@ -449,23 +460,28 @@ func Test_mswin_event_character_keys() for modkey in [s:VK.SHIFT, s:VK.LSHIFT, s:VK.RSHIFT] for kc in range(65, 90) call SendKeyGroup([modkey, kc]) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc), ch) call SendKeyWithModifiers(kc, s:MOD_MASK_SHIFT) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc), ch) endfor endfor - " Test for <Ctrl-A> to <Ctrl-Z> keys - " Expect the unicode characters 0x01 to 0x1A +" Test for <Ctrl-A> to <Ctrl-Z> keys +" Expect the unicode characters 0x01 to 0x1A +" Note: Skip C because it triggers an Interrupt (CTRL-C) +" which causes a test failure for modkey in [s:VK.CONTROL, s:VK.LCONTROL, s:VK.RCONTROL] for kc in range(65, 90) + if kc == 67 + continue + endif call SendKeyGroup([modkey, kc]) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc - 64), ch) call SendKeyWithModifiers(kc, s:MOD_MASK_CTRL) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(kc - 64), ch) endfor endfor @@ -518,7 +534,7 @@ func Test_mswin_event_function_keys() while getchar(0) endwhile call SendKeyWithModifiers(111+n, vim_mod_mask) - let ch = getcharstr(0) + let ch = Getcharstr() let mod_mask = getcharmod() call assert_equal(keycode, $"{ch}", $"key = {kstr}") " workaround for the virtual termcap maps changing the character @@ -590,21 +606,21 @@ func Test_mswin_event_movement_keys() while getchar(0) endwhile execute 'call feedkeys("\<' .. kstr .. '>")' - let chstr_fk = getcharstr(0) + let chstr_fk = Getcharstr() call assert_equal(chstr_eval, chstr_fk, $"feedkeys = <{kstr}>") " flush out the typeahead buffer while getchar(0) endwhile call SendKey(kcode) - let chstr_alone = getcharstr(0) + let chstr_alone = Getcharstr() let chstr_alone_end = chstr_alone[len(chstr_alone)-2:len(chstr_alone)-1] " flush out the typeahead buffer while getchar(0) endwhile call SendKeyGroup(mod_keycodes + [kcode]) - let chstr_mswin = getcharstr(0) + let chstr_mswin = Getcharstr() let chstr_mswin_end = chstr_mswin[len(chstr_mswin)-2:len(chstr_mswin)-1] let mod_mask = getcharmod() @@ -653,7 +669,7 @@ func Test_QWERTY_Ctrl_minus() new call SendKeyGroup([s:VK.CONTROL, s:VK.OEM_MINUS]) - let ch = getcharstr(0) + let ch = Getcharstr() call assert_equal(nr2char(0x1f),ch) call SendKey(s:VK.KEY_I) @@ -727,14 +743,14 @@ func Test_mswin_event_mouse() if has('gui_running') let args = { } let args.row = 9 - let args.col = 7 + let args.col = 5 let args.move = 1 let args.cell = 1 call test_mswin_event("mouse", args) call feedkeys("\<Esc>", 'Lx!') let pos = getmousepos() call assert_equal(9, pos.screenrow) - call assert_equal(7, pos.screencol) + call assert_equal(5, pos.screencol) let args.cell = 0 call test_mswin_event("mouse", args) diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index 38ad810..b180637 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -2235,7 +2235,7 @@ func Test_normal29_brace() [DATA] call assert_equal(expected, getline(1, '$')) - " Test with { in cpooptions + " Test with { in cpoptions %d call append(0, text) set cpo+={ @@ -2347,23 +2347,31 @@ func Test_normal30_changecase() norm! 1ggVu call assert_equal('this is a simple test: äüöß', getline('.')) norm! VU - call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.')) norm! guu - call assert_equal('this is a simple test: äüöss', getline('.')) + call assert_equal('this is a simple test: äüöß', getline('.')) norm! gUgU - call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.')) norm! gugu - call assert_equal('this is a simple test: äüöss', getline('.')) + call assert_equal('this is a simple test: äüöß', getline('.')) norm! gUU - call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.')) + call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.')) norm! 010~ - call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.')) + call assert_equal('this is a SIMPLE TEST: ÄÜÖẞ', getline('.')) norm! V~ - call assert_equal('THIS IS A simple test: äüöss', getline('.')) + call assert_equal('THIS IS A simple test: äüöß', getline('.')) call assert_beeps('norm! c~') %d call assert_beeps('norm! ~') + " Test with multiple lines + call setline(1, ['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD']) + norm! ggguG + call assert_equal(['aa', 'bbbb', 'cccccc', 'dddddddd'], getline(1, '$')) + norm! GgUgg + call assert_equal(['AA', 'BBBB', 'CCCCCC', 'DDDDDDDD'], getline(1, '$')) + %d + " Test for changing case across lines using 'whichwrap' call setline(1, ['aaaaaa', 'aaaaaa']) normal! gg10~ @@ -3158,7 +3166,7 @@ func Test_normal50_commandline() CheckFeature cmdline_hist func! DoTimerWork(id) - call assert_equal('[Command Line]', bufname('')) + call assert_equal(1, getbufinfo('')[0].command) " should fail, with E11, but does fail with E23? "call feedkeys("\<c-^>", 'tm') diff --git a/src/testdir/test_number.vim b/src/testdir/test_number.vim index 81f8f73..b57c1ed 100644 --- a/src/testdir/test_number.vim +++ b/src/testdir/test_number.vim @@ -146,8 +146,7 @@ func Test_number_with_linewrap1() call s:close_windows() endfunc -" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI -func XTest_number_with_linewrap2() +func Test_number_with_linewrap2() call s:test_windows(3, 20) normal! 61ia setl number wrap @@ -164,8 +163,7 @@ func XTest_number_with_linewrap2() call s:close_windows() endfunc -" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI -func XTest_number_with_linewrap3() +func Test_number_with_linewrap3() call s:test_windows(4, 20) normal! 81ia setl number wrap @@ -174,7 +172,7 @@ func XTest_number_with_linewrap3() call s:validate_cursor() let lines = s:screen_lines(1, 4) let expect = [ -\ "aaaaaaaa", +\ "<<<aaaaa", \ "aaaaaaaa", \ "aaaaaaaa", \ "a ", @@ -278,9 +276,7 @@ func Test_relativenumber_colors() [CODE] call writefile(lines, 'XTest_relnr', 'D') - " Check that the balloon shows up after a mouse move let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50}) - call TermWait(buf, 50) " Default colors call VerifyScreenDump(buf, 'Test_relnr_colors_1', {}) @@ -297,6 +293,36 @@ func Test_relativenumber_colors() call StopVimInTerminal(buf) endfunc +func Test_relativenumber_colors_wrapped() + CheckScreendump + + let lines =<< trim [CODE] + set display=lastline scrolloff=0 + call setline(1, range(200)->map('v:val->string()->repeat(40)')) + 111 + set number relativenumber + hi LineNr ctermbg=red ctermfg=black + hi LineNrAbove ctermbg=blue ctermfg=black + hi LineNrBelow ctermbg=green ctermfg=black + [CODE] + call writefile(lines, 'XTest_relnr_wrap', 'D') + + let buf = RunVimInTerminal('-S XTest_relnr_wrap', {'rows': 20, 'cols': 50}) + + call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_1', {}) + call term_sendkeys(buf, "k") + call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_2', {}) + call term_sendkeys(buf, "2j") + call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_3', {}) + call term_sendkeys(buf, "2j") + call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_4', {}) + call term_sendkeys(buf, "k") + call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_5', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + func Test_relativenumber_callback() CheckScreendump CheckFeature timers @@ -321,6 +347,31 @@ func Test_relativenumber_callback() call StopVimInTerminal(buf) endfunc +" Test that line numbers below inserted/deleted lines are updated. +func Test_number_insert_delete_lines() + CheckScreendump + + let lines =<< trim END + call setline(1, range(1, 7)) + set number + call cursor(2, 1) + END + call writefile(lines, 'Xnumber_insert_delete_lines', 'D') + + let buf = RunVimInTerminal('-S Xnumber_insert_delete_lines', #{rows: 8}) + call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {}) + call term_sendkeys(buf, "dd") + call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_2', {}) + call term_sendkeys(buf, "P") + call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {}) + call term_sendkeys(buf, "2dd") + call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_3', {}) + call term_sendkeys(buf, "P") + call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {}) + + call StopVimInTerminal(buf) +endfunc + " Test for displaying line numbers with 'rightleft' func Test_number_rightleft() CheckFeature rightleft diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 37dc201..fbfbaae 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -1293,6 +1293,44 @@ func Test_shortmess_F2() call assert_fails('call test_getvalue("abc")', 'E475:') endfunc +func Test_shortmess_F3() + call writefile(['foo'], 'X_dummy', 'D') + + set hidden + set autoread + e X_dummy + e Xotherfile + call assert_equal(['foo'], getbufline('X_dummy', 1, '$')) + set shortmess+=F + echo '' + + if has('nanotime') + sleep 10m + else + sleep 2 + endif + call writefile(['bar'], 'X_dummy') + bprev + call assert_equal('', Screenline(&lines)) + call assert_equal(['bar'], getbufline('X_dummy', 1, '$')) + + if has('nanotime') + sleep 10m + else + sleep 2 + endif + call writefile(['baz'], 'X_dummy') + checktime + call assert_equal('', Screenline(&lines)) + call assert_equal(['baz'], getbufline('X_dummy', 1, '$')) + + set shortmess& + set autoread& + set hidden& + bwipe X_dummy + bwipe Xotherfile +endfunc + func Test_local_scrolloff() set so=5 set siso=7 @@ -2234,4 +2272,34 @@ func Test_set_wrap() set wrap& smoothscroll& scrolloff& endfunc +func Test_delcombine() + new + set backspace=indent,eol,start + + set delcombine + call setline(1, 'β̳̈:β̳̈') + normal! 0x + call assert_equal('β̈:β̳̈', getline(1)) + exe "normal! A\<BS>" + call assert_equal('β̈:β̈', getline(1)) + normal! 0x + call assert_equal('β:β̈', getline(1)) + exe "normal! A\<BS>" + call assert_equal('β:β', getline(1)) + normal! 0x + call assert_equal(':β', getline(1)) + exe "normal! A\<BS>" + call assert_equal(':', getline(1)) + + set nodelcombine + call setline(1, 'β̳̈:β̳̈') + normal! 0x + call assert_equal(':β̳̈', getline(1)) + exe "normal! A\<BS>" + call assert_equal(':', getline(1)) + + set backspace& delcombine& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_perl.vim b/src/testdir/test_perl.vim index 681aaae..721179c 100644 --- a/src/testdir/test_perl.vim +++ b/src/testdir/test_perl.vim @@ -211,10 +211,25 @@ func Test_perldo() call assert_false(search('\Cperl')) bw! - " Check deleting lines does not trigger ml_get error. new + + " Check deleting lines does not trigger ml_get error. call setline(1, ['one', 'two', 'three']) perldo VIM::DoCommand("%d_") + call assert_equal([''], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + perldo VIM::DoCommand("1,2d_") + call assert_equal(['three'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + perldo VIM::DoCommand("2,3d_"); $_ = "REPLACED" + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3perldo VIM::DoCommand("1,2d_"); $_ = "REPLACED" + call assert_equal(['three'], getline(1, '$')) + bwipe! " Check a Perl expression which gives an error. diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index a0a1f74..f5cb8b2 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -1139,6 +1139,10 @@ func Test_CompleteChanged() let g:event = copy(v:event) let g:item = get(v:event, 'completed_item', {}) let g:word = get(g:item, 'word', v:null) + let l:line = getline('.') + if g:word == v:null && l:line == "bc" + let g:word = l:line + endif endfunction augroup AAAAA_Group au! @@ -1158,10 +1162,24 @@ func Test_CompleteChanged() call assert_equal(v:null, g:word) call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'tx') call assert_equal('foobar', g:word) + call feedkeys("S\<C-N>bc", 'tx') + call assert_equal("bc", g:word) + + func Omni_test(findstart, base) + if a:findstart + return col(".") + endif + return [#{word: "one"}, #{word: "two"}, #{word: "five"}] + endfunc + set omnifunc=Omni_test + set completeopt=menu,menuone + call feedkeys("i\<C-X>\<C-O>\<BS>\<BS>\<BS>f", 'tx') + call assert_equal('five', g:word) autocmd! AAAAA_Group set complete& completeopt& delfunc! OnPumChange + delfunc! Omni_test bw! endfunc diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index c20ff48..a397f70 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -4215,4 +4215,22 @@ func Test_popup_close_callback_recursive() set maxfuncdepth& endfunc +func Test_popupwin_setbufvar_changing_window_view() + " Test for Github Issue https://github.com/vim/vim/issues/13863 + " using setbufvar(buf, '&option') should not scroll + " the current window + 20new + call append(0, range(1, 25)) + setlocal scrollbind + norm! G + let topline = winsaveview()['topline'] + call setbufvar(winbufnr(popup_atcursor(['foobar'], {})), '&syntax', 'python') + " close popup + call popup_clear() + call assert_equal(topline, winsaveview()['topline']) + + " clean up + bw! +endfunc + " vim: shiftwidth=2 sts=2 diff --git a/src/testdir/test_prompt_buffer.vim b/src/testdir/test_prompt_buffer.vim index d173731..c5ef010 100644 --- a/src/testdir/test_prompt_buffer.vim +++ b/src/testdir/test_prompt_buffer.vim @@ -297,4 +297,49 @@ func Test_prompt_appending_while_hidden() call StopVimInTerminal(buf) endfunc +" Modifying a hidden buffer while leaving a prompt buffer should not prevent +" stopping of Insert mode, and returning to the prompt buffer later should +" restore Insert mode. +func Test_prompt_leave_modify_hidden() + call CanTestPromptBuffer() + + let script =<< trim END + file hidden + set bufhidden=hide + enew + new prompt + set buftype=prompt + + inoremap <buffer> w <Cmd>wincmd w<CR> + inoremap <buffer> q <Cmd>bwipe!<CR> + autocmd BufLeave prompt call appendbufline('hidden', '$', 'Leave') + autocmd BufEnter prompt call appendbufline('hidden', '$', 'Enter') + autocmd BufWinLeave prompt call appendbufline('hidden', '$', 'Close') + END + call writefile(script, 'XpromptLeaveModifyHidden', 'D') + + let buf = RunVimInTerminal('-S XpromptLeaveModifyHidden', {'rows': 10}) + call TermWait(buf) + + call term_sendkeys(buf, "a") + call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "w") + call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "\<C-W>w") + call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, "q") + call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))}) + + call term_sendkeys(buf, ":bwipe!\<CR>") + call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 2))}) + call WaitForAssert({-> assert_equal('Enter', term_getline(buf, 3))}) + call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 4))}) + call WaitForAssert({-> assert_equal('Close', term_getline(buf, 5))}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim index 72479ac..5b5c354 100644 --- a/src/testdir/test_put.vim +++ b/src/testdir/test_put.vim @@ -12,6 +12,16 @@ func Test_put_block() bwipe! endfunc +func Test_put_block_unicode() + new + call setreg('a', "À\nÀÀ\naaaaaaaaaaaa", "\<C-V>") + call setline(1, [' 1', ' 2', ' 3']) + exe "norm! \<C-V>jj\"ap" + let expected = ['À 1', 'ÀÀ 2', 'aaaaaaaaaaaa3'] + call assert_equal(expected, getline(1, 3)) + bw! +endfunc + func Test_put_char_block() new call setline(1, ['Line 1', 'Line 2']) @@ -280,5 +290,33 @@ func Test_put_in_last_displayed_line() call StopVimInTerminal(buf) endfunc +func Test_put_visual_replace_whole_fold() + new + let lines = repeat(['{{{1', 'foo', 'bar', ''], 2) + call setline(1, lines) + setlocal foldmethod=marker + call setreg('"', 'baz') + call setreg('1', '') + normal! Vp + call assert_equal("{{{1\nfoo\nbar\n\n", getreg('1')) + call assert_equal(['baz', '{{{1', 'foo', 'bar', ''], getline(1, '$')) + + bwipe! +endfunc + +func Test_put_visual_replace_fold_marker() + new + let lines = repeat(['{{{1', 'foo', 'bar', ''], 4) + call setline(1, lines) + setlocal foldmethod=marker + normal! Gkzo + call setreg('"', '{{{1') + call setreg('1', '') + normal! Vp + call assert_equal("{{{1\n", getreg('1')) + call assert_equal(lines, getline(1, '$')) + + bwipe! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_python2.vim b/src/testdir/test_python2.vim index 066b4bd..ac43e60 100644 --- a/src/testdir/test_python2.vim +++ b/src/testdir/test_python2.vim @@ -56,10 +56,25 @@ func Test_AAA_python_setup() endfunc func Test_pydo() - " Check deleting lines does not trigger an ml_get error. new + + " Check deleting lines does not trigger an ml_get error. call setline(1, ['one', 'two', 'three']) pydo vim.command("%d_") + call assert_equal([''], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + pydo vim.command("1,2d_") + call assert_equal(['three'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + pydo vim.command("2,3d_"); return "REPLACED" + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3pydo vim.command("1,2d_"); return "REPLACED" + call assert_equal(['three'], getline(1, '$')) + bwipe! " Check switching to another buffer does not trigger an ml_get error. diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim index e975cb6..7f04f11 100644 --- a/src/testdir/test_python3.vim +++ b/src/testdir/test_python3.vim @@ -88,10 +88,25 @@ func Test_AAA_python3_setup() endfunc func Test_py3do() - " Check deleting lines does not trigger an ml_get error. new + + " Check deleting lines does not trigger an ml_get error. call setline(1, ['one', 'two', 'three']) py3do vim.command("%d_") + call assert_equal([''], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + py3do vim.command("1,2d_") + call assert_equal(['three'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + py3do vim.command("2,3d_"); return "REPLACED" + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3py3do vim.command("1,2d_"); return "REPLACED" + call assert_equal(['three'], getline(1, '$')) + bwipe! " Check switching to another buffer does not trigger an ml_get error. diff --git a/src/testdir/test_quotestar.vim b/src/testdir/test_quotestar.vim index 1d26942..322ce62 100644 --- a/src/testdir/test_quotestar.vim +++ b/src/testdir/test_quotestar.vim @@ -139,8 +139,8 @@ func Test_quotestar() if has('macunix') let skipped = Do_test_quotestar_for_macunix() elseif has('x11') - if empty($DISPLAY) - let skipped = "Test can only run when $DISPLAY is set." + if empty($DISPLAY) || !empty($WAYLAND_DISPLAY) + let skipped = "Test can only run when $DISPLAY is set and $WAYLAND_DISPLAY is not set." else let skipped = Do_test_quotestar_for_x11() endif diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index 50f3910..cb4cee7 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -868,6 +868,8 @@ func Test_replay_charsearch_omap() call timer_start(10, {-> feedkeys(",bar\<Esc>q", 't')}) call feedkeys('qrct[', 'xt!') call assert_equal(',bar[blah]', getline(1)) + call assert_equal("ct[\<Ignore>,bar\<Esc>", @r) + call assert_equal('ct[<Ignore>,bar<Esc>', keytrans(@r)) undo call assert_equal('foo[blah]', getline(1)) call feedkeys('@r', 'xt!') @@ -949,7 +951,7 @@ endfunc func Test_insert_small_delete_replace_mode() new call setline(1, ['foo', 'bar', 'foobar', 'bar']) - let @-='foo' + let @- = 'foo' call cursor(2, 1) exe ":norm! R\<C-R>-\<C-R>-" call assert_equal('foofoo', getline(2)) @@ -960,9 +962,21 @@ func Test_insert_small_delete_replace_mode() exe ":norm! R\<C-R>-ZZZZ" call assert_equal(['foo', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4)) call cursor(1, 1) - let @-='' + let @- = '' exe ":norm! R\<C-R>-ZZZ" call assert_equal(['ZZZ', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4)) + let @- = 'βbβ' + call cursor(4, 1) + exe ":norm! R\<C-R>-" + call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4)) + let @- = 'bβb' + call cursor(4, 1) + exe ":norm! R\<C-R>-" + call assert_equal(['ZZZ', 'foofoo', '', 'bβbobarZZZZ'], getline(1, 4)) + let @- = 'βbβ' + call cursor(4, 1) + exe ":norm! R\<C-R>-" + call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4)) bwipe! endfunc diff --git a/src/testdir/test_remote.vim b/src/testdir/test_remote.vim new file mode 100644 index 0000000..ae931fd --- /dev/null +++ b/src/testdir/test_remote.vim @@ -0,0 +1,79 @@ +" Test for the --remote functionality + +source check.vim +CheckFeature clientserver +CheckFeature terminal + +source shared.vim +source screendump.vim +source mouse.vim +source term_util.vim + +let s:remote_works = 0 +let s:skip = 'Skipped: --remote feature is not possible' + +" nees to be run as first test to verify, that vim --servername works +func Verify_remote_feature_works() + CheckRunVimInTerminal + enew + let buf = RunVimInTerminal('--servername XVIMTEST', {'rows': 8}) + call TermWait(buf) + let cmd = GetVimCommandCleanTerm() .. '--serverlist' + call term_sendkeys(buf, ":r! " .. cmd .. "\<CR>") + call TermWait(buf) + call term_sendkeys(buf, ":w! XVimRemoteTest.txt\<CR>") + call TermWait(buf) + call term_sendkeys(buf, ":q\<CR>") + call StopVimInTerminal(buf) + bw! + let result = readfile('XVimRemoteTest.txt') + call delete('XVimRemoteTest.txt') + if empty(result) + throw s:skip + endif + let s:remote = 1 +endfunc + +call Verify_remote_feature_works() + +if !s:remote + finish +endif + +func Test_remote_servername() + CheckRunVimInTerminal + + " That is the file we want the server to open, + " despite the wildignore setting + call writefile(range(1, 20), 'XTEST.txt', 'D') + " just a dummy file, so that the ':wq' further down is successful + call writefile(range(1, 20), 'Xdummy.log', 'D') + + " Run Vim in a terminal and open a terminal window to run Vim in. + let lines =<< trim END + set wildignore=*.txt + END + call writefile(lines, 'XRemoteEditing.vim', 'D') + let buf = RunVimInTerminal('--servername XVIMTEST -S XRemoteEditing.vim Xdummy.log', {'rows': 8}) + call TermWait(buf) + botright new + " wildignore setting should be ignored and the XVIMTEST server should now + " open XTEST.txt, if wildignore setting is not ignored, the server + " will continue with the Xdummy.log file + let buf2 = RunVimInTerminal('--servername XVIMTEST --remote-silent XTEST.txt', {'rows': 5, 'wait_for_ruler': 0}) + " job should be no-longer running, so we can just close it + exe buf2 .. 'bw!' + call term_sendkeys(buf, ":sil :3,$d\<CR>") + call TermWait(buf) + call term_sendkeys(buf, ":wq!\<CR>") + call TermWait(buf) + if term_getstatus(buf) == 'running' + call StopVimInTerminal(buf) + endif + let buf_contents = readfile('XTEST.txt') + call assert_equal(2, len(buf_contents)) + bw! + close +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_ruby.vim b/src/testdir/test_ruby.vim index 2e0835c..f155168 100644 --- a/src/testdir/test_ruby.vim +++ b/src/testdir/test_ruby.vim @@ -11,10 +11,25 @@ func Test_ruby_change_buffer() endfunc func Test_rubydo() - " Check deleting lines does not trigger ml_get error. new + + " Check deleting lines does not trigger ml_get error. call setline(1, ['one', 'two', 'three']) rubydo Vim.command("%d_") + call assert_equal(['one'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + rubydo Vim.command("1,2d_") + call assert_equal(['one'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + rubydo Vim.command("2,3d_"); $_ = "REPLACED" + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3rubydo Vim.command("1,2d_"); $_ = "REPLACED" + call assert_equal(['three'], getline(1, '$')) + bwipe! " Check switching to another buffer does not trigger ml_get error. diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim index f41f0e2..3467760 100644 --- a/src/testdir/test_scroll_opt.vim +++ b/src/testdir/test_scroll_opt.vim @@ -960,4 +960,42 @@ func Test_smoothscroll_insert_bottom() call StopVimInTerminal(buf) endfunc +func Test_smoothscroll_in_zero_width_window() + set cpo+=n number smoothscroll + set winwidth=99999 winminwidth=0 + + vsplit + call assert_equal(0, winwidth(winnr('#'))) + call win_execute(win_getid(winnr('#')), "norm! \<C-Y>") + + only! + set winwidth& winminwidth& + set cpo-=n nonumber nosmoothscroll +endfunc + +func Test_smoothscroll_textoff_small_winwidth() + set smoothscroll number + call setline(1, 'llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch') + vsplit + + let textoff = getwininfo(win_getid())[0].textoff + execute 'vertical resize' textoff + 1 + redraw + call assert_equal(0, winsaveview().skipcol) + execute "normal! 0\<C-E>" + redraw + call assert_equal(1, winsaveview().skipcol) + execute 'vertical resize' textoff - 1 + " This caused a signed integer overflow. + redraw + call assert_equal(1, winsaveview().skipcol) + execute 'vertical resize' textoff + " This caused an infinite loop. + redraw + call assert_equal(1, winsaveview().skipcol) + + %bw! + set smoothscroll& number& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index 1a81318..7c70391 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -518,18 +518,24 @@ func Test_geometry() call writefile([&columns, &lines, getwinposx(), getwinposy(), string(getwinpos())], "Xtest_geometry") qall [CODE] + " Hide menu because gtk insists to make the window wide enough to show it completely " Some window managers have a bar at the top that pushes windows down, " need to use at least 130, let's do 150 - if RunVim([], after, '-f -g -geometry 31x13+41+150') + if RunVim(['set guioptions-=m'], after, '-f -g -geometry 31x13+41+150') let lines = readfile('Xtest_geometry') " Depending on the GUI library and the windowing system the final size " might be a bit different, allow for some tolerance. Tuned based on " actual failures. call assert_inrange(31, 35, str2nr(lines[0])) - call assert_equal('13', lines[1]) - call assert_equal('41', lines[2]) - call assert_equal('150', lines[3]) - call assert_equal('[41, 150]', lines[4]) + " for some reason, the window may contain fewer lines than requested + " for GTK, so allow some tolerance + call assert_inrange(8, 13, str2nr(lines[1])) + " on Wayland there is no way to set or retrieve window positions + if empty($WAYLAND_DISPLAY) + call assert_equal('41', lines[2]) + call assert_equal('150', lines[3]) + call assert_equal('[41, 150]', lines[4]) + endif endif endif diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 906fefc..a531f19 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -156,14 +156,85 @@ func Test_tabpage_drop() tab split f3 normal! gt call assert_equal(1, tabpagenr()) + tab drop f4 + call assert_equal(1, tabpagenr('#')) tab drop f3 - call assert_equal(3, tabpagenr()) - call assert_equal(1, tabpagenr('#')) + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + bwipe! bwipe! bwipe! bwipe! call assert_equal(1, tabpagenr('$')) + + call assert_equal(1, winnr('$')) + call assert_equal('', bufname('')) + call writefile(['L1', 'L2'], 'Xdropfile', 'D') + + " Test for ':tab drop single-file': reuse current buffer + let expected_nr = bufnr() + tab drop Xdropfile + call assert_equal(1, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + bwipe! + + " Test for ':tab drop single-file': not reuse modified buffer + set modified + let expected_nr = bufnr() + 1 + tab drop Xdropfile + call assert_equal(2, tabpagenr()) + call assert_equal(2, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + bwipe! + + " Test for ':tab drop single-file': multiple tabs already exist + tab split f2 + tab split f3 + let expected_nr = bufnr() + 1 + tab drop Xdropfile + call assert_equal(4, tabpagenr()) + call assert_equal(4, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + %bwipe! + + " Test for ':tab drop multi-files': reuse current buffer + let expected_nr = bufnr() + tab drop Xdropfile f1 f2 f3 + call assert_equal(1, tabpagenr()) + call assert_equal(4, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + %bwipe! + + " Test for ':tab drop multi-files': not reuse modified buffer + set modified + let expected_nr = bufnr() + 1 + tab drop Xdropfile f1 f2 f3 + call assert_equal(2, tabpagenr()) + call assert_equal(5, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + %bwipe! + + " Test for ':tab drop multi-files': multiple tabs already exist + tab split f2 + tab split f3 + let expected_nr = bufnr() + 1 + tab drop a b c + call assert_equal(4, tabpagenr()) + call assert_equal(6, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + let expected_nr = bufnr() + 3 + tab drop Xdropfile f1 f2 f3 + call assert_equal(5, tabpagenr()) + call assert_equal(8, tabpagenr('$')) + call assert_equal(expected_nr, bufnr()) + call assert_equal('L2', getline(2)) + %bwipe! endfunc " Test autocommands @@ -260,14 +331,14 @@ function Test_tabpage_with_autocmd_tab_drop() let s:li = [] tab drop test1 - call assert_equal(['BufLeave', 'BufEnter'], s:li) + call assert_equal(['BufEnter'], s:li) let s:li = [] tab drop test2 test3 call assert_equal([ \ 'TabLeave', 'TabEnter', 'TabLeave', 'TabEnter', \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter', - \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter'], s:li) + \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter', 'BufEnter'], s:li) autocmd! TestTabpageGroup augroup! TestTabpageGroup @@ -922,4 +993,21 @@ func Test_tabpage_drop_tabmove() bwipe! endfunc +" Test that settabvar() shouldn't change the last accessed tabpage. +func Test_lastused_tabpage_settabvar() + tabonly! + tabnew + tabnew + tabnew + call assert_equal(3, tabpagenr('#')) + + call settabvar(2, 'myvar', 'tabval') + call assert_equal('tabval', gettabvar(2, 'myvar')) + call assert_equal(3, tabpagenr('#')) + + bwipe! + bwipe! + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 8b85bd6..2abf1f6 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -900,18 +900,33 @@ func Test_tag_stack() endfor call writefile(l, 'Xfoo', 'D') - " Jump to a tag when the tag stack is full. Oldest entry should be removed. enew + " Jump to a tag when the tag stack is full. Oldest entry should be removed. for i in range(10, 30) exe "tag var" .. i endfor - let l = gettagstack() - call assert_equal(20, l.length) - call assert_equal('var11', l.items[0].tagname) + let t = gettagstack() + call assert_equal(20, t.length) + call assert_equal('var11', t.items[0].tagname) + let full = deepcopy(t.items) + tag var31 + let t = gettagstack() + call assert_equal('var12', t.items[0].tagname) + call assert_equal('var31', t.items[19].tagname) + + " Jump to a tag when the tag stack is full, but with user data this time. + call foreach(full, {i, item -> extend(item, {'user_data': $'udata{i}'})}) + call settagstack(0, {'items': full}) + let t = gettagstack() + call assert_equal(20, t.length) + call assert_equal('var11', t.items[0].tagname) + call assert_equal('udata0', t.items[0].user_data) tag var31 - let l = gettagstack() - call assert_equal('var12', l.items[0].tagname) - call assert_equal('var31', l.items[19].tagname) + let t = gettagstack() + call assert_equal('var12', t.items[0].tagname) + call assert_equal('udata1', t.items[0].user_data) + call assert_equal('var31', t.items[19].tagname) + call assert_false(has_key(t.items[19], 'user_data')) " Use tnext with a single match call assert_fails('tnext', 'E427:') diff --git a/src/testdir/test_tcl.vim b/src/testdir/test_tcl.vim index 4c6537f..68a6d63 100644 --- a/src/testdir/test_tcl.vim +++ b/src/testdir/test_tcl.vim @@ -11,10 +11,25 @@ func TclEval(tcl_expr) endfunc func Test_tcldo() - " Check deleting lines does not trigger ml_get error. new + + " Check deleting lines does not trigger ml_get error. call setline(1, ['one', 'two', 'three']) tcldo ::vim::command %d_ + call assert_equal(['one'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + tcldo ::vim::command 1,2d_ + call assert_equal(['one'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + tcldo ::vim::command 2,3d_ ; set line REPLACED + call assert_equal(['REPLACED'], getline(1, '$')) + + call setline(1, ['one', 'two', 'three']) + 2,3tcldo ::vim::command 1,2d_ ; set line REPLACED + call assert_equal(['three'], getline(1, '$')) + bwipe! " Check that switching to another buffer does not trigger ml_get error. diff --git a/src/testdir/test_terminal2.vim b/src/testdir/test_terminal2.vim index 9798c51..05b228e 100644 --- a/src/testdir/test_terminal2.vim +++ b/src/testdir/test_terminal2.vim @@ -535,6 +535,7 @@ func Test_term_getcursor() endfunc " Test for term_gettitle() +" Known to be flaky on Mac-OS X and the GH runners func Test_term_gettitle() " term_gettitle() returns an empty string for a non-terminal buffer " and for a non-existing buffer. @@ -544,6 +545,13 @@ func Test_term_gettitle() if !has('title') || empty(&t_ts) throw "Skipped: can't get/set title" endif + if has('osx') && !empty($CI) && system('uname -m') =~# 'arm64' + " This test often fails with the following error message on Github runners + " MacOS-14 + " '^\\[No Name\\] - VIM\\d*$' does not match 'e] - VIM' + " Why? Is the terminal that runs Vim too small? + throw 'Skipped: FIXME: Running this test on M1 Mac fails on GitHub Actions' + endif let term = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', '-c', 'set title']) call TermWait(term) diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index 97fea60..a06f733 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -3075,10 +3075,17 @@ func Test_prop_with_text_above_below_empty() let vt = 'test' call prop_type_add(vt, {'highlight': 'ToDo'}) for ln in range(1, line('$')) - call prop_add(ln, 0, {'type': vt, 'text': '---', 'text_align': 'above'}) - call prop_add(ln, 0, {'type': vt, 'text': '+++', 'text_align': 'below'}) + " use 1 character text to test for off-by-one regressions + call prop_add(ln, 0, {'type': vt, 'text': '-', 'text_align': 'above'}) + call prop_add(ln, 0, {'type': vt, 'text': '+', 'text_align': 'below'}) endfor normal G + + func AddMore() + call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'}) + call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'}) + call prop_add(5, 0, {'type': g:vt, 'text': '!', 'text_align': 'above'}) + endfunc END call writefile(lines, 'XscriptPropAboveBelowEmpty', 'D') let buf = RunVimInTerminal('-S XscriptPropAboveBelowEmpty', #{rows: 16, cols: 60}) @@ -3100,6 +3107,12 @@ func Test_prop_with_text_above_below_empty() call term_sendkeys(buf, "kk") call VerifyScreenDump(buf, 'Test_prop_above_below_empty_5', {}) + " This was drawing line number over cmdline and leaking memory. + call term_sendkeys(buf, ":call AddMore()\<CR>") + call term_sendkeys(buf, "gg") + call term_sendkeys(buf, "j") + call VerifyScreenDump(buf, 'Test_prop_above_below_empty_6', {}) + call StopVimInTerminal(buf) endfunc @@ -4090,6 +4103,46 @@ func Test_text_below_nowrap() call StopVimInTerminal(buf) endfunc +func Test_virtual_text_overlap_with_highlight() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + setline(1, ['one', 'two', 'three', 'four', 'five']) + set number + + prop_type_add('demo_highlight_warning', {highlight: 'WarningMsg'}) + prop_type_add('demo_virtual_text_error', {highlight: 'Error'}) + + prop_add(2, 4, { + type: 'demo_highlight_warning', + end_col: 4, + }) + prop_add(2, 0, { + type: 'demo_virtual_text_error', + text: 'syntax error', + text_align: 'below', + }) + normal 2j + + prop_add(4, 4, { + type: 'demo_highlight_warning', + end_lnum: 5, + end_col: 1, + }) + prop_add(4, 0, { + type: 'demo_virtual_text_error', + text: 'other error', + text_align: 'right', + }) + END + call writefile(lines, 'XVirtualTextOverlapWithHighlight', 'D') + let buf = RunVimInTerminal('-S XVirtualTextOverlapWithHighlight', #{rows: 8, cols: 60}) + call VerifyScreenDump(buf, 'Test_virtual_text_overlap_with_highlight_1', {}) + + call StopVimInTerminal(buf) +endfunc + func Test_virtual_text_in_popup_highlight() CheckRunVimInTerminal @@ -4425,4 +4478,81 @@ func Test_textprop_notype_join() bwipe! endfunc +" This was causing text property corruption. +func Test_textprop_backspace_fo_aw() + new + call setline(1, 'foobar') + call prop_type_add('test', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'type': 'test', 'length': 3}) + set backspace=indent,eol,start + setlocal formatoptions+=aw + call feedkeys("A \<CR>\<BS>\<Esc>", 'tx') + call assert_equal('foobar', getline(1)) + call assert_equal([ + \ #{id: 0, col: 1, start: 1, end: 1, type_bufnr: 0, + \ type: 'test', length: 3}], prop_list(1)) + + bwipe! + set backspace& + call prop_type_delete('test') +endfunc + +func Test_textprop_with_wincolor() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, 'some text here') + call setline(2, 'some much longer text here') + call setline(3, 'more text here') + call prop_type_add('afterprop', #{highlight: 'Search'}) + call prop_type_add('belowprop', #{highlight: 'DiffAdd'}) + call prop_add(3, 0, #{type: 'afterprop', text: 'AFTER', + \ text_align: 'after', text_padding_left: 3}) + call prop_add(1, 0, #{type: 'belowprop', text: 'BELOW', + \ text_align: 'below', text_padding_left: 3}) + set wincolor=DiffChange wrap + END + call writefile(lines, 'XtextPropWincolor', 'D') + let buf = RunVimInTerminal('-S XtextPropWincolor', #{rows: 8, cols: 60}) + + call term_sendkeys(buf, ":\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_1', {}) + + call term_sendkeys(buf, ":set cursorline\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_2', {}) + + call term_sendkeys(buf, ":set nowrap\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_2', {}) + + call term_sendkeys(buf, ":set nocursorline\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_1', {}) + + call term_sendkeys(buf, ":set cursorline colorcolumn=30\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_3', {}) + + call term_sendkeys(buf, ":hi CursorLine ctermbg=Brown\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_4', {}) + + call term_sendkeys(buf, ":set cursorcolumn\<CR>:\<CR>") + call term_sendkeys(buf, '$') + call VerifyScreenDump(buf, 'Test_prop_wincolor_5', {}) + + call term_sendkeys(buf, 'j') + call VerifyScreenDump(buf, 'Test_prop_wincolor_6', {}) + + call term_sendkeys(buf, ":set virtualedit=all\<CR>:\<CR>") + call term_sendkeys(buf, 'l') + call VerifyScreenDump(buf, 'Test_prop_wincolor_7', {}) + + call term_sendkeys(buf, 'k') + call VerifyScreenDump(buf, 'Test_prop_wincolor_8', {}) + + if has('rightleft') + call term_sendkeys(buf, ":set rightleft\<CR>:\<CR>") + call VerifyScreenDump(buf, 'Test_prop_wincolor_9', {}) + endif + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim index 13c4990..eec0e0b 100644 --- a/src/testdir/test_undo.vim +++ b/src/testdir/test_undo.vim @@ -583,7 +583,7 @@ funct Test_undofile() endif call assert_equal('', undofile('')) - " Test undofile() with 'undodir' set to to an existing directory. + " Test undofile() with 'undodir' set to an existing directory. call mkdir('Xundodir') set undodir=Xundodir let cwd = getcwd() diff --git a/src/testdir/test_user_func.vim b/src/testdir/test_user_func.vim index 57a093c..992329b 100644 --- a/src/testdir/test_user_func.vim +++ b/src/testdir/test_user_func.vim @@ -968,4 +968,23 @@ func Test_multidefer_with_exception() delfunc Foo endfunc +func Test_func_curly_brace_invalid_name() + func Fail() + func Foo{'()'}bar() + endfunc + endfunc + + call assert_fails('call Fail()', 'E475: Invalid argument: Foo()bar') + + silent! call Fail() + call assert_equal([], getcompletion('Foo', 'function')) + + set formatexpr=Fail() + normal! gqq + call assert_equal([], getcompletion('Foo', 'function')) + + set formatexpr& + delfunc Fail +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_utf8_comparisons.vim b/src/testdir/test_utf8_comparisons.vim index 3431226..2c1972b 100644 --- a/src/testdir/test_utf8_comparisons.vim +++ b/src/testdir/test_utf8_comparisons.vim @@ -93,4 +93,39 @@ func Test_gap() call assert_equal(["ABCD", "", "defg"], getline(1,3)) endfunc +" test that g~, ~ and gU correctly upper-cases ß +func Test_uppercase_sharp_ss() + new + call setline(1, repeat(['ß'], 4)) + + call cursor(1, 1) + norm! ~ + call assert_equal('ẞ', getline(line('.'))) + norm! ~ + call assert_equal('ß', getline(line('.'))) + + call cursor(2, 1) + norm! g~l + call assert_equal('ẞ', getline(line('.'))) + norm! g~l + call assert_equal('ß', getline(line('.'))) + + call cursor(3, 1) + norm! gUl + call assert_equal('ẞ', getline(line('.'))) + norm! vgU + call assert_equal('ẞ', getline(line('.'))) + norm! vgu + call assert_equal('ß', getline(line('.'))) + norm! gul + call assert_equal('ß', getline(line('.'))) + + call cursor(4, 1) + norm! vgU + call assert_equal('ẞ', getline(line('.'))) + norm! vgu + call assert_equal('ß', getline(line('.'))) + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index aef09c5..4414f55 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -3484,4 +3484,101 @@ def Test_assign_type_to_list_dict() v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value') enddef +" Test for modifying a final variable using a compound operator +def Test_final_var_modification_with_compound_op() + var lines =<< trim END + vim9script + + final i: number = 1000 + assert_fails('i += 2', 'E46: Cannot change read-only variable "i"') + assert_fails('i -= 2', 'E46: Cannot change read-only variable "i"') + assert_fails('i *= 2', 'E46: Cannot change read-only variable "i"') + assert_fails('i /= 2', 'E46: Cannot change read-only variable "i"') + assert_fails('i %= 2', 'E46: Cannot change read-only variable "i"') + assert_equal(1000, i) + + final f: float = 1000.0 + assert_fails('f += 2', 'E46: Cannot change read-only variable "f"') + assert_fails('f -= 2', 'E46: Cannot change read-only variable "f"') + assert_fails('f *= 2', 'E46: Cannot change read-only variable "f"') + assert_fails('f /= 2', 'E46: Cannot change read-only variable "f"') + assert_equal(1000.0, f) + + final s: string = 'abc' + assert_fails('s ..= "y"', 'E46: Cannot change read-only variable "s"') + assert_equal('abc', s) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for modifying a final variable with a List value +def Test_final_var_with_list_value() + var lines =<< trim END + vim9script + + final listA: list<string> = [] + var listB = listA + + listB->add('a') + assert_true(listA is listB) + assert_equal(['a'], listA) + assert_equal(['a'], listB) + + listB += ['b'] + assert_true(listA is listB) + assert_equal(['a', 'b'], listA) + assert_equal(['a', 'b'], listB) + + listA->add('c') + assert_true(listA is listB) + assert_equal(['a', 'b', 'c'], listA) + assert_equal(['a', 'b', 'c'], listB) + + listA += ['d'] + assert_true(listA is listB) + assert_equal(['a', 'b', 'c', 'd'], listA) + assert_equal(['a', 'b', 'c', 'd'], listB) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for modifying a final variable with a List value using "+=" from a legacy +" function. +func Test_final_var_with_list_value_legacy() + vim9cmd final g:TestVar = ['a'] + vim9cmd g:TestVar += ['b'] + call assert_equal(['a', 'b'], g:TestVar) +endfunc + +" Test for modifying a final variable with a Blob value +def Test_final_var_with_blob_value() + var lines =<< trim END + vim9script + + final blobA: blob = 0z10 + var blobB = blobA + + blobB->add(32) + assert_true(blobA is blobB) + assert_equal(0z1020, blobA) + assert_equal(0z1020, blobB) + + blobB += 0z30 + assert_true(blobA is blobB) + assert_equal(0z102030, blobA) + assert_equal(0z102030, blobB) + + blobA->add(64) + assert_true(blobA is blobB) + assert_equal(0z10203040, blobA) + assert_equal(0z10203040, blobB) + + blobA += 0z50 + assert_true(blobA is blobB) + assert_equal(0z1020304050, blobA) + assert_equal(0z1020304050, blobB) + END + v9.CheckScriptSuccess(lines) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 9af0d07..442d375 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -3409,7 +3409,7 @@ def Test_remote_foreground() CheckFeature clientserver # remote_foreground() doesn't fail on MS-Windows CheckNotMSWindows - CheckEnv DISPLAY + CheckX11 v9.CheckDefAndScriptFailure(['remote_foreground(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_fails('remote_foreground("NonExistingServer")', 'E241:') @@ -4101,30 +4101,10 @@ def Test_simplify() enddef def Test_slice() - assert_equal('12345', slice('012345', 1)) - assert_equal('123', slice('012345', 1, 4)) - assert_equal('1234', slice('012345', 1, -1)) - assert_equal('1', slice('012345', 1, -4)) - assert_equal('', slice('012345', 1, -5)) - assert_equal('', slice('012345', 1, -6)) - - assert_equal([1, 2, 3, 4, 5], slice(range(6), 1)) - assert_equal([1, 2, 3], slice(range(6), 1, 4)) - assert_equal([1, 2, 3, 4], slice(range(6), 1, -1)) - assert_equal([1], slice(range(6), 1, -4)) - assert_equal([], slice(range(6), 1, -5)) - assert_equal([], slice(range(6), 1, -6)) - var lds: list<dict<string>> = [{key: 'value'}] assert_equal(['val'], lds->slice(0, 1)->map((_, v) => 'val')) assert_equal(['val'], lds[ : ]->map((_, v) => 'val')) - assert_equal(0z1122334455, slice(0z001122334455, 1)) - assert_equal(0z112233, slice(0z001122334455, 1, 4)) - assert_equal(0z11223344, slice(0z001122334455, 1, -1)) - assert_equal(0z11, slice(0z001122334455, 1, -4)) - assert_equal(0z, slice(0z001122334455, 1, -5)) - assert_equal(0z, slice(0z001122334455, 1, -6)) v9.CheckDefAndScriptFailure(['slice({"a": 10}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) v9.CheckDefAndScriptFailure(['slice([1, 2, 3], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) v9.CheckDefAndScriptFailure(['slice("abc", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) @@ -5197,4 +5177,12 @@ def Test_passing_type_to_builtin() v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') enddef +def Test_getregion() + assert_equal(['x'], getregion(getpos('.'), getpos('.'))->map((_, _) => 'x')) + + v9.CheckDefAndScriptFailure(['getregion(10, getpos("."))'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) + assert_equal([''], getregion(getpos('.'), getpos('.'))) + v9.CheckDefExecFailure(['getregion(getpos("a"), getpos("."))'], 'E1209:') +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index b34d2ad..d6c55bf 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -67,7 +67,23 @@ def Test_class_basic() END v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3) - # Use old "this." prefixed member variable declaration syntax (without intialization) + # Try to define a class with the same name as an existing variable + lines =<< trim END + vim9script + var Something: list<number> = [1] + class Thing + endclass + interface Api + endinterface + class Something extends Thing implements Api + var v1: string = '' + def Foo() + enddef + endclass + END + v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 7) + + # Use old "this." prefixed member variable declaration syntax (without initialization) lines =<< trim END vim9script class Something @@ -76,7 +92,7 @@ def Test_class_basic() END v9.CheckSourceFailure(lines, 'E1318: Not a valid command in a class: this.count: number', 3) - # Use old "this." prefixed member variable declaration syntax (with intialization) + # Use old "this." prefixed member variable declaration syntax (with initialization) lines =<< trim END vim9script class Something @@ -9659,31 +9675,749 @@ def Test_const_class_object_variable() v9.CheckSourceFailure(lines, 'E1022: Type or initialization required', 3) enddef -" Test for using double underscore prefix in a class/object method name. -def Test_method_double_underscore_prefix() - # class method +" Test for compiling class/object methods using :defcompile +def Test_defcompile_class() + # defcompile all the classes in the current script var lines =<< trim END vim9script class A - static def __foo() - echo "foo" + def Foo() + var i = 10 + enddef + endclass + class B + def Bar() + var i = 20 + xxx enddef endclass defcompile END - v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3) + v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 2) - # object method + # defcompile a specific class lines =<< trim END vim9script class A - def __foo() - echo "foo" + def Foo() + xxx + enddef + endclass + class B + def Bar() + yyy + enddef + endclass + defcompile B + END + v9.CheckSourceFailure(lines, 'E476: Invalid command: yyy', 1) + + # defcompile a non-class + lines =<< trim END + vim9script + class A + def Foo() + enddef + endclass + var X: list<number> = [] + defcompile X + END + v9.CheckSourceFailure(lines, 'E1061: Cannot find function X', 7) + + # defcompile a class twice + lines =<< trim END + vim9script + class A + def new() + enddef + endclass + defcompile A + defcompile A + assert_equal('Function A.new does not need compiling', v:statusmsg) + END + v9.CheckSourceSuccess(lines) + + # defcompile should not compile an imported class + lines =<< trim END + vim9script + export class A + def Foo() + xxx enddef endclass + END + writefile(lines, 'Xdefcompileimport.vim', 'D') + lines =<< trim END + vim9script + + import './Xdefcompileimport.vim' + class B + endclass defcompile END - v9.CheckSourceFailure(lines, 'E1034: Cannot use reserved name __foo()', 3) + v9.CheckScriptSuccess(lines) +enddef + +" Test for cases common to all the object builtin methods +def Test_object_builtin_method() + var lines =<< trim END + vim9script + class A + def abc() + enddef + endclass + END + v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: abc()', 3) + + for funcname in ["len", "string", "empty"] + lines =<< trim eval END + vim9script + class A + static def {funcname}(): number + enddef + endclass + END + v9.CheckSourceFailure(lines, 'E1413: Builtin class method not supported', 3) + endfor +enddef + +" Test for using the empty() builtin method with an object +" This is a legacy function to use the test_garbagecollect_now() function. +func Test_object_empty() + let lines =<< trim END + vim9script + class A + def empty(): bool + return true + enddef + endclass + + def Foo() + var afoo = A.new() + assert_equal(true, empty(afoo)) + assert_equal(true, afoo->empty()) + enddef + + var a = A.new() + assert_equal(1, empty(a)) + assert_equal(1, a->empty()) + test_garbagecollect_now() + assert_equal(1, empty(a)) + Foo() + test_garbagecollect_now() + Foo() + END + call v9.CheckSourceSuccess(lines) + + " empty() should return 1 without a builtin method + let lines =<< trim END + vim9script + class A + endclass + + def Foo() + var afoo = A.new() + assert_equal(1, empty(afoo)) + enddef + + var a = A.new() + assert_equal(1, empty(a)) + Foo() + END + call v9.CheckSourceSuccess(lines) + + " Unsupported signature for the empty() method + let lines =<< trim END + vim9script + class A + def empty() + enddef + endclass + END + call v9.CheckSourceFailure(lines, 'E1383: Method "empty": type mismatch, expected func(): bool but got func()', 4) + + " Error when calling the empty() method + let lines =<< trim END + vim9script + class A + def empty(): bool + throw "Failed to check emptiness" + enddef + endclass + + def Foo() + var afoo = A.new() + var i = empty(afoo) + enddef + + var a = A.new() + assert_fails('empty(a)', 'Failed to check emptiness') + assert_fails('Foo()', 'Failed to check emptiness') + END + call v9.CheckSourceSuccess(lines) + + " call empty() using an object from a script + let lines =<< trim END + vim9script + class A + def empty(): bool + return true + enddef + endclass + var afoo = A.new() + assert_equal(true, afoo.empty()) + END + call v9.CheckSourceSuccess(lines) + + " call empty() using an object from a method + let lines =<< trim END + vim9script + class A + def empty(): bool + return true + enddef + endclass + def Foo() + var afoo = A.new() + assert_equal(true, afoo.empty()) + enddef + Foo() + END + call v9.CheckSourceSuccess(lines) + + " call empty() using "this" from an object method + let lines =<< trim END + vim9script + class A + def empty(): bool + return true + enddef + def Foo(): bool + return this.empty() + enddef + endclass + def Bar() + var abar = A.new() + assert_equal(true, abar.Foo()) + enddef + Bar() + END + call v9.CheckSourceSuccess(lines) + + " Call empty() from a derived object + let lines =<< trim END + vim9script + class A + def empty(): bool + return false + enddef + endclass + class B extends A + def empty(): bool + return true + enddef + endclass + def Foo(afoo: A) + assert_equal(true, empty(afoo)) + var bfoo = B.new() + assert_equal(true, empty(bfoo)) + enddef + var b = B.new() + assert_equal(1, empty(b)) + Foo(b) + END + call v9.CheckSourceSuccess(lines) + + " Invoking empty method using an interface + let lines =<< trim END + vim9script + interface A + def empty(): bool + endinterface + class B implements A + def empty(): bool + return false + enddef + endclass + def Foo(a: A) + assert_equal(false, empty(a)) + enddef + var b = B.new() + Foo(b) + END + call v9.CheckSourceSuccess(lines) +endfunc + +" Test for using the len() builtin method with an object +" This is a legacy function to use the test_garbagecollect_now() function. +func Test_object_length() + let lines =<< trim END + vim9script + class A + var mylen: number = 0 + def new(n: number) + this.mylen = n + enddef + def len(): number + return this.mylen + enddef + endclass + + def Foo() + var afoo = A.new(12) + assert_equal(12, len(afoo)) + assert_equal(12, afoo->len()) + enddef + + var a = A.new(22) + assert_equal(22, len(a)) + assert_equal(22, a->len()) + test_garbagecollect_now() + assert_equal(22, len(a)) + Foo() + test_garbagecollect_now() + Foo() + END + call v9.CheckSourceSuccess(lines) + + " len() should return 0 without a builtin method + let lines =<< trim END + vim9script + class A + endclass + + def Foo() + var afoo = A.new() + assert_equal(0, len(afoo)) + enddef + + var a = A.new() + assert_equal(0, len(a)) + Foo() + END + call v9.CheckSourceSuccess(lines) + + " Unsupported signature for the len() method + let lines =<< trim END + vim9script + class A + def len() + enddef + endclass + END + call v9.CheckSourceFailure(lines, 'E1383: Method "len": type mismatch, expected func(): number but got func()', 4) + + " Error when calling the len() method + let lines =<< trim END + vim9script + class A + def len(): number + throw "Failed to compute length" + enddef + endclass + + def Foo() + var afoo = A.new() + var i = len(afoo) + enddef + + var a = A.new() + assert_fails('len(a)', 'Failed to compute length') + assert_fails('Foo()', 'Failed to compute length') + END + call v9.CheckSourceSuccess(lines) + + " call len() using an object from a script + let lines =<< trim END + vim9script + class A + def len(): number + return 5 + enddef + endclass + var afoo = A.new() + assert_equal(5, afoo.len()) + END + call v9.CheckSourceSuccess(lines) + + " call len() using an object from a method + let lines =<< trim END + vim9script + class A + def len(): number + return 5 + enddef + endclass + def Foo() + var afoo = A.new() + assert_equal(5, afoo.len()) + enddef + Foo() + END + call v9.CheckSourceSuccess(lines) + + " call len() using "this" from an object method + let lines =<< trim END + vim9script + class A + def len(): number + return 8 + enddef + def Foo(): number + return this.len() + enddef + endclass + def Bar() + var abar = A.new() + assert_equal(8, abar.Foo()) + enddef + Bar() + END + call v9.CheckSourceSuccess(lines) + + " Call len() from a derived object + let lines =<< trim END + vim9script + class A + def len(): number + return 10 + enddef + endclass + class B extends A + def len(): number + return 20 + enddef + endclass + def Foo(afoo: A) + assert_equal(20, len(afoo)) + var bfoo = B.new() + assert_equal(20, len(bfoo)) + enddef + var b = B.new() + assert_equal(20, len(b)) + Foo(b) + END + call v9.CheckSourceSuccess(lines) + + " Invoking len method using an interface + let lines =<< trim END + vim9script + interface A + def len(): number + endinterface + class B implements A + def len(): number + return 123 + enddef + endclass + def Foo(a: A) + assert_equal(123, len(a)) + enddef + var b = B.new() + Foo(b) + END + call v9.CheckSourceSuccess(lines) +endfunc + +" Test for using the string() builtin method with an object +" This is a legacy function to use the test_garbagecollect_now() function. +func Test_object_string() + let lines =<< trim END + vim9script + class A + var name: string + def string(): string + return this.name + enddef + endclass + + def Foo() + var afoo = A.new("foo-A") + assert_equal('foo-A', string(afoo)) + assert_equal('foo-A', afoo->string()) + enddef + + var a = A.new("script-A") + assert_equal('script-A', string(a)) + assert_equal('script-A', a->string()) + assert_equal(['script-A'], execute('echo a')->split("\n")) + test_garbagecollect_now() + assert_equal('script-A', string(a)) + Foo() + test_garbagecollect_now() + Foo() + END + call v9.CheckSourceSuccess(lines) + + " string() should return "object of A {}" without a builtin method + let lines =<< trim END + vim9script + class A + endclass + + def Foo() + var afoo = A.new() + assert_equal('object of A {}', string(afoo)) + enddef + + var a = A.new() + assert_equal('object of A {}', string(a)) + Foo() + END + call v9.CheckSourceSuccess(lines) + + " Unsupported signature for the string() method + let lines =<< trim END + vim9script + class A + def string() + enddef + endclass + END + call v9.CheckSourceFailure(lines, 'E1383: Method "string": type mismatch, expected func(): string but got func()', 4) + + " Error when calling the string() method + let lines =<< trim END + vim9script + class A + def string(): string + throw "Failed to get text" + enddef + endclass + + def Foo() + var afoo = A.new() + var i = string(afoo) + enddef + + var a = A.new() + assert_fails('string(a)', 'Failed to get text') + assert_fails('Foo()', 'Failed to get text') + END + call v9.CheckSourceSuccess(lines) + + " call string() using an object from a script + let lines =<< trim END + vim9script + class A + def string(): string + return 'A' + enddef + endclass + var afoo = A.new() + assert_equal('A', afoo.string()) + END + call v9.CheckSourceSuccess(lines) + + " call string() using an object from a method + let lines =<< trim END + vim9script + class A + def string(): string + return 'A' + enddef + endclass + def Foo() + var afoo = A.new() + assert_equal('A', afoo.string()) + enddef + Foo() + END + call v9.CheckSourceSuccess(lines) + + " call string() using "this" from an object method + let lines =<< trim END + vim9script + class A + def string(): string + return 'A' + enddef + def Foo(): string + return this.string() + enddef + endclass + def Bar() + var abar = A.new() + assert_equal('A', abar.string()) + enddef + Bar() + END + call v9.CheckSourceSuccess(lines) + + " Call string() from a derived object + let lines =<< trim END + vim9script + class A + def string(): string + return 'A' + enddef + endclass + class B extends A + def string(): string + return 'B' + enddef + endclass + def Foo(afoo: A) + assert_equal('B', string(afoo)) + var bfoo = B.new() + assert_equal('B', string(bfoo)) + enddef + var b = B.new() + assert_equal('B', string(b)) + Foo(b) + END + call v9.CheckSourceSuccess(lines) + + " Invoking string method using an interface + let lines =<< trim END + vim9script + interface A + def string(): string + endinterface + class B implements A + def string(): string + return 'B' + enddef + endclass + def Foo(a: A) + assert_equal('B', string(a)) + enddef + var b = B.new() + Foo(b) + END + call v9.CheckSourceSuccess(lines) +endfunc + +" Test for using a class in the class definition +def Test_Ref_Class_Within_Same_Class() + var lines =<< trim END + vim9script + class A + var n: number = 0 + def Equals(other: A): bool + return this.n == other.n + enddef + endclass + + var a1 = A.new(10) + var a2 = A.new(10) + var a3 = A.new(20) + assert_equal(true, a1.Equals(a2)) + assert_equal(false, a2.Equals(a3)) + END + v9.CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + + class Foo + var num: number + def Clone(): Foo + return Foo.new(this.num) + enddef + endclass + + var f1 = Foo.new(1) + + def F() + var f2: Foo = f1.Clone() + assert_equal(false, f2 is f1) + assert_equal(true, f2.num == f1.num) + enddef + F() + + var f3: Foo = f1.Clone() + assert_equal(false, f3 is f1) + assert_equal(true, f3.num == f1.num) + END + v9.CheckScriptSuccess(lines) + + # Test for trying to use a class to extend when defining the same class + lines =<< trim END + vim9script + class A extends A + endclass + END + v9.CheckScriptFailure(lines, 'E1354: Cannot extend A', 3) + + # Test for trying to use a class to implement when defining the same class + lines =<< trim END + vim9script + class A implements A + endclass + END + v9.CheckScriptFailure(lines, 'E1347: Not a valid interface: A', 3) +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 + var lines =<< trim END + vim9script + class A + var n: number = 10 + def Foo() + var Fn = () => { + this.n += 1 + } + Fn() + enddef + endclass + + var a = A.new() + a.Foo() + assert_equal(11, a.n) + END + v9.CheckScriptSuccess(lines) + + # Test using the "..=" operator + lines =<< trim END + vim9script + class A + var s: string = "a" + def Foo() + var Fn = () => { + this.s ..= "a" + } + Fn() + enddef + endclass + + var a = A.new() + a.Foo() + a.Foo() + assert_equal("aaa", a.s) + END + v9.CheckScriptSuccess(lines) +enddef + +" call a lambda function in one object from another object +def Test_lambda_invocation_across_classes() + var lines =<< trim END + vim9script + class A + var s: string = "foo" + def GetFn(): func + var Fn = (): string => { + return this.s + } + return Fn + enddef + endclass + + class B + var s: string = "bar" + def GetFn(): func + var a = A.new() + return a.GetFn() + enddef + endclass + + var b = B.new() + var Fn = b.GetFn() + assert_equal("foo", Fn()) + END + v9.CheckScriptSuccess(lines) enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 1a192cc..1daef22 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -3273,4 +3273,199 @@ def Test_funcref_with_class() unlet g:instr enddef +" Disassemble instructions for calls to a string() function in an object +def Test_disassemble_object_string() + var lines =<< trim END + vim9script + class A + def string(): string + return 'A' + enddef + endclass + def Bar() + var a = A.new() + var s = string(a) + s = string(A) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = string(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 METHODCALL A.string(argc 0)\_s*' .. + '4 STORE $1\_s*' .. + 's = string(A)\_s*' .. + '5 LOADSCRIPT A-0 from .*\_s*' .. + '6 BCALL string(argc 1)\_s*' .. + '7 STORE $1\_s*' .. + '8 RETURN void', g:instr) + unlet g:instr + + # Use the default string() function for a class + lines =<< trim END + vim9script + class A + endclass + def Bar() + var a = A.new() + var s = string(a) + s = string(A) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = string(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 BCALL string(argc 1)\_s*' .. + '4 STORE $1\_s*' .. + 's = string(A)\_s*' .. + '5 LOADSCRIPT A-0 from .*\_s*' .. + '6 BCALL string(argc 1)\_s*' .. + '7 STORE $1\_s*' .. + '8 RETURN void', g:instr) + unlet g:instr +enddef + +" Disassemble instructions for calls to a empty() function in an object +def Test_disassemble_object_empty() + var lines =<< trim END + vim9script + class A + def empty(): bool + return true + enddef + endclass + def Bar() + var a = A.new() + var s = empty(a) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = empty(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 METHODCALL A.empty(argc 0)\_s*' .. + '4 STORE $1\_s*' .. + '5 RETURN void', g:instr) + unlet g:instr + + # Use the default empty() function for a class + lines =<< trim END + vim9script + class A + endclass + def Bar() + var a = A.new() + var s = empty(a) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = empty(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 BCALL empty(argc 1)\_s*' .. + '4 STORE $1\_s*' .. + '5 RETURN void', g:instr) + unlet g:instr +enddef + +" Disassemble instructions for calls to a len() function in an object +def Test_disassemble_object_len() + var lines =<< trim END + vim9script + class A + def len(): number + return 10 + enddef + endclass + def Bar() + var a = A.new() + var s = len(a) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = len(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 METHODCALL A.len(argc 0)\_s*' .. + '4 STORE $1\_s*' .. + '5 RETURN void', g:instr) + unlet g:instr + + # Use the default len() function for a class + lines =<< trim END + vim9script + class A + endclass + def Bar() + var a = A.new() + var s = len(a) + enddef + g:instr = execute('disassemble Bar') + END + v9.CheckScriptSuccess(lines) + assert_match('<SNR>\d*_Bar\_s*' .. + 'var a = A.new()\_s*' .. + '0 DCALL new(argc 0)\_s*' .. + '1 STORE $0\_s*' .. + 'var s = len(a)\_s*' .. + '2 LOAD $0\_s*' .. + '3 BCALL len(argc 1)\_s*' .. + '4 STORE $1\_s*' .. + '5 RETURN void', g:instr) + unlet g:instr +enddef + +" Disassemble instructions for using a compound operator in a closure +def Test_disassemble_compound_op_in_closure() + var lines =<< trim END + vim9script + class A + var foo: number = 1 + def Foo(): func + var Fn = () => { + this.foo += 1 + } + return Fn + enddef + endclass + var a = A.new() + var Lambda = a.Foo() + var num = matchstr(string(Lambda), '\d\+') + g:instr = execute($'disassemble <lambda>{num}') + END + v9.CheckScriptSuccess(lines) + assert_match('<lambda>\d\+\_s*' .. + 'this.foo += 1\_s*' .. + '0 LOADOUTER level 0 $0\_s*' .. + '1 OBJ_MEMBER 0\_s*' .. + '2 PUSHNR 1\_s*' .. + '3 OPNR +\_s*' .. + '4 PUSHNR 0\_s*' .. + '5 LOADOUTER level 0 $0\_s*' .. + '6 STOREINDEX object\_s*' .. + '7 RETURN void', 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_expr.vim b/src/testdir/test_vim9_expr.vim index 6285ba1..7764b37 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -311,6 +311,33 @@ def Test_expr2() assert_equal([1], g:vals) END v9.CheckDefAndScriptSuccess(lines) + + # test the short-circuit operation + lines =<< trim END + assert_equal(true, true && true) + assert_equal(false, true && !true) + assert_equal(false, !true && true) + assert_equal(false, !true && !true) + + assert_equal(true, true || true) + assert_equal(true, true || !true) + assert_equal(true, !true || true) + assert_equal(false, !true || !true) + + assert_equal(false, false && false) + assert_equal(false, false && !false) + assert_equal(false, !false && false) + assert_equal(true, !false && !false) + + assert_equal(false, false || false) + assert_equal(true, false || !false) + assert_equal(true, !false || false) + assert_equal(true, !false || !false) + + assert_equal(false, !true && !true && !true) + assert_equal(true, !false || !false || !false) + END + v9.CheckDefAndScriptSuccess(lines) enddef def Test_expr2_vimscript() diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index d470a34..fa1aeb1 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -2929,5 +2929,54 @@ def Test_export_in_conditional_block() v9.CheckScriptSuccess(lines) enddef +" Import fails when an autoloaded script is imported again. +" Github issue #14171 +def Test_import_autloaded_script() + mkdir('Ximporttwice', 'pR') + mkdir('Ximporttwice/plugin') + mkdir('Ximporttwice/autoload') + var save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Ximporttwice' + + var lines =<< trim END + vim9script + + export def H(): number + return 10 + enddef + END + writefile(lines, 'Ximporttwice/autoload/hello.vim') + + lines =<< trim END + vim9script + + import "./hello.vim" + export def W(): number + return 20 + enddef + END + writefile(lines, 'Ximporttwice/autoload/world.vim') + + lines =<< trim END + vim9script + + import autoload '../autoload/hello.vim' + import autoload '../autoload/world.vim' + + command Hello echo hello.H() + command World echo world.W() + END + writefile(lines, 'Ximporttwice/plugin/main.vim') + + lines =<< trim END + vim9script + + source ./Ximporttwice/plugin/main.vim + assert_equal(['20'], execute('World')->split("\n")) + END + v9.CheckScriptSuccess(lines) + + &rtp = save_rtp +enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 7ae4d55..77b8831 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -4906,6 +4906,31 @@ def Test_for_stmt_space_before_type() v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: :number in range(10)', 2) enddef +" This test used to cause an use-after-free memory access +def Test_for_empty_line_after_lambda() + var lines =<< trim END + vim9script + echomsg range(0, 2)->map((_, v) => { + return 1 + }) + + assert_equal('[1, 1, 1]', v:statusmsg) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + echomsg range(0, 1)->map((_, v) => { + return 1 + }) range(0, 1)->map((_, v) => { + return 2 + }) # comment + + assert_equal('[1, 1] [2, 2]', v:statusmsg) + END + v9.CheckSourceSuccess(lines) +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/testdir/test_vim9_typealias.vim b/src/testdir/test_vim9_typealias.vim index 4155744..998079c 100644 --- a/src/testdir/test_vim9_typealias.vim +++ b/src/testdir/test_vim9_typealias.vim @@ -641,7 +641,7 @@ def Test_type_as_func_argument_or_return_value() END v9.CheckScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1) - # check defered function using typealias as arg + # check deferred function using typealias as arg lines =<< trim END vim9script type A = number @@ -764,7 +764,7 @@ def Test_class_as_func_argument_or_return_value() END v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value', 1) - # check defered function using class typealias as arg + # check deferred function using class typealias as arg lines =<< trim END vim9script class C diff --git a/src/testdir/test_virtualedit.vim b/src/testdir/test_virtualedit.vim index ec2b276..48d4aa0 100644 --- a/src/testdir/test_virtualedit.vim +++ b/src/testdir/test_virtualedit.vim @@ -77,13 +77,30 @@ endfunc func Test_edit_change() new set virtualedit=all + call setline(1, "\t⒌") normal Cx call assert_equal('x', getline(1)) + + call setline(1, "\ta̳") + normal Cx + call assert_equal('x', getline(1)) + + call setline(1, "\tβ̳") + normal Cx + call assert_equal('x', getline(1)) + + if has('arabic') + call setline(1, "\tلا") + normal Cx + call assert_equal('x', getline(1)) + endif + " Do a visual block change call setline(1, ['a', 'b', 'c']) exe "normal gg3l\<C-V>2jcx" call assert_equal(['a x', 'b x', 'c x'], getline(1, '$')) + bwipe! set virtualedit= endfunc diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index 401a350..fd174a9 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -3,6 +3,7 @@ source shared.vim source check.vim source screendump.vim +import './vim9.vim' as v9 func Test_block_shift_multibyte() " Uses double-wide character. @@ -1008,7 +1009,7 @@ endfunc " Test for changing case func Test_visual_change_case() new - " gUe must uppercase a whole word, also when ß changes to SS + " gUe must uppercase a whole word, also when ß changes to ẞ exe "normal Gothe youtußeuu end\<Esc>Ypk0wgUe\r" " gUfx must uppercase until x, inclusive. exe "normal O- youßtußexu -\<Esc>0fogUfx\r" @@ -1020,9 +1021,9 @@ func Test_visual_change_case() exe "normal Oblah di\rdoh dut\<Esc>VkUj\r" " Uppercase part of two lines exe "normal ddppi333\<Esc>k0i222\<Esc>fyllvjfuUk" - call assert_equal(['the YOUTUSSEUU end', '- yOUSSTUSSEXu -', - \ 'THE YOUTUSSEUU END', '111THE YOUTUSSEUU END', 'BLAH DI', 'DOH DUT', - \ '222the yoUTUSSEUU END', '333THE YOUTUßeuu end'], getline(2, '$')) + call assert_equal(['the YOUTUẞEUU end', '- yOUẞTUẞEXu -', + \ 'THE YOUTUẞEUU END', '111THE YOUTUẞEUU END', 'BLAH DI', 'DOH DUT', + \ '222the yoUTUẞEUU END', '333THE YOUTUßeuu end'], getline(2, '$')) bwipe! endfunc @@ -1622,4 +1623,336 @@ func Test_visual_drag_out_of_window() bwipe! endfunc +func Test_visual_substitute_visual() + new + call setline(1, ['one', 'two', 'three']) + call feedkeys("Gk\<C-V>j$:s/\\%V\\_.*\\%V/foobar\<CR>", 'tx') + call assert_equal(['one', 'foobar'], getline(1, '$')) + bwipe! +endfunc + +func Test_visual_getregion() + let lines =<< trim END + new + + call setline(1, ['one', 'two', 'three']) + + #" Visual mode + call cursor(1, 1) + call feedkeys("\<ESC>vjl", 'tx') + call assert_equal(['one', 'tw'], + \ 'v'->getpos()->getregion(getpos('.'))) + call assert_equal(['one', 'tw'], + \ '.'->getpos()->getregion(getpos('v'))) + call assert_equal(['o'], + \ 'v'->getpos()->getregion(getpos('v'))) + call assert_equal(['w'], + \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' })) + call assert_equal(['one', 'two'], + \ getpos('.')->getregion(getpos('v'), {'type': 'V' })) + call assert_equal(['on', 'tw'], + \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" })) + + #" Line visual mode + call cursor(1, 1) + call feedkeys("\<ESC>Vl", 'tx') + call assert_equal(['one'], + \ getregion(getpos('v'), getpos('.'), {'type': 'V' })) + call assert_equal(['one'], + \ getregion(getpos('.'), getpos('v'), {'type': 'V' })) + call assert_equal(['one'], + \ getregion(getpos('v'), getpos('v'), {'type': 'V' })) + call assert_equal(['one'], + \ getregion(getpos('.'), getpos('.'), {'type': 'V' })) + call assert_equal(['on'], + \ getpos('.')->getregion(getpos('v'), {'type': 'v' })) + call assert_equal(['on'], + \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" })) + + #" Block visual mode + call cursor(1, 1) + call feedkeys("\<ESC>\<C-v>ll", 'tx') + call assert_equal(['one'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal(['one'], + \ getregion(getpos('.'), getpos('v'), {'type': "\<C-v>" })) + call assert_equal(['o'], + \ getregion(getpos('v'), getpos('v'), {'type': "\<C-v>" })) + call assert_equal(['e'], + \ getregion(getpos('.'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal(['one'], + \ '.'->getpos()->getregion(getpos('v'), {'type': 'V' })) + call assert_equal(['one'], + \ '.'->getpos()->getregion(getpos('v'), {'type': 'v' })) + + #" Using Marks + call setpos("'a", [0, 2, 3, 0]) + call cursor(1, 1) + call assert_equal(['one', 'two'], + \ "'a"->getpos()->getregion(getpos('.'), {'type': 'v' })) + call assert_equal(['one', 'two'], + \ "."->getpos()->getregion(getpos("'a"), {'type': 'v' })) + call assert_equal(['one', 'two'], + \ "."->getpos()->getregion(getpos("'a"), {'type': 'V' })) + call assert_equal(['two'], + \ "'a"->getpos()->getregion(getpos("'a"), {'type': 'V' })) + call assert_equal(['one', 'two'], + \ "."->getpos()->getregion(getpos("'a"), {'type': "\<c-v>" })) + + #" Using List + call cursor(1, 1) + call assert_equal(['one', 'two'], + \ [0, 2, 3, 0]->getregion(getpos('.'), {'type': 'v' })) + call assert_equal(['one', 'two'], + \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'v' })) + call assert_equal(['one', 'two'], + \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'V' })) + call assert_equal(['two'], + \ [0, 2, 3, 0]->getregion([0, 2, 3, 0], {'type': 'V' })) + call assert_equal(['one', 'two'], + \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': "\<c-v>" })) + + #" Multiline with line visual mode + call cursor(1, 1) + call feedkeys("\<ESC>Vjj", 'tx') + call assert_equal(['one', 'two', 'three'], + \ getregion(getpos('v'), getpos('.'), {'type': 'V' })) + + #" Multiline with block visual mode + call cursor(1, 1) + call feedkeys("\<ESC>\<C-v>jj", 'tx') + call assert_equal(['o', 't', 't'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + + call cursor(1, 1) + call feedkeys("\<ESC>\<C-v>jj$", 'tx') + call assert_equal(['one', 'two', 'three'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + + #" 'virtualedit' + set virtualedit=all + call cursor(1, 1) + call feedkeys("\<ESC>\<C-v>10ljj$", 'tx') + call assert_equal(['one ', 'two ', 'three '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + set virtualedit& + + #" using wrong types for positions + call cursor(1, 1) + call feedkeys("\<ESC>vjj$", 'tx') + call assert_fails("call getregion(1, 2)", 'E1211:') + call assert_fails("call getregion(getpos('.'), {})", 'E1211:') + call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:') + + #" using invalid value for "type" + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '' })", 'E475:') + + #" using a mark from another buffer to current buffer + new + LET g:buf = bufnr() + call setline(1, range(10)) + normal! GmA + wincmd p + call assert_equal([g:buf, 10, 1, 0], getpos("'A")) + call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' })) + call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' })) + + #" using two marks from another buffer + wincmd p + normal! GmB + wincmd p + call assert_equal([g:buf, 10, 1, 0], getpos("'B")) + call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' })) + + #" using two positions from another buffer + for type in ['v', 'V', "\<C-V>"] + for exclusive in [v:false, v:true] + call assert_equal(range(10)->mapnew('string(v:val)'), + \ getregion([g:buf, 1, 1, 0], [g:buf, 10, 2, 0], + \ {'type': type, 'exclusive': exclusive })) + call assert_equal(range(10)->mapnew('string(v:val)'), + \ getregion([g:buf, 10, 2, 0], [g:buf, 1, 1, 0], + \ {'type': type, 'exclusive': exclusive })) + endfor + endfor + + #" using invalid positions in buffer + call assert_fails('call getregion([g:buf, 0, 1, 0], [g:buf, 10, 2, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 10, 2, 0], [g:buf, 0, 1, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 11, 2, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 11, 2, 0], [g:buf, 1, 1, 0])', 'E966:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 0, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 10, 0, 0], [g:buf, 1, 1, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 3, 0])', 'E964:') + call assert_fails('call getregion([g:buf, 10, 3, 0], [g:buf, 1, 1, 0])', 'E964:') + + #" using invalid buffer + call assert_fails('call getregion([10000, 10, 1, 0], [10000, 10, 1, 0])', 'E681:') + + exe $':{g:buf}bwipe!' + unlet g:buf + END + call v9.CheckLegacyAndVim9Success(lines) + + bwipe! + + let lines =<< trim END + #" Selection in starts or ends in the middle of a multibyte character + new + call setline(1, [ + \ "abcdefghijk\u00ab", + \ "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9", + \ "1234567890" + \ ]) + call cursor(1, 3) + call feedkeys("\<Esc>\<C-v>ljj", 'xt') + call assert_equal(['cd', "\u00ab ", '34'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 4) + call feedkeys("\<Esc>\<C-v>ljj", 'xt') + call assert_equal(['de', "\U0001f1e7", '45'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 5) + call feedkeys("\<Esc>\<C-v>jj", 'xt') + call assert_equal(['e', ' ', '5'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 1) + call feedkeys("\<Esc>vj", 'xt') + call assert_equal(['abcdefghijk«', "\U0001f1e6"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + + #" marks on multibyte chars + :set selection=exclusive + call setpos("'a", [0, 1, 11, 0]) + call setpos("'b", [0, 2, 16, 0]) + call setpos("'c", [0, 2, 0, 0]) + call cursor(1, 1) + call assert_equal(['ghijk', '🇨«🇩'], + \ getregion(getpos("'a"), getpos("'b"), {'type': "\<c-v>" })) + call assert_equal(['k«', '🇦«🇧«🇨'], + \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' })) + call assert_equal(['k«'], + \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' })) + + #" use inclusive selection, although 'selection' is exclusive + call setpos("'a", [0, 1, 11, 0]) + call setpos("'b", [0, 1, 1, 0]) + call assert_equal(['abcdefghijk'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': "\<c-v>", 'exclusive': v:false })) + call assert_equal(['abcdefghij'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': "\<c-v>", 'exclusive': v:true })) + call assert_equal(['abcdefghijk'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': 'v', 'exclusive': 0 })) + call assert_equal(['abcdefghij'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': 'v', 'exclusive': 1 })) + call assert_equal(['abcdefghijk«'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': 'V', 'exclusive': 0 })) + call assert_equal(['abcdefghijk«'], + \ getregion(getpos("'a"), getpos("'b"), + \ {'type': 'V', 'exclusive': 1 })) + :set selection& + END + call v9.CheckLegacyAndVim9Success(lines) + + bwipe! + + let lines =<< trim END + #" Exclusive selection + new + set selection=exclusive + call setline(1, ["a\tc", "x\tz", '', '']) + call cursor(1, 1) + call feedkeys("\<Esc>v2l", 'xt') + call assert_equal(["a\t"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 1) + call feedkeys("\<Esc>v$G", 'xt') + call assert_equal(["a\tc", "x\tz", ''], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 1) + call feedkeys("\<Esc>v$j", 'xt') + call assert_equal(["a\tc", "x\tz"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 1) + call feedkeys("\<Esc>\<C-v>$j", 'xt') + call assert_equal(["a\tc", "x\tz"], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 1) + call feedkeys("\<Esc>\<C-v>$G", 'xt') + call assert_equal(["a", "x", '', ''], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call cursor(1, 1) + call feedkeys("\<Esc>wv2j", 'xt') + call assert_equal(["c", "x\tz"], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + set selection& + + #" Exclusive selection 2 + new + call setline(1, ["a\tc", "x\tz", '', '']) + call cursor(1, 1) + call feedkeys("\<Esc>v2l", 'xt') + call assert_equal(["a\t"], + \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) + call feedkeys("\<Esc>v$G", 'xt') + call assert_equal(["a\tc", "x\tz", ''], + \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) + call feedkeys("\<Esc>v$j", 'xt') + call assert_equal(["a\tc", "x\tz"], + \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + call cursor(1, 1) + call feedkeys("\<Esc>\<C-v>$j", 'xt') + call assert_equal(["a\tc", "x\tz"], + \ getregion(getpos('v'), getpos('.'), + \ {'exclusive': v:true, 'type': "\<C-v>" })) + call cursor(1, 1) + call feedkeys("\<Esc>\<C-v>$G", 'xt') + call assert_equal(["a", "x", '', ''], + \ getregion(getpos('v'), getpos('.'), + \ {'exclusive': v:true, 'type': "\<C-v>" })) + call cursor(1, 1) + call feedkeys("\<Esc>wv2j", 'xt') + call assert_equal(["c", "x\tz"], + \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true })) + + #" virtualedit + set selection=exclusive + set virtualedit=all + call cursor(1, 1) + call feedkeys("\<Esc>2lv2lj", 'xt') + call assert_equal([' c', 'x '], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 1) + call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt') + call assert_equal([' ', ' ', ' '], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + set virtualedit& + set selection& + + bwipe! + END + call v9.CheckLegacyAndVim9Success(lines) +endfunc + +func Test_getregion_invalid_buf() + new + help + call cursor(5, 7) + norm! mA + call cursor(5, 18) + norm! mB + call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B"))) + " close the help window + q + call assert_fails("call getregion(getpos(\"'A\"), getpos(\"'B\"))", 'E681:') + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 6b7dccb..91adb9b 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -131,64 +131,6 @@ func Test_window_quit() bw Xa Xb endfunc -func Test_window_curwin_not_prevwin() - botright split - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - quit - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - - botright split - botright split - call assert_equal(3, winnr()) - call assert_equal(2, winnr('#')) - 1quit - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - botright split - call assert_equal(1, tabpagenr()) - call assert_equal(3, winnr()) - call assert_equal(2, winnr('#')) - wincmd T - call assert_equal(2, tabpagenr()) - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - tabfirst - call assert_equal(1, tabpagenr()) - call assert_equal(2, winnr()) - call assert_equal(0, winnr('#')) - - tabonly - botright split - wincmd t - wincmd p - call assert_equal(3, winnr()) - call assert_equal(1, winnr('#')) - quit - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - botright split - wincmd t - wincmd p - call assert_equal(1, tabpagenr()) - call assert_equal(3, winnr()) - call assert_equal(1, winnr('#')) - wincmd T - call assert_equal(2, tabpagenr()) - call assert_equal(1, winnr()) - call assert_equal(0, winnr('#')) - tabfirst - call assert_equal(1, tabpagenr()) - call assert_equal(2, winnr()) - call assert_equal(1, winnr('#')) - - tabonly - only -endfunc - func Test_window_horizontal_split() call assert_equal(1, winnr('$')) 3wincmd s @@ -276,6 +218,20 @@ func Test_window_split_edit_bufnr() %bw! endfunc +func s:win_layout_info(tp = tabpagenr()) abort + return #{ + \ layout: winlayout(a:tp), + \ pos_sizes: range(1, tabpagewinnr(a:tp, '$')) + \ ->map({_, nr -> win_getid(nr, a:tp)->getwininfo()[0]}) + \ ->map({_, wininfo -> #{id: wininfo.winid, + \ row: wininfo.winrow, + \ col: wininfo.wincol, + \ width: wininfo.width, + \ height: wininfo.height}}) + \ ->sort({a, b -> a.id - b.id}) + \ } +endfunc + func Test_window_split_no_room() " N horizontal windows need >= 2*N + 1 lines: " - 1 line + 1 status line in each window @@ -290,6 +246,14 @@ func Test_window_split_no_room() for s in range(1, hor_split_count) | split | endfor call assert_fails('split', 'E36:') + botright vsplit + wincmd | + let info = s:win_layout_info() + call assert_fails('wincmd J', 'E36:') + call assert_fails('wincmd K', 'E36:') + call assert_equal(info, s:win_layout_info()) + only + " N vertical windows need >= 2*(N - 1) + 1 columns: " - 1 column + 1 separator for each window (except last window) " - 1 column for the last window which does not have separator @@ -302,7 +266,37 @@ func Test_window_split_no_room() for s in range(1, ver_split_count) | vsplit | endfor call assert_fails('vsplit', 'E36:') + split + wincmd | + let info = s:win_layout_info() + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd L', 'E36:') + call assert_equal(info, s:win_layout_info()) + + " Check that the last statusline isn't lost. + " Set its window's width to 2 for the test. + wincmd j + set laststatus=0 winminwidth=0 + vertical resize 2 + " Update expected positions/sizes after the resize. Layout is unchanged. + let info.pos_sizes = s:win_layout_info().pos_sizes + set winminwidth& + call setwinvar(winnr('k'), '&statusline', '@#') + let last_stl_row = win_screenpos(0)[0] - 1 + redraw + call assert_equal('@#|', GetScreenStr(last_stl_row)) + call assert_equal('~ |', GetScreenStr(&lines - &cmdheight)) + + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd L', 'E36:') + call assert_equal(info, s:win_layout_info()) + call setwinvar(winnr('k'), '&statusline', '=-') + redraw + call assert_equal('=-|', GetScreenStr(last_stl_row)) + call assert_equal('~ |', GetScreenStr(&lines - &cmdheight)) + %bw! + set laststatus& endfunc func Test_window_exchange() @@ -1066,6 +1060,18 @@ func Test_win_splitmove() leftabove split b leftabove vsplit c leftabove split d + + " win_splitmove doesn't actually create or close any windows, so expect an + " unchanged winid and no WinNew/WinClosed events, like :wincmd H/J/K/L. + let s:triggered = [] + augroup WinSplitMove + au! + au WinNewPre * let s:triggered += ['WinNewPre'] + au WinNew * let s:triggered += ['WinNew', win_getid()] + au WinClosed * let s:triggered += ['WinClosed', str2nr(expand('<afile>'))] + augroup END + let winid = win_getid() + call assert_equal(0, win_splitmove(winnr(), winnr('l'))) call assert_equal(bufname(winbufnr(1)), 'c') call assert_equal(bufname(winbufnr(2)), 'd') @@ -1088,6 +1094,11 @@ func Test_win_splitmove() call assert_equal(bufname(winbufnr(3)), 'a') call assert_equal(bufname(winbufnr(4)), 'd') call assert_fails('call win_splitmove(winnr(), winnr("k"), test_null_dict())', 'E1297:') + call assert_equal([], s:triggered) + call assert_equal(winid, win_getid()) + + unlet! s:triggered + au! WinSplitMove only | bd call assert_fails('call win_splitmove(winnr(), 123)', 'E957:') @@ -1097,6 +1108,54 @@ func Test_win_splitmove() tabnew call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:') tabclose + + split + augroup WinSplitMove + au! + au WinEnter * ++once call win_gotoid(win_getid(winnr('#'))) + augroup END + call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:') + + augroup WinSplitMove + au! + au WinLeave * ++once quit + augroup END + call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E855:') + + split + split + augroup WinSplitMove + au! + au WinEnter * ++once let s:triggered = v:true + \| call assert_fails('call win_splitmove(winnr(), winnr("$"))', 'E242:') + \| call assert_fails('call win_splitmove(winnr("$"), winnr())', 'E242:') + augroup END + quit + call assert_equal(v:true, s:triggered) + unlet! s:triggered + + new + augroup WinSplitMove + au! + au BufHidden * ++once let s:triggered = v:true + \| call assert_fails('call win_splitmove(winnr(), winnr("#"))', 'E1159:') + augroup END + hide + call assert_equal(v:true, s:triggered) + unlet! s:triggered + + split + let close_win = winnr('#') + augroup WinSplitMove + au! + au WinEnter * ++once quit! + augroup END + call win_splitmove(close_win, winnr()) + call assert_equal(0, win_id2win(close_win)) + + au! WinSplitMove + augroup! WinSplitMove + %bw! endfunc " Test for the :only command @@ -2060,24 +2119,160 @@ func Test_new_help_window_on_error() call assert_equal(expand("<cword>"), "'mod'") endfunc -func Test_smoothscroll_in_zero_width_window() - let save_lines = &lines - let save_columns = &columns +func Test_splitmove_flatten_frame() + split + vsplit - winsize 0 24 - set cpo+=n - exe "noremap 0 \<C-W>n\<C-W>L" - norm 000000 - set number smoothscroll - exe "norm \<C-Y>" + wincmd L + let layout = winlayout() + wincmd K + wincmd L + call assert_equal(winlayout(), layout) only! - let &lines = save_lines - let &columns = save_columns - set cpo-=n - unmap 0 - set nonumber nosmoothscroll endfunc +func Test_autocmd_window_force_room() + " Open as many windows as possible + while v:true + try + split + catch /E36:/ + break + endtry + endwhile + while v:true + try + vsplit + catch /E36:/ + break + endtry + endwhile + + wincmd j + vsplit + call assert_fails('wincmd H', 'E36:') + call assert_fails('wincmd J', 'E36:') + call assert_fails('wincmd K', 'E36:') + call assert_fails('wincmd L', 'E36:') + + edit unload me + enew + bunload! unload\ me + augroup AucmdWinForceRoom + au! + au BufEnter * ++once let s:triggered = v:true + \| call assert_equal('autocmd', win_gettype()) + augroup END + let info = s:win_layout_info() + " bufload opening the autocommand window shouldn't give E36. + call bufload('unload me') + call assert_equal(v:true, s:triggered) + call assert_equal(info, s:win_layout_info()) + + unlet! s:triggered + au! AucmdWinForceRoom + augroup! AucmdWinForceRoom + %bw! +endfunc + +func Test_win_gotoid_splitmove_textlock_cmdwin() + call setline(1, 'foo') + new + let curwin = win_getid() + call setline(1, 'bar') + + set debug+=throw indentexpr=win_gotoid(win_getid(winnr('#'))) + call assert_fails('normal! ==', 'E565:') + call assert_equal(curwin, win_getid()) + " No error if attempting to switch to curwin; nothing happens. + set indentexpr=assert_equal(1,win_gotoid(win_getid())) + normal! == + call assert_equal(curwin, win_getid()) + + set indentexpr=win_splitmove(winnr('#'),winnr()) + call assert_fails('normal! ==', 'E565:') + call assert_equal(curwin, win_getid()) + + %bw! + set debug-=throw indentexpr& + + call feedkeys('q:' + \ .. ":call assert_fails('call win_splitmove(winnr(''#''), winnr())', 'E11:')\<CR>" + \ .. ":call assert_equal('command', win_gettype())\<CR>" + \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx') + + call feedkeys('q:' + \ .. ":call assert_fails('call win_gotoid(win_getid(winnr(''#'')))', 'E11:')\<CR>" + "\ No error if attempting to switch to curwin; nothing happens. + \ .. ":call assert_equal(1, win_gotoid(win_getid()))\<CR>" + \ .. ":call assert_equal('command', win_gettype())\<CR>" + \ .. ":call assert_equal('', win_gettype(winnr('#')))\<CR>", 'ntx') +endfunc + +func Test_winfixsize_positions() + " Check positions are correct when closing a window in a non-current tabpage + " causes non-adjacent window to fill the space due to 'winfix{width,height}'. + tabnew + vsplit + wincmd | + split + set winfixheight + split foo + tabfirst + + bwipe! foo + " Save actual values before entering the tabpage. + let info = s:win_layout_info(2) + tabnext + " Compare it with the expected value (after win_comp_pos) from entering. + call assert_equal(s:win_layout_info(), info) + + $tabnew + split + split + wincmd k + belowright vsplit + set winfixwidth + belowright vsplit foo + tabprevious + + bwipe! foo + " Save actual values before entering the tabpage. + let info = s:win_layout_info(3) + tabnext + " Compare it with the expected value (after win_comp_pos) from entering. + call assert_equal(s:win_layout_info(), info) + + " Check positions unchanged when failing to move a window, if 'winfix{width, + " height}' would otherwise cause a non-adjacent window to fill the space. + %bwipe + call assert_fails('execute "split|"->repeat(&lines)', 'E36:') + wincmd p + vsplit + set winfixwidth + vsplit + set winfixwidth + vsplit + vsplit + set winfixwidth + wincmd p + + let info = s:win_layout_info() + call assert_fails('wincmd J', 'E36:') + call assert_equal(info, s:win_layout_info()) + + only + call assert_fails('execute "vsplit|"->repeat(&columns)', 'E36:') + belowright split + set winfixheight + belowright split + + let info = s:win_layout_info() + call assert_fails('wincmd H', 'E36:') + call assert_equal(info, s:win_layout_info()) + + %bwipe +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_winfixbuf.vim b/src/testdir/test_winfixbuf.vim new file mode 100644 index 0000000..04043f8 --- /dev/null +++ b/src/testdir/test_winfixbuf.vim @@ -0,0 +1,3286 @@ +" Test 'winfixbuf' + +source check.vim + +" Find the number of open windows in the current tab +func s:get_windows_count() + return tabpagewinnr(tabpagenr(), '$') +endfunc + +" Create some unnamed buffers. +func s:make_buffers_list() + enew + file first + let l:first = bufnr() + + enew + file middle + let l:middle = bufnr() + + enew + file last + let l:last = bufnr() + + set winfixbuf + + return [l:first, l:last] +endfunc + +" Create some unnamed buffers and add them to an args list +func s:make_args_list() + let [l:first, l:last] = s:make_buffers_list() + + args! first middle last + + return [l:first, l:last] +endfunc + +" Create two buffers and then set the window to 'winfixbuf' +func s:make_buffer_pairs(...) + let l:reversed = get(a:, 1, 0) + + if l:reversed == 1 + enew + file original + + set winfixbuf + + enew! + file other + let l:other = bufnr() + + return l:other + endif + + enew + file other + let l:other = bufnr() + + enew + file current + + set winfixbuf + + return l:other +endfunc + +" Create 3 quick buffers and set the window to 'winfixbuf' +func s:make_buffer_trio() + edit first + let l:first = bufnr() + edit second + let l:second = bufnr() + + set winfixbuf + + edit! third + let l:third = bufnr() + + execute ":buffer! " . l:second + + return [l:first, l:second, l:third] +endfunc + +" Create a location list with at least 2 entries + a 'winfixbuf' window. +func s:make_simple_location_list() + enew + file middle + let l:middle = bufnr() + call append(0, ["winfix search-term", "another line"]) + + enew! + file first + let l:first = bufnr() + call append(0, "first search-term") + + enew! + file last + let l:last = bufnr() + call append(0, "last search-term") + + call setloclist( + \ 0, + \ [ + \ { + \ "filename": "first", + \ "bufnr": l:first, + \ "lnum": 1, + \ }, + \ { + \ "filename": "middle", + \ "bufnr": l:middle, + \ "lnum": 1, + \ }, + \ { + \ "filename": "middle", + \ "bufnr": l:middle, + \ "lnum": 2, + \ }, + \ { + \ "filename": "last", + \ "bufnr": l:last, + \ "lnum": 1, + \ }, + \ ] + \) + + set winfixbuf + + return [l:first, l:middle, l:last] +endfunc + +" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. +func s:make_simple_quickfix() + enew + file current + let l:current = bufnr() + call append(0, ["winfix search-term", "another line"]) + + enew! + file first + let l:first = bufnr() + call append(0, "first search-term") + + enew! + file last + let l:last = bufnr() + call append(0, "last search-term") + + call setqflist( + \ [ + \ { + \ "filename": "first", + \ "bufnr": l:first, + \ "lnum": 1, + \ }, + \ { + \ "filename": "current", + \ "bufnr": l:current, + \ "lnum": 1, + \ }, + \ { + \ "filename": "current", + \ "bufnr": l:current, + \ "lnum": 2, + \ }, + \ { + \ "filename": "last", + \ "bufnr": l:last, + \ "lnum": 1, + \ }, + \ ] + \) + + set winfixbuf + + return [l:current, l:last] +endfunc + +" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. +func s:make_quickfix_windows() + let [l:current, _] = s:make_simple_quickfix() + execute "buffer! " . l:current + + split + let l:first_window = win_getid() + execute "normal \<C-w>j" + let l:winfix_window = win_getid() + + " Open the quickfix in a separate split and go to it + copen + let l:quickfix_window = win_getid() + + return [l:first_window, l:winfix_window, l:quickfix_window] +endfunc + +" Revert all changes that occurred in any past test +func s:reset_all_buffers() + %bwipeout! + set nowinfixbuf + + call setqflist([]) + + for l:window_info in getwininfo() + call setloclist(l:window_info["winid"], []) + endfor + + delmarks A-Z0-9 +endfunc + +" Find and set the first quickfix entry that points to `buffer` +func s:set_quickfix_by_buffer(buffer) + let l:index = 1 " quickfix indices start at 1 + for l:entry in getqflist() + if l:entry["bufnr"] == a:buffer + execute l:index . "cc" + + return + endif + + let l:index += 1 + endfor + + echoerr 'No quickfix entry matching "' . a:buffer . '" could be found.' +endfunc + +" Fail to call :Next on a 'winfixbuf' window unless :Next! is used. +func Test_Next() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("Next", "E1513:") + call assert_notequal(l:first, bufnr()) + + Next! + call assert_equal(l:first, bufnr()) +endfunc + +" Call :argdo and choose the next available 'nowinfixbuf' window. +func Test_argdo_choose_available_window() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :argdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + argdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :argdo and create a new split window if all available windows are 'winfixbuf'. +func Test_argdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, l:last] = s:make_args_list() + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + argdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :argedit but :argedit! is allowed +func Test_argedit() + call s:reset_all_buffers() + + args! first middle last + enew + file first + let l:first = bufnr() + + enew + file middle + let l:middle = bufnr() + + enew + file last + let l:last = bufnr() + + set winfixbuf + + let l:current = bufnr() + call assert_fails("argedit first middle last", "E1513:") + call assert_equal(l:current, bufnr()) + + argedit! first middle last + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :arglocal but :arglocal! is allowed +func Test_arglocal() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + argglobal! other + execute "buffer! " . l:current + + call assert_fails("arglocal other", "E1513:") + call assert_equal(l:current, bufnr()) + + arglocal! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :argglobal but :argglobal! is allowed +func Test_argglobal() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("argglobal other", "E1513:") + call assert_equal(l:current, bufnr()) + + argglobal! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :args but :args! is allowed +func Test_args() + call s:reset_all_buffers() + + let [l:first, _] = s:make_buffers_list() + let l:current = bufnr() + + call assert_fails("args first middle last", "E1513:") + call assert_equal(l:current, bufnr()) + + args! first middle last + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :bNext but :bNext! is allowed +func Test_bNext() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + call assert_fails("bNext", "E1513:") + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + + bNext! + call assert_equal(l:other, bufnr()) +endfunc + +" Allow :badd because it doesn't actually change the current window's buffer +func Test_badd() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + badd other + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :balt because it doesn't actually change the current window's buffer +func Test_balt() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + balt other + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :bfirst but :bfirst! is allowed +func Test_bfirst() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bfirst", "E1513:") + call assert_equal(l:current, bufnr()) + + bfirst! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :blast but :blast! is allowed +func Test_blast() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs(1) + bfirst! + let l:current = bufnr() + + call assert_fails("blast", "E1513:") + call assert_equal(l:current, bufnr()) + + blast! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bmodified but :bmodified! is allowed +func Test_bmodified() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + execute "buffer! " . l:other + set modified + execute "buffer! " . l:current + + call assert_fails("bmodified", "E1513:") + call assert_equal(l:current, bufnr()) + + bmodified! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bnext but :bnext! is allowed +func Test_bnext() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bnext", "E1513:") + call assert_equal(l:current, bufnr()) + + bnext! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :bprevious but :bprevious! is allowed +func Test_bprevious() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("bprevious", "E1513:") + call assert_equal(l:current, bufnr()) + + bprevious! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :brewind but :brewind! is allowed +func Test_brewind() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("brewind", "E1513:") + call assert_equal(l:current, bufnr()) + + brewind! + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :browse edit but :browse edit! is allowed +func Test_browse_edit_fail() + " A GUI dialog may stall the test. + CheckNotGui + + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("browse edit other", "E1513:") + call assert_equal(l:current, bufnr()) + + try + browse edit! other + call assert_equal(l:other, bufnr()) + catch /^Vim\%((\a\+)\)\=:E338:/ + " Ignore E338, which occurs if console Vim is built with +browse. + " Console Vim without +browse will treat this as a regular :edit. + endtry +endfunc + +" Allow :browse w because it doesn't change the buffer in the current file +func Test_browse_edit_pass() + " A GUI dialog may stall the test. + CheckNotGui + + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + try + browse write other + catch /^Vim\%((\a\+)\)\=:E338:/ + " Ignore E338, which occurs if console Vim is built with +browse. + " Console Vim without +browse will treat this as a regular :write. + endtry + + call delete("other") +endfunc + +" Call :bufdo and choose the next available 'nowinfixbuf' window. +func Test_bufdo_choose_available_window() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :bufdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + + let l:current = bufnr() + let l:expected_windows = s:get_windows_count() + + call assert_notequal(l:current, l:other) + + bufdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_notequal(l:other, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :bufdo and create a new split window if all available windows are 'winfixbuf'. +func Test_bufdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, l:last] = s:make_buffers_list() + execute "buffer! " . l:first + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + bufdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :buffer but :buffer! is allowed +func Test_buffer() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("buffer " . l:other, "E1513:") + call assert_equal(l:current, bufnr()) + + execute "buffer! " . l:other + call assert_equal(l:other, bufnr()) +endfunc + +" Allow :buffer on a 'winfixbuf' window if there is no change in buffer +func Test_buffer_same_buffer() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + let l:current = bufnr() + + execute "buffer " . l:current + call assert_equal(l:current, bufnr()) + + execute "buffer! " . l:current + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :cNext but the 'nowinfixbuf' window is selected, instead +func Test_cNext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cNext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cNext + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cNfile but the 'nowinfixbuf' window is selected, instead +func Test_cNfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cNfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cNfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :caddexpr because it doesn't change the current buffer +func Test_caddexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["Error - bad-thing-found"], l:file_path) + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + execute 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' + call assert_equal(l:current, bufnr()) + + call delete(l:file_path) +endfunc + +" Fail :cbuffer but :cbuffer! is allowed +func Test_cbuffer() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path) + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + call assert_fails("cbuffer " . l:file_buffer) + call assert_equal(l:current, bufnr()) + + execute "cbuffer! " . l:file_buffer + call assert_equal("first.unittest", expand("%:t")) + + call delete(l:file_path) +endfunc + +" Allow :cc but the 'nowinfixbuf' window is selected, instead +func Test_cc() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + " Go up one line in the quickfix window to an quickfix entry that doesn't + " point to a winfixbuf buffer + normal k + " Attempt to make the previous window, winfixbuf buffer, to go to the + " non-winfixbuf quickfix entry + .cc + + " Confirm that :.cc did not change the winfixbuf-enabled window + call assert_equal(l:first_window, win_getid()) +endfunc + +" Call :cdo and choose the next available 'nowinfixbuf' window. +func Test_cdo_choose_available_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :cdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + cdo echo '' + + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :cdo and create a new split window if all available windows are 'winfixbuf'. +func Test_cdo_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current_buffer, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current_buffer + + let l:current_window = win_getid() + let l:current_windows = s:get_windows_count() + + cdo echo '' + call assert_notequal(l:current_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current_buffer, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :cexpr but :cexpr! is allowed +func Test_cexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file = tempname() + let l:entry = '["' . l:file . ':1:bar"]' + let l:current = bufnr() + + set winfixbuf + + call assert_fails("cexpr " . l:entry) + call assert_equal(l:current, bufnr()) + + execute "cexpr! " . l:entry + call assert_equal(fnamemodify(l:file, ":t"), expand("%:t")) +endfunc + +" Call :cfdo and choose the next available 'nowinfixbuf' window. +func Test_cfdo_choose_available_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :cfdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + let l:expected_windows = s:get_windows_count() + + cfdo echo '' + + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :cfdo and create a new split window if all available windows are 'winfixbuf'. +func Test_cfdo_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current_buffer, l:last] = s:make_simple_quickfix() + execute "buffer! " . l:current_buffer + + let l:current_window = win_getid() + let l:current_windows = s:get_windows_count() + + cfdo echo '' + call assert_notequal(l:current_window, win_getid()) + call assert_equal(l:last, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:current_buffer, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :cfile but :cfile! is allowed +func Test_cfile() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + write + let l:first = bufnr() + + edit! second.unittest + call append(0, ["some-search-term"]) + write + + let l:file = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file) + + let l:current = bufnr() + + set winfixbuf + + call assert_fails(":cfile " . l:file) + call assert_equal(l:current, bufnr()) + + execute ":cfile! " . l:file + call assert_equal(l:first, bufnr()) + + call delete(l:file) + call delete("first.unittest") + call delete("second.unittest") +endfunc + +" Allow :cfirst but the 'nowinfixbuf' window is selected, instead +func Test_cfirst() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cfirst` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cfirst + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :clast but the 'nowinfixbuf' window is selected, instead +func Test_clast() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:clast` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + clast + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cnext but the 'nowinfixbuf' window is selected, instead +" Make sure no new windows are created and previous windows are reused +func Test_cnext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + let l:expected = s:get_windows_count() + + " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + cnext! + call assert_equal(l:expected, s:get_windows_count()) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cnext + call assert_equal(l:first_window, win_getid()) + call assert_equal(l:expected, s:get_windows_count()) +endfunc + +" Make sure :cnext creates a split window if no previous window exists +func Test_cnext_no_previous_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, _] = s:make_simple_quickfix() + execute "buffer! " . l:current + + let l:expected = s:get_windows_count() + + " Open the quickfix in a separate split and go to it + copen + + call assert_equal(l:expected + 1, s:get_windows_count()) +endfunc + +" Allow :cnext and create a 'nowinfixbuf' window if none exists +func Test_cnext_make_new_window() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:current, _] = s:make_simple_quickfix() + let l:current = win_getid() + + cfirst! + + let l:windows = s:get_windows_count() + let l:expected = l:windows + 1 " We're about to create a new split window + + cnext + call assert_equal(l:expected, s:get_windows_count()) + + cnext! + call assert_equal(l:expected, s:get_windows_count()) +endfunc + +" Allow :cprevious but the 'nowinfixbuf' window is selected, instead +func Test_cprevious() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cprevious` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cprevious + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cnfile but the 'nowinfixbuf' window is selected, instead +func Test_cnfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cnfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cnfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :cpfile but the 'nowinfixbuf' window is selected, instead +func Test_cpfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:cpfile` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + cpfile + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow :crewind but the 'nowinfixbuf' window is selected, instead +func Test_crewind() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() + + " The call to `:crewind` succeeds but it selects the window with 'nowinfixbuf' instead + call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) + cnext! + + " Make sure the previous window has 'winfixbuf' so we can test that our + " "skip 'winfixbuf' window" logic works. + call win_gotoid(l:winfix_window) + call win_gotoid(l:quickfix_window) + + crewind + call assert_equal(l:first_window, win_getid()) +endfunc + +" Allow <C-w>f because it opens in a new split +func Test_ctrl_w_f() + call s:reset_all_buffers() + + enew + let l:file_name = tempname() + call writefile([], l:file_name) + let l:file_buffer = bufnr() + + enew + file other + let l:other_buffer = bufnr() + + set winfixbuf + + call setline(1, l:file_name) + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>f" + + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + call delete(l:file_name) +endfunc + +" Fail :djump but :djump! is allowed +func Test_djump() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("djump 1 /min/", "E1513:") + call assert_equal(l:current, bufnr()) + + djump! 1 /min/ + call assert_notequal(l:current, bufnr()) + + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail :drop but :drop! is allowed +func Test_drop() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("drop other", "E1513:") + call assert_equal(l:current, bufnr()) + + drop! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :edit but :edit! is allowed +func Test_edit() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("edit other", "E1513:") + call assert_equal(l:current, bufnr()) + + edit! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :enew but :enew! is allowed +func Test_enew() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("enew", "E1513:") + call assert_equal(l:current, bufnr()) + + enew! + call assert_notequal(l:other, bufnr()) + call assert_notequal(3, bufnr()) +endfunc + +" Fail :ex but :ex! is allowed +func Test_ex() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("ex other", "E1513:") + call assert_equal(l:current, bufnr()) + + ex! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :find but :find! is allowed +func Test_find() + call s:reset_all_buffers() + + let l:current = bufnr() + let l:file = tempname() + call writefile([], l:file) + let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style. + let l:directory = fnamemodify(l:file, ":p:h") + let l:name = fnamemodify(l:file, ":p:t") + + let l:original_path = &path + execute "set path=" . l:directory + + set winfixbuf + + call assert_fails("execute 'find " . l:name . "'", "E1513:") + call assert_equal(l:current, bufnr()) + + execute "find! " . l:name + call assert_equal(l:file, expand("%:p")) + + execute "set path=" . l:original_path + call delete(l:file) +endfunc + +" Fail :first but :first! is allowed +func Test_first() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("first", "E1513:") + call assert_notequal(l:first, bufnr()) + + first! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :grep but :grep! is allowed +func Test_grep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + let l:first = bufnr() + + edit current.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + set winfixbuf + + buffer! current.unittest + + call assert_fails("silent! grep some-search-term *.unittest", "E1513:") + call assert_equal(l:current, bufnr()) + execute "edit! " . l:first + + silent! grep! some-search-term *.unittest + call assert_notequal(l:first, bufnr()) + + call delete("first.unittest") + call delete("current.unittest") + call delete("last.unittest") +endfunc + +" Fail :ijump but :ijump! is allowed +func Test_ijump() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile([ + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + + set winfixbuf + + let l:current = bufnr() + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + call assert_fails("ijump /min/", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + ijump! /min/ + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail :lNext but :lNext! is allowed +func Test_lNext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + call assert_fails("lNext", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lnext! + call assert_equal(3, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lNext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lNext! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lNfile but :lNfile! is allowed +func Test_lNfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:current, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + call assert_fails("lNfile", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lnext! + call assert_equal(3, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lNfile! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Allow :laddexpr because it doesn't change the current buffer +func Test_laddexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["Error - bad-thing-found"], l:file_path) + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + execute 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' + call assert_equal(l:current, bufnr()) + + call delete(l:file_path) +endfunc + +" Fail :last but :last! is allowed +func Test_last() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + next! + + call assert_fails("last", "E1513:") + call assert_notequal(l:last, bufnr()) + + last! + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lbuffer but :lbuffer! is allowed +func Test_lbuffer() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file_path = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path) + execute "edit " . l:file_path + let l:file_buffer = bufnr() + let l:current = bufnr() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + + edit! other.unittest + + set winfixbuf + + execute "buffer! " . l:file_buffer + + call assert_fails("lbuffer " . l:file_buffer) + call assert_equal(l:current, bufnr()) + + execute "lbuffer! " . l:file_buffer + call assert_equal("first.unittest", expand("%:t")) + + call delete(l:file_path) +endfunc + +" Fail :ldo but :ldo! is allowed +func Test_ldo() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lnext! + + call assert_fails('execute "ldo buffer ' . l:first . '"', "E1513:") + call assert_equal(l:middle, bufnr()) + execute "ldo! buffer " . l:first + call assert_notequal(l:last, bufnr()) +endfunc + +" Fail :lfdo but :lfdo! is allowed +func Test_lexpr() + CheckFeature quickfix + call s:reset_all_buffers() + + let l:file = tempname() + let l:entry = '["' . l:file . ':1:bar"]' + let l:current = bufnr() + + set winfixbuf + + call assert_fails("lexpr " . l:entry) + call assert_equal(l:current, bufnr()) + + execute "lexpr! " . l:entry + call assert_equal(fnamemodify(l:file, ":t"), expand("%:t")) +endfunc + +" Fail :lfdo but :lfdo! is allowed +func Test_lfdo() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lnext! + + call assert_fails('execute "lfdo buffer ' . l:first . '"', "E1513:") + call assert_equal(l:middle, bufnr()) + execute "lfdo! buffer " . l:first + call assert_notequal(l:last, bufnr()) +endfunc + +" Fail :lfile but :lfile! is allowed +func Test_lfile() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term bad-thing-found"]) + write + let l:first = bufnr() + + edit! second.unittest + call append(0, ["some-search-term"]) + write + + let l:file = tempname() + call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file) + + let l:current = bufnr() + + set winfixbuf + + call assert_fails(":lfile " . l:file) + call assert_equal(l:current, bufnr()) + + execute ":lfile! " . l:file + call assert_equal(l:first, bufnr()) + + call delete(l:file) + call delete("first.unittest") + call delete("second.unittest") +endfunc + +" Fail :ll but :ll! is allowed +func Test_ll() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + lopen + lfirst! + execute "normal \<C-w>j" + normal j + + call assert_fails(".ll", "E1513:") + execute "normal \<C-w>k" + call assert_equal(l:first, bufnr()) + execute "normal \<C-w>j" + .ll! + execute "normal \<C-w>k" + call assert_equal(l:middle, bufnr()) +endfunc + +" Fail :llast but :llast! is allowed +func Test_llast() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, _, l:last] = s:make_simple_location_list() + lfirst! + + call assert_fails("llast", "E1513:") + call assert_equal(l:first, bufnr()) + + llast! + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lnext but :lnext! is allowed +func Test_lnext() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, l:last] = s:make_simple_location_list() + ll! + + call assert_fails("lnext", "E1513:") + call assert_equal(l:first, bufnr()) + + lnext! + call assert_equal(l:middle, bufnr()) +endfunc + +" Fail :lnfile but :lnfile! is allowed +func Test_lnfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [_, l:current, l:last] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + call assert_fails("lnfile", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:current, bufnr()) + + lnfile! + call assert_equal(4, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:last, bufnr()) +endfunc + +" Fail :lpfile but :lpfile! is allowed +func Test_lpfile() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:current, _] = s:make_simple_location_list() + lnext! + + call assert_fails("lpfile", "E1513:") + call assert_equal(l:current, bufnr()) + + lnext! " Reset for the next test call + + lpfile! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lprevious but :lprevious! is allowed +func Test_lprevious() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + + lnext! + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + call assert_fails("lprevious", "E1513:") + " Ensure the entry didn't change. + call assert_equal(2, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:middle, bufnr()) + + lprevious! + call assert_equal(1, getloclist(0, #{idx: 0}).idx) + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :lrewind but :lrewind! is allowed +func Test_lrewind() + CheckFeature quickfix + call s:reset_all_buffers() + + let [l:first, l:middle, _] = s:make_simple_location_list() + lnext! + + call assert_fails("lrewind", "E1513:") + call assert_equal(l:middle, bufnr()) + + lrewind! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail :ltag but :ltag! is allowed +func Test_ltag() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("ltag one", "E1513:") + + ltag! one + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail vim.command if we try to change buffers while 'winfixbuf' is set +func Test_lua_command() + CheckFeature lua + call s:reset_all_buffers() + + enew + file first + let l:previous = bufnr() + + enew + file second + let l:current = bufnr() + + set winfixbuf + + call assert_fails('lua vim.command("buffer " .. ' . l:previous . ')') + call assert_equal(l:current, bufnr()) + + execute 'lua vim.command("buffer! " .. ' . l:previous . ')' + call assert_equal(l:previous, bufnr()) +endfunc + +" Fail :lvimgrep but :lvimgrep! is allowed +func Test_lvimgrep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("lvimgrep /some-search-term/ *.unittest", "E1513:") + call assert_equal(l:current, bufnr()) + + lvimgrep! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :lvimgrepadd but :lvimgrepadd! is allowed +func Test_lvimgrepadd() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("lvimgrepadd /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + lvimgrepadd! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Don't allow global marks to change the current 'winfixbuf' window +func Test_marks_mappings_fail() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + execute "buffer! " . l:other + normal mA + execute "buffer! " . l:current + normal mB + + call assert_fails("normal `A", "E1513:") + call assert_equal(l:current, bufnr()) + + call assert_fails("normal 'A", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + normal `A + call assert_equal(l:other, bufnr()) +endfunc + +" Allow global marks in a 'winfixbuf' window if the jump is the same buffer +func Test_marks_mappings_pass_intra_move() + call s:reset_all_buffers() + + let l:current = bufnr() + call append(0, ["some line", "another line"]) + normal mA + normal j + normal mB + + set winfixbuf + + normal `A + call assert_equal(l:current, bufnr()) +endfunc + +" Fail :next but :next! is allowed +func Test_next() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + first! + + call assert_fails("next", "E1513:") + call assert_equal(l:first, bufnr()) + + next! + call assert_notequal(l:first, bufnr()) +endfunc + +" Ensure :mksession saves 'winfixbuf' details +func Test_mksession() + CheckFeature mksession + call s:reset_all_buffers() + + set sessionoptions+=options + set winfixbuf + + mksession test_winfixbuf_Test_mksession.vim + + call s:reset_all_buffers() + let l:winfixbuf = &winfixbuf + call assert_equal(0, l:winfixbuf) + + source test_winfixbuf_Test_mksession.vim + + let l:winfixbuf = &winfixbuf + call assert_equal(1, l:winfixbuf) + + set sessionoptions& + call delete("test_winfixbuf_Test_mksession.vim") +endfunc + +" Allow :next if the next index is the same as the current buffer +func Test_next_same_buffer() + call s:reset_all_buffers() + + enew + file foo + enew + file bar + enew + file fizz + enew + file buzz + args foo foo bar fizz buzz + + edit foo + set winfixbuf + let l:current = bufnr() + + " Allow :next because the args list is `[foo] foo bar fizz buzz + next + call assert_equal(l:current, bufnr()) + + " Fail :next because the args list is `foo [foo] bar fizz buzz + " and the next buffer would be bar, which is a different buffer + call assert_fails("next", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Fail to jump to a tag with g<C-]> if 'winfixbuf' is enabled +func Test_normal_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled +func Test_normal_g_rightmouse() + call s:reset_all_buffers() + set mouse=n + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g\<RightMouse>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + set mouse& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with g] if 'winfixbuf' is enabled +func Test_normal_g_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal g]", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled +func Test_normal_ctrl_rightmouse() + call s:reset_all_buffers() + set mouse=n + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-RightMouse>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + set mouse& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled +func Test_normal_ctrl_t() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + execute "normal \<C-]>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-t>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Disallow <C-^> in 'winfixbuf' windows +func Test_normal_ctrl_hat() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-^>", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Allow <C-i> in 'winfixbuf' windows if the movement stays within the buffer +func Test_normal_ctrl_i_pass() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew! + file current + let l:current = bufnr() + " Add some lines so we can populate a jumplist" + call append(0, ["some line", "another line"]) + " Add an entry to the jump list + " Go up another line + normal m` + normal k + execute "normal \<C-o>" + + set winfixbuf + + let l:line = getcurpos()[1] + execute "normal 1\<C-i>" + call assert_notequal(l:line, getcurpos()[1]) +endfunc + +" Disallow <C-o> in 'winfixbuf' windows if it would cause the buffer to switch +func Test_normal_ctrl_o_fail() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-o>", "E1513:") + call assert_equal(l:current, bufnr()) +endfunc + +" Allow <C-o> in 'winfixbuf' windows if the movement stays within the buffer +func Test_normal_ctrl_o_pass() + call s:reset_all_buffers() + clearjumps + + enew + file first + let l:first = bufnr() + + enew! + file current + let l:current = bufnr() + " Add some lines so we can populate a jumplist + call append(0, ["some line", "another line"]) + " Add an entry to the jump list + " Go up another line + normal m` + normal k + + set winfixbuf + + execute "normal \<C-o>" + call assert_equal(l:current, bufnr()) +endfunc + +" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled +func Test_normal_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window +func Test_normal_ctrl_w_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>\<C-]>" + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window +func Test_normal_ctrl_w_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current_windows = s:get_windows_count() + execute "normal \<C-w>g\<C-]>" + call assert_equal(l:current_windows + 1, s:get_windows_count()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled +func Test_normal_gt() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one", "two", "three"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal \<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Prevent gF from switching a 'winfixbuf' window's buffer +func Test_normal_gF() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file) + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gF, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal gF", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal gF + call assert_notequal(l:buffer, bufnr()) + + call delete(l:file) +endfunc + +" Prevent gf from switching a 'winfixbuf' window's buffer +func Test_normal_gf() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file) + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal gf", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal gf + call assert_notequal(l:buffer, bufnr()) + + call delete(l:file) +endfunc + +" Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`) +func Test_normal_square_bracket_left_f() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file) + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal [f", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal [f + call assert_notequal(l:buffer, bufnr()) + + call delete(l:file) +endfunc + +" Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled +func Test_normal_square_bracket_left_ctrl_d() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + normal ]\<C-d> + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal [\<C-d>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal [\<C-d>" + call assert_notequal(l:current, bufnr()) + + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled +func Test_normal_square_bracket_right_ctrl_d() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal ]\<C-d>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal ]\<C-d>" + call assert_notequal(l:current, bufnr()) + + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled +func Test_normal_square_bracket_left_ctrl_i() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(['#include "' . l:include_file . '"', + \ "min(1, 12);", + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + " Move to the line with `min(1, 12);` on it" + normal j + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal [\<C-i>", "E1513:") + + set nowinfixbuf + + execute "normal [\<C-i>" + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled +func Test_normal_square_bracket_right_ctrl_i() + call s:reset_all_buffers() + + let l:include_file = tempname() . ".h" + call writefile(["min(1, 12);", + \ '#include "' . l:include_file . '"' + \ ], + \ "main.c") + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + edit main.c + + set winfixbuf + + set define=^\\s*#\\s*define + set include=^\\s*#\\s*include + set path=.,/usr/include,, + + let l:current = bufnr() + + call assert_fails("normal ]\<C-i>", "E1513:") + call assert_equal(l:current, bufnr()) + + set nowinfixbuf + + execute "normal ]\<C-i>" + call assert_notequal(l:current, bufnr()) + + set define& + set include& + set path& + call delete("main.c") + call delete(l:include_file) +endfunc + +" Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`) +func Test_normal_square_bracket_right_f() + call s:reset_all_buffers() + + let l:file = tempname() + call append(0, [l:file]) + call writefile([], l:file) + " Place the cursor onto the line that has `l:file` + normal gg + " Prevent Vim from erroring with "No write since last change @ command + " line" when we try to call gf, later. + set hidden + + set winfixbuf + + let l:buffer = bufnr() + + call assert_fails("normal ]f", "E1513:") + call assert_equal(l:buffer, bufnr()) + + set nowinfixbuf + + normal ]f + call assert_notequal(l:buffer, bufnr()) + + call delete(l:file) +endfunc + +" Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled +func Test_normal_v_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal v\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled +func Test_normal_v_g_ctrl_square_bracket_right() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("normal vg\<C-]>", "E1513:") + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Allow :pedit because, unlike :edit, it uses a separate window +func Test_pedit() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + + pedit other + + execute "normal \<C-w>w" + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :pop but :pop! is allowed +func Test_pop() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags") + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") + call writefile(["thesame one"], "Xother") + edit Xother + + tag thesame + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("pop", "E1513:") + call assert_equal(l:current, bufnr()) + + pop! + call assert_notequal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail :previous but :previous! is allowed +func Test_previous() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("previous", "E1513:") + call assert_notequal(l:first, bufnr()) + + previous! + call assert_equal(l:first, bufnr()) +endfunc + +" Fail pyxdo if it changes a window with 'winfixbuf' is set +func Test_pythonx_pyxdo() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + set winfixbuf + + pythonx << EOF +import vim + +def test_winfixbuf_Test_pythonx_pyxdo_set_buffer(): + buffer = vim.vars['_previous_buffer'] + vim.current.buffer = vim.buffers[buffer] +EOF + + try + pyxdo test_winfixbuf_Test_pythonx_pyxdo_set_buffer() + catch /Vim\%((\a\+)\)\=:E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + + unlet g:_previous_buffer +endfunc + +" Fail pyxfile if it changes a window with 'winfixbuf' is set +func Test_pythonx_pyxfile() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + set winfixbuf + + call writefile(["import vim", + \ "buffer = vim.vars['_previous_buffer']", + \ "vim.current.buffer = vim.buffers[buffer]", + \ ], + \ "file.py") + + try + pyxfile file.py + catch /Vim\%((\a\+)\)\=:E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + + call delete("file.py") + unlet g:_previous_buffer +endfunc + +" Fail vim.current.buffer if 'winfixbuf' is set +func Test_pythonx_vim_current_buffer() + CheckFeature pythonx + call s:reset_all_buffers() + + enew + file first + let g:_previous_buffer = bufnr() + + enew + file second + + let l:caught = 0 + + set winfixbuf + + try + pythonx << EOF +import vim + +buffer = vim.vars["_previous_buffer"] +vim.current.buffer = vim.buffers[buffer] +EOF + catch /Vim\%((\a\+)\)\=:E1513:/ + let l:caught = 1 + endtry + + call assert_equal(1, l:caught) + unlet g:_previous_buffer +endfunc + +" Ensure remapping to a disabled action still triggers failures +func Test_remap_key_fail() + call s:reset_all_buffers() + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + nnoremap g <C-^> + + call assert_fails("normal g", "E1513:") + call assert_equal(l:current, bufnr()) + + nunmap g +endfunc + +" Ensure remapping a disabled key to something valid does trigger any failures +func Test_remap_key_pass() + call s:reset_all_buffers() + + enew + file first + let l:first = bufnr() + + enew + file current + let l:current = bufnr() + + set winfixbuf + + call assert_fails("normal \<C-^>", "E1513:") + call assert_equal(l:current, bufnr()) + + " Disallow <C-^> by default but allow it if the command does something else + nnoremap <C-^> :echo "hello!" + + execute "normal \<C-^>" + call assert_equal(l:current, bufnr()) + + nunmap <C-^> +endfunc + +" Fail :rewind but :rewind! is allowed +func Test_rewind() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("rewind", "E1513:") + call assert_notequal(l:first, bufnr()) + + rewind! + call assert_equal(l:first, bufnr()) +endfunc + +" Allow :sblast because it opens the buffer in a new, split window +func Test_sblast() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs(1) + bfirst! + let l:current = bufnr() + + sblast + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :sbprevious but :sbprevious! is allowed +func Test_sbprevious() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + sbprevious + call assert_equal(l:other, bufnr()) +endfunc + +" Make sure 'winfixbuf' can be set using 'winfixbuf' or 'wfb' +func Test_short_option() + call s:reset_all_buffers() + + call s:make_buffer_pairs() + + set winfixbuf + call assert_fails("edit something_else", "E1513") + + set nowinfixbuf + set wfb + call assert_fails("edit another_place", "E1513") + + set nowfb + edit last_place +endfunc + +" Allow :snext because it makes a new window +func Test_snext() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + first! + + let l:current_window = win_getid() + + snext + call assert_notequal(l:current_window, win_getid()) + call assert_notequal(l:first, bufnr()) +endfunc + +" Ensure the first has 'winfixbuf' and a new split window is 'nowinfixbuf' +func Test_split_window() + call s:reset_all_buffers() + + split + execute "normal \<C-w>j" + + set winfixbuf + + let l:winfix_window_1 = win_getid() + vsplit + let l:winfix_window_2 = win_getid() + + call assert_equal(1, getwinvar(l:winfix_window_1, "&winfixbuf")) + call assert_equal(0, getwinvar(l:winfix_window_2, "&winfixbuf")) +endfunc + +" Fail :tNext but :tNext! is allowed +func Test_tNext() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags") + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") + call writefile(["thesame one"], "Xother") + edit Xother + + tag thesame + execute "normal \<C-^>" + tnext! + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tNext", "E1513:") + call assert_equal(l:current, bufnr()) + + tNext! + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Call :tabdo and choose the next available 'nowinfixbuf' window. +func Test_tabdo_choose_available_window() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + + " Make a split window that is 'nowinfixbuf' but make it the second-to-last + " window so that :tabdo will first try the 'winfixbuf' window, pass over it, + " and prefer the other 'nowinfixbuf' window, instead. + " + " +-------------------+ + " | 'nowinfixbuf' | + " +-------------------+ + " | 'winfixbuf' | <-- Cursor is here + " +-------------------+ + split + let l:nowinfixbuf_window = win_getid() + " Move to the 'winfixbuf' window now + execute "normal \<C-w>j" + let l:winfixbuf_window = win_getid() + + let l:expected_windows = s:get_windows_count() + tabdo echo '' + call assert_equal(l:nowinfixbuf_window, win_getid()) + call assert_equal(l:first, bufnr()) + call assert_equal(l:expected_windows, s:get_windows_count()) +endfunc + +" Call :tabdo and create a new split window if all available windows are 'winfixbuf'. +func Test_tabdo_make_new_window() + call s:reset_all_buffers() + + let [l:first, _] = s:make_buffers_list() + execute "buffer! " . l:first + + let l:current = win_getid() + let l:current_windows = s:get_windows_count() + + tabdo echo '' + call assert_notequal(l:current, win_getid()) + call assert_equal(l:first, bufnr()) + execute "normal \<C-w>j" + call assert_equal(l:first, bufnr()) + call assert_equal(l:current_windows + 1, s:get_windows_count()) +endfunc + +" Fail :tag but :tag! is allowed +func Test_tag() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tag one", "E1513:") + call assert_equal(l:current, bufnr()) + + tag! one + call assert_notequal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + + +" Fail :tfirst but :tfirst! is allowed +func Test_tfirst() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tfirst", "E1513:") + call assert_equal(l:current, bufnr()) + + tfirst! + call assert_notequal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail :tjump but :tjump! is allowed +func Test_tjump() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + call writefile(["one"], "Xother") + edit Xother + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tjump one", "E1513:") + call assert_equal(l:current, bufnr()) + + tjump! one + call assert_notequal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail :tlast but :tlast! is allowed +func Test_tlast() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "one\tXfile\t1", + \ "three\tXfile\t3", + \ "two\tXfile\t2"], + \ "Xtags") + call writefile(["one", "two", "three"], "Xfile") + edit Xfile + tjump one + edit Xfile + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tlast", "E1513:") + call assert_equal(l:current, bufnr()) + + tlast! + call assert_equal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") +endfunc + +" Fail :tnext but :tnext! is allowed +func Test_tnext() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags") + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") + call writefile(["thesame one"], "Xother") + edit Xother + + tag thesame + execute "normal \<C-^>" + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tnext", "E1513:") + call assert_equal(l:current, bufnr()) + + tnext! + call assert_notequal(l:current, bufnr()) + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail :tprevious but :tprevious! is allowed +func Test_tprevious() + call s:reset_all_buffers() + + set tags=Xtags + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "thesame\tXfile\t1;\"\td\tfile:", + \ "thesame\tXfile\t2;\"\td\tfile:", + \ "thesame\tXfile\t3;\"\td\tfile:", + \ ], + \ "Xtags") + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") + call writefile(["thesame one"], "Xother") + edit Xother + + tag thesame + execute "normal \<C-^>" + tnext! + + set winfixbuf + + let l:current = bufnr() + + call assert_fails("tprevious", "E1513:") + call assert_equal(l:current, bufnr()) + + tprevious! + + set tags& + call delete("Xtags") + call delete("Xfile") + call delete("Xother") +endfunc + +" Fail :view but :view! is allowed +func Test_view() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("view other", "E1513:") + call assert_equal(l:current, bufnr()) + + view! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :visual but :visual! is allowed +func Test_visual() + call s:reset_all_buffers() + + let l:other = s:make_buffer_pairs() + let l:current = bufnr() + + call assert_fails("visual other", "E1513:") + call assert_equal(l:current, bufnr()) + + visual! other + call assert_equal(l:other, bufnr()) +endfunc + +" Fail :vimgrep but :vimgrep! is allowed +func Test_vimgrep() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("vimgrep /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + " Don't error and also do swap to the first match because ! was included + vimgrep! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :vimgrepadd but ::vimgrepadd! is allowed +func Test_vimgrepadd() + CheckFeature quickfix + call s:reset_all_buffers() + + edit first.unittest + call append(0, ["some-search-term"]) + write + + edit winfix.unittest + call append(0, ["some-search-term"]) + write + let l:current = bufnr() + + set winfixbuf + + edit! last.unittest + call append(0, ["some-search-term"]) + write + let l:last = bufnr() + + buffer! winfix.unittest + + call assert_fails("vimgrepadd /some-search-term/ *.unittest") + call assert_equal(l:current, bufnr()) + + vimgrepadd! /some-search-term/ *.unittest + call assert_notequal(l:current, bufnr()) + call delete("first.unittest") + call delete("winfix.unittest") + call delete("last.unittest") +endfunc + +" Fail :wNext but :wNext! is allowed +func Test_wNext() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("wNext", "E1513:") + call assert_notequal(l:first, bufnr()) + + wNext! + call assert_equal(l:first, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +" Allow :windo unless `:windo foo` would change a 'winfixbuf' window's buffer +func Test_windo() + call s:reset_all_buffers() + + let l:current_window = win_getid() + let l:current_buffer = bufnr() + split + enew + file some_other_buffer + + set winfixbuf + + let l:current = win_getid() + + windo echo '' + call assert_equal(l:current_window, win_getid()) + + call assert_fails('execute "windo buffer ' . l:current_buffer . '"', "E1513:") + call assert_equal(l:current_window, win_getid()) + + execute "windo buffer! " . l:current_buffer + call assert_equal(l:current_window, win_getid()) +endfunc + +" Fail :wnext but :wnext! is allowed +func Test_wnext() + call s:reset_all_buffers() + + let [_, l:last] = s:make_args_list() + next! + + call assert_fails("wnext", "E1513:") + call assert_notequal(l:last, bufnr()) + + wnext! + call assert_equal(l:last, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +" Fail :wprevious but :wprevious! is allowed +func Test_wprevious() + call s:reset_all_buffers() + + let [l:first, _] = s:make_args_list() + next! + + call assert_fails("wprevious", "E1513:") + call assert_notequal(l:first, bufnr()) + + wprevious! + call assert_equal(l:first, bufnr()) + + call delete("first") + call delete("middle") + call delete("last") +endfunc + +func Test_quickfix_switchbuf_invalid_prevwin() + call s:reset_all_buffers() + + call s:make_simple_quickfix() + call assert_equal(1, getqflist(#{idx: 0}).idx) + + set switchbuf=uselast + split + copen + execute winnr('#') 'quit' + call assert_equal(2, winnr('$')) + + cnext " Would've triggered a null pointer member access + call assert_equal(2, getqflist(#{idx: 0}).idx) + + set switchbuf& +endfunc + +func Test_listdo_goto_prevwin() + call s:reset_all_buffers() + call s:make_buffers_list() + + new + call assert_equal(0, &winfixbuf) + wincmd p + call assert_equal(1, &winfixbuf) + call assert_notequal(bufnr(), bufnr('#')) + + augroup ListDoGotoPrevwin + au! + au BufLeave * let s:triggered = 1 + \| call assert_equal(bufnr(), winbufnr(winnr())) + augroup END + " Should correctly switch to the window without 'winfixbuf', and curbuf should + " be consistent with curwin->w_buffer for autocommands. + bufdo " + call assert_equal(0, &winfixbuf) + call assert_equal(1, s:triggered) + unlet! s:triggered + au! ListDoGotoPrevwin + + set winfixbuf + wincmd p + call assert_equal(2, winnr('$')) + " Both curwin and prevwin have 'winfixbuf' set, so should split a new window + " without it set. + bufdo " + call assert_equal(0, &winfixbuf) + call assert_equal(3, winnr('$')) + + quit + call assert_equal(2, winnr('$')) + call assert_equal(1, &winfixbuf) + augroup ListDoGotoPrevwin + au! + au WinEnter * ++once set winfixbuf + augroup END + " Same as before, but naughty autocommands set 'winfixbuf' for the new window. + " :bufdo should give up in this case. + call assert_fails('bufdo "', 'E1513:') + + au! ListDoGotoPrevwin + augroup! ListDoGotoPrevwin +endfunc + +func Test_quickfix_changed_split_failed() + call s:reset_all_buffers() + + call s:make_simple_quickfix() + call assert_equal(1, winnr('$')) + + " Quickfix code will open a split in an attempt to get a 'nowinfixbuf' window + " to switch buffers in. Interfere with things by setting 'winfixbuf' in it. + augroup QfChanged + au! + au WinEnter * ++once call assert_equal(2, winnr('$')) + \| set winfixbuf | call setqflist([], 'f') + augroup END + call assert_fails('cnext', ['E1513:', 'E925:']) + " Check that the split was automatically closed. + call assert_equal(1, winnr('$')) + + au! QfChanged + augroup! QfChanged +endfunc + +func Test_bufdo_cnext_splitwin_fails() + call s:reset_all_buffers() + call s:make_simple_quickfix() + call assert_equal(1, getqflist(#{idx: 0}).idx) + " Make sure there is not enough room to + " split the winfixedbuf window + let &winheight=&lines + let &winminheight=&lines-2 + " Still want E1513, or it may not be clear why a split was attempted and why + " it failing caused the commands to abort. + call assert_fails(':bufdo echo 1', ['E36:', 'E1513:']) + call assert_fails(':cnext', ['E36:', 'E1513:']) + " Ensure the entry didn't change. + call assert_equal(1, getqflist(#{idx: 0}).idx) + set winminheight&vim winheight&vim +endfunc + +" vim: shiftwidth=2 sts=2 expandtab |