1" Test various aspects of the Vim script language.
2" Most of this was formerly in test49.
3
4"-------------------------------------------------------------------------------
5" Test environment							    {{{1
6"-------------------------------------------------------------------------------
7
8com!		   XpathINIT  let g:Xpath = ''
9com! -nargs=1 -bar Xpath      let g:Xpath = g:Xpath . <args>
10
11" Append a message to the "messages" file
12func Xout(text)
13    split messages
14    $put =a:text
15    wq
16endfunc
17
18com! -nargs=1	     Xout     call Xout(<args>)
19
20" MakeScript() - Make a script file from a function.			    {{{2
21"
22" Create a script that consists of the body of the function a:funcname.
23" Replace any ":return" by a ":finish", any argument variable by a global
24" variable, and every ":call" by a ":source" for the next following argument
25" in the variable argument list.  This function is useful if similar tests are
26" to be made for a ":return" from a function call or a ":finish" in a script
27" file.
28function! MakeScript(funcname, ...)
29    let script = tempname()
30    execute "redir! >" . script
31    execute "function" a:funcname
32    redir END
33    execute "edit" script
34    " Delete the "function" and the "endfunction" lines.  Do not include the
35    " word "function" in the pattern since it might be translated if LANG is
36    " set.  When MakeScript() is being debugged, this deletes also the debugging
37    " output of its line 3 and 4.
38    exec '1,/.*' . a:funcname . '(.*)/d'
39    /^\d*\s*endfunction\>/,$d
40    %s/^\d*//e
41    %s/return/finish/e
42    %s/\<a:\(\h\w*\)/g:\1/ge
43    normal gg0
44    let cnt = 0
45    while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
46	let cnt = cnt + 1
47	s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
48    endwhile
49    g/^\s*$/d
50    write
51    bwipeout
52    return script
53endfunc
54
55" ExecAsScript - Source a temporary script made from a function.	    {{{2
56"
57" Make a temporary script file from the function a:funcname, ":source" it, and
58" delete it afterwards.  However, if an exception is thrown the file may remain,
59" the caller should call DeleteTheScript() afterwards.
60let s:script_name = ''
61function! ExecAsScript(funcname)
62    " Make a script from the function passed as argument.
63    let s:script_name = MakeScript(a:funcname)
64
65    " Source and delete the script.
66    exec "source" s:script_name
67    call delete(s:script_name)
68    let s:script_name = ''
69endfunction
70
71function! DeleteTheScript()
72    if s:script_name
73	call delete(s:script_name)
74	let s:script_name = ''
75    endif
76endfunc
77
78com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
79
80
81"-------------------------------------------------------------------------------
82" Test 1:   :endwhile in function					    {{{1
83"
84"	    Detect if a broken loop is (incorrectly) reactivated by the
85"	    :endwhile.  Use a :return to prevent an endless loop, and make
86"	    this test first to get a meaningful result on an error before other
87"	    tests will hang.
88"-------------------------------------------------------------------------------
89
90function! T1_F()
91    Xpath 'a'
92    let first = 1
93    while 1
94	Xpath 'b'
95	if first
96	    Xpath 'c'
97	    let first = 0
98	    break
99	else
100	    Xpath 'd'
101	    return
102	endif
103    endwhile
104endfunction
105
106function! T1_G()
107    Xpath 'h'
108    let first = 1
109    while 1
110	Xpath 'i'
111	if first
112	    Xpath 'j'
113	    let first = 0
114	    break
115	else
116	    Xpath 'k'
117	    return
118	endif
119	if 1	" unmatched :if
120    endwhile
121endfunction
122
123func Test_endwhile_function()
124  XpathINIT
125  call T1_F()
126  Xpath 'F'
127
128  try
129    call T1_G()
130  catch
131    " Catch missing :endif
132    call assert_true(v:exception =~ 'E171')
133    Xpath 'x'
134  endtry
135  Xpath 'G'
136
137  call assert_equal('abcFhijxG', g:Xpath)
138endfunc
139
140"-------------------------------------------------------------------------------
141" Test 2:   :endwhile in script						    {{{1
142"
143"	    Detect if a broken loop is (incorrectly) reactivated by the
144"	    :endwhile.  Use a :finish to prevent an endless loop, and place
145"	    this test before others that might hang to get a meaningful result
146"	    on an error.
147"
148"	    This test executes the bodies of the functions T1_F and T1_G from
149"	    the previous test as script files (:return replaced by :finish).
150"-------------------------------------------------------------------------------
151
152func Test_endwhile_script()
153  XpathINIT
154  ExecAsScript T1_F
155  Xpath 'F'
156  call DeleteTheScript()
157
158  try
159    ExecAsScript T1_G
160  catch
161    " Catch missing :endif
162    call assert_true(v:exception =~ 'E171')
163    Xpath 'x'
164  endtry
165  Xpath 'G'
166  call DeleteTheScript()
167
168  call assert_equal('abcFhijxG', g:Xpath)
169endfunc
170
171"-------------------------------------------------------------------------------
172" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
173"-------------------------------------------------------------------------------
174
175function Test_if_while()
176    XpathINIT
177    if 1
178	Xpath 'a'
179	let loops = 3
180	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
181	    if loops <= 0
182		let break_err = 1
183		let loops = -1
184	    else
185		Xpath 'b' . loops
186	    endif
187	    if (loops == 2)
188		while loops == 2 " dummy loop
189		    Xpath 'c' . loops
190		    let loops = loops - 1
191		    continue    " stop dummy loop
192		    Xpath 'd' . loops
193		endwhile
194		continue	    " continue main loop
195		Xpath 'e' . loops
196	    elseif (loops == 1)
197		let p = 1
198		while p	    " dummy loop
199		    Xpath 'f' . loops
200		    let p = 0
201		    break	    " break dummy loop
202		    Xpath 'g' . loops
203		endwhile
204		Xpath 'h' . loops
205		unlet p
206		break	    " break main loop
207		Xpath 'i' . loops
208	    endif
209	    if (loops > 0)
210		Xpath 'j' . loops
211	    endif
212	    while loops == 3    " dummy loop
213		let loops = loops - 1
214	    endwhile	    " end dummy loop
215	endwhile		    " end main loop
216	Xpath 'k'
217    else
218	Xpath 'l'
219    endif
220    Xpath 'm'
221    if exists("break_err")
222	Xpath 'm'
223	unlet break_err
224    endif
225
226    unlet loops
227
228    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
229endfunc
230
231"-------------------------------------------------------------------------------
232" Test 4:   :return							    {{{1
233"-------------------------------------------------------------------------------
234
235function! T4_F()
236    if 1
237	Xpath 'a'
238	let loops = 3
239	while loops > 0				"    3:  2:     1:
240	    Xpath 'b' . loops
241	    if (loops == 2)
242		Xpath 'c' . loops
243		return
244		Xpath 'd' . loops
245	    endif
246	    Xpath 'e' . loops
247	    let loops = loops - 1
248	endwhile
249	Xpath 'f'
250    else
251	Xpath 'g'
252    endif
253endfunction
254
255function Test_return()
256    XpathINIT
257    call T4_F()
258    Xpath '4'
259
260    call assert_equal('ab3e3b2c24', g:Xpath)
261endfunction
262
263
264"-------------------------------------------------------------------------------
265" Test 5:   :finish							    {{{1
266"
267"	    This test executes the body of the function T4_F from the previous
268"	    test as a script file (:return replaced by :finish).
269"-------------------------------------------------------------------------------
270
271function Test_finish()
272    XpathINIT
273    ExecAsScript T4_F
274    Xpath '5'
275    call DeleteTheScript()
276
277    call assert_equal('ab3e3b2c25', g:Xpath)
278endfunction
279
280
281
282"-------------------------------------------------------------------------------
283" Test 6:   Defining functions in :while loops				    {{{1
284"
285"	     Functions can be defined inside other functions.  An inner function
286"	     gets defined when the outer function is executed.  Functions may
287"	     also be defined inside while loops.  Expressions in braces for
288"	     defining the function name are allowed.
289"
290"	     The functions are defined when sourcing the script, only the
291"	     resulting path is checked in the test function.
292"-------------------------------------------------------------------------------
293
294XpathINIT
295
296" The command CALL collects the argument of all its invocations in "calls"
297" when used from a function (that is, when the global variable "calls" needs
298" the "g:" prefix).  This is to check that the function code is skipped when
299" the function is defined.  For inner functions, do so only if the outer
300" function is not being executed.
301"
302let calls = ""
303com! -nargs=1 CALL
304	    \ if !exists("calls") && !exists("outer") |
305	    \ let g:calls = g:calls . <args> |
306	    \ endif
307
308let i = 0
309while i < 3
310    let i = i + 1
311    if i == 1
312	Xpath 'a'
313	function! F1(arg)
314	    CALL a:arg
315	    let outer = 1
316
317	    let j = 0
318	    while j < 1
319		Xpath 'b'
320		let j = j + 1
321		function! G1(arg)
322		    CALL a:arg
323		endfunction
324		Xpath 'c'
325	    endwhile
326	endfunction
327	Xpath 'd'
328
329	continue
330    endif
331
332    Xpath 'e' . i
333    function! F{i}(i, arg)
334	CALL a:arg
335	let outer = 1
336
337	if a:i == 3
338	    Xpath 'f'
339	endif
340	let k = 0
341	while k < 3
342	    Xpath 'g' . k
343	    let k = k + 1
344	    function! G{a:i}{k}(arg)
345		CALL a:arg
346	    endfunction
347	    Xpath 'h' . k
348	endwhile
349    endfunction
350    Xpath 'i'
351
352endwhile
353
354if exists("*G1")
355    Xpath 'j'
356endif
357if exists("*F1")
358    call F1("F1")
359    if exists("*G1")
360       call G1("G1")
361    endif
362endif
363
364if exists("G21") || exists("G22") || exists("G23")
365    Xpath 'k'
366endif
367if exists("*F2")
368    call F2(2, "F2")
369    if exists("*G21")
370       call G21("G21")
371    endif
372    if exists("*G22")
373       call G22("G22")
374    endif
375    if exists("*G23")
376       call G23("G23")
377    endif
378endif
379
380if exists("G31") || exists("G32") || exists("G33")
381    Xpath 'l'
382endif
383if exists("*F3")
384    call F3(3, "F3")
385    if exists("*G31")
386       call G31("G31")
387    endif
388    if exists("*G32")
389       call G32("G32")
390    endif
391    if exists("*G33")
392       call G33("G33")
393    endif
394endif
395
396Xpath 'm'
397
398let g:test6_result = g:Xpath
399let g:test6_calls = calls
400
401unlet calls
402delfunction F1
403delfunction G1
404delfunction F2
405delfunction G21
406delfunction G22
407delfunction G23
408delfunction G31
409delfunction G32
410delfunction G33
411
412function Test_defining_functions()
413    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
414    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
415endfunc
416
417"-------------------------------------------------------------------------------
418" Test 7:   Continuing on errors outside functions			    {{{1
419"
420"	    On an error outside a function, the script processing continues
421"	    at the line following the outermost :endif or :endwhile.  When not
422"	    inside an :if or :while, the script processing continues at the next
423"	    line.
424"-------------------------------------------------------------------------------
425
426XpathINIT
427
428if 1
429    Xpath 'a'
430    while 1
431	Xpath 'b'
432	asdf
433	Xpath 'c'
434	break
435    endwhile | Xpath 'd'
436    Xpath 'e'
437endif | Xpath 'f'
438Xpath 'g'
439
440while 1
441    Xpath 'h'
442    if 1
443	Xpath 'i'
444	asdf
445	Xpath 'j'
446    endif | Xpath 'k'
447    Xpath 'l'
448    break
449endwhile | Xpath 'm'
450Xpath 'n'
451
452asdf
453Xpath 'o'
454
455asdf | Xpath 'p'
456Xpath 'q'
457
458let g:test7_result = g:Xpath
459
460func Test_error_in_script()
461    call assert_equal('abghinoq', g:test7_result)
462endfunc
463
464"-------------------------------------------------------------------------------
465" Test 8:   Aborting and continuing on errors inside functions		    {{{1
466"
467"	    On an error inside a function without the "abort" attribute, the
468"	    script processing continues at the next line (unless the error was
469"	    in a :return command).  On an error inside a function with the
470"	    "abort" attribute, the function is aborted and the script processing
471"	    continues after the function call; the value -1 is returned then.
472"-------------------------------------------------------------------------------
473
474XpathINIT
475
476function! T8_F()
477    if 1
478	Xpath 'a'
479	while 1
480	    Xpath 'b'
481	    asdf
482	    Xpath 'c'
483	    asdf | Xpath 'd'
484	    Xpath 'e'
485	    break
486	endwhile
487	Xpath 'f'
488    endif | Xpath 'g'
489    Xpath 'h'
490
491    while 1
492	Xpath 'i'
493	if 1
494	    Xpath 'j'
495	    asdf
496	    Xpath 'k'
497	    asdf | Xpath 'l'
498	    Xpath 'm'
499	endif
500	Xpath 'n'
501	break
502    endwhile | Xpath 'o'
503    Xpath 'p'
504
505    return novar		" returns (default return value 0)
506    Xpath 'q'
507    return 1			" not reached
508endfunction
509
510function! T8_G() abort
511    if 1
512	Xpath 'r'
513	while 1
514	    Xpath 's'
515	    asdf		" returns -1
516	    Xpath 't'
517	    break
518	endwhile
519	Xpath 'v'
520    endif | Xpath 'w'
521    Xpath 'x'
522
523    return -4			" not reached
524endfunction
525
526function! T8_H() abort
527    while 1
528	Xpath 'A'
529	if 1
530	    Xpath 'B'
531	    asdf		" returns -1
532	    Xpath 'C'
533	endif
534	Xpath 'D'
535	break
536    endwhile | Xpath 'E'
537    Xpath 'F'
538
539    return -4			" not reached
540endfunction
541
542" Aborted functions (T8_G and T8_H) return -1.
543let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
544Xpath 'X'
545let g:test8_result = g:Xpath
546
547func Test_error_in_function()
548    call assert_equal(13, g:test8_sum)
549    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
550
551    delfunction T8_F
552    delfunction T8_G
553    delfunction T8_H
554endfunc
555
556
557"-------------------------------------------------------------------------------
558" Test 9:   Continuing after aborted functions				    {{{1
559"
560"	    When a function with the "abort" attribute is aborted due to an
561"	    error, the next function back in the call hierarchy without an
562"	    "abort" attribute continues; the value -1 is returned then.
563"-------------------------------------------------------------------------------
564
565XpathINIT
566
567function! F() abort
568    Xpath 'a'
569    let result = G()	" not aborted
570    Xpath 'b'
571    if result != 2
572	Xpath 'c'
573    endif
574    return 1
575endfunction
576
577function! G()		" no abort attribute
578    Xpath 'd'
579    if H() != -1	" aborted
580	Xpath 'e'
581    endif
582    Xpath 'f'
583    return 2
584endfunction
585
586function! H() abort
587    Xpath 'g'
588    call I()		" aborted
589    Xpath 'h'
590    return 4
591endfunction
592
593function! I() abort
594    Xpath 'i'
595    asdf		" error
596    Xpath 'j'
597    return 8
598endfunction
599
600if F() != 1
601    Xpath 'k'
602endif
603
604let g:test9_result = g:Xpath
605
606delfunction F
607delfunction G
608delfunction H
609delfunction I
610
611func Test_func_abort()
612    call assert_equal('adgifb', g:test9_result)
613endfunc
614
615
616"-------------------------------------------------------------------------------
617" Test 10:  :if, :elseif, :while argument parsing			    {{{1
618"
619"	    A '"' or '|' in an argument expression must not be mixed up with
620"	    a comment or a next command after a bar.  Parsing errors should
621"	    be recognized.
622"-------------------------------------------------------------------------------
623
624XpathINIT
625
626function! MSG(enr, emsg)
627    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
628    if a:enr == ""
629	Xout "TODO: Add message number for:" a:emsg
630	let v:errmsg = ":" . v:errmsg
631    endif
632    let match = 1
633    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
634	let match = 0
635	if v:errmsg == ""
636	    Xout "Message missing."
637	else
638	    let v:errmsg = v:errmsg->escape('"')
639	    Xout "Unexpected message:" v:errmsg
640	endif
641    endif
642    return match
643endfunc
644
645if 1 || strlen("\"") | Xpath 'a'
646    Xpath 'b'
647endif
648Xpath 'c'
649
650if 0
651elseif 1 || strlen("\"") | Xpath 'd'
652    Xpath 'e'
653endif
654Xpath 'f'
655
656while 1 || strlen("\"") | Xpath 'g'
657    Xpath 'h'
658    break
659endwhile
660Xpath 'i'
661
662let v:errmsg = ""
663if 1 ||| strlen("\"") | Xpath 'j'
664    Xpath 'k'
665endif
666Xpath 'l'
667if !MSG('E15', "Invalid expression")
668    Xpath 'm'
669endif
670
671let v:errmsg = ""
672if 0
673elseif 1 ||| strlen("\"") | Xpath 'n'
674    Xpath 'o'
675endif
676Xpath 'p'
677if !MSG('E15', "Invalid expression")
678    Xpath 'q'
679endif
680
681let v:errmsg = ""
682while 1 ||| strlen("\"") | Xpath 'r'
683    Xpath 's'
684    break
685endwhile
686Xpath 't'
687if !MSG('E15', "Invalid expression")
688    Xpath 'u'
689endif
690
691let g:test10_result = g:Xpath
692delfunction MSG
693
694func Test_expr_parsing()
695    call assert_equal('abcdefghilpt', g:test10_result)
696endfunc
697
698
699"-------------------------------------------------------------------------------
700" Test 11:  :if, :elseif, :while argument evaluation after abort	    {{{1
701"
702"	    When code is skipped over due to an error, the boolean argument to
703"	    an :if, :elseif, or :while must not be evaluated.
704"-------------------------------------------------------------------------------
705
706XpathINIT
707
708let calls = 0
709
710function! P(num)
711    let g:calls = g:calls + a:num   " side effect on call
712    return 0
713endfunction
714
715if 1
716    Xpath 'a'
717    asdf		" error
718    Xpath 'b'
719    if P(1)		" should not be called
720	Xpath 'c'
721    elseif !P(2)	" should not be called
722	Xpath 'd'
723    else
724	Xpath 'e'
725    endif
726    Xpath 'f'
727    while P(4)		" should not be called
728	Xpath 'g'
729    endwhile
730    Xpath 'h'
731endif
732Xpath 'x'
733
734let g:test11_calls = calls
735let g:test11_result = g:Xpath
736
737unlet calls
738delfunction P
739
740func Test_arg_abort()
741    call assert_equal(0, g:test11_calls)
742    call assert_equal('ax', g:test11_result)
743endfunc
744
745
746"-------------------------------------------------------------------------------
747" Test 12:  Expressions in braces in skipped code			    {{{1
748"
749"	    In code skipped over due to an error or inactive conditional,
750"	    an expression in braces as part of a variable or function name
751"	    should not be evaluated.
752"-------------------------------------------------------------------------------
753
754XpathINIT
755
756function! NULL()
757    Xpath 'a'
758    return 0
759endfunction
760
761function! ZERO()
762    Xpath 'b'
763    return 0
764endfunction
765
766function! F0()
767    Xpath 'c'
768endfunction
769
770function! F1(arg)
771    Xpath 'e'
772endfunction
773
774let V0 = 1
775
776Xpath 'f'
777echo 0 ? F{NULL() + V{ZERO()}}() : 1
778
779Xpath 'g'
780if 0
781    Xpath 'h'
782    call F{NULL() + V{ZERO()}}()
783endif
784
785Xpath 'i'
786if 1
787    asdf		" error
788    Xpath 'j'
789    call F1(F{NULL() + V{ZERO()}}())
790endif
791
792Xpath 'k'
793if 1
794    asdf		" error
795    Xpath 'l'
796    call F{NULL() + V{ZERO()}}()
797endif
798
799let g:test12_result = g:Xpath
800
801func Test_braces_skipped()
802    call assert_equal('fgik', g:test12_result)
803endfunc
804
805
806"-------------------------------------------------------------------------------
807" Test 13:  Failure in argument evaluation for :while			    {{{1
808"
809"	    A failure in the expression evaluation for the condition of a :while
810"	    causes the whole :while loop until the matching :endwhile being
811"	    ignored.  Continuation is at the next following line.
812"-------------------------------------------------------------------------------
813
814XpathINIT
815
816Xpath 'a'
817while asdf
818    Xpath 'b'
819    while 1
820	Xpath 'c'
821	break
822    endwhile
823    Xpath 'd'
824    break
825endwhile
826Xpath 'e'
827
828while asdf | Xpath 'f' | endwhile | Xpath 'g'
829Xpath 'h'
830let g:test13_result = g:Xpath
831
832func Test_while_fail()
833    call assert_equal('aeh', g:test13_result)
834endfunc
835
836
837"-------------------------------------------------------------------------------
838" Test 14:  Failure in argument evaluation for :if			    {{{1
839"
840"	    A failure in the expression evaluation for the condition of an :if
841"	    does not cause the corresponding :else or :endif being matched to
842"	    a previous :if/:elseif.  Neither of both branches of the failed :if
843"	    are executed.
844"-------------------------------------------------------------------------------
845
846XpathINIT
847
848function! F()
849    Xpath 'a'
850    let x = 0
851    if x		" false
852	Xpath 'b'
853    elseif !x		" always true
854	Xpath 'c'
855	let x = 1
856	if g:boolvar	" possibly undefined
857	    Xpath 'd'
858	else
859	    Xpath 'e'
860	endif
861	Xpath 'f'
862    elseif x		" never executed
863	Xpath 'g'
864    endif
865    Xpath 'h'
866endfunction
867
868let boolvar = 1
869call F()
870Xpath '-'
871
872unlet boolvar
873call F()
874let g:test14_result = g:Xpath
875
876delfunction F
877
878func Test_if_fail()
879    call assert_equal('acdfh-acfh', g:test14_result)
880endfunc
881
882
883"-------------------------------------------------------------------------------
884" Test 15:  Failure in argument evaluation for :if (bar)		    {{{1
885"
886"	    Like previous test, except that the failing :if ... | ... | :endif
887"	    is in a single line.
888"-------------------------------------------------------------------------------
889
890XpathINIT
891
892function! F()
893    Xpath 'a'
894    let x = 0
895    if x		" false
896	Xpath 'b'
897    elseif !x		" always true
898	Xpath 'c'
899	let x = 1
900	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
901	Xpath 'f'
902    elseif x		" never executed
903	Xpath 'g'
904    endif
905    Xpath 'h'
906endfunction
907
908let boolvar = 1
909call F()
910Xpath '-'
911
912unlet boolvar
913call F()
914let g:test15_result = g:Xpath
915
916delfunction F
917
918func Test_if_bar_fail()
919    call assert_equal('acdfh-acfh', g:test15_result)
920endfunc
921
922"-------------------------------------------------------------------------------
923" Test 16:  Double :else or :elseif after :else				    {{{1
924"
925"	    Multiple :elses or an :elseif after an :else are forbidden.
926"-------------------------------------------------------------------------------
927
928func T16_F() abort
929  if 0
930    Xpath 'a'
931  else
932    Xpath 'b'
933  else		" aborts function
934    Xpath 'c'
935  endif
936  Xpath 'd'
937endfunc
938
939func T16_G() abort
940  if 0
941    Xpath 'a'
942  else
943    Xpath 'b'
944  elseif 1		" aborts function
945    Xpath 'c'
946  else
947    Xpath 'd'
948  endif
949  Xpath 'e'
950endfunc
951
952func T16_H() abort
953  if 0
954    Xpath 'a'
955  elseif 0
956    Xpath 'b'
957  else
958    Xpath 'c'
959  else		" aborts function
960    Xpath 'd'
961  endif
962  Xpath 'e'
963endfunc
964
965func T16_I() abort
966  if 0
967    Xpath 'a'
968  elseif 0
969    Xpath 'b'
970  else
971    Xpath 'c'
972  elseif 1		" aborts function
973    Xpath 'd'
974  else
975    Xpath 'e'
976  endif
977  Xpath 'f'
978endfunc
979
980func Test_Multi_Else()
981  XpathINIT
982  try
983    call T16_F()
984  catch /E583:/
985    Xpath 'e'
986  endtry
987  call assert_equal('be', g:Xpath)
988
989  XpathINIT
990  try
991    call T16_G()
992  catch /E584:/
993    Xpath 'f'
994  endtry
995  call assert_equal('bf', g:Xpath)
996
997  XpathINIT
998  try
999    call T16_H()
1000  catch /E583:/
1001    Xpath 'f'
1002  endtry
1003  call assert_equal('cf', g:Xpath)
1004
1005  XpathINIT
1006  try
1007    call T16_I()
1008  catch /E584:/
1009    Xpath 'g'
1010  endtry
1011  call assert_equal('cg', g:Xpath)
1012endfunc
1013
1014"-------------------------------------------------------------------------------
1015" Test 17:  Nesting of unmatched :if or :endif inside a :while		    {{{1
1016"
1017"	    The :while/:endwhile takes precedence in nesting over an unclosed
1018"	    :if or an unopened :endif.
1019"-------------------------------------------------------------------------------
1020
1021" While loops inside a function are continued on error.
1022func T17_F()
1023  let loops = 3
1024  while loops > 0
1025    let loops -= 1
1026    Xpath 'a' . loops
1027    if (loops == 1)
1028      Xpath 'b' . loops
1029      continue
1030    elseif (loops == 0)
1031      Xpath 'c' . loops
1032      break
1033    elseif 1
1034      Xpath 'd' . loops
1035    " endif missing!
1036  endwhile	" :endwhile after :if 1
1037  Xpath 'e'
1038endfunc
1039
1040func T17_G()
1041  let loops = 2
1042  while loops > 0
1043    let loops -= 1
1044    Xpath 'a' . loops
1045    if 0
1046      Xpath 'b' . loops
1047    " endif missing
1048  endwhile	" :endwhile after :if 0
1049endfunc
1050
1051func T17_H()
1052  let loops = 2
1053  while loops > 0
1054    let loops -= 1
1055    Xpath 'a' . loops
1056    " if missing!
1057    endif	" :endif without :if in while
1058    Xpath 'b' . loops
1059  endwhile
1060endfunc
1061
1062" Error continuation outside a function is at the outermost :endwhile or :endif.
1063XpathINIT
1064let v:errmsg = ''
1065let loops = 2
1066while loops > 0
1067    let loops -= 1
1068    Xpath 'a' . loops
1069    if 0
1070	Xpath 'b' . loops
1071    " endif missing! Following :endwhile fails.
1072endwhile | Xpath 'c'
1073Xpath 'd'
1074call assert_match('E171:', v:errmsg)
1075call assert_equal('a1d', g:Xpath)
1076
1077func Test_unmatched_if_in_while()
1078  XpathINIT
1079  call assert_fails('call T17_F()', 'E171:')
1080  call assert_equal('a2d2a1b1a0c0e', g:Xpath)
1081
1082  XpathINIT
1083  call assert_fails('call T17_G()', 'E171:')
1084  call assert_equal('a1a0', g:Xpath)
1085
1086  XpathINIT
1087  call assert_fails('call T17_H()', 'E580:')
1088  call assert_equal('a1b1a0b0', g:Xpath)
1089endfunc
1090
1091"-------------------------------------------------------------------------------
1092"-------------------------------------------------------------------------------
1093"-------------------------------------------------------------------------------
1094" Test 87   using (expr) ? funcref : funcref				    {{{1
1095"
1096"	    Vim needs to correctly parse the funcref and even when it does
1097"	    not execute the funcref, it needs to consume the trailing ()
1098"-------------------------------------------------------------------------------
1099
1100func Add2(x1, x2)
1101  return a:x1 + a:x2
1102endfu
1103
1104func GetStr()
1105  return "abcdefghijklmnopqrstuvwxyp"
1106endfu
1107
1108func Test_funcref_with_condexpr()
1109  call assert_equal(5, function('Add2')(2,3))
1110
1111  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
1112  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
1113  " Make sure, GetStr() still works.
1114  call assert_equal('abcdefghijk', GetStr()[0:10])
1115endfunc
1116
1117"-------------------------------------------------------------------------------
1118" Test 90:  Recognizing {} in variable name.			    {{{1
1119"-------------------------------------------------------------------------------
1120
1121func Test_curlies()
1122    let s:var = 66
1123    let ns = 's'
1124    call assert_equal(66, {ns}:var)
1125
1126    let g:a = {}
1127    let g:b = 't'
1128    let g:a[g:b] = 77
1129    call assert_equal(77, g:a['t'])
1130endfunc
1131
1132"-------------------------------------------------------------------------------
1133" Test 91:  using type().					    {{{1
1134"-------------------------------------------------------------------------------
1135
1136func Test_type()
1137    call assert_equal(0, type(0))
1138    call assert_equal(1, type(""))
1139    call assert_equal(2, type(function("tr")))
1140    call assert_equal(2, type(function("tr", [8])))
1141    call assert_equal(3, type([]))
1142    call assert_equal(4, type({}))
1143    call assert_equal(5, type(0.0))
1144    call assert_equal(6, type(v:false))
1145    call assert_equal(6, type(v:true))
1146    call assert_equal(7, type(v:null))
1147    call assert_equal(v:t_number, type(0))
1148    call assert_equal(v:t_string, type(""))
1149    call assert_equal(v:t_func, type(function("tr")))
1150    call assert_equal(v:t_list, type([]))
1151    call assert_equal(v:t_dict, type({}))
1152    call assert_equal(v:t_float, type(0.0))
1153    call assert_equal(v:t_bool, type(v:false))
1154    call assert_equal(v:t_bool, type(v:true))
1155    call assert_equal(v:t_string, type(v:_null_string))
1156    call assert_equal(v:t_list, type(v:_null_list))
1157    call assert_equal(v:t_dict, type(v:_null_dict))
1158    call assert_equal(v:t_blob, type(v:_null_blob))
1159endfunc
1160
1161"-------------------------------------------------------------------------------
1162" Test 92:  skipping code                       {{{1
1163"-------------------------------------------------------------------------------
1164
1165func Test_skip()
1166    let Fn = function('Test_type')
1167    call assert_false(0 && Fn[1])
1168    call assert_false(0 && string(Fn))
1169    call assert_false(0 && len(Fn))
1170    let l = []
1171    call assert_false(0 && l[1])
1172    call assert_false(0 && string(l))
1173    call assert_false(0 && len(l))
1174    let f = 1.0
1175    call assert_false(0 && f[1])
1176    call assert_false(0 && string(f))
1177    call assert_false(0 && len(f))
1178    let sp = v:null
1179    call assert_false(0 && sp[1])
1180    call assert_false(0 && string(sp))
1181    call assert_false(0 && len(sp))
1182
1183endfunc
1184
1185"-------------------------------------------------------------------------------
1186" Test 93:  :echo and string()					    {{{1
1187"-------------------------------------------------------------------------------
1188
1189func Test_echo_and_string()
1190    " String
1191    let a = 'foo bar'
1192    redir => result
1193    echo a
1194    echo string(a)
1195    redir END
1196    let l = split(result, "\n")
1197    call assert_equal(["foo bar",
1198		     \ "'foo bar'"], l)
1199
1200    " Float
1201    if has('float')
1202	let a = -1.2e0
1203	redir => result
1204	echo a
1205	echo string(a)
1206	redir END
1207	let l = split(result, "\n")
1208	call assert_equal(["-1.2",
1209			 \ "-1.2"], l)
1210    endif
1211
1212    " Funcref
1213    redir => result
1214    echo function('string')
1215    echo string(function('string'))
1216    redir END
1217    let l = split(result, "\n")
1218    call assert_equal(["string",
1219		     \ "function('string')"], l)
1220
1221    " Empty dictionaries in a list
1222    let a = {}
1223    redir => result
1224    echo [a, a, a]
1225    echo string([a, a, a])
1226    redir END
1227    let l = split(result, "\n")
1228    call assert_equal(["[{}, {}, {}]",
1229		     \ "[{}, {}, {}]"], l)
1230
1231    " Empty dictionaries in a dictionary
1232    let a = {}
1233    let b = {"a": a, "b": a}
1234    redir => result
1235    echo b
1236    echo string(b)
1237    redir END
1238    let l = split(result, "\n")
1239    call assert_equal(["{'a': {}, 'b': {}}",
1240		     \ "{'a': {}, 'b': {}}"], l)
1241
1242    " Empty lists in a list
1243    let a = []
1244    redir => result
1245    echo [a, a, a]
1246    echo string([a, a, a])
1247    redir END
1248    let l = split(result, "\n")
1249    call assert_equal(["[[], [], []]",
1250		     \ "[[], [], []]"], l)
1251
1252    " Empty lists in a dictionary
1253    let a = []
1254    let b = {"a": a, "b": a}
1255    redir => result
1256    echo b
1257    echo string(b)
1258    redir END
1259    let l = split(result, "\n")
1260    call assert_equal(["{'a': [], 'b': []}",
1261		     \ "{'a': [], 'b': []}"], l)
1262endfunc
1263
1264"-------------------------------------------------------------------------------
1265" Test 94:  64-bit Numbers					    {{{1
1266"-------------------------------------------------------------------------------
1267
1268func Test_num64()
1269    call assert_notequal( 4294967296, 0)
1270    call assert_notequal(-4294967296, 0)
1271    call assert_equal( 4294967296,  0xFFFFffff + 1)
1272    call assert_equal(-4294967296, -0xFFFFffff - 1)
1273
1274    call assert_equal( 9223372036854775807,  1 / 0)
1275    call assert_equal(-9223372036854775807, -1 / 0)
1276    call assert_equal(-9223372036854775807 - 1,  0 / 0)
1277
1278    if has('float')
1279      call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
1280      call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
1281    endif
1282
1283    let rng = range(0xFFFFffff, 0x100000001)
1284    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
1285    call assert_equal(0x100000001, max(rng))
1286    call assert_equal(0xFFFFffff, min(rng))
1287    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
1288endfunc
1289
1290"-------------------------------------------------------------------------------
1291" Test 95:  lines of :append, :change, :insert			    {{{1
1292"-------------------------------------------------------------------------------
1293
1294function! DefineFunction(name, body)
1295    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
1296    exec func
1297endfunction
1298
1299func Test_script_lines()
1300    " :append
1301    try
1302	call DefineFunction('T_Append', [
1303		    \ 'append',
1304		    \ 'py <<EOS',
1305		    \ '.',
1306		    \ ])
1307    catch
1308	call assert_report("Can't define function")
1309    endtry
1310    try
1311	call DefineFunction('T_Append', [
1312		    \ 'append',
1313		    \ 'abc',
1314		    \ ])
1315	call assert_report("Shouldn't be able to define function")
1316    catch
1317	call assert_exception('Vim(function):E126: Missing :endfunction')
1318    endtry
1319
1320    " :change
1321    try
1322	call DefineFunction('T_Change', [
1323		    \ 'change',
1324		    \ 'py <<EOS',
1325		    \ '.',
1326		    \ ])
1327    catch
1328	call assert_report("Can't define function")
1329    endtry
1330    try
1331	call DefineFunction('T_Change', [
1332		    \ 'change',
1333		    \ 'abc',
1334		    \ ])
1335	call assert_report("Shouldn't be able to define function")
1336    catch
1337	call assert_exception('Vim(function):E126: Missing :endfunction')
1338    endtry
1339
1340    " :insert
1341    try
1342	call DefineFunction('T_Insert', [
1343		    \ 'insert',
1344		    \ 'py <<EOS',
1345		    \ '.',
1346		    \ ])
1347    catch
1348	call assert_report("Can't define function")
1349    endtry
1350    try
1351	call DefineFunction('T_Insert', [
1352		    \ 'insert',
1353		    \ 'abc',
1354		    \ ])
1355	call assert_report("Shouldn't be able to define function")
1356    catch
1357	call assert_exception('Vim(function):E126: Missing :endfunction')
1358    endtry
1359endfunc
1360
1361"-------------------------------------------------------------------------------
1362" Test 96:  line continuation						    {{{1
1363"
1364"	    Undefined behavior was detected by ubsan with line continuation
1365"	    after an empty line.
1366"-------------------------------------------------------------------------------
1367func Test_script_emty_line_continuation()
1368
1369    \
1370endfunc
1371
1372"-------------------------------------------------------------------------------
1373" Test 97:  bitwise functions						    {{{1
1374"-------------------------------------------------------------------------------
1375func Test_bitwise_functions()
1376    " and
1377    call assert_equal(127, and(127, 127))
1378    call assert_equal(16, and(127, 16))
1379    eval 127->and(16)->assert_equal(16)
1380    call assert_equal(0, and(127, 128))
1381    call assert_fails("call and(1.0, 1)", 'E805:')
1382    call assert_fails("call and([], 1)", 'E745:')
1383    call assert_fails("call and({}, 1)", 'E728:')
1384    call assert_fails("call and(1, 1.0)", 'E805:')
1385    call assert_fails("call and(1, [])", 'E745:')
1386    call assert_fails("call and(1, {})", 'E728:')
1387    " or
1388    call assert_equal(23, or(16, 7))
1389    call assert_equal(15, or(8, 7))
1390    eval 8->or(7)->assert_equal(15)
1391    call assert_equal(123, or(0, 123))
1392    call assert_fails("call or(1.0, 1)", 'E805:')
1393    call assert_fails("call or([], 1)", 'E745:')
1394    call assert_fails("call or({}, 1)", 'E728:')
1395    call assert_fails("call or(1, 1.0)", 'E805:')
1396    call assert_fails("call or(1, [])", 'E745:')
1397    call assert_fails("call or(1, {})", 'E728:')
1398    " xor
1399    call assert_equal(0, xor(127, 127))
1400    call assert_equal(111, xor(127, 16))
1401    eval 127->xor(16)->assert_equal(111)
1402    call assert_equal(255, xor(127, 128))
1403    call assert_fails("call xor(1.0, 1)", 'E805:')
1404    call assert_fails("call xor([], 1)", 'E745:')
1405    call assert_fails("call xor({}, 1)", 'E728:')
1406    call assert_fails("call xor(1, 1.0)", 'E805:')
1407    call assert_fails("call xor(1, [])", 'E745:')
1408    call assert_fails("call xor(1, {})", 'E728:')
1409    " invert
1410    call assert_equal(65408, and(invert(127), 65535))
1411    eval 127->invert()->and(65535)->assert_equal(65408)
1412    call assert_equal(65519, and(invert(16), 65535))
1413    call assert_equal(65407, and(invert(128), 65535))
1414    call assert_fails("call invert(1.0)", 'E805:')
1415    call assert_fails("call invert([])", 'E745:')
1416    call assert_fails("call invert({})", 'E728:')
1417endfunc
1418
1419" Test trailing text after :endfunction				    {{{1
1420func Test_endfunction_trailing()
1421    call assert_false(exists('*Xtest'))
1422
1423    exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'"
1424    call assert_true(exists('*Xtest'))
1425    call assert_equal('yes', done)
1426    delfunc Xtest
1427    unlet done
1428
1429    exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'"
1430    call assert_true(exists('*Xtest'))
1431    call assert_equal('yes', done)
1432    delfunc Xtest
1433    unlet done
1434
1435    " trailing line break
1436    exe "func Xtest()\necho 'hello'\nendfunc\n"
1437    call assert_true(exists('*Xtest'))
1438    delfunc Xtest
1439
1440    set verbose=1
1441    exe "func Xtest()\necho 'hello'\nendfunc \" garbage"
1442    call assert_notmatch('W22:', split(execute('1messages'), "\n")[0])
1443    call assert_true(exists('*Xtest'))
1444    delfunc Xtest
1445
1446    exe "func Xtest()\necho 'hello'\nendfunc garbage"
1447    call assert_match('W22:', split(execute('1messages'), "\n")[0])
1448    call assert_true(exists('*Xtest'))
1449    delfunc Xtest
1450    set verbose=0
1451
1452    function Foo()
1453	echo 'hello'
1454    endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
1455    delfunc Foo
1456endfunc
1457
1458func Test_delfunction_force()
1459    delfunc! Xtest
1460    delfunc! Xtest
1461    func Xtest()
1462	echo 'nothing'
1463    endfunc
1464    delfunc! Xtest
1465    delfunc! Xtest
1466endfunc
1467
1468" Test using bang after user command				    {{{1
1469func Test_user_command_with_bang()
1470    command -bang Nieuw let nieuw = 1
1471    Ni!
1472    call assert_equal(1, nieuw)
1473    unlet nieuw
1474    delcommand Nieuw
1475endfunc
1476
1477" Test for script-local function
1478func <SID>DoLast()
1479  call append(line('$'), "last line")
1480endfunc
1481
1482func s:DoNothing()
1483  call append(line('$'), "nothing line")
1484endfunc
1485
1486func Test_script_local_func()
1487  set nocp nomore viminfo+=nviminfo
1488  new
1489  nnoremap <buffer> _x	:call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
1490
1491  normal _x
1492  call assert_equal('nothing line', getline(2))
1493  call assert_equal('last line', getline(3))
1494  enew! | close
1495endfunc
1496
1497func Test_compound_assignment_operators()
1498    " Test for number
1499    let x = 1
1500    let x += 10
1501    call assert_equal(11, x)
1502    let x -= 5
1503    call assert_equal(6, x)
1504    let x *= 4
1505    call assert_equal(24, x)
1506    let x /= 3
1507    call assert_equal(8, x)
1508    let x %= 3
1509    call assert_equal(2, x)
1510    let x .= 'n'
1511    call assert_equal('2n', x)
1512
1513    " Test special cases: division or modulus with 0.
1514    let x = 1
1515    let x /= 0
1516    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
1517
1518    let x = -1
1519    let x /= 0
1520    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
1521
1522    let x = 0
1523    let x /= 0
1524    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
1525
1526    let x = 1
1527    let x %= 0
1528    call assert_equal(0, x)
1529
1530    let x = -1
1531    let x %= 0
1532    call assert_equal(0, x)
1533
1534    let x = 0
1535    let x %= 0
1536    call assert_equal(0, x)
1537
1538    " Test for string
1539    let x = 'str'
1540    let x .= 'ing'
1541    call assert_equal('string', x)
1542    let x += 1
1543    call assert_equal(1, x)
1544
1545    if has('float')
1546      " Test for float
1547      let x -= 1.5
1548      call assert_equal(-0.5, x)
1549      let x = 0.5
1550      let x += 4.5
1551      call assert_equal(5.0, x)
1552      let x -= 1.5
1553      call assert_equal(3.5, x)
1554      let x *= 3.0
1555      call assert_equal(10.5, x)
1556      let x /= 2.5
1557      call assert_equal(4.2, x)
1558      call assert_fails('let x %= 0.5', 'E734')
1559      call assert_fails('let x .= "f"', 'E734')
1560    endif
1561
1562    " Test for environment variable
1563    let $FOO = 1
1564    call assert_fails('let $FOO += 1', 'E734')
1565    call assert_fails('let $FOO -= 1', 'E734')
1566    call assert_fails('let $FOO *= 1', 'E734')
1567    call assert_fails('let $FOO /= 1', 'E734')
1568    call assert_fails('let $FOO %= 1', 'E734')
1569    let $FOO .= 's'
1570    call assert_equal('1s', $FOO)
1571    unlet $FOO
1572
1573    " Test for option variable (type: number)
1574    let &scrolljump = 1
1575    let &scrolljump += 5
1576    call assert_equal(6, &scrolljump)
1577    let &scrolljump -= 2
1578    call assert_equal(4, &scrolljump)
1579    let &scrolljump *= 3
1580    call assert_equal(12, &scrolljump)
1581    let &scrolljump /= 2
1582    call assert_equal(6, &scrolljump)
1583    let &scrolljump %= 5
1584    call assert_equal(1, &scrolljump)
1585    call assert_fails('let &scrolljump .= "j"', 'E734')
1586    set scrolljump&vim
1587
1588    " Test for register
1589    let @/ = 1
1590    call assert_fails('let @/ += 1', 'E734')
1591    call assert_fails('let @/ -= 1', 'E734')
1592    call assert_fails('let @/ *= 1', 'E734')
1593    call assert_fails('let @/ /= 1', 'E734')
1594    call assert_fails('let @/ %= 1', 'E734')
1595    let @/ .= 's'
1596    call assert_equal('1s', @/)
1597    let @/ = ''
1598endfunc
1599
1600func Test_unlet_env()
1601    let $TESTVAR = 'yes'
1602    call assert_equal('yes', $TESTVAR)
1603    call assert_fails('lockvar $TESTVAR', 'E940')
1604    call assert_fails('unlockvar $TESTVAR', 'E940')
1605    call assert_equal('yes', $TESTVAR)
1606    if 0
1607        unlet $TESTVAR
1608    endif
1609    call assert_equal('yes', $TESTVAR)
1610    unlet $TESTVAR
1611    call assert_equal('', $TESTVAR)
1612endfunc
1613
1614func Test_funccall_garbage_collect()
1615    func Func(x, ...)
1616        call add(a:x, a:000)
1617    endfunc
1618    call Func([], [])
1619    " Must not crash cause by invalid freeing
1620    call test_garbagecollect_now()
1621    call assert_true(v:true)
1622    delfunc Func
1623endfunc
1624
1625func Test_function_defined_line()
1626    if has('gui_running')
1627        " Can't catch the output of gvim.
1628        return
1629    endif
1630
1631    let lines =<< trim [CODE]
1632    " F1
1633    func F1()
1634        " F2
1635        func F2()
1636            "
1637            "
1638            "
1639            return
1640        endfunc
1641        " F3
1642        execute "func F3()\n\n\n\nreturn\nendfunc"
1643        " F4
1644        execute "func F4()\n
1645                    \\n
1646                    \\n
1647                    \\n
1648                    \return\n
1649                    \endfunc"
1650    endfunc
1651    " F5
1652    execute "func F5()\n\n\n\nreturn\nendfunc"
1653    " F6
1654    execute "func F6()\n
1655                \\n
1656                \\n
1657                \\n
1658                \return\n
1659                \endfunc"
1660    call F1()
1661    verbose func F1
1662    verbose func F2
1663    verbose func F3
1664    verbose func F4
1665    verbose func F5
1666    verbose func F6
1667    qall!
1668    [CODE]
1669
1670    call writefile(lines, 'Xtest.vim')
1671    let res = system(v:progpath .. ' --clean -es -X -S Xtest.vim')
1672    call assert_equal(0, v:shell_error)
1673
1674    let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*')
1675    call assert_match(' line 2$', m)
1676
1677    let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*')
1678    call assert_match(' line 4$', m)
1679
1680    let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*')
1681    call assert_match(' line 11$', m)
1682
1683    let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*')
1684    call assert_match(' line 13$', m)
1685
1686    let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*')
1687    call assert_match(' line 21$', m)
1688
1689    let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*')
1690    call assert_match(' line 23$', m)
1691
1692    call delete('Xtest.vim')
1693endfunc
1694
1695"-------------------------------------------------------------------------------
1696" Modelines								    {{{1
1697" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1698"-------------------------------------------------------------------------------
1699