Mercurial > vim
view src/testdir/test_expr.vim @ 34686:83875247fbc0 v9.1.0224
patch 9.1.0224: cursor may move too many lines over "right" & "below" virt text
Commit: https://github.com/vim/vim/commit/515f734e687f28f7199b2a8042197624d9f3ec15
Author: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Date: Thu Mar 28 12:01:14 2024 +0100
patch 9.1.0224: cursor may move too many lines over "right" & "below" virt text
Problem: If a line has "right" & "below" virtual text properties,
where the "below" property may be stored first due to lack of
ordering between them, then the line height is calculated to
be 1 more and causes the cursor to far over the line.
Solution: Remove some unnecessary setting of a
`next_right_goes_below = TRUE` flag for "below" and "above"
text properties. (Dylan Thacker-Smith)
I modified a regression test I recently added to cover this case,
leveraging the fact that "after", "right" & "below" text properties are
being stored in the reverse of the order they are added in. The
previous version of this regression test was crafted to workaround this
issue so it can be addressed by this separate patch.
closes: #14317
Signed-off-by: Dylan Thacker-Smith <dylan.ah.smith@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 28 Mar 2024 12:15:03 +0100 |
parents | 4635e43f2c6f |
children | 1e6f45f5ca23 |
line wrap: on
line source
" Tests for expressions. source check.vim import './vim9.vim' as v9 func Test_equal() let base = {} func base.method() return 1 endfunc func base.other() dict return 1 endfunc let instance = copy(base) call assert_true(base.method == instance.method) call assert_true([base.method] == [instance.method]) call assert_true(base.other == instance.other) call assert_true([base.other] == [instance.other]) call assert_false(base.method == base.other) call assert_false([base.method] == [base.other]) call assert_false(base.method == instance.other) call assert_false([base.method] == [instance.other]) call assert_fails('echo base.method > instance.method') call assert_equal(0, test_null_function() == function('min')) call assert_equal(1, test_null_function() == test_null_function()) call assert_fails('eval 10 == test_unknown()', ['E340:', 'E685:']) endfunc func Test_version() call assert_true(has('patch-7.4.001')) call assert_true(has('patch-7.4.01')) call assert_true(has('patch-7.4.1')) call assert_true(has('patch-6.9.999')) call assert_true(has('patch-7.1.999')) call assert_true(has('patch-7.4.123')) call assert_true(has('patch-7.4.123 ')) " Trailing space can be allowed. call assert_true(has('patch-9.1.0')) call assert_true(has('patch-9.1.0000')) call assert_false(has('patch-7')) call assert_false(has('patch-7.4')) call assert_false(has('patch-7.4.')) call assert_false(has('patch-9.2.0')) call assert_false(has('patch-9.9.1')) call assert_false(has('patch-abc')) call assert_false(has('patchabc')) call assert_false(has('patch-8x001')) call assert_false(has('patch-9X0X0')) call assert_false(has('patch-9-0-0')) call assert_false(has('patch-09.0.0')) call assert_false(has('patch-9.00.0')) endfunc func Test_op_ternary() let lines =<< trim END call assert_equal('yes', 1 ? 'yes' : 'no') call assert_equal('no', 0 ? 'yes' : 'no') call assert_fails('echo [1] ? "yes" : "no"', 'E745:') call assert_fails('echo {} ? "yes" : "no"', 'E728:') END call v9.CheckLegacyAndVim9Success(lines) call assert_equal('no', 'x' ? 'yes' : 'no') call v9.CheckDefAndScriptFailure(["'x' ? 'yes' : 'no'"], 'E1135:') call assert_equal('yes', '1x' ? 'yes' : 'no') call v9.CheckDefAndScriptFailure(["'1x' ? 'yes' : 'no'"], 'E1135:') endfunc func Test_op_falsy() let lines =<< trim END call assert_equal(v:true, v:true ?? 456) call assert_equal(123, 123 ?? 456) call assert_equal('yes', 'yes' ?? 456) call assert_equal(0z00, 0z00 ?? 456) call assert_equal([1], [1] ?? 456) call assert_equal({'one': 1}, {'one': 1} ?? 456) call assert_equal(0.1, 0.1 ?? 456) call assert_equal(456, v:false ?? 456) call assert_equal(456, 0 ?? 456) call assert_equal(456, '' ?? 456) call assert_equal(456, 0z ?? 456) call assert_equal(456, [] ?? 456) call assert_equal(456, {} ?? 456) call assert_equal(456, 0.0 ?? 456) call assert_equal(456, v:null ?? 456) call assert_equal(456, v:none ?? 456) call assert_equal(456, test_null_string() ?? 456) call assert_equal(456, test_null_blob() ?? 456) call assert_equal(456, test_null_list() ?? 456) call assert_equal(456, test_null_dict() ?? 456) call assert_equal(456, test_null_function() ?? 456) call assert_equal(456, test_null_partial() ?? 456) if has('job') call assert_equal(456, test_null_job() ?? 456) endif if has('channel') call assert_equal(456, test_null_channel() ?? 456) endif END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_dict() let lines =<< trim END VAR d = {'': 'empty', 'a': 'a', 0: 'zero'} call assert_equal('empty', d['']) call assert_equal('a', d['a']) call assert_equal('zero', d[0]) call assert_true(has_key(d, '')) call assert_true(has_key(d, 'a')) LET d[''] = 'none' LET d['a'] = 'aaa' call assert_equal('none', d['']) call assert_equal('aaa', d['a']) LET d[ 'b' ] = 'bbb' call assert_equal('bbb', d[ 'b' ]) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(["VAR i = has_key([], 'a')"], ['E1206:', 'E1013:', 'E1206:']) endfunc func Test_strgetchar() let lines =<< trim END call assert_equal(char2nr('a'), strgetchar('axb', 0)) call assert_equal(char2nr('x'), 'axb'->strgetchar(1)) call assert_equal(char2nr('b'), strgetchar('axb', 2)) call assert_equal(-1, strgetchar('axb', -1)) call assert_equal(-1, strgetchar('axb', 3)) call assert_equal(-1, strgetchar('', 0)) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(["VAR c = strgetchar([], 1)"], ['E730:', 'E1013:', 'E1174:']) call v9.CheckLegacyAndVim9Failure(["VAR c = strgetchar('axb', [])"], ['E745:', 'E1013:', 'E1210:']) endfunc func Test_strcharpart() let lines =<< trim END call assert_equal('a', strcharpart('axb', 0, 1)) call assert_equal('x', 'axb'->strcharpart(1, 1)) call assert_equal('b', strcharpart('axb', 2, 1)) call assert_equal('xb', strcharpart('axb', 1)) call assert_equal('', strcharpart('axb', 1, 0)) call assert_equal('', strcharpart('axb', 1, -1)) call assert_equal('', strcharpart('axb', -1, 1)) call assert_equal('', strcharpart('axb', -2, 2)) call assert_equal('a', strcharpart('axb', -1, 2)) call assert_equal('edit', "editor"[-10 : 3]) END call v9.CheckLegacyAndVim9Success(lines) call assert_fails('call strcharpart("", 0, 0, {})', ['E728:', 'E728:']) call assert_fails('call strcharpart("", 0, 0, -1)', ['E1023:', 'E1023:']) endfunc func Test_getreg_empty_list() let lines =<< trim END call assert_equal('', getreg('x')) call assert_equal([], getreg('x', 1, 1)) VAR x = getreg('x', 1, 1) VAR y = x call add(x, 'foo') call assert_equal(['foo'], y) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(['call getreg([])'], ['E730:', 'E1013:', 'E1174:']) endfunc func Test_loop_over_null_list() let lines =<< trim END VAR nulllist = test_null_list() for i in nulllist call assert_report('should not get here') endfor END call v9.CheckLegacyAndVim9Success(lines) let lines =<< trim END var nulllist = null_list for i in nulllist call assert_report('should not get here') endfor END call v9.CheckDefAndScriptSuccess(lines) let lines =<< trim END let nulllist = null_list for i in nulllist call assert_report('should not get here') endfor END call v9.CheckScriptFailure(lines, 'E121: Undefined variable: null_list') endfunc func Test_compare_with_null() let s:value = v:null call assert_true(s:value == v:null) let s:value = v:true call assert_false(s:value == v:null) let s:value = v:none call assert_false(s:value == v:null) let s:value = 0 call assert_true(s:value == v:null) let s:value = 0.0 call assert_true(s:value == v:null) let s:value = '' call assert_false(s:value == v:null) let s:value = 0z call assert_false(s:value == v:null) let s:value = [] call assert_false(s:value == v:null) let s:value = {} call assert_false(s:value == v:null) let s:value = function('len') call assert_false(s:value == v:null) if has('job') let s:value = test_null_job() call assert_true(s:value == v:null) let s:value = test_null_channel() call assert_true(s:value == v:null) endif unlet s:value endfunc func Test_setreg_null_list() let lines =<< trim END call setreg('x', test_null_list()) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_special_char() " The failure is only visible using valgrind. call v9.CheckLegacyAndVim9Failure(['echo "\<C-">'], ['E15:', 'E1004:', 'E1004:']) endfunc func Test_method_with_prefix() let lines =<< trim END call assert_equal(TRUE, !range(5)->empty()) call assert_equal(FALSE, !-3) END call v9.CheckLegacyAndVim9Success(lines) call assert_equal([0, 1, 2], --3->range()) call v9.CheckDefAndScriptFailure(['eval --3->range()'], 'E15') call assert_equal(1, !+-+0) call v9.CheckDefAndScriptFailure(['eval !+-+0'], 'E15') endfunc func Test_option_value() let lines =<< trim END #" boolean set bri call assert_equal(TRUE, &bri) set nobri call assert_equal(FALSE, &bri) #" number set ts=1 call assert_equal(1, &ts) set ts=8 call assert_equal(8, &ts) #" string exe "set cedit=\<Esc>" call assert_equal("\<Esc>", &cedit) set cpo= call assert_equal("", &cpo) set cpo=abcdefgi call assert_equal("abcdefgi", &cpo) set cpo&vim END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_printf_misc() let lines =<< trim END call assert_equal('123', printf('123')) call assert_equal('', printf('%')) call assert_equal('', printf('%.0d', 0)) call assert_equal('123', printf('%d', 123)) call assert_equal('123', printf('%i', 123)) call assert_equal('123', printf('%D', 123)) call assert_equal('123', printf('%U', 123)) call assert_equal('173', printf('%o', 123)) call assert_equal('173', printf('%O', 123)) call assert_equal('7b', printf('%x', 123)) call assert_equal('7B', printf('%X', 123)) call assert_equal('123', printf('%hd', 123)) call assert_equal('-123', printf('%hd', -123)) call assert_equal('-1', printf('%hd', 0xFFFF)) call assert_equal('-1', printf('%hd', 0x1FFFFF)) call assert_equal('123', printf('%hu', 123)) call assert_equal('65413', printf('%hu', -123)) call assert_equal('65535', printf('%hu', 0xFFFF)) call assert_equal('65535', printf('%hu', 0x1FFFFF)) call assert_equal('123', printf('%ld', 123)) call assert_equal('-123', printf('%ld', -123)) call assert_equal('65535', printf('%ld', 0xFFFF)) call assert_equal('131071', printf('%ld', 0x1FFFF)) call assert_equal('{', printf('%c', 123)) call assert_equal('abc', printf('%s', 'abc')) call assert_equal('abc', printf('%S', 'abc')) call assert_equal('+123', printf('%+d', 123)) call assert_equal('-123', printf('%+d', -123)) call assert_equal('+123', printf('%+ d', 123)) call assert_equal(' 123', printf('% d', 123)) call assert_equal(' 123', printf('% d', 123)) call assert_equal('-123', printf('% d', -123)) call assert_equal('123', printf('%2d', 123)) call assert_equal(' 123', printf('%6d', 123)) call assert_equal('000123', printf('%06d', 123)) call assert_equal('+00123', printf('%+06d', 123)) call assert_equal(' 00123', printf('% 06d', 123)) call assert_equal(' +123', printf('%+6d', 123)) call assert_equal(' 123', printf('% 6d', 123)) call assert_equal(' -123', printf('% 6d', -123)) #" Test left adjusted. call assert_equal('123 ', printf('%-6d', 123)) call assert_equal('+123 ', printf('%-+6d', 123)) call assert_equal(' 123 ', printf('%- 6d', 123)) call assert_equal('-123 ', printf('%- 6d', -123)) call assert_equal(' 00123', printf('%7.5d', 123)) call assert_equal(' -00123', printf('%7.5d', -123)) call assert_equal(' +00123', printf('%+7.5d', 123)) #" Precision field should not be used when combined with %0 call assert_equal(' 00123', printf('%07.5d', 123)) call assert_equal(' -00123', printf('%07.5d', -123)) call assert_equal(' 123', printf('%*d', 5, 123)) call assert_equal('123 ', printf('%*d', -5, 123)) call assert_equal('00123', printf('%.*d', 5, 123)) call assert_equal(' 123', printf('% *d', 5, 123)) call assert_equal(' +123', printf('%+ *d', 5, 123)) call assert_equal('foobar', printf('%.*s', 9, 'foobar')) call assert_equal('foo', printf('%.*s', 3, 'foobar')) call assert_equal('', printf('%.*s', 0, 'foobar')) call assert_equal('foobar', printf('%.*s', -1, 'foobar')) #" Simple quote (thousand grouping char) is ignored. call assert_equal('+00123456', printf("%+'09d", 123456)) #" Unrecognized format specifier kept as-is. call assert_equal('_123', printf("%_%d", 123)) #" Test alternate forms. call assert_equal('0x7b', printf('%#x', 123)) call assert_equal('0X7B', printf('%#X', 123)) call assert_equal('0173', printf('%#o', 123)) call assert_equal('0173', printf('%#O', 123)) call assert_equal('abc', printf('%#s', 'abc')) call assert_equal('abc', printf('%#S', 'abc')) call assert_equal(' 0173', printf('%#6o', 123)) call assert_equal(' 00173', printf('%#6.5o', 123)) call assert_equal(' 0173', printf('%#6.2o', 123)) call assert_equal(' 0173', printf('%#6.2o', 123)) call assert_equal('0173', printf('%#2.2o', 123)) call assert_equal(' 00123', printf('%6.5d', 123)) call assert_equal(' 0007b', printf('%6.5x', 123)) call assert_equal('123', printf('%.2d', 123)) call assert_equal('0123', printf('%.4d', 123)) call assert_equal('0000000123', printf('%.10d', 123)) call assert_equal('123', printf('%.0d', 123)) call assert_equal('abc', printf('%2s', 'abc')) call assert_equal('abc', printf('%2S', 'abc')) call assert_equal('abc', printf('%.4s', 'abc')) call assert_equal('abc', printf('%.4S', 'abc')) call assert_equal('ab', printf('%.2s', 'abc')) call assert_equal('ab', printf('%.2S', 'abc')) call assert_equal('', printf('%.0s', 'abc')) call assert_equal('', printf('%.s', 'abc')) call assert_equal(' abc', printf('%4s', 'abc')) call assert_equal(' abc', printf('%4S', 'abc')) call assert_equal('0abc', printf('%04s', 'abc')) call assert_equal('0abc', printf('%04S', 'abc')) call assert_equal('abc ', printf('%-4s', 'abc')) call assert_equal('abc ', printf('%-4S', 'abc')) call assert_equal('π', printf('%.2S', 'ππ')) call assert_equal('', printf('%.1S', 'ππ')) call assert_equal('[ γγγ]', printf('[%10.6S]', 'γγγγγ')) call assert_equal('[ γγγγ]', printf('[%10.8S]', 'γγγγγ')) call assert_equal('[γγγγγ]', printf('[%10.10S]', 'γγγγγ')) call assert_equal('[γγγγγ]', printf('[%10.12S]', 'γγγγγ')) call assert_equal('γγγ', printf('%S', 'γγγ')) call assert_equal('γγγ', printf('%#S', 'γγγ')) call assert_equal('γb', printf('%2S', 'γb')) call assert_equal('γb', printf('%.4S', 'γb')) call assert_equal('γ', printf('%.2S', 'γb')) call assert_equal(' γb', printf('%4S', 'γb')) call assert_equal('0γb', printf('%04S', 'γb')) call assert_equal('γb ', printf('%-4S', 'γb')) call assert_equal('γ ', printf('%-4.2S', 'γb')) call assert_equal('aγ', printf('%2S', 'aγ')) call assert_equal('aγ', printf('%.4S', 'aγ')) call assert_equal('a', printf('%.2S', 'aγ')) call assert_equal(' aγ', printf('%4S', 'aγ')) call assert_equal('0aγ', printf('%04S', 'aγ')) call assert_equal('aγ ', printf('%-4S', 'aγ')) call assert_equal('a ', printf('%-4.2S', 'aγ')) call assert_equal('[γγγ]', printf('[%05S]', 'γγγ')) call assert_equal('[γγγ]', printf('[%06S]', 'γγγ')) call assert_equal('[0γγγ]', printf('[%07S]', 'γγγ')) call assert_equal('[γiγ]', printf('[%05S]', 'γiγ')) call assert_equal('[0γiγ]', printf('[%06S]', 'γiγ')) call assert_equal('[00γiγ]', printf('[%07S]', 'γiγ')) call assert_equal('[0γγ]', printf('[%05.4S]', 'γγγ')) call assert_equal('[00γγ]', printf('[%06.4S]', 'γγγ')) call assert_equal('[000γγ]', printf('[%07.4S]', 'γγγ')) call assert_equal('[00γi]', printf('[%05.4S]', 'γiγ')) call assert_equal('[000γi]', printf('[%06.4S]', 'γiγ')) call assert_equal('[0000γi]', printf('[%07.4S]', 'γiγ')) call assert_equal('[0γγ]', printf('[%05.5S]', 'γγγ')) call assert_equal('[00γγ]', printf('[%06.5S]', 'γγγ')) call assert_equal('[000γγ]', printf('[%07.5S]', 'γγγ')) call assert_equal('[γiγ]', printf('[%05.5S]', 'γiγ')) call assert_equal('[0γiγ]', printf('[%06.5S]', 'γiγ')) call assert_equal('[00γiγ]', printf('[%07.5S]', 'γiγ')) call assert_equal('[0000000000]', printf('[%010.0S]', 'γγγ')) call assert_equal('[0000000000]', printf('[%010.1S]', 'γγγ')) call assert_equal('[00000000γ]', printf('[%010.2S]', 'γγγ')) call assert_equal('[00000000γ]', printf('[%010.3S]', 'γγγ')) call assert_equal('[000000γγ]', printf('[%010.4S]', 'γγγ')) call assert_equal('[000000γγ]', printf('[%010.5S]', 'γγγ')) call assert_equal('[0000γγγ]', printf('[%010.6S]', 'γγγ')) call assert_equal('[0000γγγ]', printf('[%010.7S]', 'γγγ')) call assert_equal('[0000000000]', printf('[%010.1S]', 'γiγ')) call assert_equal('[00000000γ]', printf('[%010.2S]', 'γiγ')) call assert_equal('[0000000γi]', printf('[%010.3S]', 'γiγ')) call assert_equal('[0000000γi]', printf('[%010.4S]', 'γiγ')) call assert_equal('[00000γiγ]', printf('[%010.5S]', 'γiγ')) call assert_equal('[00000γiγ]', printf('[%010.6S]', 'γiγ')) call assert_equal('[00000γiγ]', printf('[%010.7S]', 'γiγ')) call assert_equal('1%', printf('%d%%', 1)) call assert_notequal('', printf('%p', "abc")) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(["call printf('123', 3)"], "E767:") " this was using uninitialized memory call v9.CheckLegacyAndVim9Failure(["eval ''->printf()"], "E119:") endfunc func Test_printf_float() let lines =<< trim END call assert_equal('1.000000', printf('%f', 1)) call assert_equal('1.230000', printf('%f', 1.23)) call assert_equal('1.230000', printf('%F', 1.23)) call assert_equal('9999999.9', printf('%g', 9999999.9)) call assert_equal('9999999.9', printf('%G', 9999999.9)) call assert_equal('1.00000001e7', printf('%.8g', 10000000.1)) call assert_equal('1.00000001E7', printf('%.8G', 10000000.1)) call assert_equal('1.230000e+00', printf('%e', 1.23)) call assert_equal('1.230000E+00', printf('%E', 1.23)) call assert_equal('1.200000e-02', printf('%e', 0.012)) call assert_equal('-1.200000e-02', printf('%e', -0.012)) call assert_equal('0.33', printf('%.2f', 1.0 / 3.0)) call assert_equal(' 0.33', printf('%6.2f', 1.0 / 3.0)) call assert_equal(' -0.33', printf('%6.2f', -1.0 / 3.0)) call assert_equal('000.33', printf('%06.2f', 1.0 / 3.0)) call assert_equal('-00.33', printf('%06.2f', -1.0 / 3.0)) call assert_equal('-00.33', printf('%+06.2f', -1.0 / 3.0)) call assert_equal('+00.33', printf('%+06.2f', 1.0 / 3.0)) call assert_equal(' 00.33', printf('% 06.2f', 1.0 / 3.0)) call assert_equal('000.33', printf('%06.2g', 1.0 / 3.0)) call assert_equal('-00.33', printf('%06.2g', -1.0 / 3.0)) call assert_equal('0.33', printf('%3.2f', 1.0 / 3.0)) call assert_equal('003.33e-01', printf('%010.2e', 1.0 / 3.0)) call assert_equal(' 03.33e-01', printf('% 010.2e', 1.0 / 3.0)) call assert_equal('+03.33e-01', printf('%+010.2e', 1.0 / 3.0)) call assert_equal('-03.33e-01', printf('%010.2e', -1.0 / 3.0)) #" When precision is 0, the dot should be omitted. call assert_equal(' 2', printf('%3.f', 7.0 / 3.0)) call assert_equal(' 2', printf('%3.g', 7.0 / 3.0)) call assert_equal(' 2e+00', printf('%7.e', 7.0 / 3.0)) #" Float zero can be signed. call assert_equal('+0.000000', printf('%+f', 0.0)) call assert_equal('0.000000', printf('%f', 1.0 / (1.0 / 0.0))) call assert_equal('-0.000000', printf('%f', 1.0 / (-1.0 / 0.0))) call assert_equal('0.0', printf('%s', 1.0 / (1.0 / 0.0))) call assert_equal('-0.0', printf('%s', 1.0 / (-1.0 / 0.0))) call assert_equal('0.0', printf('%S', 1.0 / (1.0 / 0.0))) call assert_equal('-0.0', printf('%S', 1.0 / (-1.0 / 0.0))) #" Float infinity can be signed. call assert_equal('inf', printf('%f', 1.0 / 0.0)) call assert_equal('-inf', printf('%f', -1.0 / 0.0)) call assert_equal('inf', printf('%g', 1.0 / 0.0)) call assert_equal('-inf', printf('%g', -1.0 / 0.0)) call assert_equal('inf', printf('%e', 1.0 / 0.0)) call assert_equal('-inf', printf('%e', -1.0 / 0.0)) call assert_equal('INF', printf('%F', 1.0 / 0.0)) call assert_equal('-INF', printf('%F', -1.0 / 0.0)) call assert_equal('INF', printf('%E', 1.0 / 0.0)) call assert_equal('-INF', printf('%E', -1.0 / 0.0)) call assert_equal('INF', printf('%E', 1.0 / 0.0)) call assert_equal('-INF', printf('%G', -1.0 / 0.0)) call assert_equal('+inf', printf('%+f', 1.0 / 0.0)) call assert_equal('-inf', printf('%+f', -1.0 / 0.0)) call assert_equal(' inf', printf('% f', 1.0 / 0.0)) call assert_equal(' inf', printf('%6f', 1.0 / 0.0)) call assert_equal(' -inf', printf('%6f', -1.0 / 0.0)) call assert_equal(' inf', printf('%6g', 1.0 / 0.0)) call assert_equal(' -inf', printf('%6g', -1.0 / 0.0)) call assert_equal(' +inf', printf('%+6f', 1.0 / 0.0)) call assert_equal(' inf', printf('% 6f', 1.0 / 0.0)) call assert_equal(' +inf', printf('%+06f', 1.0 / 0.0)) call assert_equal('inf ', printf('%-6f', 1.0 / 0.0)) call assert_equal('-inf ', printf('%-6f', -1.0 / 0.0)) call assert_equal('+inf ', printf('%-+6f', 1.0 / 0.0)) call assert_equal(' inf ', printf('%- 6f', 1.0 / 0.0)) call assert_equal('-INF ', printf('%-6F', -1.0 / 0.0)) call assert_equal('+INF ', printf('%-+6F', 1.0 / 0.0)) call assert_equal(' INF ', printf('%- 6F', 1.0 / 0.0)) call assert_equal('INF ', printf('%-6G', 1.0 / 0.0)) call assert_equal('-INF ', printf('%-6G', -1.0 / 0.0)) call assert_equal('INF ', printf('%-6E', 1.0 / 0.0)) call assert_equal('-INF ', printf('%-6E', -1.0 / 0.0)) call assert_equal('inf', printf('%s', 1.0 / 0.0)) call assert_equal('-inf', printf('%s', -1.0 / 0.0)) #" Test special case where max precision is truncated at 340. call assert_equal('1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', printf('%.330f', 1.0)) call assert_equal('1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', printf('%.340f', 1.0)) call assert_equal('1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', printf('%.350f', 1.0)) #" Float nan (not a number) has no sign. call assert_equal('nan', printf('%f', sqrt(-1.0))) call assert_equal('nan', printf('%f', 0.0 / 0.0)) call assert_equal('nan', printf('%f', -0.0 / 0.0)) call assert_equal('nan', printf('%g', 0.0 / 0.0)) call assert_equal('nan', printf('%e', 0.0 / 0.0)) call assert_equal('NAN', printf('%F', 0.0 / 0.0)) call assert_equal('NAN', printf('%G', 0.0 / 0.0)) call assert_equal('NAN', printf('%E', 0.0 / 0.0)) call assert_equal('NAN', printf('%F', -0.0 / 0.0)) call assert_equal('NAN', printf('%G', -0.0 / 0.0)) call assert_equal('NAN', printf('%E', -0.0 / 0.0)) call assert_equal(' nan', printf('%6f', 0.0 / 0.0)) call assert_equal(' nan', printf('%06f', 0.0 / 0.0)) call assert_equal('nan ', printf('%-6f', 0.0 / 0.0)) call assert_equal('nan ', printf('%- 6f', 0.0 / 0.0)) call assert_equal('nan', printf('%s', 0.0 / 0.0)) call assert_equal('nan', printf('%s', -0.0 / 0.0)) call assert_equal('nan', printf('%S', 0.0 / 0.0)) call assert_equal('nan', printf('%S', -0.0 / 0.0)) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') endfunc func Test_printf_errors() call v9.CheckLegacyAndVim9Failure(['echo printf("%d", {})'], 'E728:') call v9.CheckLegacyAndVim9Failure(['echo printf("%d", [])'], 'E745:') call v9.CheckLegacyAndVim9Failure(['echo printf("%d", 1, 2)'], 'E767:') call v9.CheckLegacyAndVim9Failure(['echo printf("%*d", 1)'], 'E766:') call v9.CheckLegacyAndVim9Failure(['echo printf("%s")'], 'E766:') call v9.CheckLegacyAndVim9Failure(['echo printf("%d", 1.2)'], 'E805:') call v9.CheckLegacyAndVim9Failure(['echo printf("%f")'], 'E766:') endfunc func Test_printf_64bit() let lines =<< trim END call assert_equal("123456789012345", printf('%d', 123456789012345)) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_printf_spec_s() let lines =<< trim END #" number call assert_equal("1234567890", printf('%s', 1234567890)) #" string call assert_equal("abcdefgi", printf('%s', "abcdefgi")) #" float call assert_equal("1.23", printf('%s', 1.23)) #" list VAR lvalue = [1, 'two', ['three', 4]] call assert_equal(string(lvalue), printf('%s', lvalue)) #" dict VAR dvalue = {'key1': 'value1', 'key2': ['list', 'lvalue'], 'key3': {'dict': 'lvalue'}} call assert_equal(string(dvalue), printf('%s', dvalue)) #" funcref call assert_equal('printf', printf('%s', 'printf'->function())) #" partial call assert_equal(string(function('printf', ['%s'])), printf('%s', function('printf', ['%s']))) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_printf_spec_b() let lines =<< trim END call assert_equal("0", printf('%b', 0)) call assert_equal("00001100", printf('%08b', 12)) call assert_equal("11111111", printf('%08b', 0xff)) call assert_equal(" 1111011", printf('%10b', 123)) call assert_equal("0001111011", printf('%010b', 123)) call assert_equal(" 0b1111011", printf('%#10b', 123)) call assert_equal("0B01111011", printf('%#010B', 123)) call assert_equal("1001001100101100000001011010010", printf('%b', 1234567890)) call assert_equal("11100000100100010000110000011011101111101111001", printf('%b', 123456789012345)) call assert_equal("1111111111111111111111111111111111111111111111111111111111111111", printf('%b', -1)) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_max_min_errors() call v9.CheckLegacyAndVim9Failure(['call max(v:true)'], ['E712:', 'E1013:', 'E1227:']) call v9.CheckLegacyAndVim9Failure(['call max(v:true)'], ['max()', 'E1013:', 'E1227:']) call v9.CheckLegacyAndVim9Failure(['call min(v:true)'], ['E712:', 'E1013:', 'E1227:']) call v9.CheckLegacyAndVim9Failure(['call min(v:true)'], ['min()', 'E1013:', 'E1227:']) endfunc func Test_function_with_funcref() let lines =<< trim END let s:F = function('type') let s:Fref = function(s:F) call assert_equal(v:t_string, s:Fref('x')) call assert_fails("call function('s:F')", 'E700:') call assert_fails("call function('foo()')", 'E475:') call assert_fails("call function('foo()')", 'foo()') call assert_fails("function('')", 'E129:') let s:Len = {s -> strlen(s)} call assert_equal(6, s:Len('foobar')) let name = string(s:Len) " can evaluate "function('<lambda>99')" call execute('let Ref = ' .. name) call assert_equal(4, Ref('text')) END call v9.CheckScriptSuccess(lines) let lines =<< trim END vim9script var F = function('type') var Fref = function(F) call assert_equal(v:t_string, Fref('x')) call assert_fails("call function('F')", 'E700:') call assert_fails("call function('foo()')", 'E475:') call assert_fails("call function('foo()')", 'foo()') call assert_fails("function('')", 'E129:') var Len = (s) => strlen(s) call assert_equal(6, Len('foobar')) var name = string(Len) # can evaluate "function('<lambda>99')" call execute('var Ref = ' .. name) call assert_equal(4, Ref('text')) END call v9.CheckScriptSuccess(lines) endfunc func Test_funcref() func! One() return 1 endfunc let OneByName = function('One') let OneByRef = funcref('One') func! One() return 2 endfunc call assert_equal(2, OneByName()) call assert_equal(1, OneByRef()) let OneByRef = 'One'->funcref() call assert_equal(2, OneByRef()) call assert_fails('echo funcref("{")', 'E475:') let OneByRef = funcref("One", repeat(["foo"], 20)) call assert_fails('let OneByRef = funcref("One", repeat(["foo"], 21))', 'E118:') call assert_fails('echo function("min") =~ function("min")', 'E694:') call assert_fails('echo test_null_function()->funcref()', 'E475: Invalid argument: NULL') endfunc " Test for calling function() and funcref() outside of a Vim script context. func Test_function_outside_script() let cleanup =<< trim END call writefile([execute('messages')], 'Xtest.out') qall END call writefile(cleanup, 'Xverify.vim', 'D') call RunVim([], [], "-c \"echo function('s:abc')\" -S Xverify.vim") call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0]) call RunVim([], [], "-c \"echo funcref('s:abc')\" -S Xverify.vim") call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0]) call delete('Xtest.out') endfunc func Test_setmatches() let lines =<< trim END hi def link 1 Comment hi def link 2 PreProc VAR set = [{"group": 1, "pattern": 2, "id": 3, "priority": 4}] VAR exp = [{"group": '1', "pattern": '2', "id": 3, "priority": 4}] if has('conceal') LET set[0]['conceal'] = 5 LET exp[0]['conceal'] = '5' endif eval set->setmatches() call assert_equal(exp, getmatches()) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(['VAR m = setmatches([], [])'], ['E745:', 'E1013:', 'E1210:']) endfunc func Test_empty_concatenate() let lines =<< trim END call assert_equal('b', 'a'[4 : 0] .. 'b') call assert_equal('b', 'b' .. 'a'[4 : 0]) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_broken_number() call v9.CheckLegacyAndVim9Failure(['VAR X = "bad"', 'echo 1X'], 'E15:') call v9.CheckLegacyAndVim9Failure(['VAR X = "bad"', 'echo 0b1X'], 'E15:') call v9.CheckLegacyAndVim9Failure(['echo 0b12'], 'E15:') call v9.CheckLegacyAndVim9Failure(['VAR X = "bad"', 'echo 0x1X'], 'E15:') call v9.CheckLegacyAndVim9Failure(['VAR X = "bad"', 'echo 011X'], 'E15:') call v9.CheckLegacyAndVim9Success(['call assert_equal(2, str2nr("2a"))']) call v9.CheckLegacyAndVim9Failure(['inoremap <Char-0b1z> b'], 'E474:') endfunc func Test_eval_after_if() let s:val = '' func SetVal(x) let s:val ..= a:x endfunc if 0 | eval SetVal('a') | endif | call SetVal('b') call assert_equal('b', s:val) endfunc func Test_divide_by_zero() " only tests that this doesn't crash, the result is not important echo 0 / 0 echo 0 / 0 / -1 endfunc " Test for command-line completion of expressions func Test_expr_completion() CheckFeature cmdline_compl for cmd in [ \ 'let a = ', \ 'const a = ', \ 'if', \ 'elseif', \ 'while', \ 'for', \ 'echo', \ 'echon', \ 'execute', \ 'echomsg', \ 'echoerr', \ 'call', \ 'return', \ 'cexpr', \ 'caddexpr', \ 'cgetexpr', \ 'lexpr', \ 'laddexpr', \ 'lgetexpr'] call feedkeys(":" . cmd . " getl\<Tab>\<Home>\"\<CR>", 'xt') call assert_equal('"' . cmd . ' getline(', getreg(':')) endfor " completion for the expression register call feedkeys(":\"\<C-R>=float2\t\"\<C-B>\"\<CR>", 'xt') call assert_equal('"float2nr("', @=) " completion for window local variables let w:wvar1 = 10 let w:wvar2 = 10 call feedkeys(":echo w:wvar\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo w:wvar1 w:wvar2', @:) unlet w:wvar1 w:wvar2 " completion for tab local variables let t:tvar1 = 10 let t:tvar2 = 10 call feedkeys(":echo t:tvar\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo t:tvar1 t:tvar2', @:) unlet t:tvar1 t:tvar2 " completion for variables let g:tvar1 = 1 let g:tvar2 = 2 call feedkeys(":let g:tv\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"let g:tvar1 g:tvar2', @:) " completion for variables after a || call feedkeys(":echo 1 || g:tv\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo 1 || g:tvar1 g:tvar2', @:) " completion for options call feedkeys(":echo &compat\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo &compatible', @:) call feedkeys(":echo 1 && &compat\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo 1 && &compatible', @:) call feedkeys(":echo &g:equala\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal('"echo &g:equalalways', @:) " completion for string call feedkeys(":echo \"Hello\\ World\"\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal("\"echo \"Hello\\ World\"\<C-A>", @:) call feedkeys(":echo 'Hello World'\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal("\"echo 'Hello World'\<C-A>", @:) " completion for command after a | call feedkeys(":echo 'Hello' | cwin\<C-A>\<C-B>\"\<CR>", 'xt') call assert_equal("\"echo 'Hello' | cwindow", @:) " completion for environment variable let $X_VIM_TEST_COMPLETE_ENV = 'foo' call feedkeys(":let $X_VIM_TEST_COMPLETE_E\<C-A>\<C-B>\"\<CR>", 'tx') call assert_match('"let $X_VIM_TEST_COMPLETE_ENV', @:) unlet $X_VIM_TEST_COMPLETE_ENV endfunc " Test for errors in expression evaluation func Test_expr_eval_error() call v9.CheckLegacyAndVim9Failure(["VAR i = 'abc' .. []"], ['E730:', 'E1105:', 'E730:']) call v9.CheckLegacyAndVim9Failure(["VAR l = [] + 10"], ['E745:', 'E1051:', 'E745']) call v9.CheckLegacyAndVim9Failure(["VAR v = 10 + []"], ['E745:', 'E1051:', 'E745:']) call v9.CheckLegacyAndVim9Failure(["VAR v = 10 / []"], ['E745:', 'E1036:', 'E745:']) call v9.CheckLegacyAndVim9Failure(["VAR v = -{}"], ['E728:', 'E1012:', 'E728:']) endfunc func Test_white_in_function_call() let lines =<< trim END VAR text = substitute ( 'some text' , 't' , 'T' , 'g' ) call assert_equal('some TexT', text) END call v9.CheckTransLegacySuccess(lines) let lines =<< trim END var text = substitute ( 'some text' , 't' , 'T' , 'g' ) call assert_equal('some TexT', text) END call v9.CheckDefAndScriptFailure(lines, ['E1001:', 'E121:']) endfunc " Test for float value comparison func Test_float_compare() let lines =<< trim END call assert_true(1.2 == 1.2) call assert_true(1.0 != 1.2) call assert_true(1.2 > 1.0) call assert_true(1.2 >= 1.2) call assert_true(1.0 < 1.2) call assert_true(1.2 <= 1.2) call assert_true(+0.0 == -0.0) #" two NaNs (not a number) are not equal call assert_true(sqrt(-4.01) != (0.0 / 0.0)) #" two inf (infinity) are equal call assert_true((1.0 / 0) == (2.0 / 0)) #" two -inf (infinity) are equal call assert_true(-(1.0 / 0) == -(2.0 / 0)) #" +infinity != -infinity call assert_true((1.0 / 0) != -(2.0 / 0)) END call v9.CheckLegacyAndVim9Success(lines) endfunc func Test_string_interp() let lines =<< trim END call assert_equal('', $"") call assert_equal('foobar', $"foobar") #" Escaping rules. call assert_equal('"foo"{bar}', $"\"foo\"{{bar}}") call assert_equal('"foo"{bar}', $'"foo"{{bar}}') call assert_equal('foobar', $"{"foo"}" .. $'{'bar'}') #" Whitespace before/after the expression. call assert_equal('3', $"{ 1 + 2 }") #" String conversion. call assert_equal('hello from ' .. v:version, $"hello from {v:version}") call assert_equal('hello from ' .. v:version, $'hello from {v:version}') #" Paper over a small difference between VimScript behaviour. call assert_equal(string(v:true), $"{v:true}") call assert_equal('(1+1=2)', $"(1+1={1 + 1})") #" Hex-escaped opening brace: char2nr('{') == 0x7b call assert_equal('esc123ape', $"esc{123}ape") call assert_equal('me{}me', $"me{"\x7b"}\x7dme") VAR var1 = "sun" VAR var2 = "shine" call assert_equal('sunshine', $"{var1}{var2}") call assert_equal('sunsunsun', $"{var1->repeat(3)}") #" Multibyte strings. call assert_equal('say γγγΌγ»γ―γΌγ«γ', $"say {'γγγΌγ»γ―γΌγ«γ'}") #" Nested. call assert_equal('foobarbaz', $"foo{$"{'bar'}"}baz") #" Do not evaluate blocks when the expr is skipped. VAR tmp = 0 if v:false echo "${ LET tmp += 1 }" endif call assert_equal(0, tmp) #" Stray closing brace. call assert_fails('echo $"moo}"', 'E1278:') #" Undefined variable in expansion. call assert_fails('echo $"{moo}"', 'E121:') #" Empty blocks are rejected. call assert_fails('echo $"{}"', 'E15:') call assert_fails('echo $"{ }"', 'E15:') END call v9.CheckLegacyAndVim9Success(lines) let lines =<< trim END call assert_equal('5', $"{({x -> x + 1})(4)}") END call v9.CheckLegacySuccess(lines) let lines =<< trim END call assert_equal('5', $"{((x) => x + 1)(4)}") call assert_fails('echo $"{ # foo }"', 'E1279:') END call v9.CheckDefAndScriptSuccess(lines) endfunc " Test for bitwise left and right shift (<< and >>) func Test_bitwise_shift() let lines =<< trim END call assert_equal(16, 1 << 4) call assert_equal(2, 16 >> 3) call assert_equal(0, 0 << 2) call assert_equal(0, 0 >> 4) call assert_equal(3, 3 << 0) call assert_equal(3, 3 >> 0) call assert_equal(0, 0 >> 4) call assert_equal(0, 999999 >> 100) call assert_equal(0, 999999 << 100) call assert_equal(-1, -1 >> 0) call assert_equal(-1, -1 << 0) VAR a = 8 VAR b = 2 call assert_equal(2, a >> b) call assert_equal(32, a << b) #" operator precedence call assert_equal(48, 1 + 2 << 5 - 1) call assert_equal(3, 8 + 4 >> 4 - 2) call assert_true(1 << 2 < 1 << 3) call assert_true(1 << 4 > 1 << 3) VAR val = 0 for i in range(0, v:numbersize - 2) LET val = or(val, 1 << i) endfor call assert_equal(v:numbermax, val) LET val = v:numbermax for i in range(0, v:numbersize - 2) LET val = and(val, invert(1 << i)) endfor #" -1 has all the bits set call assert_equal(-2, -1 << 1) call assert_equal(-4, -1 << 2) call assert_equal(-8, -1 << 3) if v:numbersize == 64 call assert_equal(0x7fffffffffffffff, -1 >> 1) call assert_equal(0x3fffffffffffffff, -1 >> 2) call assert_equal(0x1fffffffffffffff, -1 >> 3) endif call assert_equal(0, val) #" multiple operators call assert_equal(16, 1 << 2 << 2) call assert_equal(4, 64 >> 2 >> 2) call assert_true(1 << 2 << 2 == 256 >> 2 >> 2) END call v9.CheckLegacyAndVim9Success(lines) call v9.CheckLegacyAndVim9Failure(['VAR v = 2 << -1'], ['E1283:', 'E1283:', 'E1283:']) call v9.CheckLegacyAndVim9Failure(['VAR a = 2', 'VAR b = -1', 'VAR v = a << b'], ['E1283:', 'E1283:', 'E1283:']) call v9.CheckLegacyAndVim9Failure(['VAR v = "8" >> 2'], ['E1282:', 'E1282:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR v = 1 << "2"'], ['E1282:', 'E1282:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR a = "8"', 'VAR b = 2', 'VAR v = a << b'], ['E1282:', 'E1012:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR a = 8', 'VAR b = "2"', 'VAR v = a >> b'], ['E1282:', 'E1012:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR v = ![] << 1'], ['E745:', 'E1012:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR v = 1 << ![]'], ['E745:', 'E1012:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR v = ![] >> 1'], ['E745:', 'E1012:', 'E1282:']) call v9.CheckLegacyAndVim9Failure(['VAR v = 1 >> ![]'], ['E745:', 'E1012:', 'E1282:']) call v9.CheckDefAndScriptFailure(['echo 1<< 2'], ['E1004:', 'E1004:']) call v9.CheckDefAndScriptFailure(['echo 1 <<2'], ['E1004:', 'E1004:']) call v9.CheckDefAndScriptFailure(['echo 1>> 2'], ['E1004:', 'E1004:']) call v9.CheckDefAndScriptFailure(['echo 1 >>2'], ['E1004:', 'E1004:']) let lines =<< trim END var a = 1 << 4 assert_equal(16, a) END call v9.CheckDefAndScriptSuccess(lines) let lines =<< trim END # Use in a lambda function const DivBy2Ref_A = (n: number): number => n >> 1 assert_equal(16, DivBy2Ref_A(32)) const DivBy2Ref_B = (n: number): number => (<number>n) >> 1 assert_equal(16, DivBy2Ref_B(32)) const MultBy2Ref_A = (n: number): number => n << 1 assert_equal(8, MultBy2Ref_A(4)) const MultBy2Ref_B = (n: number): number => (<number>n) << 1 assert_equal(8, MultBy2Ref_B(4)) def DivBy2_A(): func(number): number return (n: number): number => n >> 1 enddef assert_equal(16, DivBy2_A()(32)) def DivBy2_B(): func(number): number return (n: number): number => (<number>n) >> 1 enddef assert_equal(16, DivBy2_B()(32)) def MultBy2_A(): func(number): number return (n: number): number => n << 1 enddef assert_equal(64, MultBy2_A()(32)) def MultBy2_B(): func(number): number return (n: number): number => (<number>n) << 1 enddef assert_equal(64, MultBy2_B()(32)) END call v9.CheckDefAndScriptSuccess(lines) " Use in a legacy lambda function const DivBy2Ref_A = {n -> n >> 1} call assert_equal(16, DivBy2Ref_A(32)) func DivBy2_A() return {n -> n >> 1} endfunc call assert_equal(16, DivBy2_A()(32)) const MultBy2Ref_A = {n -> n << 1} call assert_equal(64, MultBy2Ref_A(32)) func MultBy2_A() return {n -> n << 1} endfunc call assert_equal(64, MultBy2_A()(32)) endfunc " vim: shiftwidth=2 sts=2 expandtab