blob: 39c0667b81409b9aeedaf22e2e86612a60a4051c [file] [log] [blame]
Bram Moolenaarf49e2402015-12-30 15:59:25 +01001" Test various aspects of the Vim language.
Bram Moolenaar4119cf82016-01-17 14:59:01 +01002" Most of this was formerly in test49.
Bram Moolenaarf49e2402015-12-30 15:59:25 +01003
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 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
53endfunction
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.
59function! ExecAsScript(funcname)
60 " Make a script from the function passed as argument.
61 let script = MakeScript(a:funcname)
62
63 " Source and delete the script.
64 exec "source" script
65 call delete(script)
66endfunction
67
68com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
69
70
71"-------------------------------------------------------------------------------
72" Test 1: :endwhile in function {{{1
73"
74" Detect if a broken loop is (incorrectly) reactivated by the
75" :endwhile. Use a :return to prevent an endless loop, and make
76" this test first to get a meaningful result on an error before other
77" tests will hang.
78"-------------------------------------------------------------------------------
79
80function! T1_F()
81 Xpath 'a'
82 let first = 1
83 while 1
84 Xpath 'b'
85 if first
86 Xpath 'c'
87 let first = 0
88 break
89 else
90 Xpath 'd'
91 return
92 endif
93 endwhile
94endfunction
95
96function! T1_G()
97 Xpath 'h'
98 let first = 1
99 while 1
100 Xpath 'i'
101 if first
102 Xpath 'j'
103 let first = 0
104 break
105 else
106 Xpath 'k'
107 return
108 endif
109 if 1 " unmatched :if
110 endwhile
111endfunction
112
113func Test_endwhile_function()
114 XpathINIT
115 call T1_F()
116 Xpath 'F'
117
118 try
119 call T1_G()
120 catch
121 " Catch missing :endif
122 call assert_true(v:exception =~ 'E171')
123 Xpath 'x'
124 endtry
125 Xpath 'G'
126
127 call assert_equal('abcFhijxG', g:Xpath)
128endfunc
129
130"-------------------------------------------------------------------------------
131" Test 2: :endwhile in script {{{1
132"
133" Detect if a broken loop is (incorrectly) reactivated by the
134" :endwhile. Use a :finish to prevent an endless loop, and place
135" this test before others that might hang to get a meaningful result
136" on an error.
137"
138" This test executes the bodies of the functions T1_F and T1_G from
139" the previous test as script files (:return replaced by :finish).
140"-------------------------------------------------------------------------------
141
142func Test_endwhile_script()
143 XpathINIT
144 ExecAsScript T1_F
145 Xpath 'F'
146
147 try
148 ExecAsScript T1_G
149 catch
150 " Catch missing :endif
151 call assert_true(v:exception =~ 'E171')
152 Xpath 'x'
153 endtry
154 Xpath 'G'
155
156 call assert_equal('abcFhijxG', g:Xpath)
157endfunc
158
159"-------------------------------------------------------------------------------
160" Test 3: :if, :elseif, :while, :continue, :break {{{1
161"-------------------------------------------------------------------------------
162
163function Test_if_while()
164 XpathINIT
165 if 1
166 Xpath 'a'
167 let loops = 3
168 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
169 if loops <= 0
170 let break_err = 1
171 let loops = -1
172 else
173 Xpath 'b' . loops
174 endif
175 if (loops == 2)
176 while loops == 2 " dummy loop
177 Xpath 'c' . loops
178 let loops = loops - 1
179 continue " stop dummy loop
180 Xpath 'd' . loops
181 endwhile
182 continue " continue main loop
183 Xpath 'e' . loops
184 elseif (loops == 1)
185 let p = 1
186 while p " dummy loop
187 Xpath 'f' . loops
188 let p = 0
189 break " break dummy loop
190 Xpath 'g' . loops
191 endwhile
192 Xpath 'h' . loops
193 unlet p
194 break " break main loop
195 Xpath 'i' . loops
196 endif
197 if (loops > 0)
198 Xpath 'j' . loops
199 endif
200 while loops == 3 " dummy loop
201 let loops = loops - 1
202 endwhile " end dummy loop
203 endwhile " end main loop
204 Xpath 'k'
205 else
206 Xpath 'l'
207 endif
208 Xpath 'm'
209 if exists("break_err")
210 Xpath 'm'
211 unlet break_err
212 endif
213
214 unlet loops
215
216 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
217endfunc
218
219"-------------------------------------------------------------------------------
220" Test 4: :return {{{1
221"-------------------------------------------------------------------------------
222
223function! T4_F()
224 if 1
225 Xpath 'a'
226 let loops = 3
227 while loops > 0 " 3: 2: 1:
228 Xpath 'b' . loops
229 if (loops == 2)
230 Xpath 'c' . loops
231 return
232 Xpath 'd' . loops
233 endif
234 Xpath 'e' . loops
235 let loops = loops - 1
236 endwhile
237 Xpath 'f'
238 else
239 Xpath 'g'
240 endif
241endfunction
242
243function Test_return()
244 XpathINIT
245 call T4_F()
246 Xpath '4'
247
248 call assert_equal('ab3e3b2c24', g:Xpath)
249endfunction
250
251
252"-------------------------------------------------------------------------------
253" Test 5: :finish {{{1
254"
255" This test executes the body of the function T4_F from the previous
256" test as a script file (:return replaced by :finish).
257"-------------------------------------------------------------------------------
258
259function Test_finish()
260 XpathINIT
261 ExecAsScript T4_F
262 Xpath '5'
263
264 call assert_equal('ab3e3b2c25', g:Xpath)
265endfunction
266
267
268
269"-------------------------------------------------------------------------------
270" Test 6: Defining functions in :while loops {{{1
271"
272" Functions can be defined inside other functions. An inner function
273" gets defined when the outer function is executed. Functions may
274" also be defined inside while loops. Expressions in braces for
275" defining the function name are allowed.
276"
277" The functions are defined when sourcing the script, only the
278" resulting path is checked in the test function.
279"-------------------------------------------------------------------------------
280
281XpathINIT
282
283" The command CALL collects the argument of all its invocations in "calls"
284" when used from a function (that is, when the global variable "calls" needs
285" the "g:" prefix). This is to check that the function code is skipped when
286" the function is defined. For inner functions, do so only if the outer
287" function is not being executed.
288"
289let calls = ""
290com! -nargs=1 CALL
291 \ if !exists("calls") && !exists("outer") |
292 \ let g:calls = g:calls . <args> |
293 \ endif
294
295let i = 0
296while i < 3
297 let i = i + 1
298 if i == 1
299 Xpath 'a'
300 function! F1(arg)
301 CALL a:arg
302 let outer = 1
303
304 let j = 0
305 while j < 1
306 Xpath 'b'
307 let j = j + 1
308 function! G1(arg)
309 CALL a:arg
310 endfunction
311 Xpath 'c'
312 endwhile
313 endfunction
314 Xpath 'd'
315
316 continue
317 endif
318
319 Xpath 'e' . i
320 function! F{i}(i, arg)
321 CALL a:arg
322 let outer = 1
323
324 if a:i == 3
325 Xpath 'f'
326 endif
327 let k = 0
328 while k < 3
329 Xpath 'g' . k
330 let k = k + 1
331 function! G{a:i}{k}(arg)
332 CALL a:arg
333 endfunction
334 Xpath 'h' . k
335 endwhile
336 endfunction
337 Xpath 'i'
338
339endwhile
340
341if exists("*G1")
342 Xpath 'j'
343endif
344if exists("*F1")
345 call F1("F1")
346 if exists("*G1")
347 call G1("G1")
348 endif
349endif
350
351if exists("G21") || exists("G22") || exists("G23")
352 Xpath 'k'
353endif
354if exists("*F2")
355 call F2(2, "F2")
356 if exists("*G21")
357 call G21("G21")
358 endif
359 if exists("*G22")
360 call G22("G22")
361 endif
362 if exists("*G23")
363 call G23("G23")
364 endif
365endif
366
367if exists("G31") || exists("G32") || exists("G33")
368 Xpath 'l'
369endif
370if exists("*F3")
371 call F3(3, "F3")
372 if exists("*G31")
373 call G31("G31")
374 endif
375 if exists("*G32")
376 call G32("G32")
377 endif
378 if exists("*G33")
379 call G33("G33")
380 endif
381endif
382
383Xpath 'm'
384
385let g:test6_result = g:Xpath
386let g:test6_calls = calls
387
388unlet calls
389delfunction F1
390delfunction G1
391delfunction F2
392delfunction G21
393delfunction G22
394delfunction G23
395delfunction G31
396delfunction G32
397delfunction G33
398
399function Test_defining_functions()
400 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
401 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
402endfunc
403
404"-------------------------------------------------------------------------------
Bram Moolenaara2cce862016-01-02 19:50:04 +0100405" Test 7: Continuing on errors outside functions {{{1
406"
407" On an error outside a function, the script processing continues
408" at the line following the outermost :endif or :endwhile. When not
409" inside an :if or :while, the script processing continues at the next
410" line.
411"-------------------------------------------------------------------------------
412
413XpathINIT
414
415if 1
416 Xpath 'a'
417 while 1
418 Xpath 'b'
419 asdf
420 Xpath 'c'
421 break
422 endwhile | Xpath 'd'
423 Xpath 'e'
424endif | Xpath 'f'
425Xpath 'g'
426
427while 1
428 Xpath 'h'
429 if 1
430 Xpath 'i'
431 asdf
432 Xpath 'j'
433 endif | Xpath 'k'
434 Xpath 'l'
435 break
436endwhile | Xpath 'm'
437Xpath 'n'
438
439asdf
440Xpath 'o'
441
442asdf | Xpath 'p'
443Xpath 'q'
444
445let g:test7_result = g:Xpath
446
447func Test_error_in_script()
448 call assert_equal('abghinoq', g:test7_result)
449endfunc
450
451"-------------------------------------------------------------------------------
452" Test 8: Aborting and continuing on errors inside functions {{{1
453"
454" On an error inside a function without the "abort" attribute, the
455" script processing continues at the next line (unless the error was
456" in a :return command). On an error inside a function with the
457" "abort" attribute, the function is aborted and the script processing
458" continues after the function call; the value -1 is returned then.
459"-------------------------------------------------------------------------------
460
461XpathINIT
462
463function! T8_F()
464 if 1
465 Xpath 'a'
466 while 1
467 Xpath 'b'
468 asdf
469 Xpath 'c'
470 asdf | Xpath 'd'
471 Xpath 'e'
472 break
473 endwhile
474 Xpath 'f'
475 endif | Xpath 'g'
476 Xpath 'h'
477
478 while 1
479 Xpath 'i'
480 if 1
481 Xpath 'j'
482 asdf
483 Xpath 'k'
484 asdf | Xpath 'l'
485 Xpath 'm'
486 endif
487 Xpath 'n'
488 break
489 endwhile | Xpath 'o'
490 Xpath 'p'
491
492 return novar " returns (default return value 0)
493 Xpath 'q'
494 return 1 " not reached
495endfunction
496
497function! T8_G() abort
498 if 1
499 Xpath 'r'
500 while 1
501 Xpath 's'
502 asdf " returns -1
503 Xpath 't'
504 break
505 endwhile
506 Xpath 'v'
507 endif | Xpath 'w'
508 Xpath 'x'
509
510 return -4 " not reached
511endfunction
512
513function! T8_H() abort
514 while 1
515 Xpath 'A'
516 if 1
517 Xpath 'B'
518 asdf " returns -1
519 Xpath 'C'
520 endif
521 Xpath 'D'
522 break
523 endwhile | Xpath 'E'
524 Xpath 'F'
525
526 return -4 " not reached
527endfunction
528
529" Aborted functions (T8_G and T8_H) return -1.
530let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
531Xpath 'X'
532let g:test8_result = g:Xpath
533
534func Test_error_in_function()
535 call assert_equal(13, g:test8_sum)
536 call assert_equal('abcefghijkmnoprsABX', g:test8_result)
537
538 delfunction T8_F
539 delfunction T8_G
540 delfunction T8_H
541endfunc
542
543
544"-------------------------------------------------------------------------------
545" Test 9: Continuing after aborted functions {{{1
546"
547" When a function with the "abort" attribute is aborted due to an
548" error, the next function back in the call hierarchy without an
549" "abort" attribute continues; the value -1 is returned then.
550"-------------------------------------------------------------------------------
551
552XpathINIT
553
554function! F() abort
555 Xpath 'a'
556 let result = G() " not aborted
557 Xpath 'b'
558 if result != 2
559 Xpath 'c'
560 endif
561 return 1
562endfunction
563
564function! G() " no abort attribute
565 Xpath 'd'
566 if H() != -1 " aborted
567 Xpath 'e'
568 endif
569 Xpath 'f'
570 return 2
571endfunction
572
573function! H() abort
574 Xpath 'g'
575 call I() " aborted
576 Xpath 'h'
577 return 4
578endfunction
579
580function! I() abort
581 Xpath 'i'
582 asdf " error
583 Xpath 'j'
584 return 8
585endfunction
586
587if F() != 1
588 Xpath 'k'
589endif
590
591let g:test9_result = g:Xpath
592
593delfunction F
594delfunction G
595delfunction H
596delfunction I
597
598func Test_func_abort()
599 call assert_equal('adgifb', g:test9_result)
600endfunc
601
602
603"-------------------------------------------------------------------------------
604" Test 10: :if, :elseif, :while argument parsing {{{1
605"
606" A '"' or '|' in an argument expression must not be mixed up with
607" a comment or a next command after a bar. Parsing errors should
608" be recognized.
609"-------------------------------------------------------------------------------
610
611XpathINIT
612
613function! MSG(enr, emsg)
614 let english = v:lang == "C" || v:lang =~ '^[Ee]n'
615 if a:enr == ""
616 Xout "TODO: Add message number for:" a:emsg
617 let v:errmsg = ":" . v:errmsg
618 endif
619 let match = 1
620 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
621 let match = 0
622 if v:errmsg == ""
623 Xout "Message missing."
624 else
625 let v:errmsg = escape(v:errmsg, '"')
626 Xout "Unexpected message:" v:errmsg
627 endif
628 endif
629 return match
630endfunction
631
632if 1 || strlen("\"") | Xpath 'a'
633 Xpath 'b'
634endif
635Xpath 'c'
636
637if 0
638elseif 1 || strlen("\"") | Xpath 'd'
639 Xpath 'e'
640endif
641Xpath 'f'
642
643while 1 || strlen("\"") | Xpath 'g'
644 Xpath 'h'
645 break
646endwhile
647Xpath 'i'
648
649let v:errmsg = ""
650if 1 ||| strlen("\"") | Xpath 'j'
651 Xpath 'k'
652endif
653Xpath 'l'
654if !MSG('E15', "Invalid expression")
655 Xpath 'm'
656endif
657
658let v:errmsg = ""
659if 0
660elseif 1 ||| strlen("\"") | Xpath 'n'
661 Xpath 'o'
662endif
663Xpath 'p'
664if !MSG('E15', "Invalid expression")
665 Xpath 'q'
666endif
667
668let v:errmsg = ""
669while 1 ||| strlen("\"") | Xpath 'r'
670 Xpath 's'
671 break
672endwhile
673Xpath 't'
674if !MSG('E15', "Invalid expression")
675 Xpath 'u'
676endif
677
678let g:test10_result = g:Xpath
679delfunction MSG
680
681func Test_expr_parsing()
682 call assert_equal('abcdefghilpt', g:test10_result)
683endfunc
684
685
686"-------------------------------------------------------------------------------
687" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
688"
689" When code is skipped over due to an error, the boolean argument to
690" an :if, :elseif, or :while must not be evaluated.
691"-------------------------------------------------------------------------------
692
693XpathINIT
694
695let calls = 0
696
697function! P(num)
698 let g:calls = g:calls + a:num " side effect on call
699 return 0
700endfunction
701
702if 1
703 Xpath 'a'
704 asdf " error
705 Xpath 'b'
706 if P(1) " should not be called
707 Xpath 'c'
708 elseif !P(2) " should not be called
709 Xpath 'd'
710 else
711 Xpath 'e'
712 endif
713 Xpath 'f'
714 while P(4) " should not be called
715 Xpath 'g'
716 endwhile
717 Xpath 'h'
718endif
719Xpath 'x'
720
721let g:test11_calls = calls
722let g:test11_result = g:Xpath
723
724unlet calls
725delfunction P
726
727func Test_arg_abort()
728 call assert_equal(0, g:test11_calls)
729 call assert_equal('ax', g:test11_result)
730endfunc
731
732
733"-------------------------------------------------------------------------------
734" Test 12: Expressions in braces in skipped code {{{1
735"
736" In code skipped over due to an error or inactive conditional,
737" an expression in braces as part of a variable or function name
738" should not be evaluated.
739"-------------------------------------------------------------------------------
740
741XpathINIT
742
743function! NULL()
744 Xpath 'a'
745 return 0
746endfunction
747
748function! ZERO()
749 Xpath 'b'
750 return 0
751endfunction
752
753function! F0()
754 Xpath 'c'
755endfunction
756
757function! F1(arg)
758 Xpath 'e'
759endfunction
760
761let V0 = 1
762
763Xpath 'f'
764echo 0 ? F{NULL() + V{ZERO()}}() : 1
765
766Xpath 'g'
767if 0
768 Xpath 'h'
769 call F{NULL() + V{ZERO()}}()
770endif
771
772Xpath 'i'
773if 1
774 asdf " error
775 Xpath 'j'
776 call F1(F{NULL() + V{ZERO()}}())
777endif
778
779Xpath 'k'
780if 1
781 asdf " error
782 Xpath 'l'
783 call F{NULL() + V{ZERO()}}()
784endif
785
786let g:test12_result = g:Xpath
787
788func Test_braces_skipped()
789 call assert_equal('fgik', g:test12_result)
790endfunc
791
792
793"-------------------------------------------------------------------------------
794" Test 13: Failure in argument evaluation for :while {{{1
795"
796" A failure in the expression evaluation for the condition of a :while
797" causes the whole :while loop until the matching :endwhile being
798" ignored. Continuation is at the next following line.
799"-------------------------------------------------------------------------------
800
801XpathINIT
802
803Xpath 'a'
804while asdf
805 Xpath 'b'
806 while 1
807 Xpath 'c'
808 break
809 endwhile
810 Xpath 'd'
811 break
812endwhile
813Xpath 'e'
814
815while asdf | Xpath 'f' | endwhile | Xpath 'g'
816Xpath 'h'
817let g:test13_result = g:Xpath
818
819func Test_while_fail()
820 call assert_equal('aeh', g:test13_result)
821endfunc
822
823
824"-------------------------------------------------------------------------------
825" Test 14: Failure in argument evaluation for :if {{{1
826"
827" A failure in the expression evaluation for the condition of an :if
828" does not cause the corresponding :else or :endif being matched to
829" a previous :if/:elseif. Neither of both branches of the failed :if
830" are executed.
831"-------------------------------------------------------------------------------
832
833XpathINIT
834
835function! F()
836 Xpath 'a'
837 let x = 0
838 if x " false
839 Xpath 'b'
840 elseif !x " always true
841 Xpath 'c'
842 let x = 1
843 if g:boolvar " possibly undefined
844 Xpath 'd'
845 else
846 Xpath 'e'
847 endif
848 Xpath 'f'
849 elseif x " never executed
850 Xpath 'g'
851 endif
852 Xpath 'h'
853endfunction
854
855let boolvar = 1
856call F()
857Xpath '-'
858
859unlet boolvar
860call F()
861let g:test14_result = g:Xpath
862
863delfunction F
864
865func Test_if_fail()
866 call assert_equal('acdfh-acfh', g:test14_result)
867endfunc
868
869
870"-------------------------------------------------------------------------------
871" Test 15: Failure in argument evaluation for :if (bar) {{{1
872"
873" Like previous test, except that the failing :if ... | ... | :endif
874" is in a single line.
875"-------------------------------------------------------------------------------
876
877XpathINIT
878
879function! F()
880 Xpath 'a'
881 let x = 0
882 if x " false
883 Xpath 'b'
884 elseif !x " always true
885 Xpath 'c'
886 let x = 1
887 if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
888 Xpath 'f'
889 elseif x " never executed
890 Xpath 'g'
891 endif
892 Xpath 'h'
893endfunction
894
895let boolvar = 1
896call F()
897Xpath '-'
898
899unlet boolvar
900call F()
901let g:test15_result = g:Xpath
902
903delfunction F
904
905func Test_if_bar_fail()
906 call assert_equal('acdfh-acfh', g:test15_result)
907endfunc
908
Bram Moolenaar4119cf82016-01-17 14:59:01 +0100909"-------------------------------------------------------------------------------
910" Test 90: Recognizing {} in variable name. {{{1
911"-------------------------------------------------------------------------------
912
913func Test_curlies()
914 let s:var = 66
915 let ns = 's'
916 call assert_equal(66, {ns}:var)
917
918 let g:a = {}
919 let g:b = 't'
920 let g:a[g:b] = 77
921 call assert_equal(77, g:a['t'])
922endfunc
Bram Moolenaara2cce862016-01-02 19:50:04 +0100923
924"-------------------------------------------------------------------------------
Bram Moolenaarf95534c2016-01-23 21:59:52 +0100925" Test 91: using type(). {{{1
926"-------------------------------------------------------------------------------
927
928func Test_type()
929 call assert_equal(0, type(0))
930 call assert_equal(1, type(""))
931 call assert_equal(2, type(function("tr")))
932 call assert_equal(3, type([]))
933 call assert_equal(4, type({}))
934 call assert_equal(5, type(0.0))
935 call assert_equal(6, type(v:false))
936 call assert_equal(6, type(v:true))
937 call assert_equal(7, type(v:none))
938 call assert_equal(7, type(v:null))
939endfunc
940
941"-------------------------------------------------------------------------------
Bram Moolenaarf49e2402015-12-30 15:59:25 +0100942" Modelines {{{1
943" vim: ts=8 sw=4 tw=80 fdm=marker
944" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
945"-------------------------------------------------------------------------------