blob: 7d8ba3c3bf25f684f48e47c372354ea11b9c3065 [file] [log] [blame]
Bram Moolenaardb913952012-06-29 12:54:53 +02001Tests for various python features. vim: set ft=vim :
2
3STARTTEST
4:so small.vim
5:if !has('python3') | e! test.ok | wq! test.out | endif
6:py3 import vim
7:fun Test()
8:let l = []
9:py3 l=vim.bindeval('l')
10:py3 f=vim.bindeval('function("strlen")')
11:" Extending List directly with different types
12:py3 l+=[1, "as'd", [1, 2, f, {'a': 1}]]
13:$put =string(l)
14:$put =string(l[-1])
15:try
16: $put =string(l[-4])
17:catch
18: $put =v:exception[:13]
19:endtry
20:" List assignment
21:py3 l[0]=0
22:$put =string(l)
23:py3 l[-2]=f
24:$put =string(l)
25:"
26:" Extending Dictionary directly with different types
27:let d = {}
28:py3 d=vim.bindeval('d')
29:py3 d['1']='asd'
30:py3 d['b']=[1, 2, f]
31:py3 d['-1']={'a': 1}
32:let dkeys = []
33:py3 dk=vim.bindeval('dkeys')
34:py3 dkeys=d.keys()
35:py3 dkeys.sort()
36:py3 dk+=dkeys
37:$put =string(dkeys)
38:for [key, val] in sort(items(d))
39: $put =string(key) . ' : ' . string(val)
40: unlet key val
41:endfor
42:"
43:" removing items with del
44:py3 del l[2]
45:$put =string(l)
46:let l = range(8)
47:py3 l=vim.bindeval('l')
48:try
49: py3 del l[:3]
50: py3 del l[1:]
51:catch
52: $put =v:exception
53:endtry
54:$put =string(l)
55:"
56:py3 del d['-1']
57:$put =string(d)
58:"
59:" removing items out of range: silently skip items that don't exist
60:let l = [0, 1, 2, 3]
61:py3 l=vim.bindeval('l')
62:" The following two ranges delete nothing as they match empty list:
63:py3 del l[2:1]
64:$put =string(l)
65:py3 del l[2:2]
66:$put =string(l)
67:py3 del l[2:3]
68:$put =string(l)
69:let l = [0, 1, 2, 3]
70:py3 l=vim.bindeval('l')
71:py3 del l[2:4]
72:$put =string(l)
73:let l = [0, 1, 2, 3]
74:py3 l=vim.bindeval('l')
75:py3 del l[2:5]
76:$put =string(l)
77:let l = [0, 1, 2, 3]
78:py3 l=vim.bindeval('l')
79:py3 del l[2:6]
80:$put =string(l)
81:let l = [0, 1, 2, 3]
82:py3 l=vim.bindeval('l')
83:" The following two ranges delete nothing as they match empty list:
84:py3 del l[-1:2]
85:$put =string(l)
86:py3 del l[-2:2]
87:$put =string(l)
88:py3 del l[-3:2]
89:$put =string(l)
90:let l = [0, 1, 2, 3]
91:py3 l=vim.bindeval('l')
92:py3 del l[-4:2]
93:$put =string(l)
94:let l = [0, 1, 2, 3]
95:py3 l=vim.bindeval('l')
96:py3 del l[-5:2]
97:$put =string(l)
98:let l = [0, 1, 2, 3]
99:py3 l=vim.bindeval('l')
100:py3 del l[-6:2]
101:$put =string(l)
102:"
103:" Slice assignment to a list
104:let l = [0, 1, 2, 3]
105:py3 l=vim.bindeval('l')
106:py3 l[0:0]=['a']
107:$put =string(l)
108:let l = [0, 1, 2, 3]
109:py3 l=vim.bindeval('l')
110:py3 l[1:2]=['b']
111:$put =string(l)
112:let l = [0, 1, 2, 3]
113:py3 l=vim.bindeval('l')
114:py3 l[2:4]=['c']
115:$put =string(l)
116:let l = [0, 1, 2, 3]
117:py3 l=vim.bindeval('l')
118:py3 l[4:4]=['d']
119:$put =string(l)
120:let l = [0, 1, 2, 3]
121:py3 l=vim.bindeval('l')
122:py3 l[-1:2]=['e']
123:$put =string(l)
124:let l = [0, 1, 2, 3]
125:py3 l=vim.bindeval('l')
126:py3 l[-10:2]=['f']
127:$put =string(l)
128:let l = [0, 1, 2, 3]
129:py3 l=vim.bindeval('l')
130:py3 l[2:-10]=['g']
131:$put =string(l)
132:let l = []
133:py3 l=vim.bindeval('l')
134:py3 l[0:0]=['h']
135:$put =string(l)
136:"
137:" Locked variables
138:let l = [0, 1, 2, 3]
139:py3 l=vim.bindeval('l')
140:lockvar! l
141:py3 l[2]='i'
142:$put =string(l)
143:unlockvar! l
144:"
145:" Function calls
146:function New(...)
147:return ['NewStart']+a:000+['NewEnd']
148:endfunction
149:function DictNew(...) dict
150:return ['DictNewStart']+a:000+['DictNewEnd', self]
151:endfunction
152:let l=[function('New'), function('DictNew')]
153:py3 l=vim.bindeval('l')
154:py3 l.extend(list(l[0](1, 2, 3)))
155:$put =string(l)
156:py3 l.extend(list(l[1](1, 2, 3, self={'a': 'b'})))
157:$put =string(l)
158:py3 l+=[l[0].name]
159:$put =string(l)
160:try
161: py3 l[1](1, 2, 3)
162:catch
163: $put =v:exception[:13]
164:endtry
165:delfunction New
166:try
167: py3 l[0](1, 2, 3)
168:catch
169: $put =v:exception[:13]
170:endtry
171:if has('float')
172: let l=[0.0]
173: py3 l=vim.bindeval('l')
174: py3 l.extend([0.0])
175: $put =string(l)
176:else
177: $put ='[0.0, 0.0]'
178:endif
Bram Moolenaarc11073c2012-09-05 19:17:42 +0200179:let messages=[]
180:py3 <<EOF
181d=vim.bindeval('{}')
182m=vim.bindeval('messages')
183try:
184 d['abc']
185except Exception as e:
186 m.extend([e.__class__.__name__])
187
188try:
189 d['abc']="\0"
190except Exception as e:
191 m.extend([e.__class__.__name__])
192
193try:
194 d['abc']=vim
195except Exception as e:
196 m.extend([e.__class__.__name__])
197
198try:
199 d['']=1
200except Exception as e:
201 m.extend([e.__class__.__name__])
202
203try:
204 d['a\0b']=1
205except Exception as e:
206 m.extend([e.__class__.__name__])
207
208try:
209 d[b'a\0b']=1
210except Exception as e:
211 m.extend([e.__class__.__name__])
212EOF
213:$put =messages
Bram Moolenaar66b79852012-09-21 14:00:35 +0200214:unlet messages
215:" locked and scope attributes
216:let d={} | let dl={} | lockvar dl
217:for s in split("d dl v: g:")
218: let name=tr(s, ':', 's')
219: execute 'py3 '.name.'=vim.bindeval("'.s.'")'
220: let toput=s.' : '.join(map(['locked', 'scope'], 'v:val.":".py3eval(name.".".v:val)'), ';')
221: $put =toput
222:endfor
223:silent! let d.abc=1
224:silent! let dl.abc=1
225:py3 d.locked=True
226:py3 dl.locked=False
227:silent! let d.def=1
228:silent! let dl.def=1
229:put ='d:'.string(d)
230:put ='dl:'.string(dl)
231:unlet d dl
232:
233:let l=[] | let ll=[] | lockvar ll
234:for s in split("l ll")
235: let name=tr(s, ':', 's')
236: execute 'py3 '.name.'=vim.bindeval("'.s.'")'
237: let toput=s.' : locked:'.py3eval(name.'.locked')
238: $put =toput
239:endfor
240:silent! call extend(l, [0])
241:silent! call extend(ll, [0])
242:py3 l.locked=True
243:py3 ll.locked=False
244:silent! call extend(l, [1])
245:silent! call extend(ll, [1])
246:put ='l:'.string(l)
247:put ='ll:'.string(ll)
248:unlet l ll
Bram Moolenaardb913952012-06-29 12:54:53 +0200249:"
250:" py3eval()
251:let l=py3eval('[0, 1, 2]')
252:$put =string(l)
253:let d=py3eval('{"a": "b", "c": 1, "d": ["e"]}')
254:$put =sort(items(d))
Bram Moolenaardb913952012-06-29 12:54:53 +0200255:if has('float')
256: let f=py3eval('0.0')
257: $put =string(f)
258:else
259: $put ='0.0'
260:endif
Bram Moolenaarc11073c2012-09-05 19:17:42 +0200261:" Invalid values:
262:for e in ['"\0"', '{"\0": 1}', 'undefined_name', 'vim']
263: try
264: let v=py3eval(e)
265: catch
266: let toput=e.":\t".v:exception[:13]
267: $put =toput
268: endtry
269:endfor
Bram Moolenaar76d711c2013-02-13 14:17:08 +0100270:"
271:" threading
272:let l = [0]
273:py3 l=vim.bindeval('l')
274:py3 <<EOF
275import threading
276import time
277
278class T(threading.Thread):
279 def __init__(self):
280 threading.Thread.__init__(self)
281 self.t = 0
282 self.running = True
283
284 def run(self):
285 while self.running:
286 self.t += 1
287 time.sleep(0.1)
288
289t = T()
290t.start()
291EOF
292:sleep 1
293:py3 t.running = False
294:py3 t.join()
295:py3 l[0] = t.t > 8 # check if the background thread is working
296:$put =string(l)
297:"
298:" settrace
299:let l = []
300:py3 l=vim.bindeval('l')
301:py3 <<EOF
302import sys
303
304def traceit(frame, event, arg):
305 global l
306 if event == "line":
307 l += [frame.f_lineno]
308 return traceit
309
310def trace_main():
311 for i in range(5):
312 pass
313EOF
314:py3 sys.settrace(traceit)
315:py3 trace_main()
316:py3 sys.settrace(None)
317:$put =string(l)
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200318:"
319:" Vars
320:let g:foo = 'bac'
321:let w:abc = 'def'
322:let b:baz = 'bar'
Bram Moolenaara4720012013-05-15 16:27:37 +0200323:let t:bar = 'jkl'
Bram Moolenaar230bb3f2013-04-24 14:07:45 +0200324:try
325: throw "Abc"
326:catch
327: put =py3eval('vim.vvars[''exception'']')
328:endtry
329:put =py3eval('vim.vars[''foo'']')
330:put =py3eval('vim.current.window.vars[''abc'']')
331:put =py3eval('vim.current.buffer.vars[''baz'']')
Bram Moolenaara4720012013-05-15 16:27:37 +0200332:put =py3eval('vim.current.tabpage.vars[''bar'']')
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +0200333:"
334:" Options
335:" paste: boolean, global
336:" previewheight number, global
337:" operatorfunc: string, global
338:" number: boolean, window-local
339:" numberwidth: number, window-local
340:" colorcolumn: string, window-local
341:" statusline: string, window-local/global
342:" autoindent: boolean, buffer-local
343:" iminsert: number, buffer-local
344:" omnifunc: string, buffer-local
345:" preserveindent: boolean, buffer-local/global
346:" path: string, buffer-local/global
347:let g:bufs=[bufnr('%')]
348:new
349:let g:bufs+=[bufnr('%')]
350:vnew
351:let g:bufs+=[bufnr('%')]
352:wincmd j
353:vnew
354:let g:bufs+=[bufnr('%')]
355:wincmd l
356:fun RecVars(opt)
357: let gval =string(eval('&g:'.a:opt))
358: let wvals=join(map(range(1, 4), 'v:val.":".string(getwinvar(v:val, "&".a:opt))'))
359: let bvals=join(map(copy(g:bufs), 'v:val.":".string(getbufvar(v:val, "&".a:opt))'))
360: put =' G: '.gval
361: put =' W: '.wvals
362: put =' B: '.wvals
363:endfun
364py3 << EOF
365def e(s, g=globals(), l=locals()):
366 try:
367 exec(s, g, l)
368 except Exception as e:
369 vim.command('throw ' + repr(e.__class__.__name__))
370
371def ev(s, g=globals(), l=locals()):
372 try:
373 return eval(s, g, l)
374 except Exception as e:
375 vim.command('throw ' + repr(e.__class__.__name__))
376 return 0
377EOF
378:function E(s)
379: python3 e(vim.eval('a:s'))
380:endfunction
381:function Ev(s)
382: return py3eval('ev(vim.eval("a:s"))')
383:endfunction
384:py3 gopts1=vim.options
385:py3 wopts1=vim.windows[2].options
386:py3 wopts2=vim.windows[0].options
387:py3 wopts3=vim.windows[1].options
388:py3 bopts1=vim.buffers[vim.bindeval("g:bufs")[2]].options
389:py3 bopts2=vim.buffers[vim.bindeval("g:bufs")[1]].options
390:py3 bopts3=vim.buffers[vim.bindeval("g:bufs")[0]].options
391:let lst=[]
392:let lst+=[['paste', 1, 0, 1, 2, 1, 1, 0 ]]
393:let lst+=[['previewheight', 5, 1, 6, 'a', 0, 1, 0 ]]
394:let lst+=[['operatorfunc', 'A', 'B', 'C', 2, 0, 1, 0 ]]
395:let lst+=[['number', 0, 1, 1, 0, 1, 0, 1 ]]
396:let lst+=[['numberwidth', 2, 3, 5, -100, 0, 0, 1 ]]
397:let lst+=[['colorcolumn', '+1', '+2', '+3', 'abc', 0, 0, 1 ]]
398:let lst+=[['statusline', '1', '2', '4', 0, 0, 1, 1 ]]
399:let lst+=[['autoindent', 0, 1, 1, 2, 1, 0, 2 ]]
400:let lst+=[['iminsert', 0, 2, 1, 3, 0, 0, 2 ]]
401:let lst+=[['omnifunc', 'A', 'B', 'C', 1, 0, 0, 2 ]]
402:let lst+=[['preserveindent', 0, 1, 1, 2, 1, 1, 2 ]]
403:let lst+=[['path', '.,,', ',,', '.', 0, 0, 1, 2 ]]
404:for [oname, oval1, oval2, oval3, invval, bool, global, local] in lst
405: py3 oname=vim.eval('oname')
406: py3 oval1=vim.bindeval('oval1')
407: py3 oval2=vim.bindeval('oval2')
408: py3 oval3=vim.bindeval('oval3')
409: if invval is 0 || invval is 1
410: py3 invval=bool(vim.bindeval('invval'))
411: else
412: py3 invval=vim.bindeval('invval')
413: endif
414: if bool
415: py3 oval1=bool(oval1)
416: py3 oval2=bool(oval2)
417: py3 oval3=bool(oval3)
418: endif
419: put ='>>> '.oname
420: for v in ['gopts1', 'wopts1', 'bopts1']
421: try
422: put =' p/'.v.': '.Ev('repr('.v.'['''.oname.'''])')
423: catch
424: put =' p/'.v.'! '.v:exception
425: endtry
426: try
427: call E(v.'["'.oname.'"]=invval')
428: catch
429: put =' inv: '.string(invval).'! '.v:exception
430: endtry
431: for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
432: let val=substitute(vv, '^.opts', 'oval', '')
433: try
434: call E(vv.'["'.oname.'"]='.val)
435: catch
436: put =' '.vv.'! '.v:exception
437: endtry
438: endfor
439: endfor
440: call RecVars(oname)
441: for v in ['wopts3', 'bopts3']
442: try
443: call E('del '.v.'["'.oname.'"]')
444: catch
445: put =' del '.v.'! '.v:exception
446: endtry
447: endfor
448: call RecVars(oname)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +0200449:endfor
450:only
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200451:for buf in g:bufs[1:]
452: execute 'bwipeout!' buf
453:endfor
Bram Moolenaarbd80f352013-05-12 21:16:23 +0200454:"
455:" Test buffer object
456:vnew
457:put ='First line'
458:put ='Second line'
459:put ='Third line'
460:1 delete _
461:py3 b=vim.current.buffer
462:wincmd w
463:mark a
464py3 << EOF
465cb = vim.current.buffer
466# Tests BufferAppend and BufferItem
467cb.append(b[0])
468# Tests BufferSlice and BufferAssSlice
469cb.append('abc') # Will be overwritten
470cb[-1:] = b[:-2]
471# Test BufferLength and BufferAssSlice
472cb.append('def') # Will not be overwritten
473cb[len(cb):] = b[:]
474# Test BufferAssItem and BufferMark
475cb.append('ghi') # Will be overwritten
476cb[-1] = repr((len(cb) - cb.mark('a')[0], cb.mark('a')[1]))
477# Test BufferRepr
478cb.append(repr(cb) + repr(b))
479# Modify foreign buffer
480b.append('foo')
481b[0]='bar'
482b[0:0]=['baz']
483vim.command('call append("$", getbufline(%i, 1, "$"))' % b.number)
484# Test CheckBuffer
485vim.command('bwipeout! ' + str(b.number))
486for expr in ('b[1]','b[:] = ["A", "B"]','b[:]','b.append("abc")'):
487 try:
488 exec(expr)
489 except vim.error:
490 pass
491 else:
492 # Usually a SEGV here
493 # Should not happen in any case
494 cb.append('No exception for ' + expr)
495EOF
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200496:"
497:" Test vim.buffers object
498:set hidden
499:edit a
500:buffer #
501:edit b
502:buffer #
503:edit c
504:buffer #
505py3 << EOF
506# Check GCing iterator that was not fully exhausted
507i = iter(vim.buffers)
508cb.append('i:' + str(next(i)))
509# and also check creating more then one iterator at a time
510i2 = iter(vim.buffers)
511cb.append('i2:' + str(next(i2)))
512cb.append('i:' + str(next(i)))
513# The following should trigger GC and not cause any problems
514del i
515del i2
516i3 = iter(vim.buffers)
517cb.append('i3:' + str(next(i3)))
518del i3
519
520prevnum = 0
521for b in vim.buffers:
522 # Check buffer order
523 if prevnum >= b.number:
524 cb.append('!!! Buffer numbers not in strictly ascending order')
525 # Check indexing: vim.buffers[number].number == number
526 cb.append(str(b.number) + ':' + repr(vim.buffers[b.number]) + '=' + repr(b))
527 prevnum = b.number
528
529cb.append(str(len(vim.buffers)))
530
531bnums = list(map(lambda b: b.number, vim.buffers))[1:]
532
533# Test wiping out buffer with existing iterator
534i4 = iter(vim.buffers)
535cb.append('i4:' + str(next(i4)))
536vim.command('bwipeout! ' + str(bnums.pop(0)))
537try:
538 next(i4)
539except vim.error:
540 pass
541else:
542 cb.append('!!!! No vim.error')
543i4 = iter(vim.buffers)
544vim.command('bwipeout! ' + str(bnums.pop(-1)))
545vim.command('bwipeout! ' + str(bnums.pop(-1)))
546cb.append('i4:' + str(next(i4)))
547try:
548 next(i4)
549except StopIteration:
550 cb.append('StopIteration')
551EOF
Bram Moolenaara4720012013-05-15 16:27:37 +0200552:"
553:" Test vim.{tabpage,window}list and vim.{tabpage,window} objects
554:tabnew 0
555:tabnew 1
556:vnew a.1
557:tabnew 2
558:vnew a.2
559:vnew b.2
560:vnew c.2
561py3 << EOF
562def W(w):
563 if '(unknown)' in repr(w):
564 return '<window object (unknown)>'
565 else:
566 return repr(w)
567cb.append('Number of tabs: ' + str(len(vim.tabpages)))
568cb.append('Current tab pages:')
569for t in vim.tabpages:
570 cb.append(' ' + repr(t) + '(' + str(t.number) + ')' + ': ' + str(len(t.windows)) + ' windows, current is ' + W(t.window))
571 cb.append(' Windows:')
572 for w in t.windows:
573 cb.append(' ' + W(w) + '(' + str(w.number) + ')' + ': displays buffer ' + repr(w.buffer) + '; cursor is at ' + repr(w.cursor))
574 # Other values depend on the size of the terminal, so they are checked partly:
575 for attr in ('height', 'row', 'width', 'col'):
576 try:
577 aval = getattr(w, attr)
578 if type(aval) is not int:
579 raise TypeError
580 if aval < 0:
581 raise ValueError
582 except Exception as e:
583 cb.append('!!!!!! Error while getting attribute ' + attr + ': ' + e.__class__.__name__)
584 w.cursor = (len(w.buffer), 0)
585cb.append('Number of windows in current tab page: ' + str(len(vim.windows)))
586if list(vim.windows) != list(vim.current.tabpage.windows):
587 cb.append('!!!!!! Windows differ')
588EOF
589:"
590:" Test vim.current
591py3 << EOF
592def H(o):
593 return repr(o)
594cb.append('Current tab page: ' + repr(vim.current.tabpage))
595cb.append('Current window: ' + repr(vim.current.window) + ': ' + H(vim.current.window) + ' is ' + H(vim.current.tabpage.window))
596cb.append('Current buffer: ' + repr(vim.current.buffer) + ': ' + H(vim.current.buffer) + ' is ' + H(vim.current.window.buffer)+ ' is ' + H(vim.current.tabpage.window.buffer))
597# Assigning: fails
598try:
599 vim.current.window = vim.tabpages[0].window
600except ValueError:
601 cb.append('ValueError at assigning foreign tab window')
602
603for attr in ('window', 'tabpage', 'buffer'):
604 try:
605 setattr(vim.current, attr, None)
606 except TypeError:
607 cb.append('Type error at assigning None to vim.current.' + attr)
608
609# Assigning: success
610vim.current.tabpage = vim.tabpages[-2]
611vim.current.buffer = cb
612vim.current.window = vim.windows[0]
613vim.current.window.cursor = (len(vim.current.buffer), 0)
614cb.append('Current tab page: ' + repr(vim.current.tabpage))
615cb.append('Current window: ' + repr(vim.current.window))
616cb.append('Current buffer: ' + repr(vim.current.buffer))
617cb.append('Current line: ' + repr(vim.current.line))
618for b in vim.buffers:
619 if b is not cb:
620 vim.command('bwipeout! ' + str(b.number))
621EOF
622:tabonly!
623:only!
Bram Moolenaardb913952012-06-29 12:54:53 +0200624:endfun
625:"
626:call Test()
627:"
628:delfunc Test
629:call garbagecollect(1)
630:"
631:/^start:/,$wq! test.out
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200632:call getchar()
Bram Moolenaardb913952012-06-29 12:54:53 +0200633ENDTEST
634
635start: