Tests for List and Dictionary types. vim: set ft=vim : STARTTEST :so small.vim :fun Test(...) :lang C :" Creating List directly with different types :let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] :$put =string(l) :$put =string(l[-1]) :$put =string(l[-4]) :try : $put =string(l[-5]) :catch : $put =v:exception[:14] :endtry :" List slices :$put =string(l[:]) :$put =string(l[1:]) :$put =string(l[:-2]) :$put =string(l[0:8]) :$put =string(l[8:-1]) :" :" List identity :let ll = l :let lx = copy(l) :try : $put =(l == ll) . (l isnot ll) . (l is ll) . (l == lx) . (l is lx) . (l isnot lx) :catch : $put =v:exception :endtry :" :" Creating Dictionary directly with different types :let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} :$put =string(d) . d.1 :$put =string(sort(keys(d))) :$put =string (values(d)) :for [key, val] in items(d) : $put =key . ':' . string(val) : unlet key val :endfor :call extend (d, {3:33, 1:99}) :call extend(d, {'b':'bbb', 'c':'ccc'}, "keep") :try : call extend(d, {3:333,4:444}, "error") :catch : $put =v:exception[:15] . v:exception[-1:-1] :endtry :$put =string(d) :call filter(d, 'v:key =~ ''[ac391]''') :$put =string(d) :" :" Dictionary identity :let dd = d :let dx = copy(d) :try : $put =(d == dd) . (d isnot dd) . (d is dd) . (d == dx) . (d is dx) . (d isnot dx) :catch : $put =v:exception :endtry :" :" Changing var type should fail :try : let d = [] :catch : $put =v:exception[:14] . v:exception[-1:-1] :endtry :try : let l = {} :catch : $put =v:exception[:14] . v:exception[-1:-1] :endtry :" :" removing items with :unlet :unlet l[2] :$put =string(l) :let l = range(8) :try :unlet l[:3] :unlet l[1:] :catch :$put =v:exception :endtry :$put =string(l) :" :unlet d.c :unlet d[-1] :$put =string(d) :" :" removing items out of range: silently skip items that don't exist let l = [0, 1, 2, 3] :unlet l[2:1] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[2:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[2:3] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[2:4] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[2:5] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-1:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-2:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-3:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-4:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-5:2] :$put =string(l) let l = [0, 1, 2, 3] :unlet l[-6:2] :$put =string(l) :" :" assignment to a list :let l = [0, 1, 2, 3] :let [va, vb] = l[2:3] :$put =va :$put =vb :try : let [va, vb] = l :catch : $put =v:exception[:14] :endtry :try : let [va, vb] = l[1:1] :catch : $put =v:exception[:14] :endtry :" :" manipulating a big Dictionary (hashtable.c has a border of 1000 entries) :let d = {} :for i in range(1500) : let d[i] = 3000 - i :endfor :$put =d[0] . ' ' . d[100] . ' ' . d[999] . ' ' . d[1400] . ' ' . d[1499] :try : let n = d[1500] :catch : $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') :endtry :" lookup each items :for i in range(1500) : if d[i] != 3000 - i : $put =d[i] : endif :endfor : let i += 1 :" delete even items :while i >= 2 : let i -= 2 : unlet d[i] :endwhile :$put =get(d, 1500 - 100, 'NONE') . ' ' . d[1] :" delete odd items, checking value, one intentionally wrong :let d[33] = 999 :let i = 1 :while i < 1500 : if d[i] != 3000 - i : $put =i . '=' . d[i] : else : unlet d[i] : endif : let i += 2 :endwhile :$put =string(d) " must be almost empty now :unlet d :" :" Dictionary function :let dict = {} :func dict.func(a) dict : $put =a:a . len(self.data) :endfunc :let dict.data = [1,2,3] :call dict.func("len: ") :let x = dict.func("again: ") :try : let Fn = dict.func : call Fn('xxx') :catch : $put =v:exception[:15] :endtry :" :" Function in script-local List or Dict :let g:dict = {} :function g:dict.func() dict : $put ='g:dict.func'.self.foo[1].self.foo[0]('asdf') :endfunc :let g:dict.foo = ['-', 2, 3] :call insert(g:dict.foo, function('strlen')) :call g:dict.func() :" :" Nasty: remove func from Dict that's being called (works) :let d = {1:1} :func d.func(a) : return "a:". a:a :endfunc :$put =d.func(string(remove(d, 'func'))) :" :" Nasty: deepcopy() dict that refers to itself (fails when noref used) :let d = {1:1, 2:2} :let l = [4, d, 6] :let d[3] = l :let dc = deepcopy(d) :try : let dc = deepcopy(d, 1) :catch : $put =v:exception[:14] :endtry :let l2 = [0, l, l, 3] :let l[1] = l2 :let l3 = deepcopy(l2) :$put ='same list: ' . (l3[1] is l3[2]) :" :" Locked variables :for depth in range(5) : $put ='depth is ' . depth : for u in range(3) : unlet l : let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] : exe "lockvar " . depth . " l" : if u == 1 : exe "unlockvar l" : elseif u == 2 : exe "unlockvar " . depth . " l" : endif : let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") : $put =ps : let ps = '' : try : let l[1][1][0] = 99 : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l[1][1] = [99] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l[1] = [99] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l[2]['6'][7] = 99 : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l[2][6] = {99: 99} : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l[2] = {99: 99} : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : let l = [99] : let ps .= 'p' : catch : let ps .= 'F' : endtry : $put =ps : endfor :endfor :" :" Unletting locked variables :$put ='Unletting:' :for depth in range(5) : $put ='depth is ' . depth : for u in range(3) : unlet l : let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] : exe "lockvar " . depth . " l" : if u == 1 : exe "unlockvar l" : elseif u == 2 : exe "unlockvar " . depth . " l" : endif : let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]") : $put =ps : let ps = '' : try : unlet l[2]['6'][7] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l[2][6] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l[2] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l[1][1][0] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l[1][1] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l[1] : let ps .= 'p' : catch : let ps .= 'F' : endtry : try : unlet l : let ps .= 'p' : catch : let ps .= 'F' : endtry : $put =ps : endfor :endfor :" :" Locked variables and :unlet or list / dict functions :$put ='Locks and commands or functions:' :" :$put ='No :unlet after lock on dict:' :unlet! d :let d = {'a': 99, 'b': 100} :lockvar 1 d :try : unlet d.a : $put ='did :unlet' :catch : $put =v:exception[:16] :endtry :$put =string(d) :" :$put =':unlet after lock on dict item:' :unlet! d :let d = {'a': 99, 'b': 100} :lockvar d.a :try : unlet d.a : $put ='did :unlet' :catch : $put =v:exception[:16] :endtry :$put =string(d) :" :$put ='filter() after lock on dict item:' :unlet! d :let d = {'a': 99, 'b': 100} :lockvar d.a :try : call filter(d, 'v:key != "a"') : $put ='did filter()' :catch : $put =v:exception[:16] :endtry :$put =string(d) :" :$put ='map() after lock on dict:' :unlet! d :let d = {'a': 99, 'b': 100} :lockvar 1 d :try : call map(d, 'v:val + 200') : $put ='did map()' :catch : $put =v:exception[:16] :endtry :$put =string(d) :" :$put ='No extend() after lock on dict item:' :unlet! d :let d = {'a': 99, 'b': 100} :lockvar d.a :try : $put =string(extend(d, {'a': 123})) : $put ='did extend()' :catch : $put =v:exception[:14] :endtry :$put =string(d) :" :$put ='No remove() of write-protected scope-level variable:' :fun! Tfunc(this_is_a_loooooooooong_parameter_name) : try : $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name')) : $put ='did remove()' : catch : $put =v:exception[:14] : endtry :endfun :call Tfunc('testval') :" :$put ='No extend() of write-protected scope-level variable:' :fun! Tfunc(this_is_a_loooooooooong_parameter_name) : try : $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234})) : $put ='did extend()' : catch : $put =v:exception[:14] : endtry :endfun :call Tfunc('testval') :" :$put ='No :unlet of variable in locked scope:' :let b:testvar = 123 :lockvar 1 b: :try : unlet b:testvar : $put ='b:testvar was :unlet: '. (!exists('b:testvar')) :catch : $put =v:exception[:16] :endtry :unlockvar 1 b: :unlet! b:testvar :" :$put ='No :let += of locked list variable:' :let l = ['a', 'b', 3] :lockvar 1 l :try : let l += ['x'] : $put ='did :let +=' :catch : $put =v:exception[:14] :endtry :$put =string(l) :" :unlet l :let l = [1, 2, 3, 4] :lockvar! l :$put =string(l) :unlockvar l[1] :unlet l[0:1] :$put =string(l) :unlet l[1:2] :$put =string(l) :unlockvar l[1] :let l[0:1] = [0, 1] :$put =string(l) :let l[1:2] = [0, 1] :$put =string(l) :unlet l :" :lockvar/islocked() triggering script autoloading :set rtp+=./sautest :lockvar g:footest#x :unlockvar g:footest#x :$put ='locked g:footest#x:'.islocked('g:footest#x') :$put ='exists g:footest#x:'.exists('g:footest#x') :$put ='g:footest#x: '.g:footest#x :" :" a:000 function argument :" first the tests that should fail :try : let a:000 = [1, 2] :catch : $put ='caught a:000' :endtry :try : let a:000[0] = 9 :catch : $put ='caught a:000[0]' :endtry :try : let a:000[2] = [9, 10] :catch : $put ='caught a:000[2]' :endtry :try : let a:000[3] = {9: 10} :catch : $put ='caught a:000[3]' :endtry :" now the tests that should pass :try : let a:000[2][1] = 9 : call extend(a:000[2], [5, 6]) : let a:000[3][5] = 8 : let a:000[3]['a'] = 12 : $put =string(a:000) :catch : $put ='caught ' . v:exception :endtry :" :" reverse(), sort(), uniq() :let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] :$put =string(uniq(copy(l))) :$put =string(reverse(l)) :$put =string(reverse(reverse(l))) :$put =string(sort(l)) :$put =string(reverse(sort(l))) :$put =string(sort(reverse(sort(l)))) :$put =string(uniq(sort(l))) :let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, 0.22, 'four'] :$put =string(sort(copy(l), 'n')) :let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] :$put =string(sort(copy(l), 1)) :$put =string(sort(copy(l), 'i')) :$put =string(sort(copy(l))) :" :" splitting a string to a List :$put =string(split(' aa bb ')) :$put =string(split(' aa bb ', '\W\+', 0)) :$put =string(split(' aa bb ', '\W\+', 1)) :$put =string(split(' aa bb ', '\W', 1)) :$put =string(split(':aa::bb:', ':', 0)) :$put =string(split(':aa::bb:', ':', 1)) :$put =string(split('aa,,bb, cc,', ',\s*', 1)) :$put =string(split('abc', '\zs')) :$put =string(split('abc', '\zs', 1)) :" :" compare recursively linked list and dict :let l = [1, 2, 3, 4] :let d = {'1': 1, '2': l, '3': 3} :let l[1] = d :$put =(l == l) :$put =(d == d) :$put =(l != deepcopy(l)) :$put =(d != deepcopy(d)) :" :" compare complex recursively linked list and dict :let l = [] :call add(l, l) :let dict4 = {"l": l} :call add(dict4.l, dict4) :let lcopy = deepcopy(l) :let dict4copy = deepcopy(dict4) :$put =(l == lcopy) :$put =(dict4 == dict4copy) :" :" Pass the same List to extend() :let l = [1, 2, 3, 4, 5] :call extend(l, l) :$put =string(l) :" :" Pass the same Dict to extend() :let d = { 'a': {'b': 'B'}} :call extend(d, d) :$put =string(d) :" :" Pass the same Dict to extend() with "error" :try : call extend(d, d, "error") :catch : $put =v:exception[:15] . v:exception[-1:-1] :endtry :$put =string(d) :" :" test for range assign :let l = [0] :let l[:] = [1, 2] :$put =string(l) :endfun :" :call Test(1, 2, [3, 4], {5: 6}) " This may take a while :" :delfunc Test :unlet dict :call garbagecollect(1) :" :" test for patch 7.3.637 :let a = 'No error caught' :try|foldopen|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry o=a :" :lang C :redir => a :try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry :redir END o=a :" :" :/^start:/,$wq! test.out ENDTEST start: