1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source term_util.vim
5source view_util.vim
6source vim9.vim
7source shared.vim
8
9def Test_range_only()
10  new
11  setline(1, ['blah', 'Blah'])
12  :/Blah/
13  assert_equal(2, getcurpos()[1])
14  bwipe!
15
16  # without range commands use current line
17  new
18  setline(1, ['one', 'two', 'three'])
19  :2
20  print
21  assert_equal('two', Screenline(&lines))
22  :3
23  list
24  assert_equal('three$', Screenline(&lines))
25  bwipe!
26
27  # won't generate anything
28  if false
29    :123
30  endif
31enddef
32
33let g:alist = [7]
34let g:astring = 'text'
35let g:anumber = 123
36
37def Test_delfunction()
38  # Check function is defined in script namespace
39  CheckScriptSuccess([
40      'vim9script',
41      'func CheckMe()',
42      '  return 123',
43      'endfunc',
44      'assert_equal(123, s:CheckMe())',
45      ])
46
47  # Check function in script namespace cannot be deleted
48  CheckScriptFailure([
49      'vim9script',
50      'func DeleteMe1()',
51      'endfunc',
52      'delfunction DeleteMe1',
53      ], 'E1084:')
54  CheckScriptFailure([
55      'vim9script',
56      'func DeleteMe2()',
57      'endfunc',
58      'def DoThat()',
59      '  delfunction DeleteMe2',
60      'enddef',
61      'DoThat()',
62      ], 'E1084:')
63  CheckScriptFailure([
64      'vim9script',
65      'def DeleteMe3()',
66      'enddef',
67      'delfunction DeleteMe3',
68      ], 'E1084:')
69  CheckScriptFailure([
70      'vim9script',
71      'def DeleteMe4()',
72      'enddef',
73      'def DoThat()',
74      '  delfunction DeleteMe4',
75      'enddef',
76      'DoThat()',
77      ], 'E1084:')
78
79  # Check that global :def function can be replaced and deleted
80  var lines =<< trim END
81      vim9script
82      def g:Global(): string
83        return "yes"
84      enddef
85      assert_equal("yes", g:Global())
86      def! g:Global(): string
87        return "no"
88      enddef
89      assert_equal("no", g:Global())
90      delfunc g:Global
91      assert_false(exists('*g:Global'))
92  END
93  CheckScriptSuccess(lines)
94
95  # Check that global function can be replaced by a :def function and deleted
96  lines =<< trim END
97      vim9script
98      func g:Global()
99        return "yes"
100      endfunc
101      assert_equal("yes", g:Global())
102      def! g:Global(): string
103        return "no"
104      enddef
105      assert_equal("no", g:Global())
106      delfunc g:Global
107      assert_false(exists('*g:Global'))
108  END
109  CheckScriptSuccess(lines)
110
111  # Check that global :def function can be replaced by a function and deleted
112  lines =<< trim END
113      vim9script
114      def g:Global(): string
115        return "yes"
116      enddef
117      assert_equal("yes", g:Global())
118      func! g:Global()
119        return "no"
120      endfunc
121      assert_equal("no", g:Global())
122      delfunc g:Global
123      assert_false(exists('*g:Global'))
124  END
125  CheckScriptSuccess(lines)
126enddef
127
128def Test_wrong_type()
129  CheckDefFailure(['var name: list<nothing>'], 'E1010:')
130  CheckDefFailure(['var name: list<list<nothing>>'], 'E1010:')
131  CheckDefFailure(['var name: dict<nothing>'], 'E1010:')
132  CheckDefFailure(['var name: dict<dict<nothing>>'], 'E1010:')
133
134  CheckDefFailure(['var name: dict<number'], 'E1009:')
135  CheckDefFailure(['var name: dict<list<number>'], 'E1009:')
136
137  CheckDefFailure(['var name: ally'], 'E1010:')
138  CheckDefFailure(['var name: bram'], 'E1010:')
139  CheckDefFailure(['var name: cathy'], 'E1010:')
140  CheckDefFailure(['var name: dom'], 'E1010:')
141  CheckDefFailure(['var name: freddy'], 'E1010:')
142  CheckDefFailure(['var name: john'], 'E1010:')
143  CheckDefFailure(['var name: larry'], 'E1010:')
144  CheckDefFailure(['var name: ned'], 'E1010:')
145  CheckDefFailure(['var name: pam'], 'E1010:')
146  CheckDefFailure(['var name: sam'], 'E1010:')
147  CheckDefFailure(['var name: vim'], 'E1010:')
148
149  CheckDefFailure(['var Ref: number', 'Ref()'], 'E1085:')
150  CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:')
151enddef
152
153def Test_script_wrong_type()
154  var lines =<< trim END
155      vim9script
156      var s:dict: dict<string>
157      s:dict['a'] = ['x']
158  END
159  CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got list<string>', 3)
160enddef
161
162def Test_const()
163  CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:')
164  CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:')
165  CheckDefFailure(['final list = [1, 2]', 'var list = [3, 4]'], 'E1017:')
166  CheckDefFailure(['final two'], 'E1125:')
167  CheckDefFailure(['final &option'], 'E996:')
168
169  var lines =<< trim END
170    final list = [1, 2, 3]
171    list[0] = 4
172    list->assert_equal([4, 2, 3])
173    const other = [5, 6, 7]
174    other->assert_equal([5, 6, 7])
175
176    var varlist = [7, 8]
177    const constlist = [1, varlist, 3]
178    varlist[0] = 77
179    # TODO: does not work yet
180    # constlist[1][1] = 88
181    var cl = constlist[1]
182    cl[1] = 88
183    constlist->assert_equal([1, [77, 88], 3])
184
185    var vardict = {five: 5, six: 6}
186    const constdict = {one: 1, two: vardict, three: 3}
187    vardict['five'] = 55
188    # TODO: does not work yet
189    # constdict['two']['six'] = 66
190    var cd = constdict['two']
191    cd['six'] = 66
192    constdict->assert_equal({one: 1, two: {five: 55, six: 66}, three: 3})
193  END
194  CheckDefAndScriptSuccess(lines)
195enddef
196
197def Test_const_bang()
198  var lines =<< trim END
199      const var = 234
200      var = 99
201  END
202  CheckDefExecFailure(lines, 'E1018:', 2)
203  CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
204
205  lines =<< trim END
206      const ll = [2, 3, 4]
207      ll[0] = 99
208  END
209  CheckDefExecFailure(lines, 'E1119:', 2)
210  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
211
212  lines =<< trim END
213      const ll = [2, 3, 4]
214      ll[3] = 99
215  END
216  CheckDefExecFailure(lines, 'E1118:', 2)
217  CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
218
219  lines =<< trim END
220      const dd = {one: 1, two: 2}
221      dd["one"] = 99
222  END
223  CheckDefExecFailure(lines, 'E1121:', 2)
224  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
225
226  lines =<< trim END
227      const dd = {one: 1, two: 2}
228      dd["three"] = 99
229  END
230  CheckDefExecFailure(lines, 'E1120:')
231  CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
232enddef
233
234def Test_range_no_colon()
235  CheckDefFailure(['%s/a/b/'], 'E1050:')
236  CheckDefFailure(['+ s/a/b/'], 'E1050:')
237  CheckDefFailure(['- s/a/b/'], 'E1050:')
238  CheckDefFailure(['. s/a/b/'], 'E1050:')
239enddef
240
241
242def Test_block()
243  var outer = 1
244  {
245    var inner = 2
246    assert_equal(1, outer)
247    assert_equal(2, inner)
248  }
249  assert_equal(1, outer)
250enddef
251
252def Test_block_failure()
253  CheckDefFailure(['{', 'var inner = 1', '}', 'echo inner'], 'E1001:')
254  CheckDefFailure(['}'], 'E1025:')
255  CheckDefFailure(['{', 'echo 1'], 'E1026:')
256enddef
257
258def Test_block_local_vars()
259  var lines =<< trim END
260      vim9script
261      v:testing = 1
262      if true
263        var text = ['hello']
264        def SayHello(): list<string>
265          return text
266        enddef
267        def SetText(v: string)
268          text = [v]
269        enddef
270      endif
271
272      if true
273        var text = ['again']
274        def SayAgain(): list<string>
275          return text
276        enddef
277      endif
278
279      # test that the "text" variables are not cleaned up
280      test_garbagecollect_now()
281
282      defcompile
283
284      assert_equal(['hello'], SayHello())
285      assert_equal(['again'], SayAgain())
286
287      SetText('foobar')
288      assert_equal(['foobar'], SayHello())
289
290      call writefile(['ok'], 'Xdidit')
291      qall!
292  END
293
294  # need to execute this with a separate Vim instance to avoid the current
295  # context gets garbage collected.
296  writefile(lines, 'Xscript')
297  RunVim([], [], '-S Xscript')
298  assert_equal(['ok'], readfile('Xdidit'))
299
300  delete('Xscript')
301  delete('Xdidit')
302enddef
303
304def Test_block_local_vars_with_func()
305  var lines =<< trim END
306      vim9script
307      if true
308        var foo = 'foo'
309        if true
310          var bar = 'bar'
311          def Func(): list<string>
312            return [foo, bar]
313          enddef
314        endif
315      endif
316      # function is compiled here, after blocks have finished, can still access
317      # "foo" and "bar"
318      assert_equal(['foo', 'bar'], Func())
319  END
320  CheckScriptSuccess(lines)
321enddef
322
323func g:NoSuchFunc()
324  echo 'none'
325endfunc
326
327def Test_try_catch_throw()
328  var l = []
329  try # comment
330    add(l, '1')
331    throw 'wrong'
332    add(l, '2')
333  catch # comment
334    add(l, v:exception)
335  finally # comment
336    add(l, '3')
337  endtry # comment
338  assert_equal(['1', 'wrong', '3'], l)
339
340  l = []
341  try
342    try
343      add(l, '1')
344      throw 'wrong'
345      add(l, '2')
346    catch /right/
347      add(l, v:exception)
348    endtry
349  catch /wrong/
350    add(l, 'caught')
351  fina
352    add(l, 'finally')
353  endtry
354  assert_equal(['1', 'caught', 'finally'], l)
355
356  var n: number
357  try
358    n = l[3]
359  catch /E684:/
360    n = 99
361  endtry
362  assert_equal(99, n)
363
364  var done = 'no'
365  if 0
366    try | catch | endtry
367  else
368    done = 'yes'
369  endif
370  assert_equal('yes', done)
371
372  done = 'no'
373  if 1
374    done = 'yes'
375  else
376    try | catch | endtry
377    done = 'never'
378  endif
379  assert_equal('yes', done)
380
381  if 1
382  else
383    try | catch /pat/ | endtry
384    try | catch /pat/
385    endtry
386    try
387    catch /pat/ | endtry
388    try
389    catch /pat/
390    endtry
391  endif
392
393  try
394    # string slice returns a string, not a number
395    n = g:astring[3]
396  catch /E1012:/
397    n = 77
398  endtry
399  assert_equal(77, n)
400
401  try
402    n = l[g:astring]
403  catch /E1012:/
404    n = 88
405  endtry
406  assert_equal(88, n)
407
408  try
409    n = s:does_not_exist
410  catch /E121:/
411    n = 111
412  endtry
413  assert_equal(111, n)
414
415  try
416    n = g:does_not_exist
417  catch /E121:/
418    n = 121
419  endtry
420  assert_equal(121, n)
421
422  var d = {one: 1}
423  try
424    n = d[g:astring]
425  catch /E716:/
426    n = 222
427  endtry
428  assert_equal(222, n)
429
430  try
431    n = -g:astring
432  catch /E39:/
433    n = 233
434  endtry
435  assert_equal(233, n)
436
437  try
438    n = +g:astring
439  catch /E1030:/
440    n = 244
441  endtry
442  assert_equal(244, n)
443
444  try
445    n = +g:alist
446  catch /E745:/
447    n = 255
448  endtry
449  assert_equal(255, n)
450
451  var nd: dict<any>
452  try
453    nd = {[g:anumber]: 1}
454  catch /E1012:/
455    n = 266
456  endtry
457  assert_equal(266, n)
458
459  try
460    [n] = [1, 2, 3]
461  catch /E1093:/
462    n = 277
463  endtry
464  assert_equal(277, n)
465
466  try
467    &ts = g:astring
468  catch /E1012:/
469    n = 288
470  endtry
471  assert_equal(288, n)
472
473  try
474    &backspace = 'asdf'
475  catch /E474:/
476    n = 299
477  endtry
478  assert_equal(299, n)
479
480  l = [1]
481  try
482    l[3] = 3
483  catch /E684:/
484    n = 300
485  endtry
486  assert_equal(300, n)
487
488  try
489    unlet g:does_not_exist
490  catch /E108:/
491    n = 322
492  endtry
493  assert_equal(322, n)
494
495  try
496    d = {text: 1, [g:astring]: 2}
497  catch /E721:/
498    n = 333
499  endtry
500  assert_equal(333, n)
501
502  try
503    l = DeletedFunc()
504  catch /E933:/
505    n = 344
506  endtry
507  assert_equal(344, n)
508
509  try
510    echo len(v:true)
511  catch /E701:/
512    n = 355
513  endtry
514  assert_equal(355, n)
515
516  var P = function('g:NoSuchFunc')
517  delfunc g:NoSuchFunc
518  try
519    echo P()
520  catch /E117:/
521    n = 366
522  endtry
523  assert_equal(366, n)
524
525  try
526    echo g:NoSuchFunc()
527  catch /E117:/
528    n = 377
529  endtry
530  assert_equal(377, n)
531
532  try
533    echo g:alist + 4
534  catch /E745:/
535    n = 388
536  endtry
537  assert_equal(388, n)
538
539  try
540    echo 4 + g:alist
541  catch /E745:/
542    n = 399
543  endtry
544  assert_equal(399, n)
545
546  try
547    echo g:alist.member
548  catch /E715:/
549    n = 400
550  endtry
551  assert_equal(400, n)
552
553  try
554    echo d.member
555  catch /E716:/
556    n = 411
557  endtry
558  assert_equal(411, n)
559enddef
560
561def Test_cnext_works_in_catch()
562  var lines =<< trim END
563      vim9script
564      au BufEnter * eval 0
565      writefile(['text'], 'Xfile1')
566      writefile(['text'], 'Xfile2')
567      var items = [
568          {lnum: 1, filename: 'Xfile1', valid: true},
569          {lnum: 1, filename: 'Xfile2', valid: true}
570        ]
571      setqflist([], ' ', {items: items})
572      cwindow
573
574      def CnextOrCfirst()
575        # if cnext fails, cfirst is used
576        try
577          cnext
578        catch
579          cfirst
580        endtry
581      enddef
582
583      CnextOrCfirst()
584      CnextOrCfirst()
585      writefile([getqflist({idx: 0}).idx], 'Xresult')
586      qall
587  END
588  writefile(lines, 'XCatchCnext')
589  RunVim([], [], '--clean -S XCatchCnext')
590  assert_equal(['1'], readfile('Xresult'))
591
592  delete('Xfile1')
593  delete('Xfile2')
594  delete('XCatchCnext')
595  delete('Xresult')
596enddef
597
598def Test_throw_skipped()
599  if 0
600    throw dontgethere
601  endif
602enddef
603
604def Test_nocatch_throw_silenced()
605  var lines =<< trim END
606    vim9script
607    def Func()
608      throw 'error'
609    enddef
610    silent! Func()
611  END
612  writefile(lines, 'XthrowSilenced')
613  source XthrowSilenced
614  delete('XthrowSilenced')
615enddef
616
617def DeletedFunc(): list<any>
618  return ['delete me']
619enddef
620defcompile
621delfunc DeletedFunc
622
623def ThrowFromDef()
624  throw "getout" # comment
625enddef
626
627func CatchInFunc()
628  try
629    call ThrowFromDef()
630  catch
631    let g:thrown_func = v:exception
632  endtry
633endfunc
634
635def CatchInDef()
636  try
637    ThrowFromDef()
638  catch
639    g:thrown_def = v:exception
640  endtry
641enddef
642
643def ReturnFinally(): string
644  try
645    return 'intry'
646  finall
647    g:in_finally = 'finally'
648  endtry
649  return 'end'
650enddef
651
652def Test_try_catch_nested()
653  CatchInFunc()
654  assert_equal('getout', g:thrown_func)
655
656  CatchInDef()
657  assert_equal('getout', g:thrown_def)
658
659  assert_equal('intry', ReturnFinally())
660  assert_equal('finally', g:in_finally)
661enddef
662
663def TryOne(): number
664  try
665    return 0
666  catch
667  endtry
668  return 0
669enddef
670
671def TryTwo(n: number): string
672  try
673    var x = {}
674  catch
675  endtry
676  return 'text'
677enddef
678
679def Test_try_catch_twice()
680  assert_equal('text', TryOne()->TryTwo())
681enddef
682
683def Test_try_catch_match()
684  var seq = 'a'
685  try
686    throw 'something'
687  catch /nothing/
688    seq ..= 'x'
689  catch /some/
690    seq ..= 'b'
691  catch /asdf/
692    seq ..= 'x'
693  catch ?a\?sdf?
694    seq ..= 'y'
695  finally
696    seq ..= 'c'
697  endtry
698  assert_equal('abc', seq)
699enddef
700
701def Test_try_catch_fails()
702  CheckDefFailure(['catch'], 'E603:')
703  CheckDefFailure(['try', 'echo 0', 'catch', 'catch'], 'E1033:')
704  CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
705  CheckDefFailure(['finally'], 'E606:')
706  CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
707  CheckDefFailure(['endtry'], 'E602:')
708  CheckDefFailure(['while 1', 'endtry'], 'E170:')
709  CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
710  CheckDefFailure(['if 1', 'endtry'], 'E171:')
711  CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
712
713  CheckDefFailure(['throw'], 'E1143:')
714  CheckDefFailure(['throw xxx'], 'E1001:')
715enddef
716
717def Test_throw_vimscript()
718  # only checks line continuation
719  var lines =<< trim END
720      vim9script
721      try
722        throw 'one'
723              .. 'two'
724      catch
725        assert_equal('onetwo', v:exception)
726      endtry
727  END
728  CheckScriptSuccess(lines)
729
730  lines =<< trim END
731    vim9script
732    @r = ''
733    def Func()
734      throw @r
735    enddef
736    var result = ''
737    try
738      Func()
739    catch /E1129:/
740      result = 'caught'
741    endtry
742    assert_equal('caught', result)
743  END
744  CheckScriptSuccess(lines)
745enddef
746
747def Test_error_in_nested_function()
748  # an error in a nested :function aborts executin in the calling :def function
749  var lines =<< trim END
750      vim9script
751      def Func()
752        Error()
753        g:test_var = 1
754      enddef
755      func Error() abort
756        eval [][0]
757      endfunc
758      Func()
759  END
760  g:test_var = 0
761  CheckScriptFailure(lines, 'E684:')
762  assert_equal(0, g:test_var)
763enddef
764
765def Test_cexpr_vimscript()
766  # only checks line continuation
767  set errorformat=File\ %f\ line\ %l
768  var lines =<< trim END
769      vim9script
770      cexpr 'File'
771                .. ' someFile' ..
772                   ' line 19'
773      assert_equal(19, getqflist()[0].lnum)
774  END
775  CheckScriptSuccess(lines)
776  set errorformat&
777enddef
778
779def Test_statusline_syntax()
780  # legacy syntax is used for 'statusline'
781  var lines =<< trim END
782      vim9script
783      func g:Status()
784        return '%{"x" is# "x"}'
785      endfunc
786      set laststatus=2 statusline=%!Status()
787      redrawstatus
788      set laststatus statusline=
789  END
790  CheckScriptSuccess(lines)
791enddef
792
793def Test_list_vimscript()
794  # checks line continuation and comments
795  var lines =<< trim END
796      vim9script
797      var mylist = [
798            'one',
799            # comment
800            'two', # empty line follows
801
802            'three',
803            ]
804      assert_equal(['one', 'two', 'three'], mylist)
805  END
806  CheckScriptSuccess(lines)
807
808  # check all lines from heredoc are kept
809  lines =<< trim END
810      # comment 1
811      two
812      # comment 3
813
814      five
815      # comment 6
816  END
817  assert_equal(['# comment 1', 'two', '# comment 3', '', 'five', '# comment 6'], lines)
818
819  lines =<< trim END
820    [{
821      a: 0}]->string()->assert_equal("[{'a': 0}]")
822  END
823  CheckDefAndScriptSuccess(lines)
824enddef
825
826if has('channel')
827  let someJob = test_null_job()
828
829  def FuncWithError()
830    echomsg g:someJob
831  enddef
832
833  func Test_convert_emsg_to_exception()
834    try
835      call FuncWithError()
836    catch
837      call assert_match('Vim:E908:', v:exception)
838    endtry
839  endfunc
840endif
841
842let s:export_script_lines =<< trim END
843  vim9script
844  var name: string = 'bob'
845  def Concat(arg: string): string
846    return name .. arg
847  enddef
848  g:result = Concat('bie')
849  g:localname = name
850
851  export const CONST = 1234
852  export var exported = 9876
853  export var exp_name = 'John'
854  export def Exported(): string
855    return 'Exported'
856  enddef
857END
858
859def Undo_export_script_lines()
860  unlet g:result
861  unlet g:localname
862enddef
863
864def Test_vim9_import_export()
865  var import_script_lines =<< trim END
866    vim9script
867    import {exported, Exported} from './Xexport.vim'
868    g:imported = exported
869    exported += 3
870    g:imported_added = exported
871    g:imported_func = Exported()
872
873    def GetExported(): string
874      var local_dict = {ref: Exported}
875      return local_dict.ref()
876    enddef
877    g:funcref_result = GetExported()
878
879    import {exp_name} from './Xexport.vim'
880    g:imported_name = exp_name
881    exp_name ..= ' Doe'
882    g:imported_name_appended = exp_name
883    g:imported_later = exported
884  END
885
886  writefile(import_script_lines, 'Ximport.vim')
887  writefile(s:export_script_lines, 'Xexport.vim')
888
889  source Ximport.vim
890
891  assert_equal('bobbie', g:result)
892  assert_equal('bob', g:localname)
893  assert_equal(9876, g:imported)
894  assert_equal(9879, g:imported_added)
895  assert_equal(9879, g:imported_later)
896  assert_equal('Exported', g:imported_func)
897  assert_equal('Exported', g:funcref_result)
898  assert_equal('John', g:imported_name)
899  assert_equal('John Doe', g:imported_name_appended)
900  assert_false(exists('g:name'))
901
902  Undo_export_script_lines()
903  unlet g:imported
904  unlet g:imported_added
905  unlet g:imported_later
906  unlet g:imported_func
907  unlet g:imported_name g:imported_name_appended
908  delete('Ximport.vim')
909
910  # similar, with line breaks
911  var import_line_break_script_lines =<< trim END
912    vim9script
913    import {
914        exported,
915        Exported,
916        }
917        from
918        './Xexport.vim'
919    g:imported = exported
920    exported += 5
921    g:imported_added = exported
922    g:imported_func = Exported()
923  END
924  writefile(import_line_break_script_lines, 'Ximport_lbr.vim')
925  source Ximport_lbr.vim
926
927  assert_equal(9876, g:imported)
928  assert_equal(9881, g:imported_added)
929  assert_equal('Exported', g:imported_func)
930
931  # exported script not sourced again
932  assert_false(exists('g:result'))
933  unlet g:imported
934  unlet g:imported_added
935  unlet g:imported_func
936  delete('Ximport_lbr.vim')
937
938  # import inside :def function
939  var import_in_def_lines =<< trim END
940    vim9script
941    def ImportInDef()
942      import exported from './Xexport.vim'
943      g:imported = exported
944      exported += 7
945      g:imported_added = exported
946    enddef
947    ImportInDef()
948  END
949  writefile(import_in_def_lines, 'Ximport2.vim')
950  source Ximport2.vim
951  # TODO: this should be 9879
952  assert_equal(9876, g:imported)
953  assert_equal(9883, g:imported_added)
954  unlet g:imported
955  unlet g:imported_added
956  delete('Ximport2.vim')
957
958  var import_star_as_lines =<< trim END
959    vim9script
960    import * as Export from './Xexport.vim'
961    def UseExport()
962      g:imported = Export.exported
963    enddef
964    UseExport()
965  END
966  writefile(import_star_as_lines, 'Ximport.vim')
967  source Ximport.vim
968  assert_equal(9883, g:imported)
969
970  var import_star_as_lines_no_dot =<< trim END
971    vim9script
972    import * as Export from './Xexport.vim'
973    def Func()
974      var dummy = 1
975      var imported = Export + dummy
976    enddef
977    defcompile
978  END
979  writefile(import_star_as_lines_no_dot, 'Ximport.vim')
980  assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func')
981
982  var import_star_as_lines_dot_space =<< trim END
983    vim9script
984    import * as Export from './Xexport.vim'
985    def Func()
986      var imported = Export . exported
987    enddef
988    defcompile
989  END
990  writefile(import_star_as_lines_dot_space, 'Ximport.vim')
991  assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func')
992
993  var import_star_as_duplicated =<< trim END
994    vim9script
995    import * as Export from './Xexport.vim'
996    var some = 'other'
997    import * as Export from './Xexport.vim'
998    defcompile
999  END
1000  writefile(import_star_as_duplicated, 'Ximport.vim')
1001  assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim')
1002
1003  var import_star_as_lines_missing_name =<< trim END
1004    vim9script
1005    import * as Export from './Xexport.vim'
1006    def Func()
1007      var imported = Export.
1008    enddef
1009    defcompile
1010  END
1011  writefile(import_star_as_lines_missing_name, 'Ximport.vim')
1012  assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func')
1013
1014  var import_star_as_lbr_lines =<< trim END
1015    vim9script
1016    import *
1017        as Export
1018        from
1019        './Xexport.vim'
1020    def UseExport()
1021      g:imported = Export.exported
1022    enddef
1023    UseExport()
1024  END
1025  writefile(import_star_as_lbr_lines, 'Ximport.vim')
1026  source Ximport.vim
1027  assert_equal(9883, g:imported)
1028
1029  var import_star_lines =<< trim END
1030    vim9script
1031    import * from './Xexport.vim'
1032  END
1033  writefile(import_star_lines, 'Ximport.vim')
1034  assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim')
1035
1036  # try to import something that exists but is not exported
1037  var import_not_exported_lines =<< trim END
1038    vim9script
1039    import name from './Xexport.vim'
1040  END
1041  writefile(import_not_exported_lines, 'Ximport.vim')
1042  assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim')
1043
1044  # try to import something that is already defined
1045  var import_already_defined =<< trim END
1046    vim9script
1047    var exported = 'something'
1048    import exported from './Xexport.vim'
1049  END
1050  writefile(import_already_defined, 'Ximport.vim')
1051  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1052
1053  # try to import something that is already defined
1054  import_already_defined =<< trim END
1055    vim9script
1056    var exported = 'something'
1057    import * as exported from './Xexport.vim'
1058  END
1059  writefile(import_already_defined, 'Ximport.vim')
1060  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1061
1062  # try to import something that is already defined
1063  import_already_defined =<< trim END
1064    vim9script
1065    var exported = 'something'
1066    import {exported} from './Xexport.vim'
1067  END
1068  writefile(import_already_defined, 'Ximport.vim')
1069  assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim')
1070
1071  # try changing an imported const
1072  var import_assign_to_const =<< trim END
1073    vim9script
1074    import CONST from './Xexport.vim'
1075    def Assign()
1076      CONST = 987
1077    enddef
1078    defcompile
1079  END
1080  writefile(import_assign_to_const, 'Ximport.vim')
1081  assert_fails('source Ximport.vim', 'E46:', '', 1, '_Assign')
1082
1083  # import a very long name, requires making a copy
1084  var import_long_name_lines =<< trim END
1085    vim9script
1086    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
1087  END
1088  writefile(import_long_name_lines, 'Ximport.vim')
1089  assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim')
1090
1091  var import_no_from_lines =<< trim END
1092    vim9script
1093    import name './Xexport.vim'
1094  END
1095  writefile(import_no_from_lines, 'Ximport.vim')
1096  assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim')
1097
1098  var import_invalid_string_lines =<< trim END
1099    vim9script
1100    import name from Xexport.vim
1101  END
1102  writefile(import_invalid_string_lines, 'Ximport.vim')
1103  assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim')
1104
1105  var import_wrong_name_lines =<< trim END
1106    vim9script
1107    import name from './XnoExport.vim'
1108  END
1109  writefile(import_wrong_name_lines, 'Ximport.vim')
1110  assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim')
1111
1112  var import_missing_comma_lines =<< trim END
1113    vim9script
1114    import {exported name} from './Xexport.vim'
1115  END
1116  writefile(import_missing_comma_lines, 'Ximport3.vim')
1117  assert_fails('source Ximport3.vim', 'E1046:', '', 2, 'Ximport3.vim')
1118
1119  delete('Ximport.vim')
1120  delete('Ximport3.vim')
1121  delete('Xexport.vim')
1122
1123  # Check that in a Vim9 script 'cpo' is set to the Vim default.
1124  set cpo&vi
1125  var cpo_before = &cpo
1126  var lines =<< trim END
1127    vim9script
1128    g:cpo_in_vim9script = &cpo
1129  END
1130  writefile(lines, 'Xvim9_script')
1131  source Xvim9_script
1132  assert_equal(cpo_before, &cpo)
1133  set cpo&vim
1134  assert_equal(&cpo, g:cpo_in_vim9script)
1135  delete('Xvim9_script')
1136enddef
1137
1138func g:Trigger()
1139  source Ximport.vim
1140  return "echo 'yes'\<CR>"
1141endfunc
1142
1143def Test_import_export_expr_map()
1144  # check that :import and :export work when buffer is locked
1145  var export_lines =<< trim END
1146    vim9script
1147    export def That(): string
1148      return 'yes'
1149    enddef
1150  END
1151  writefile(export_lines, 'Xexport_that.vim')
1152
1153  var import_lines =<< trim END
1154    vim9script
1155    import That from './Xexport_that.vim'
1156    assert_equal('yes', That())
1157  END
1158  writefile(import_lines, 'Ximport.vim')
1159
1160  nnoremap <expr> trigger g:Trigger()
1161  feedkeys('trigger', "xt")
1162
1163  delete('Xexport_that.vim')
1164  delete('Ximport.vim')
1165  nunmap trigger
1166enddef
1167
1168def Test_import_in_filetype()
1169  # check that :import works when the buffer is locked
1170  mkdir('ftplugin', 'p')
1171  var export_lines =<< trim END
1172    vim9script
1173    export var That = 'yes'
1174  END
1175  writefile(export_lines, 'ftplugin/Xexport_ft.vim')
1176
1177  var import_lines =<< trim END
1178    vim9script
1179    import That from './Xexport_ft.vim'
1180    assert_equal('yes', That)
1181    g:did_load_mytpe = 1
1182  END
1183  writefile(import_lines, 'ftplugin/qf.vim')
1184
1185  var save_rtp = &rtp
1186  &rtp = getcwd() .. ',' .. &rtp
1187
1188  filetype plugin on
1189  copen
1190  assert_equal(1, g:did_load_mytpe)
1191
1192  quit!
1193  delete('Xexport_ft.vim')
1194  delete('ftplugin', 'rf')
1195  &rtp = save_rtp
1196enddef
1197
1198def Test_use_import_in_mapping()
1199  var lines =<< trim END
1200      vim9script
1201      export def Funcx()
1202        g:result = 42
1203      enddef
1204  END
1205  writefile(lines, 'XsomeExport.vim')
1206  lines =<< trim END
1207      vim9script
1208      import Funcx from './XsomeExport.vim'
1209      nnoremap <F3> :call <sid>Funcx()<cr>
1210  END
1211  writefile(lines, 'Xmapscript.vim')
1212
1213  source Xmapscript.vim
1214  feedkeys("\<F3>", "xt")
1215  assert_equal(42, g:result)
1216
1217  unlet g:result
1218  delete('XsomeExport.vim')
1219  delete('Xmapscript.vim')
1220  nunmap <F3>
1221enddef
1222
1223def Test_vim9script_fails()
1224  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
1225  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
1226  CheckScriptFailure(['export var some = 123'], 'E1042:')
1227  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:')
1228  CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
1229  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
1230
1231  CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:')
1232  CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:')
1233
1234  assert_fails('vim9script', 'E1038:')
1235  assert_fails('export something', 'E1043:')
1236enddef
1237
1238func Test_import_fails_without_script()
1239  CheckRunVimInTerminal
1240
1241  " call indirectly to avoid compilation error for missing functions
1242  call Run_Test_import_fails_on_command_line()
1243endfunc
1244
1245def Run_Test_import_fails_on_command_line()
1246  var export =<< trim END
1247    vim9script
1248    export def Foo(): number
1249        return 0
1250    enddef
1251  END
1252  writefile(export, 'XexportCmd.vim')
1253
1254  var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', {
1255                rows: 6, wait_for_ruler: 0})
1256  WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5)))
1257
1258  delete('XexportCmd.vim')
1259  StopVimInTerminal(buf)
1260enddef
1261
1262def Test_vim9script_reload_noclear()
1263  var lines =<< trim END
1264    vim9script
1265    export var exported = 'thexport'
1266  END
1267  writefile(lines, 'XExportReload')
1268  lines =<< trim END
1269    vim9script noclear
1270    g:loadCount += 1
1271    var s:reloaded = 'init'
1272    import exported from './XExportReload'
1273
1274    def Again(): string
1275      return 'again'
1276    enddef
1277
1278    if exists('s:loaded') | finish | endif
1279    var s:loaded = true
1280
1281    var s:notReloaded = 'yes'
1282    s:reloaded = 'first'
1283    def g:Values(): list<string>
1284      return [s:reloaded, s:notReloaded, Again(), Once(), exported]
1285    enddef
1286
1287    def Once(): string
1288      return 'once'
1289    enddef
1290  END
1291  writefile(lines, 'XReloaded')
1292  g:loadCount = 0
1293  source XReloaded
1294  assert_equal(1, g:loadCount)
1295  assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values())
1296  source XReloaded
1297  assert_equal(2, g:loadCount)
1298  assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values())
1299  source XReloaded
1300  assert_equal(3, g:loadCount)
1301  assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values())
1302
1303  delete('XReloaded')
1304  delete('XExportReload')
1305  delfunc g:Values
1306  unlet g:loadCount
1307enddef
1308
1309def Test_vim9script_reload_import()
1310  var lines =<< trim END
1311    vim9script
1312    const var = ''
1313    var valone = 1234
1314    def MyFunc(arg: string)
1315       valone = 5678
1316    enddef
1317  END
1318  var morelines =<< trim END
1319    var valtwo = 222
1320    export def GetValtwo(): number
1321      return valtwo
1322    enddef
1323  END
1324  writefile(lines + morelines, 'Xreload.vim')
1325  source Xreload.vim
1326  source Xreload.vim
1327  source Xreload.vim
1328
1329  var testlines =<< trim END
1330    vim9script
1331    def TheFunc()
1332      import GetValtwo from './Xreload.vim'
1333      assert_equal(222, GetValtwo())
1334    enddef
1335    TheFunc()
1336  END
1337  writefile(testlines, 'Ximport.vim')
1338  source Ximport.vim
1339
1340  # Test that when not using "morelines" GetValtwo() and valtwo are still
1341  # defined, because import doesn't reload a script.
1342  writefile(lines, 'Xreload.vim')
1343  source Ximport.vim
1344
1345  # cannot declare a var twice
1346  lines =<< trim END
1347    vim9script
1348    var valone = 1234
1349    var valone = 5678
1350  END
1351  writefile(lines, 'Xreload.vim')
1352  assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim')
1353
1354  delete('Xreload.vim')
1355  delete('Ximport.vim')
1356enddef
1357
1358" if a script is reloaded with a script-local variable that changed its type, a
1359" compiled function using that variable must fail.
1360def Test_script_reload_change_type()
1361  var lines =<< trim END
1362    vim9script noclear
1363    var str = 'string'
1364    def g:GetStr(): string
1365      return str .. 'xxx'
1366    enddef
1367  END
1368  writefile(lines, 'Xreload.vim')
1369  source Xreload.vim
1370  echo g:GetStr()
1371
1372  lines =<< trim END
1373    vim9script noclear
1374    var str = 1234
1375  END
1376  writefile(lines, 'Xreload.vim')
1377  source Xreload.vim
1378  assert_fails('echo g:GetStr()', 'E1150:')
1379
1380  delfunc g:GetStr
1381  delete('Xreload.vim')
1382enddef
1383
1384def s:RetSome(): string
1385  return 'some'
1386enddef
1387
1388" Not exported function that is referenced needs to be accessed by the
1389" script-local name.
1390def Test_vim9script_funcref()
1391  var sortlines =<< trim END
1392      vim9script
1393      def Compare(i1: number, i2: number): number
1394        return i2 - i1
1395      enddef
1396
1397      export def FastSort(): list<number>
1398        return range(5)->sort(Compare)
1399      enddef
1400  END
1401  writefile(sortlines, 'Xsort.vim')
1402
1403  var lines =<< trim END
1404    vim9script
1405    import FastSort from './Xsort.vim'
1406    def Test()
1407      g:result = FastSort()
1408    enddef
1409    Test()
1410  END
1411  writefile(lines, 'Xscript.vim')
1412
1413  source Xscript.vim
1414  assert_equal([4, 3, 2, 1, 0], g:result)
1415
1416  unlet g:result
1417  delete('Xsort.vim')
1418  delete('Xscript.vim')
1419
1420  var Funcref = function('s:RetSome')
1421  assert_equal('some', Funcref())
1422enddef
1423
1424" Check that when searching for "FilterFunc" it finds the import in the
1425" script where FastFilter() is called from, both as a string and as a direct
1426" function reference.
1427def Test_vim9script_funcref_other_script()
1428  var filterLines =<< trim END
1429    vim9script
1430    export def FilterFunc(idx: number, val: number): bool
1431      return idx % 2 == 1
1432    enddef
1433    export def FastFilter(): list<number>
1434      return range(10)->filter('FilterFunc')
1435    enddef
1436    export def FastFilterDirect(): list<number>
1437      return range(10)->filter(FilterFunc)
1438    enddef
1439  END
1440  writefile(filterLines, 'Xfilter.vim')
1441
1442  var lines =<< trim END
1443    vim9script
1444    import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim'
1445    def Test()
1446      var x: list<number> = FastFilter()
1447    enddef
1448    Test()
1449    def TestDirect()
1450      var x: list<number> = FastFilterDirect()
1451    enddef
1452    TestDirect()
1453  END
1454  CheckScriptSuccess(lines)
1455  delete('Xfilter.vim')
1456enddef
1457
1458def Test_vim9script_reload_delfunc()
1459  var first_lines =<< trim END
1460    vim9script
1461    def FuncYes(): string
1462      return 'yes'
1463    enddef
1464  END
1465  var withno_lines =<< trim END
1466    def FuncNo(): string
1467      return 'no'
1468    enddef
1469    def g:DoCheck(no_exists: bool)
1470      assert_equal('yes', FuncYes())
1471      assert_equal('no', FuncNo())
1472    enddef
1473  END
1474  var nono_lines =<< trim END
1475    def g:DoCheck(no_exists: bool)
1476      assert_equal('yes', FuncYes())
1477      assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck')
1478    enddef
1479  END
1480
1481  # FuncNo() is defined
1482  writefile(first_lines + withno_lines, 'Xreloaded.vim')
1483  source Xreloaded.vim
1484  g:DoCheck(true)
1485
1486  # FuncNo() is not redefined
1487  writefile(first_lines + nono_lines, 'Xreloaded.vim')
1488  source Xreloaded.vim
1489  g:DoCheck(false)
1490
1491  # FuncNo() is back
1492  writefile(first_lines + withno_lines, 'Xreloaded.vim')
1493  source Xreloaded.vim
1494  g:DoCheck(false)
1495
1496  delete('Xreloaded.vim')
1497enddef
1498
1499def Test_vim9script_reload_delvar()
1500  # write the script with a script-local variable
1501  var lines =<< trim END
1502    vim9script
1503    var name = 'string'
1504  END
1505  writefile(lines, 'XreloadVar.vim')
1506  source XreloadVar.vim
1507
1508  # now write the script using the same variable locally - works
1509  lines =<< trim END
1510    vim9script
1511    def Func()
1512      var name = 'string'
1513    enddef
1514  END
1515  writefile(lines, 'XreloadVar.vim')
1516  source XreloadVar.vim
1517
1518  delete('XreloadVar.vim')
1519enddef
1520
1521def Test_import_absolute()
1522  var import_lines = [
1523        'vim9script',
1524        'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
1525        'def UseExported()',
1526        '  g:imported_abs = exported',
1527        '  exported = 8888',
1528        '  g:imported_after = exported',
1529        'enddef',
1530        'UseExported()',
1531        'g:import_disassembled = execute("disass UseExported")',
1532        ]
1533  writefile(import_lines, 'Ximport_abs.vim')
1534  writefile(s:export_script_lines, 'Xexport_abs.vim')
1535
1536  source Ximport_abs.vim
1537
1538  assert_equal(9876, g:imported_abs)
1539  assert_equal(8888, g:imported_after)
1540  assert_match('<SNR>\d\+_UseExported\_s*' ..
1541          'g:imported_abs = exported\_s*' ..
1542          '0 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' ..
1543          '1 STOREG g:imported_abs\_s*' ..
1544          'exported = 8888\_s*' ..
1545          '2 PUSHNR 8888\_s*' ..
1546          '3 STORESCRIPT exported-2 in .*Xexport_abs.vim\_s*' ..
1547          'g:imported_after = exported\_s*' ..
1548          '4 LOADSCRIPT exported-2 from .*Xexport_abs.vim\_s*' ..
1549          '5 STOREG g:imported_after',
1550        g:import_disassembled)
1551
1552  Undo_export_script_lines()
1553  unlet g:imported_abs
1554  unlet g:import_disassembled
1555
1556  delete('Ximport_abs.vim')
1557  delete('Xexport_abs.vim')
1558enddef
1559
1560def Test_import_rtp()
1561  var import_lines = [
1562        'vim9script',
1563        'import exported from "Xexport_rtp.vim"',
1564        'g:imported_rtp = exported',
1565        ]
1566  writefile(import_lines, 'Ximport_rtp.vim')
1567  mkdir('import')
1568  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
1569
1570  var save_rtp = &rtp
1571  &rtp = getcwd()
1572  source Ximport_rtp.vim
1573  &rtp = save_rtp
1574
1575  assert_equal(9876, g:imported_rtp)
1576
1577  Undo_export_script_lines()
1578  unlet g:imported_rtp
1579  delete('Ximport_rtp.vim')
1580  delete('import', 'rf')
1581enddef
1582
1583def Test_import_compile_error()
1584  var export_lines = [
1585        'vim9script',
1586        'export def ExpFunc(): string',
1587        '  return notDefined',
1588        'enddef',
1589        ]
1590  writefile(export_lines, 'Xexported.vim')
1591
1592  var import_lines = [
1593        'vim9script',
1594        'import ExpFunc from "./Xexported.vim"',
1595        'def ImpFunc()',
1596        '  echo ExpFunc()',
1597        'enddef',
1598        'defcompile',
1599        ]
1600  writefile(import_lines, 'Ximport.vim')
1601
1602  try
1603    source Ximport.vim
1604  catch /E1001/
1605    # Error should be fore the Xexported.vim file.
1606    assert_match('E1001: Variable not found: notDefined', v:exception)
1607    assert_match('function <SNR>\d\+_ImpFunc\[1\]..<SNR>\d\+_ExpFunc, line 1', v:throwpoint)
1608  endtry
1609
1610  delete('Xexported.vim')
1611  delete('Ximport.vim')
1612enddef
1613
1614def Test_func_redefine_error()
1615  var lines = [
1616        'vim9script',
1617        'def Func()',
1618        '  eval [][0]',
1619        'enddef',
1620        'Func()',
1621        ]
1622  writefile(lines, 'Xtestscript.vim')
1623
1624  for count in range(3)
1625    try
1626      source Xtestscript.vim
1627    catch /E684/
1628      # function name should contain <SNR> every time
1629      assert_match('E684: list index out of range', v:exception)
1630      assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint)
1631    endtry
1632  endfor
1633
1634  delete('Xtestscript.vim')
1635enddef
1636
1637def Test_func_overrules_import_fails()
1638  var export_lines =<< trim END
1639      vim9script
1640      export def Func()
1641        echo 'imported'
1642      enddef
1643  END
1644  writefile(export_lines, 'XexportedFunc.vim')
1645
1646  var lines =<< trim END
1647    vim9script
1648    import Func from './XexportedFunc.vim'
1649    def Func()
1650      echo 'local to function'
1651    enddef
1652  END
1653  CheckScriptFailure(lines, 'E1073:')
1654
1655  lines =<< trim END
1656    vim9script
1657    import Func from './XexportedFunc.vim'
1658    def Outer()
1659      def Func()
1660        echo 'local to function'
1661      enddef
1662    enddef
1663    defcompile
1664  END
1665  CheckScriptFailure(lines, 'E1073:')
1666
1667  delete('XexportedFunc.vim')
1668enddef
1669
1670def Test_func_redefine_fails()
1671  var lines =<< trim END
1672    vim9script
1673    def Func()
1674      echo 'one'
1675    enddef
1676    def Func()
1677      echo 'two'
1678    enddef
1679  END
1680  CheckScriptFailure(lines, 'E1073:')
1681
1682  lines =<< trim END
1683    vim9script
1684    def Foo(): string
1685      return 'foo'
1686      enddef
1687    def Func()
1688      var  Foo = {-> 'lambda'}
1689    enddef
1690    defcompile
1691  END
1692  CheckScriptFailure(lines, 'E1073:')
1693enddef
1694
1695def Test_fixed_size_list()
1696  # will be allocated as one piece of memory, check that changes work
1697  var l = [1, 2, 3, 4]
1698  l->remove(0)
1699  l->add(5)
1700  l->insert(99, 1)
1701  assert_equal([2, 99, 3, 4, 5], l)
1702enddef
1703
1704def Test_no_insert_xit()
1705  CheckDefExecFailure(['a = 1'], 'E1100:')
1706  CheckDefExecFailure(['c = 1'], 'E1100:')
1707  CheckDefExecFailure(['i = 1'], 'E1100:')
1708  CheckDefExecFailure(['t = 1'], 'E1100:')
1709  CheckDefExecFailure(['x = 1'], 'E1100:')
1710
1711  CheckScriptFailure(['vim9script', 'a = 1'], 'E488:')
1712  CheckScriptFailure(['vim9script', 'a'], 'E1100:')
1713  CheckScriptFailure(['vim9script', 'c = 1'], 'E488:')
1714  CheckScriptFailure(['vim9script', 'c'], 'E1100:')
1715  CheckScriptFailure(['vim9script', 'i = 1'], 'E488:')
1716  CheckScriptFailure(['vim9script', 'i'], 'E1100:')
1717  CheckScriptFailure(['vim9script', 't'], 'E1100:')
1718  CheckScriptFailure(['vim9script', 't = 1'], 'E1100:')
1719  CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:')
1720enddef
1721
1722def IfElse(what: number): string
1723  var res = ''
1724  if what == 1
1725    res = "one"
1726  elseif what == 2
1727    res = "two"
1728  else
1729    res = "three"
1730  endif
1731  return res
1732enddef
1733
1734def Test_if_elseif_else()
1735  assert_equal('one', IfElse(1))
1736  assert_equal('two', IfElse(2))
1737  assert_equal('three', IfElse(3))
1738enddef
1739
1740def Test_if_elseif_else_fails()
1741  CheckDefFailure(['elseif true'], 'E582:')
1742  CheckDefFailure(['else'], 'E581:')
1743  CheckDefFailure(['endif'], 'E580:')
1744  CheckDefFailure(['if g:abool', 'elseif xxx'], 'E1001:')
1745  CheckDefFailure(['if true', 'echo 1'], 'E171:')
1746enddef
1747
1748let g:bool_true = v:true
1749let g:bool_false = v:false
1750
1751def Test_if_const_expr()
1752  var res = false
1753  if true ? true : false
1754    res = true
1755  endif
1756  assert_equal(true, res)
1757
1758  g:glob = 2
1759  if false
1760    execute('g:glob = 3')
1761  endif
1762  assert_equal(2, g:glob)
1763  if true
1764    execute('g:glob = 3')
1765  endif
1766  assert_equal(3, g:glob)
1767
1768  res = false
1769  if g:bool_true ? true : false
1770    res = true
1771  endif
1772  assert_equal(true, res)
1773
1774  res = false
1775  if true ? g:bool_true : false
1776    res = true
1777  endif
1778  assert_equal(true, res)
1779
1780  res = false
1781  if true ? true : g:bool_false
1782    res = true
1783  endif
1784  assert_equal(true, res)
1785
1786  res = false
1787  if true ? false : true
1788    res = true
1789  endif
1790  assert_equal(false, res)
1791
1792  res = false
1793  if false ? false : true
1794    res = true
1795  endif
1796  assert_equal(true, res)
1797
1798  res = false
1799  if false ? true : false
1800    res = true
1801  endif
1802  assert_equal(false, res)
1803
1804  res = false
1805  if has('xyz') ? true : false
1806    res = true
1807  endif
1808  assert_equal(false, res)
1809
1810  res = false
1811  if true && true
1812    res = true
1813  endif
1814  assert_equal(true, res)
1815
1816  res = false
1817  if true && false
1818    res = true
1819  endif
1820  assert_equal(false, res)
1821
1822  res = false
1823  if g:bool_true && false
1824    res = true
1825  endif
1826  assert_equal(false, res)
1827
1828  res = false
1829  if true && g:bool_false
1830    res = true
1831  endif
1832  assert_equal(false, res)
1833
1834  res = false
1835  if false && false
1836    res = true
1837  endif
1838  assert_equal(false, res)
1839
1840  res = false
1841  if true || false
1842    res = true
1843  endif
1844  assert_equal(true, res)
1845
1846  res = false
1847  if g:bool_true || false
1848    res = true
1849  endif
1850  assert_equal(true, res)
1851
1852  res = false
1853  if true || g:bool_false
1854    res = true
1855  endif
1856  assert_equal(true, res)
1857
1858  res = false
1859  if false || false
1860    res = true
1861  endif
1862  assert_equal(false, res)
1863
1864  # with constant "false" expression may be invalid so long as the syntax is OK
1865  if false | eval 0 | endif
1866  if false | eval burp + 234 | endif
1867  if false | echo burp 234 'asd' | endif
1868  if false
1869    burp
1870  endif
1871enddef
1872
1873def Test_if_const_expr_fails()
1874  CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
1875  CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
1876  CheckDefFailure(["if has('aaa'"], 'E110:')
1877  CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
1878enddef
1879
1880def RunNested(i: number): number
1881  var x: number = 0
1882  if i % 2
1883    if 1
1884      # comment
1885    else
1886      # comment
1887    endif
1888    x += 1
1889  else
1890    x += 1000
1891  endif
1892  return x
1893enddef
1894
1895def Test_nested_if()
1896  assert_equal(1, RunNested(1))
1897  assert_equal(1000, RunNested(2))
1898enddef
1899
1900def Test_execute_cmd()
1901  # missing argument is ignored
1902  execute
1903  execute # comment
1904
1905  new
1906  setline(1, 'default')
1907  execute 'setline(1, "execute-string")'
1908  assert_equal('execute-string', getline(1))
1909
1910  execute "setline(1, 'execute-string')"
1911  assert_equal('execute-string', getline(1))
1912
1913  var cmd1 = 'setline(1,'
1914  var cmd2 = '"execute-var")'
1915  execute cmd1 cmd2 # comment
1916  assert_equal('execute-var', getline(1))
1917
1918  execute cmd1 cmd2 '|setline(1, "execute-var-string")'
1919  assert_equal('execute-var-string', getline(1))
1920
1921  var cmd_first = 'call '
1922  var cmd_last = 'setline(1, "execute-var-var")'
1923  execute cmd_first .. cmd_last
1924  assert_equal('execute-var-var', getline(1))
1925  bwipe!
1926
1927  var n = true
1928  execute 'echomsg' (n ? '"true"' : '"no"')
1929  assert_match('^true$', Screenline(&lines))
1930
1931  echomsg [1, 2, 3] {a: 1, b: 2}
1932  assert_match('^\[1, 2, 3\] {''a'': 1, ''b'': 2}$', Screenline(&lines))
1933
1934  CheckDefFailure(['execute xxx'], 'E1001:', 1)
1935  CheckDefExecFailure(['execute "tabnext " .. 8'], 'E475:', 1)
1936  CheckDefFailure(['execute "cmd"# comment'], 'E488:', 1)
1937enddef
1938
1939def Test_execute_cmd_vimscript()
1940  # only checks line continuation
1941  var lines =<< trim END
1942      vim9script
1943      execute 'g:someVar'
1944                .. ' = ' ..
1945                   '28'
1946      assert_equal(28, g:someVar)
1947      unlet g:someVar
1948  END
1949  CheckScriptSuccess(lines)
1950enddef
1951
1952def Test_echo_cmd()
1953  echo 'some' # comment
1954  echon 'thing'
1955  assert_match('^something$', Screenline(&lines))
1956
1957  echo "some" # comment
1958  echon "thing"
1959  assert_match('^something$', Screenline(&lines))
1960
1961  var str1 = 'some'
1962  var str2 = 'more'
1963  echo str1 str2
1964  assert_match('^some more$', Screenline(&lines))
1965
1966  CheckDefFailure(['echo "xxx"# comment'], 'E488:')
1967enddef
1968
1969def Test_echomsg_cmd()
1970  echomsg 'some' 'more' # comment
1971  assert_match('^some more$', Screenline(&lines))
1972  echo 'clear'
1973  :1messages
1974  assert_match('^some more$', Screenline(&lines))
1975
1976  CheckDefFailure(['echomsg "xxx"# comment'], 'E488:')
1977enddef
1978
1979def Test_echomsg_cmd_vimscript()
1980  # only checks line continuation
1981  var lines =<< trim END
1982      vim9script
1983      echomsg 'here'
1984                .. ' is ' ..
1985                   'a message'
1986      assert_match('^here is a message$', Screenline(&lines))
1987  END
1988  CheckScriptSuccess(lines)
1989enddef
1990
1991def Test_echoerr_cmd()
1992  try
1993    echoerr 'something' 'wrong' # comment
1994  catch
1995    assert_match('something wrong', v:exception)
1996  endtry
1997enddef
1998
1999def Test_echoerr_cmd_vimscript()
2000  # only checks line continuation
2001  var lines =<< trim END
2002      vim9script
2003      try
2004        echoerr 'this'
2005                .. ' is ' ..
2006                   'wrong'
2007      catch
2008        assert_match('this is wrong', v:exception)
2009      endtry
2010  END
2011  CheckScriptSuccess(lines)
2012enddef
2013
2014def Test_for_outside_of_function()
2015  var lines =<< trim END
2016    vim9script
2017    new
2018    for var in range(0, 3)
2019      append(line('$'), var)
2020    endfor
2021    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
2022    bwipe!
2023  END
2024  writefile(lines, 'Xvim9for.vim')
2025  source Xvim9for.vim
2026  delete('Xvim9for.vim')
2027enddef
2028
2029def Test_for_loop()
2030  var result = ''
2031  for cnt in range(7)
2032    if cnt == 4
2033      break
2034    endif
2035    if cnt == 2
2036      continue
2037    endif
2038    result ..= cnt .. '_'
2039  endfor
2040  assert_equal('0_1_3_', result)
2041
2042  var concat = ''
2043  for str in eval('["one", "two"]')
2044    concat ..= str
2045  endfor
2046  assert_equal('onetwo', concat)
2047
2048  var total = 0
2049  for nr in
2050      [1, 2, 3]
2051    total += nr
2052  endfor
2053  assert_equal(6, total)
2054
2055  total = 0
2056  for nr
2057    in [1, 2, 3]
2058    total += nr
2059  endfor
2060  assert_equal(6, total)
2061
2062  total = 0
2063  for nr
2064    in
2065    [1, 2, 3]
2066    total += nr
2067  endfor
2068  assert_equal(6, total)
2069
2070  var res = ""
2071  for [n: number, s: string] in [[1, 'a'], [2, 'b']]
2072    res ..= n .. s
2073  endfor
2074  assert_equal('1a2b', res)
2075enddef
2076
2077def Test_for_loop_fails()
2078  CheckDefFailure(['for '], 'E1097:')
2079  CheckDefFailure(['for x'], 'E1097:')
2080  CheckDefFailure(['for x in'], 'E1097:')
2081  CheckDefFailure(['for # in range(5)'], 'E690:')
2082  CheckDefFailure(['for i In range(5)'], 'E690:')
2083  CheckDefFailure(['var x = 5', 'for x in range(5)'], 'E1017:')
2084  CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:')
2085  delfunc! g:Func
2086  CheckDefFailure(['for i in "text"'], 'E1012:')
2087  CheckDefFailure(['for i in xxx'], 'E1001:')
2088  CheckDefFailure(['endfor'], 'E588:')
2089  CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
2090enddef
2091
2092def Test_for_loop_script_var()
2093  # cannot use s:var in a :def function
2094  CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:')
2095
2096  # can use s:var in Vim9 script, with or without s:
2097  var lines =<< trim END
2098    vim9script
2099    var total = 0
2100    for s:var in [1, 2, 3]
2101      total += s:var
2102    endfor
2103    assert_equal(6, total)
2104
2105    total = 0
2106    for var in [1, 2, 3]
2107      total += var
2108    endfor
2109    assert_equal(6, total)
2110  END
2111enddef
2112
2113def Test_for_loop_unpack()
2114  var lines =<< trim END
2115      var result = []
2116      for [v1, v2] in [[1, 2], [3, 4]]
2117        result->add(v1)
2118        result->add(v2)
2119      endfor
2120      assert_equal([1, 2, 3, 4], result)
2121
2122      result = []
2123      for [v1, v2; v3] in [[1, 2], [3, 4, 5, 6]]
2124        result->add(v1)
2125        result->add(v2)
2126        result->add(v3)
2127      endfor
2128      assert_equal([1, 2, [], 3, 4, [5, 6]], result)
2129
2130      result = []
2131      for [&ts, &sw] in [[1, 2], [3, 4]]
2132        result->add(&ts)
2133        result->add(&sw)
2134      endfor
2135      assert_equal([1, 2, 3, 4], result)
2136
2137      var slist: list<string>
2138      for [$LOOPVAR, @r, v:errmsg] in [['a', 'b', 'c'], ['d', 'e', 'f']]
2139        slist->add($LOOPVAR)
2140        slist->add(@r)
2141        slist->add(v:errmsg)
2142      endfor
2143      assert_equal(['a', 'b', 'c', 'd', 'e', 'f'], slist)
2144
2145      slist = []
2146      for [g:globalvar, b:bufvar, w:winvar, t:tabvar] in [['global', 'buf', 'win', 'tab'], ['1', '2', '3', '4']]
2147        slist->add(g:globalvar)
2148        slist->add(b:bufvar)
2149        slist->add(w:winvar)
2150        slist->add(t:tabvar)
2151      endfor
2152      assert_equal(['global', 'buf', 'win', 'tab', '1', '2', '3', '4'], slist)
2153      unlet! g:globalvar b:bufvar w:winvar t:tabvar
2154  END
2155  CheckDefAndScriptSuccess(lines)
2156
2157  lines =<< trim END
2158      for [v1, v2] in [[1, 2, 3], [3, 4]]
2159        echo v1 v2
2160      endfor
2161  END
2162  CheckDefExecFailure(lines, 'E710:', 1)
2163
2164  lines =<< trim END
2165      for [v1, v2] in [[1], [3, 4]]
2166        echo v1 v2
2167      endfor
2168  END
2169  CheckDefExecFailure(lines, 'E711:', 1)
2170
2171  lines =<< trim END
2172      for [v1, v1] in [[1, 2], [3, 4]]
2173        echo v1
2174      endfor
2175  END
2176  CheckDefExecFailure(lines, 'E1017:', 1)
2177enddef
2178
2179def Test_while_loop()
2180  var result = ''
2181  var cnt = 0
2182  while cnt < 555
2183    if cnt == 3
2184      break
2185    endif
2186    cnt += 1
2187    if cnt == 2
2188      continue
2189    endif
2190    result ..= cnt .. '_'
2191  endwhile
2192  assert_equal('1_3_', result)
2193enddef
2194
2195def Test_while_loop_fails()
2196  CheckDefFailure(['while xxx'], 'E1001:')
2197  CheckDefFailure(['endwhile'], 'E588:')
2198  CheckDefFailure(['continue'], 'E586:')
2199  CheckDefFailure(['if true', 'continue'], 'E586:')
2200  CheckDefFailure(['break'], 'E587:')
2201  CheckDefFailure(['if true', 'break'], 'E587:')
2202  CheckDefFailure(['while 1', 'echo 3'], 'E170:')
2203enddef
2204
2205def Test_interrupt_loop()
2206  var caught = false
2207  var x = 0
2208  try
2209    while 1
2210      x += 1
2211      if x == 100
2212        feedkeys("\<C-C>", 'Lt')
2213      endif
2214    endwhile
2215  catch
2216    caught = true
2217    assert_equal(100, x)
2218  endtry
2219  assert_true(caught, 'should have caught an exception')
2220  # consume the CTRL-C
2221  getchar(0)
2222enddef
2223
2224def Test_automatic_line_continuation()
2225  var mylist = [
2226      'one',
2227      'two',
2228      'three',
2229      ] # comment
2230  assert_equal(['one', 'two', 'three'], mylist)
2231
2232  var mydict = {
2233      ['one']: 1,
2234      ['two']: 2,
2235      ['three']:
2236          3,
2237      } # comment
2238  assert_equal({one: 1, two: 2, three: 3}, mydict)
2239  mydict = {
2240      one: 1,  # comment
2241      two:     # comment
2242           2,  # comment
2243      three: 3 # comment
2244      }
2245  assert_equal({one: 1, two: 2, three: 3}, mydict)
2246  mydict = {
2247      one: 1,
2248      two:
2249           2,
2250      three: 3
2251      }
2252  assert_equal({one: 1, two: 2, three: 3}, mydict)
2253
2254  assert_equal(
2255        ['one', 'two', 'three'],
2256        split('one two three')
2257        )
2258enddef
2259
2260def Test_vim9_comment()
2261  CheckScriptSuccess([
2262      'vim9script',
2263      '# something',
2264      '#something',
2265      '#{something',
2266      ])
2267
2268  split Xfile
2269  CheckScriptSuccess([
2270      'vim9script',
2271      'edit #something',
2272      ])
2273  CheckScriptSuccess([
2274      'vim9script',
2275      'edit #{something',
2276      ])
2277  close
2278
2279  CheckScriptFailure([
2280      'vim9script',
2281      ':# something',
2282      ], 'E488:')
2283  CheckScriptFailure([
2284      '# something',
2285      ], 'E488:')
2286  CheckScriptFailure([
2287      ':# something',
2288      ], 'E488:')
2289
2290  { # block start
2291  } # block end
2292  CheckDefFailure([
2293      '{# comment',
2294      ], 'E488:')
2295  CheckDefFailure([
2296      '{',
2297      '}# comment',
2298      ], 'E488:')
2299
2300  echo "yes" # comment
2301  CheckDefFailure([
2302      'echo "yes"# comment',
2303      ], 'E488:')
2304  CheckScriptSuccess([
2305      'vim9script',
2306      'echo "yes" # something',
2307      ])
2308  CheckScriptFailure([
2309      'vim9script',
2310      'echo "yes"# something',
2311      ], 'E121:')
2312  CheckScriptFailure([
2313      'vim9script',
2314      'echo# something',
2315      ], 'E1144:')
2316  CheckScriptFailure([
2317      'echo "yes" # something',
2318      ], 'E121:')
2319
2320  exe "echo" # comment
2321  CheckDefFailure([
2322      'exe "echo"# comment',
2323      ], 'E488:')
2324  CheckScriptSuccess([
2325      'vim9script',
2326      'exe "echo" # something',
2327      ])
2328  CheckScriptFailure([
2329      'vim9script',
2330      'exe "echo"# something',
2331      ], 'E121:')
2332  CheckScriptFailure([
2333      'vim9script',
2334      'exe# something',
2335      ], 'E1144:')
2336  CheckScriptFailure([
2337      'exe "echo" # something',
2338      ], 'E121:')
2339
2340  CheckDefFailure([
2341      'try# comment',
2342      '  echo "yes"',
2343      'catch',
2344      'endtry',
2345      ], 'E1144:')
2346  CheckScriptFailure([
2347      'vim9script',
2348      'try# comment',
2349      'echo "yes"',
2350      ], 'E1144:')
2351  CheckDefFailure([
2352      'try',
2353      '  throw#comment',
2354      'catch',
2355      'endtry',
2356      ], 'E1144:')
2357  CheckDefFailure([
2358      'try',
2359      '  throw "yes"#comment',
2360      'catch',
2361      'endtry',
2362      ], 'E488:')
2363  CheckDefFailure([
2364      'try',
2365      '  echo "yes"',
2366      'catch# comment',
2367      'endtry',
2368      ], 'E1144:')
2369  CheckScriptFailure([
2370      'vim9script',
2371      'try',
2372      '  echo "yes"',
2373      'catch# comment',
2374      'endtry',
2375      ], 'E1144:')
2376  CheckDefFailure([
2377      'try',
2378      '  echo "yes"',
2379      'catch /pat/# comment',
2380      'endtry',
2381      ], 'E488:')
2382  CheckDefFailure([
2383      'try',
2384      'echo "yes"',
2385      'catch',
2386      'endtry# comment',
2387      ], 'E1144:')
2388  CheckScriptFailure([
2389      'vim9script',
2390      'try',
2391      '  echo "yes"',
2392      'catch',
2393      'endtry# comment',
2394      ], 'E1144:')
2395
2396  CheckScriptSuccess([
2397      'vim9script',
2398      'hi # comment',
2399      ])
2400  CheckScriptFailure([
2401      'vim9script',
2402      'hi# comment',
2403      ], 'E1144:')
2404  CheckScriptSuccess([
2405      'vim9script',
2406      'hi Search # comment',
2407      ])
2408  CheckScriptFailure([
2409      'vim9script',
2410      'hi Search# comment',
2411      ], 'E416:')
2412  CheckScriptSuccess([
2413      'vim9script',
2414      'hi link This Search # comment',
2415      ])
2416  CheckScriptFailure([
2417      'vim9script',
2418      'hi link This That# comment',
2419      ], 'E413:')
2420  CheckScriptSuccess([
2421      'vim9script',
2422      'hi clear This # comment',
2423      'hi clear # comment',
2424      ])
2425  # not tested, because it doesn't give an error but a warning:
2426  # hi clear This# comment',
2427  CheckScriptFailure([
2428      'vim9script',
2429      'hi clear# comment',
2430      ], 'E416:')
2431
2432  CheckScriptSuccess([
2433      'vim9script',
2434      'hi Group term=bold',
2435      'match Group /todo/ # comment',
2436      ])
2437  CheckScriptFailure([
2438      'vim9script',
2439      'hi Group term=bold',
2440      'match Group /todo/# comment',
2441      ], 'E488:')
2442  CheckScriptSuccess([
2443      'vim9script',
2444      'match # comment',
2445      ])
2446  CheckScriptFailure([
2447      'vim9script',
2448      'match# comment',
2449      ], 'E1144:')
2450  CheckScriptSuccess([
2451      'vim9script',
2452      'match none # comment',
2453      ])
2454  CheckScriptFailure([
2455      'vim9script',
2456      'match none# comment',
2457      ], 'E475:')
2458
2459  CheckScriptSuccess([
2460      'vim9script',
2461      'menutrans clear # comment',
2462      ])
2463  CheckScriptFailure([
2464      'vim9script',
2465      'menutrans clear# comment text',
2466      ], 'E474:')
2467
2468  CheckScriptSuccess([
2469      'vim9script',
2470      'syntax clear # comment',
2471      ])
2472  CheckScriptFailure([
2473      'vim9script',
2474      'syntax clear# comment text',
2475      ], 'E28:')
2476  CheckScriptSuccess([
2477      'vim9script',
2478      'syntax keyword Word some',
2479      'syntax clear Word # comment',
2480      ])
2481  CheckScriptFailure([
2482      'vim9script',
2483      'syntax keyword Word some',
2484      'syntax clear Word# comment text',
2485      ], 'E28:')
2486
2487  CheckScriptSuccess([
2488      'vim9script',
2489      'syntax list # comment',
2490      ])
2491  CheckScriptFailure([
2492      'vim9script',
2493      'syntax list# comment text',
2494      ], 'E28:')
2495
2496  CheckScriptSuccess([
2497      'vim9script',
2498      'syntax match Word /pat/ oneline # comment',
2499      ])
2500  CheckScriptFailure([
2501      'vim9script',
2502      'syntax match Word /pat/ oneline# comment',
2503      ], 'E475:')
2504
2505  CheckScriptSuccess([
2506      'vim9script',
2507      'syntax keyword Word word # comm[ent',
2508      ])
2509  CheckScriptFailure([
2510      'vim9script',
2511      'syntax keyword Word word# comm[ent',
2512      ], 'E789:')
2513
2514  CheckScriptSuccess([
2515      'vim9script',
2516      'syntax match Word /pat/ # comment',
2517      ])
2518  CheckScriptFailure([
2519      'vim9script',
2520      'syntax match Word /pat/# comment',
2521      ], 'E402:')
2522
2523  CheckScriptSuccess([
2524      'vim9script',
2525      'syntax match Word /pat/ contains=Something # comment',
2526      ])
2527  CheckScriptFailure([
2528      'vim9script',
2529      'syntax match Word /pat/ contains=Something# comment',
2530      ], 'E475:')
2531  CheckScriptFailure([
2532      'vim9script',
2533      'syntax match Word /pat/ contains= # comment',
2534      ], 'E406:')
2535  CheckScriptFailure([
2536      'vim9script',
2537      'syntax match Word /pat/ contains=# comment',
2538      ], 'E475:')
2539
2540  CheckScriptSuccess([
2541      'vim9script',
2542      'syntax region Word start=/pat/ end=/pat/ # comment',
2543      ])
2544  CheckScriptFailure([
2545      'vim9script',
2546      'syntax region Word start=/pat/ end=/pat/# comment',
2547      ], 'E402:')
2548
2549  CheckScriptSuccess([
2550      'vim9script',
2551      'syntax sync # comment',
2552      ])
2553  CheckScriptFailure([
2554      'vim9script',
2555      'syntax sync# comment',
2556      ], 'E404:')
2557  CheckScriptSuccess([
2558      'vim9script',
2559      'syntax sync ccomment # comment',
2560      ])
2561  CheckScriptFailure([
2562      'vim9script',
2563      'syntax sync ccomment# comment',
2564      ], 'E404:')
2565
2566  CheckScriptSuccess([
2567      'vim9script',
2568      'syntax cluster Some contains=Word # comment',
2569      ])
2570  CheckScriptFailure([
2571      'vim9script',
2572      'syntax cluster Some contains=Word# comment',
2573      ], 'E475:')
2574
2575  CheckScriptSuccess([
2576      'vim9script',
2577      'command Echo echo # comment',
2578      'command Echo # comment',
2579      'delcommand Echo',
2580      ])
2581  CheckScriptFailure([
2582      'vim9script',
2583      'command Echo echo# comment',
2584      'Echo',
2585      ], 'E1144:')
2586  delcommand Echo
2587
2588  var curdir = getcwd()
2589  CheckScriptSuccess([
2590      'command Echo cd " comment',
2591      'Echo',
2592      'delcommand Echo',
2593      ])
2594  CheckScriptSuccess([
2595      'vim9script',
2596      'command Echo cd # comment',
2597      'Echo',
2598      'delcommand Echo',
2599      ])
2600  CheckScriptFailure([
2601      'vim9script',
2602      'command Echo cd " comment',
2603      'Echo',
2604      ], 'E344:')
2605  delcommand Echo
2606  chdir(curdir)
2607
2608  CheckScriptFailure([
2609      'vim9script',
2610      'command Echo# comment',
2611      ], 'E182:')
2612  CheckScriptFailure([
2613      'vim9script',
2614      'command Echo echo',
2615      'command Echo# comment',
2616      ], 'E182:')
2617  delcommand Echo
2618
2619  CheckScriptSuccess([
2620      'vim9script',
2621      'function # comment',
2622      ])
2623  CheckScriptFailure([
2624      'vim9script',
2625      'function " comment',
2626      ], 'E129:')
2627  CheckScriptFailure([
2628      'vim9script',
2629      'function# comment',
2630      ], 'E1144:')
2631  CheckScriptSuccess([
2632      'vim9script',
2633      'function CheckScriptSuccess # comment',
2634      ])
2635  CheckScriptFailure([
2636      'vim9script',
2637      'function CheckScriptSuccess# comment',
2638      ], 'E488:')
2639
2640  CheckScriptSuccess([
2641      'vim9script',
2642      'func g:DeleteMeA()',
2643      'endfunc',
2644      'delfunction g:DeleteMeA # comment',
2645      ])
2646  CheckScriptFailure([
2647      'vim9script',
2648      'func g:DeleteMeB()',
2649      'endfunc',
2650      'delfunction g:DeleteMeB# comment',
2651      ], 'E488:')
2652
2653  CheckScriptSuccess([
2654      'vim9script',
2655      'call execute("ls") # comment',
2656      ])
2657  CheckScriptFailure([
2658      'vim9script',
2659      'call execute("ls")# comment',
2660      ], 'E488:')
2661
2662  CheckScriptFailure([
2663      'def Test() " comment',
2664      'enddef',
2665      ], 'E488:')
2666  CheckScriptFailure([
2667      'vim9script',
2668      'def Test() " comment',
2669      'enddef',
2670      ], 'E488:')
2671
2672  CheckScriptSuccess([
2673      'func Test() " comment',
2674      'endfunc',
2675      'delfunc Test',
2676      ])
2677  CheckScriptSuccess([
2678      'vim9script',
2679      'func Test() " comment',
2680      'endfunc',
2681      ])
2682
2683  CheckScriptSuccess([
2684      'def Test() # comment',
2685      'enddef',
2686      ])
2687  CheckScriptFailure([
2688      'func Test() # comment',
2689      'endfunc',
2690      ], 'E488:')
2691enddef
2692
2693def Test_vim9_comment_gui()
2694  CheckCanRunGui
2695
2696  CheckScriptFailure([
2697      'vim9script',
2698      'gui#comment'
2699      ], 'E1144:')
2700  CheckScriptFailure([
2701      'vim9script',
2702      'gui -f#comment'
2703      ], 'E499:')
2704enddef
2705
2706def Test_vim9_comment_not_compiled()
2707  au TabEnter *.vim g:entered = 1
2708  au TabEnter *.x g:entered = 2
2709
2710  edit test.vim
2711  doautocmd TabEnter #comment
2712  assert_equal(1, g:entered)
2713
2714  doautocmd TabEnter f.x
2715  assert_equal(2, g:entered)
2716
2717  g:entered = 0
2718  doautocmd TabEnter f.x #comment
2719  assert_equal(2, g:entered)
2720
2721  assert_fails('doautocmd Syntax#comment', 'E216:')
2722
2723  au! TabEnter
2724  unlet g:entered
2725
2726  CheckScriptSuccess([
2727      'vim9script',
2728      'g:var = 123',
2729      'b:var = 456',
2730      'w:var = 777',
2731      't:var = 888',
2732      'unlet g:var w:var # something',
2733      ])
2734
2735  CheckScriptFailure([
2736      'vim9script',
2737      'let var = 123',
2738      ], 'E1126: Cannot use :let in Vim9 script')
2739
2740  CheckScriptFailure([
2741      'vim9script',
2742      'var g:var = 123',
2743      ], 'E1016: Cannot declare a global variable:')
2744
2745  CheckScriptFailure([
2746      'vim9script',
2747      'var b:var = 123',
2748      ], 'E1016: Cannot declare a buffer variable:')
2749
2750  CheckScriptFailure([
2751      'vim9script',
2752      'var w:var = 123',
2753      ], 'E1016: Cannot declare a window variable:')
2754
2755  CheckScriptFailure([
2756      'vim9script',
2757      'var t:var = 123',
2758      ], 'E1016: Cannot declare a tab variable:')
2759
2760  CheckScriptFailure([
2761      'vim9script',
2762      'var v:version = 123',
2763      ], 'E1016: Cannot declare a v: variable:')
2764
2765  CheckScriptFailure([
2766      'vim9script',
2767      'var $VARIABLE = "text"',
2768      ], 'E1016: Cannot declare an environment variable:')
2769
2770  CheckScriptFailure([
2771      'vim9script',
2772      'g:var = 123',
2773      'unlet g:var# comment1',
2774      ], 'E108:')
2775
2776  CheckScriptFailure([
2777      'let g:var = 123',
2778      'unlet g:var # something',
2779      ], 'E488:')
2780
2781  CheckScriptSuccess([
2782      'vim9script',
2783      'if 1 # comment2',
2784      '  echo "yes"',
2785      'elseif 2 #comment',
2786      '  echo "no"',
2787      'endif',
2788      ])
2789
2790  CheckScriptFailure([
2791      'vim9script',
2792      'if 1# comment3',
2793      '  echo "yes"',
2794      'endif',
2795      ], 'E15:')
2796
2797  CheckScriptFailure([
2798      'vim9script',
2799      'if 0 # comment4',
2800      '  echo "yes"',
2801      'elseif 2#comment',
2802      '  echo "no"',
2803      'endif',
2804      ], 'E15:')
2805
2806  CheckScriptSuccess([
2807      'vim9script',
2808      'var v = 1 # comment5',
2809      ])
2810
2811  CheckScriptFailure([
2812      'vim9script',
2813      'var v = 1# comment6',
2814      ], 'E15:')
2815
2816  CheckScriptSuccess([
2817      'vim9script',
2818      'new'
2819      'setline(1, ["# define pat", "last"])',
2820      ':$',
2821      'dsearch /pat/ #comment',
2822      'bwipe!',
2823      ])
2824
2825  CheckScriptFailure([
2826      'vim9script',
2827      'new'
2828      'setline(1, ["# define pat", "last"])',
2829      ':$',
2830      'dsearch /pat/#comment',
2831      'bwipe!',
2832      ], 'E488:')
2833
2834  CheckScriptFailure([
2835      'vim9script',
2836      'func! SomeFunc()',
2837      ], 'E477:')
2838enddef
2839
2840def Test_finish()
2841  var lines =<< trim END
2842    vim9script
2843    g:res = 'one'
2844    if v:false | finish | endif
2845    g:res = 'two'
2846    finish
2847    g:res = 'three'
2848  END
2849  writefile(lines, 'Xfinished')
2850  source Xfinished
2851  assert_equal('two', g:res)
2852
2853  unlet g:res
2854  delete('Xfinished')
2855enddef
2856
2857def Test_forward_declaration()
2858  var lines =<< trim END
2859    vim9script
2860    def GetValue(): string
2861      return theVal
2862    enddef
2863    var theVal = 'something'
2864    g:initVal = GetValue()
2865    theVal = 'else'
2866    g:laterVal = GetValue()
2867  END
2868  writefile(lines, 'Xforward')
2869  source Xforward
2870  assert_equal('something', g:initVal)
2871  assert_equal('else', g:laterVal)
2872
2873  unlet g:initVal
2874  unlet g:laterVal
2875  delete('Xforward')
2876enddef
2877
2878def Test_source_vim9_from_legacy()
2879  var vim9_lines =<< trim END
2880    vim9script
2881    var local = 'local'
2882    g:global = 'global'
2883    export var exported = 'exported'
2884    export def GetText(): string
2885       return 'text'
2886    enddef
2887  END
2888  writefile(vim9_lines, 'Xvim9_script.vim')
2889
2890  var legacy_lines =<< trim END
2891    source Xvim9_script.vim
2892
2893    call assert_false(exists('local'))
2894    call assert_false(exists('exported'))
2895    call assert_false(exists('s:exported'))
2896    call assert_equal('global', global)
2897    call assert_equal('global', g:global)
2898
2899    " imported variable becomes script-local
2900    import exported from './Xvim9_script.vim'
2901    call assert_equal('exported', s:exported)
2902    call assert_false(exists('exported'))
2903
2904    " imported function becomes script-local
2905    import GetText from './Xvim9_script.vim'
2906    call assert_equal('text', s:GetText())
2907    call assert_false(exists('*GetText'))
2908  END
2909  writefile(legacy_lines, 'Xlegacy_script.vim')
2910
2911  source Xlegacy_script.vim
2912  assert_equal('global', g:global)
2913  unlet g:global
2914
2915  delete('Xlegacy_script.vim')
2916  delete('Xvim9_script.vim')
2917enddef
2918
2919func Test_vim9script_not_global()
2920  " check that items defined in Vim9 script are script-local, not global
2921  let vim9lines =<< trim END
2922    vim9script
2923    var name = 'local'
2924    func TheFunc()
2925      echo 'local'
2926    endfunc
2927    def DefFunc()
2928      echo 'local'
2929    enddef
2930  END
2931  call writefile(vim9lines, 'Xvim9script.vim')
2932  source Xvim9script.vim
2933  try
2934    echo g:var
2935    assert_report('did not fail')
2936  catch /E121:/
2937    " caught
2938  endtry
2939  try
2940    call TheFunc()
2941    assert_report('did not fail')
2942  catch /E117:/
2943    " caught
2944  endtry
2945  try
2946    call DefFunc()
2947    assert_report('did not fail')
2948  catch /E117:/
2949    " caught
2950  endtry
2951
2952  call delete('Xvim9script.vim')
2953endfunc
2954
2955def Test_vim9_copen()
2956  # this was giving an error for setting w:quickfix_title
2957  copen
2958  quit
2959enddef
2960
2961" test using an auto-loaded function and variable
2962def Test_vim9_autoload()
2963  var lines =<< trim END
2964     vim9script
2965     def some#gettest(): string
2966       return 'test'
2967     enddef
2968     g:some#name = 'name'
2969  END
2970
2971  mkdir('Xdir/autoload', 'p')
2972  writefile(lines, 'Xdir/autoload/some.vim')
2973  var save_rtp = &rtp
2974  exe 'set rtp^=' .. getcwd() .. '/Xdir'
2975
2976  assert_equal('test', g:some#gettest())
2977  assert_equal('name', g:some#name)
2978  g:some#other = 'other'
2979  assert_equal('other', g:some#other)
2980
2981  # upper case script name works
2982  lines =<< trim END
2983     vim9script
2984     def Other#getOther(): string
2985       return 'other'
2986     enddef
2987  END
2988  writefile(lines, 'Xdir/autoload/Other.vim')
2989  assert_equal('other', g:Other#getOther())
2990
2991  delete('Xdir', 'rf')
2992  &rtp = save_rtp
2993enddef
2994
2995" test using a vim9script that is auto-loaded from an autocmd
2996def Test_vim9_aucmd_autoload()
2997  var lines =<< trim END
2998     vim9script
2999     def foo#test()
3000         echomsg getreg('"')
3001     enddef
3002  END
3003
3004  mkdir('Xdir/autoload', 'p')
3005  writefile(lines, 'Xdir/autoload/foo.vim')
3006  var save_rtp = &rtp
3007  exe 'set rtp^=' .. getcwd() .. '/Xdir'
3008  augroup test
3009    autocmd TextYankPost * call foo#test()
3010  augroup END
3011
3012  normal Y
3013
3014  augroup test
3015    autocmd!
3016  augroup END
3017  delete('Xdir', 'rf')
3018  &rtp = save_rtp
3019enddef
3020
3021" This was causing a crash because suppress_errthrow wasn't reset.
3022def Test_vim9_autoload_error()
3023  var lines =<< trim END
3024      vim9script
3025      def crash#func()
3026          try
3027              for x in List()
3028              endfor
3029          catch
3030          endtry
3031          g:ok = true
3032      enddef
3033      fu List()
3034          invalid
3035      endfu
3036      try
3037          alsoinvalid
3038      catch /wontmatch/
3039      endtry
3040  END
3041  call mkdir('Xruntime/autoload', 'p')
3042  call writefile(lines, 'Xruntime/autoload/crash.vim')
3043
3044  # run in a separate Vim to avoid the side effects of assert_fails()
3045  lines =<< trim END
3046    exe 'set rtp^=' .. getcwd() .. '/Xruntime'
3047    call crash#func()
3048    call writefile(['ok'], 'Xdidit')
3049    qall!
3050  END
3051  writefile(lines, 'Xscript')
3052  RunVim([], [], '-S Xscript')
3053  assert_equal(['ok'], readfile('Xdidit'))
3054
3055  delete('Xdidit')
3056  delete('Xscript')
3057  delete('Xruntime', 'rf')
3058
3059  lines =<< trim END
3060    vim9script
3061    var foo#bar = 'asdf'
3062  END
3063  CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2)
3064enddef
3065
3066def Test_script_var_in_autocmd()
3067  # using a script variable from an autocommand, defined in a :def function in a
3068  # legacy Vim script, cannot check the variable type.
3069  var lines =<< trim END
3070    let s:counter = 1
3071    def s:Func()
3072      au! CursorHold
3073      au CursorHold * s:counter += 1
3074    enddef
3075    call s:Func()
3076    doau CursorHold
3077    call assert_equal(2, s:counter)
3078    au! CursorHold
3079  END
3080  CheckScriptSuccess(lines)
3081enddef
3082
3083def Test_cmdline_win()
3084  # if the Vim syntax highlighting uses Vim9 constructs they can be used from
3085  # the command line window.
3086  mkdir('rtp/syntax', 'p')
3087  var export_lines =<< trim END
3088    vim9script
3089    export var That = 'yes'
3090  END
3091  writefile(export_lines, 'rtp/syntax/Xexport.vim')
3092  var import_lines =<< trim END
3093    vim9script
3094    import That from './Xexport.vim'
3095  END
3096  writefile(import_lines, 'rtp/syntax/vim.vim')
3097  var save_rtp = &rtp
3098  &rtp = getcwd() .. '/rtp' .. ',' .. &rtp
3099  syntax on
3100  augroup CmdWin
3101    autocmd CmdwinEnter * g:got_there = 'yes'
3102  augroup END
3103  # this will open and also close the cmdline window
3104  feedkeys('q:', 'xt')
3105  assert_equal('yes', g:got_there)
3106
3107  augroup CmdWin
3108    au!
3109  augroup END
3110  &rtp = save_rtp
3111  delete('rtp', 'rf')
3112enddef
3113
3114def Test_invalid_sid()
3115  assert_fails('func <SNR>1234_func', 'E123:')
3116
3117  if RunVim([], ['wq! Xdidit'], '+"func <SNR>1_func"')
3118    assert_equal([], readfile('Xdidit'))
3119  endif
3120  delete('Xdidit')
3121enddef
3122
3123def Test_restoring_cpo()
3124  writefile(['vim9script', 'set nocp'], 'Xsourced')
3125  writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose')
3126  if RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose')
3127    assert_equal(['done'], readfile('Xdone'))
3128  endif
3129  delete('Xsourced')
3130  delete('Xclose')
3131  delete('Xdone')
3132enddef
3133
3134
3135def Test_unset_any_variable()
3136  var lines =<< trim END
3137    var name: any
3138    assert_equal(0, name)
3139  END
3140  CheckDefAndScriptSuccess(lines)
3141enddef
3142
3143func Test_define_func_at_command_line()
3144  CheckRunVimInTerminal
3145
3146  " call indirectly to avoid compilation error for missing functions
3147  call Run_Test_define_func_at_command_line()
3148endfunc
3149
3150def Run_Test_define_func_at_command_line()
3151  # run in a separate Vim instance to avoid the script context
3152  var lines =<< trim END
3153    func CheckAndQuit()
3154      call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc')
3155      call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd')
3156    endfunc
3157  END
3158  writefile([''], 'Xdidcmd')
3159  writefile(lines, 'XcallFunc')
3160  var buf = RunVimInTerminal('-S XcallFunc', {rows: 6})
3161  # define Afunc() on the command line
3162  term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>")
3163  term_sendkeys(buf, ":call CheckAndQuit()\<CR>")
3164  WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd')))
3165
3166  call StopVimInTerminal(buf)
3167  delete('XcallFunc')
3168  delete('Xdidcmd')
3169enddef
3170
3171def Test_script_var_scope()
3172  var lines =<< trim END
3173      vim9script
3174      if true
3175        if true
3176          var one = 'one'
3177          echo one
3178        endif
3179        echo one
3180      endif
3181  END
3182  CheckScriptFailure(lines, 'E121:', 7)
3183
3184  lines =<< trim END
3185      vim9script
3186      if true
3187        if false
3188          var one = 'one'
3189          echo one
3190        else
3191          var one = 'one'
3192          echo one
3193        endif
3194        echo one
3195      endif
3196  END
3197  CheckScriptFailure(lines, 'E121:', 10)
3198
3199  lines =<< trim END
3200      vim9script
3201      while true
3202        var one = 'one'
3203        echo one
3204        break
3205      endwhile
3206      echo one
3207  END
3208  CheckScriptFailure(lines, 'E121:', 7)
3209
3210  lines =<< trim END
3211      vim9script
3212      for i in range(1)
3213        var one = 'one'
3214        echo one
3215      endfor
3216      echo one
3217  END
3218  CheckScriptFailure(lines, 'E121:', 6)
3219
3220  lines =<< trim END
3221      vim9script
3222      {
3223        var one = 'one'
3224        assert_equal('one', one)
3225      }
3226      assert_false(exists('one'))
3227      assert_false(exists('s:one'))
3228  END
3229  CheckScriptSuccess(lines)
3230
3231  lines =<< trim END
3232      vim9script
3233      {
3234        var one = 'one'
3235        echo one
3236      }
3237      echo one
3238  END
3239  CheckScriptFailure(lines, 'E121:', 6)
3240enddef
3241
3242def Test_catch_exception_in_callback()
3243  var lines =<< trim END
3244    vim9script
3245    def Callback(...l: any)
3246      try
3247        var x: string
3248        var y: string
3249        # this error should be caught with CHECKLEN
3250        [x, y] = ['']
3251      catch
3252        g:caught = 'yes'
3253      endtry
3254    enddef
3255    popup_menu('popup', {callback: Callback})
3256    feedkeys("\r", 'xt')
3257  END
3258  CheckScriptSuccess(lines)
3259
3260  unlet g:caught
3261enddef
3262
3263def Test_no_unknown_error_after_error()
3264  if !has('unix') || !has('job')
3265    throw 'Skipped: not unix of missing +job feature'
3266  endif
3267  var lines =<< trim END
3268      vim9script
3269      var source: list<number>
3270      def Out_cb(...l: any)
3271          eval [][0]
3272      enddef
3273      def Exit_cb(...l: any)
3274          sleep 1m
3275          source += l
3276      enddef
3277      var myjob = job_start('echo burp', {out_cb: Out_cb, exit_cb: Exit_cb, mode: 'raw'})
3278      while job_status(myjob) == 'run'
3279        sleep 10m
3280      endwhile
3281      sleep 10m
3282  END
3283  writefile(lines, 'Xdef')
3284  assert_fails('so Xdef', ['E684:', 'E1012:'])
3285  delete('Xdef')
3286enddef
3287
3288def InvokeNormal()
3289  exe "norm! :m+1\r"
3290enddef
3291
3292def Test_invoke_normal_in_visual_mode()
3293  xnoremap <F3> <Cmd>call <SID>InvokeNormal()<CR>
3294  new
3295  setline(1, ['aaa', 'bbb'])
3296  feedkeys("V\<F3>", 'xt')
3297  assert_equal(['bbb', 'aaa'], getline(1, 2))
3298  xunmap <F3>
3299enddef
3300
3301def Test_white_space_after_command()
3302  var lines =<< trim END
3303    exit_cb: Func})
3304  END
3305  CheckDefAndScriptFailure(lines, 'E1144:', 1)
3306
3307  lines =<< trim END
3308    e#
3309  END
3310  CheckDefAndScriptFailure(lines, 'E1144:', 1)
3311enddef
3312
3313def Test_script_var_gone_when_sourced_twice()
3314  var lines =<< trim END
3315      vim9script
3316      if exists('g:guard')
3317        finish
3318      endif
3319      g:guard = 1
3320      var name = 'thename'
3321      def g:GetName(): string
3322        return name
3323      enddef
3324      def g:SetName(arg: string)
3325        name = arg
3326      enddef
3327  END
3328  writefile(lines, 'XscriptTwice.vim')
3329  so XscriptTwice.vim
3330  assert_equal('thename', g:GetName())
3331  g:SetName('newname')
3332  assert_equal('newname', g:GetName())
3333  so XscriptTwice.vim
3334  assert_fails('call g:GetName()', 'E1149:')
3335  assert_fails('call g:SetName("x")', 'E1149:')
3336
3337  delfunc g:GetName
3338  delfunc g:SetName
3339  delete('XscriptTwice.vim')
3340  unlet g:guard
3341enddef
3342
3343def Test_import_gone_when_sourced_twice()
3344  var exportlines =<< trim END
3345      vim9script
3346      if exists('g:guard')
3347        finish
3348      endif
3349      g:guard = 1
3350      export var name = 'someName'
3351  END
3352  writefile(exportlines, 'XexportScript.vim')
3353
3354  var lines =<< trim END
3355      vim9script
3356      import name from './XexportScript.vim'
3357      def g:GetName(): string
3358        return name
3359      enddef
3360  END
3361  writefile(lines, 'XscriptImport.vim')
3362  so XscriptImport.vim
3363  assert_equal('someName', g:GetName())
3364
3365  so XexportScript.vim
3366  assert_fails('call g:GetName()', 'E1149:')
3367
3368  delfunc g:GetName
3369  delete('XexportScript.vim')
3370  delete('XscriptImport.vim')
3371  unlet g:guard
3372enddef
3373
3374" Keep this last, it messes up highlighting.
3375def Test_substitute_cmd()
3376  new
3377  setline(1, 'something')
3378  :substitute(some(other(
3379  assert_equal('otherthing', getline(1))
3380  bwipe!
3381
3382  # also when the context is Vim9 script
3383  var lines =<< trim END
3384    vim9script
3385    new
3386    setline(1, 'something')
3387    :substitute(some(other(
3388    assert_equal('otherthing', getline(1))
3389    bwipe!
3390  END
3391  writefile(lines, 'Xvim9lines')
3392  source Xvim9lines
3393
3394  delete('Xvim9lines')
3395enddef
3396
3397" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
3398