blob: 51de0e32d6319dff01a2335e65ff52749b2be91f [file] [log] [blame]
Bram Moolenaar2b618522019-01-12 13:26:03 +01001" Tests for the :source command.
2
Bram Moolenaar5c504f62021-04-01 13:39:51 +02003source check.vim
4source view_util.vim
5
Bram Moolenaar2b618522019-01-12 13:26:03 +01006func Test_source_autocmd()
7 call writefile([
8 \ 'let did_source = 1',
Dominique Pellecaa1d192022-09-28 10:45:15 +01009 \ ], 'Xsourced', 'D')
Bram Moolenaar2b618522019-01-12 13:26:03 +010010 au SourcePre *source* let did_source_pre = 1
11 au SourcePost *source* let did_source_post = 1
12
13 source Xsourced
14
15 call assert_equal(g:did_source, 1)
16 call assert_equal(g:did_source_pre, 1)
17 call assert_equal(g:did_source_post, 1)
18
Bram Moolenaar2b618522019-01-12 13:26:03 +010019 au! SourcePre
20 au! SourcePost
21 unlet g:did_source
22 unlet g:did_source_pre
23 unlet g:did_source_post
24endfunc
25
26func Test_source_cmd()
27 au SourceCmd *source* let did_source = expand('<afile>')
28 au SourcePre *source* let did_source_pre = 2
29 au SourcePost *source* let did_source_post = 2
30
31 source Xsourced
32
33 call assert_equal(g:did_source, 'Xsourced')
34 call assert_false(exists('g:did_source_pre'))
35 call assert_equal(g:did_source_post, 2)
36
37 au! SourceCmd
38 au! SourcePre
39 au! SourcePost
40endfunc
Bram Moolenaar53575522019-05-22 22:38:25 +020041
42func Test_source_sandbox()
43 new
Dominique Pellecaa1d192022-09-28 10:45:15 +010044 call writefile(["Ohello\<Esc>"], 'Xsourcehello', 'D')
Bram Moolenaar53575522019-05-22 22:38:25 +020045 source! Xsourcehello | echo
46 call assert_equal('hello', getline(1))
47 call assert_fails('sandbox source! Xsourcehello', 'E48:')
48 bwipe!
49endfunc
Bram Moolenaarca33eb22020-01-19 20:18:09 +010050
51" When deleting a file and immediately creating a new one the inode may be
52" recycled. Vim should not recognize it as the same script.
53func Test_different_script()
Bram Moolenaarca33eb22020-01-19 20:18:09 +010054 call writefile(['let s:var = "asdf"'], 'XoneScript')
55 source XoneScript
56 call delete('XoneScript')
57 call writefile(['let g:var = s:var'], 'XtwoScript')
58 call assert_fails('source XtwoScript', 'E121:')
59 call delete('XtwoScript')
60endfunc
Bram Moolenaar9f6277b2020-02-11 22:04:02 +010061
62" When sourcing a vim script, shebang should be ignored.
63func Test_source_ignore_shebang()
Dominique Pellecaa1d192022-09-28 10:45:15 +010064 call writefile(['#!./xyzabc', 'let g:val=369'], 'Xsisfile.vim', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +010065 source Xsisfile.vim
Bram Moolenaar9f6277b2020-02-11 22:04:02 +010066 call assert_equal(g:val, 369)
Bram Moolenaar9f6277b2020-02-11 22:04:02 +010067endfunc
68
Dominique Pelleaf4a61a2021-12-27 17:21:41 +000069" Test for expanding <sfile> in an autocmd and for <slnum> and <sflnum>
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +010070func Test_source_autocmd_sfile()
71 let code =<< trim [CODE]
72 let g:SfileName = ''
73 augroup sfiletest
74 au!
75 autocmd User UserAutoCmd let g:Sfile = '<sfile>:t'
76 augroup END
77 doautocmd User UserAutoCmd
78 let g:Slnum = expand('<slnum>')
79 let g:Sflnum = expand('<sflnum>')
80 augroup! sfiletest
81 [CODE]
Dominique Pellecaa1d192022-09-28 10:45:15 +010082 call writefile(code, 'Xscript.vim', 'D')
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +010083 source Xscript.vim
84 call assert_equal('Xscript.vim', g:Sfile)
85 call assert_equal('7', g:Slnum)
86 call assert_equal('8', g:Sflnum)
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +010087endfunc
88
Bram Moolenaar476a6132020-04-08 19:48:56 +020089func Test_source_error()
90 call assert_fails('scriptencoding utf-8', 'E167:')
91 call assert_fails('finish', 'E168:')
92 call assert_fails('scriptversion 2', 'E984:')
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +000093 call assert_fails('source!', 'E471:')
94 new
95 call setline(1, ['', '', '', ''])
96 call assert_fails('1,3source Xscript.vim', 'E481:')
97 call assert_fails('1,3source! Xscript.vim', 'E481:')
98 bw!
Bram Moolenaar476a6132020-04-08 19:48:56 +020099endfunc
100
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200101" Test for sourcing a script recursively
102func Test_nested_script()
103 CheckRunVimInTerminal
Dominique Pellecaa1d192022-09-28 10:45:15 +0100104 call writefile([':source! Xscript.vim', ''], 'Xscript.vim', 'D')
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200105 let buf = RunVimInTerminal('', {'rows': 6})
106 call term_wait(buf)
107 call term_sendkeys(buf, ":set noruler\n")
108 call term_sendkeys(buf, ":source! Xscript.vim\n")
109 call term_wait(buf)
110 call WaitForAssert({-> assert_match('E22: Scripts nested too deep\s*', term_getline(buf, 6))})
Bram Moolenaar5c504f62021-04-01 13:39:51 +0200111 call StopVimInTerminal(buf)
112endfunc
113
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000114" Test for sourcing a script from the current buffer
115func Test_source_buffer()
116 new
117 " Source a simple script
118 let lines =<< trim END
119 let a = "Test"
120 let b = 20
121
122 let c = [1.1]
123 END
124 call setline(1, lines)
125 source
126 call assert_equal(['Test', 20, [1.1]], [g:a, g:b, g:c])
127
128 " Source a range of lines in the current buffer
129 %d _
130 let lines =<< trim END
131 let a = 10
132 let a += 20
133 let a += 30
134 let a += 40
135 END
136 call setline(1, lines)
137 .source
138 call assert_equal(10, g:a)
139 3source
140 call assert_equal(40, g:a)
141 2,3source
142 call assert_equal(90, g:a)
143
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000144 " Make sure the script line number is correct when sourcing a range of
145 " lines.
146 %d _
147 let lines =<< trim END
148 Line 1
149 Line 2
150 func Xtestfunc()
151 return expand("<sflnum>")
152 endfunc
153 Line 3
154 Line 4
155 END
156 call setline(1, lines)
157 3,5source
158 call assert_equal('4', Xtestfunc())
159 delfunc Xtestfunc
160
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000161 " Source a script with line continuation lines
162 %d _
163 let lines =<< trim END
164 let m = [
165 \ 1,
166 \ 2,
167 \ ]
168 call add(m, 3)
169 END
170 call setline(1, lines)
171 source
172 call assert_equal([1, 2, 3], g:m)
173 " Source a script with line continuation lines and a comment
174 %d _
175 let lines =<< trim END
176 let m = [
177 "\ first entry
178 \ 'a',
179 "\ second entry
180 \ 'b',
181 \ ]
182 " third entry
183 call add(m, 'c')
184 END
185 call setline(1, lines)
186 source
187 call assert_equal(['a', 'b', 'c'], g:m)
188 " Source an incomplete line continuation line
189 %d _
190 let lines =<< trim END
191 let k = [
192 \
193 END
194 call setline(1, lines)
195 call assert_fails('source', 'E697:')
196 " Source a function with a for loop
197 %d _
198 let lines =<< trim END
199 let m = []
200 " test function
201 func! Xtest()
202 for i in range(5, 7)
203 call add(g:m, i)
204 endfor
205 endfunc
206 call Xtest()
207 END
208 call setline(1, lines)
209 source
210 call assert_equal([5, 6, 7], g:m)
211 " Source an empty buffer
212 %d _
213 source
214
215 " test for script local functions and variables
216 let lines =<< trim END
217 let s:var1 = 10
218 func s:F1()
219 let s:var1 += 1
220 return s:var1
221 endfunc
222 func s:F2()
223 endfunc
224 let g:ScriptID = expand("<SID>")
225 END
226 call setline(1, lines)
227 source
228 call assert_true(g:ScriptID != '')
229 call assert_true(exists('*' .. g:ScriptID .. 'F1'))
230 call assert_true(exists('*' .. g:ScriptID .. 'F2'))
231 call assert_equal(11, call(g:ScriptID .. 'F1', []))
232
233 " the same script ID should be used even if the buffer is sourced more than
234 " once
235 %d _
236 let lines =<< trim END
237 let g:ScriptID = expand("<SID>")
238 let g:Count += 1
239 END
240 call setline(1, lines)
241 let g:Count = 0
242 source
243 call assert_true(g:ScriptID != '')
244 let scid = g:ScriptID
245 source
246 call assert_equal(scid, g:ScriptID)
247 call assert_equal(2, g:Count)
248 source
249 call assert_equal(scid, g:ScriptID)
250 call assert_equal(3, g:Count)
251
252 " test for the script line number
253 %d _
254 let lines =<< trim END
255 " comment
256 let g:Slnum1 = expand("<slnum>")
257 let i = 1 +
258 \ 2 +
259 "\ comment
260 \ 3
261 let g:Slnum2 = expand("<slnum>")
262 END
263 call setline(1, lines)
264 source
265 call assert_equal('2', g:Slnum1)
266 call assert_equal('7', g:Slnum2)
267
268 " test for retaining the same script number across source calls
269 let lines =<< trim END
270 let g:ScriptID1 = expand("<SID>")
271 let g:Slnum1 = expand("<slnum>")
272 let l =<< trim END
273 let g:Slnum2 = expand("<slnum>")
274 let g:ScriptID2 = expand("<SID>")
275 END
276 new
277 call setline(1, l)
278 source
279 bw!
280 let g:ScriptID3 = expand("<SID>")
281 let g:Slnum3 = expand("<slnum>")
282 END
Dominique Pellecaa1d192022-09-28 10:45:15 +0100283 call writefile(lines, 'Xscript', 'D')
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000284 source Xscript
285 call assert_true(g:ScriptID1 != g:ScriptID2)
286 call assert_equal(g:ScriptID1, g:ScriptID3)
287 call assert_equal('2', g:Slnum1)
288 call assert_equal('1', g:Slnum2)
289 call assert_equal('12', g:Slnum3)
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000290
291 " test for sourcing a heredoc
292 %d _
293 let lines =<< trim END
294 let a = 1
295 let heredoc =<< trim DATA
296 red
297 green
298 blue
299 DATA
300 let b = 2
301 END
302 call setline(1, lines)
303 source
304 call assert_equal(['red', ' green', 'blue'], g:heredoc)
305
306 " test for a while and for statement
307 %d _
308 let lines =<< trim END
309 let a = 0
310 let b = 1
311 while b <= 10
312 let a += 10
313 let b += 1
314 endwhile
315 for i in range(5)
316 let a += 10
317 endfor
318 END
319 call setline(1, lines)
320 source
321 call assert_equal(150, g:a)
322
323 " test for sourcing the same buffer multiple times after changing a function
324 %d _
325 let lines =<< trim END
326 func Xtestfunc()
327 return "one"
328 endfunc
329 END
330 call setline(1, lines)
331 source
332 call assert_equal("one", Xtestfunc())
333 call setline(2, ' return "two"')
334 source
335 call assert_equal("two", Xtestfunc())
336 call setline(2, ' return "three"')
337 source
338 call assert_equal("three", Xtestfunc())
339 delfunc Xtestfunc
340
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000341 " test for using try/catch
342 %d _
343 let lines =<< trim END
344 let Trace = '1'
345 try
346 let a1 = b1
347 catch
348 let Trace ..= '2'
349 finally
350 let Trace ..= '3'
351 endtry
352 END
353 call setline(1, lines)
354 source
355 call assert_equal("123", g:Trace)
356
357 " test with the finish command
358 %d _
359 let lines =<< trim END
360 let g:Color = 'blue'
361 finish
362 let g:Color = 'green'
363 END
364 call setline(1, lines)
365 source
366 call assert_equal('blue', g:Color)
367
368 " Test for the SourcePre and SourcePost autocmds
369 augroup Xtest
370 au!
371 au SourcePre * let g:XsourcePre=4
372 \ | let g:XsourcePreFile = expand("<afile>")
373 au SourcePost * let g:XsourcePost=6
374 \ | let g:XsourcePostFile = expand("<afile>")
375 augroup END
376 %d _
377 let lines =<< trim END
378 let a = 1
379 END
380 call setline(1, lines)
381 source
382 call assert_equal(4, g:XsourcePre)
383 call assert_equal(6, g:XsourcePost)
384 call assert_equal(':source buffer=' .. bufnr(), g:XsourcePreFile)
385 call assert_equal(':source buffer=' .. bufnr(), g:XsourcePostFile)
386 augroup Xtest
387 au!
388 augroup END
389 augroup! Xtest
390
391 %bw!
392endfunc
393
394" Test for sourcing a Vim9 script from the current buffer
395func Test_source_buffer_vim9()
396 new
397
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000398 " test for sourcing a Vim9 script
399 %d _
400 let lines =<< trim END
401 vim9script
402
403 # check dict
404 var x: number = 10
405 def g:Xtestfunc(): number
406 return x
407 enddef
408 END
409 call setline(1, lines)
410 source
411 call assert_equal(10, Xtestfunc())
412
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000413 " test for sourcing a vim9 script with line continuation
414 %d _
415 let lines =<< trim END
416 vim9script
417
418 g:Str1 = "hello "
419 .. "world"
420 .. ", how are you?"
421 g:Colors = [
422 'red',
423 # comment
424 'blue'
425 ]
426 g:Dict = {
427 a: 22,
428 # comment
429 b: 33
430 }
431
432 # calling a function with line continuation
433 def Sum(...values: list<number>): number
434 var sum: number = 0
435 for v in values
436 sum += v
437 endfor
438 return sum
439 enddef
440 g:Total1 = Sum(10,
441 20,
442 30)
443
444 var i: number = 0
445 while i < 10
446 # while loop
447 i +=
448 1
449 endwhile
450 g:Count1 = i
451
452 # for loop
453 g:Count2 = 0
454 for j in range(10, 20)
455 g:Count2 +=
456 i
457 endfor
458
459 g:Total2 = 10 +
460 20 -
461 5
462
463 g:Result1 = g:Total2 > 1
464 ? 'red'
465 : 'blue'
466
467 g:Str2 = 'x'
468 ->repeat(10)
469 ->trim()
470 ->strpart(4)
471
472 g:Result2 = g:Dict
473 .a
474
475 augroup Test
476 au!
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100477 au BufNewFile Xsubfile g:readFile = 1
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000478 | g:readExtra = 2
479 augroup END
480 g:readFile = 0
481 g:readExtra = 0
Bram Moolenaarb18b4962022-09-02 21:55:50 +0100482 new Xsubfile
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000483 bwipe!
484 augroup Test
485 au!
486 augroup END
487 END
488 call setline(1, lines)
489 source
490 call assert_equal("hello world, how are you?", g:Str1)
491 call assert_equal(['red', 'blue'], g:Colors)
492 call assert_equal(#{a: 22, b: 33}, g:Dict)
493 call assert_equal(60, g:Total1)
494 call assert_equal(10, g:Count1)
495 call assert_equal(110, g:Count2)
496 call assert_equal(25, g:Total2)
497 call assert_equal('red', g:Result1)
498 call assert_equal('xxxxxx', g:Str2)
499 call assert_equal(22, g:Result2)
500 call assert_equal(1, g:readFile)
501 call assert_equal(2, g:readExtra)
502
503 " test for sourcing the same buffer multiple times after changing a function
504 %d _
505 let lines =<< trim END
506 vim9script
507 def g:Xtestfunc(): string
508 return "one"
509 enddef
510 END
511 call setline(1, lines)
512 source
513 call assert_equal("one", Xtestfunc())
514 call setline(3, ' return "two"')
515 source
516 call assert_equal("two", Xtestfunc())
517 call setline(3, ' return "three"')
518 source
519 call assert_equal("three", Xtestfunc())
520 delfunc Xtestfunc
521
522 " Test for sourcing a range of lines. Make sure the script line number is
523 " correct.
524 %d _
525 let lines =<< trim END
526 Line 1
527 Line 2
528 vim9script
529 def g:Xtestfunc(): string
530 return expand("<sflnum>")
531 enddef
532 Line 3
533 Line 4
534 END
535 call setline(1, lines)
536 3,6source
537 call assert_equal('5', Xtestfunc())
538 delfunc Xtestfunc
539
540 " test for sourcing a heredoc
541 %d _
542 let lines =<< trim END
543 vim9script
544 var a = 1
545 g:heredoc =<< trim DATA
546 red
547 green
548 blue
549 DATA
550 var b = 2
551 END
552 call setline(1, lines)
553 source
554 call assert_equal(['red', ' green', 'blue'], g:heredoc)
555
556 " test for using the :vim9cmd modifier
557 %d _
558 let lines =<< trim END
559 first line
560 g:Math = {
561 pi: 3.12,
562 e: 2.71828
563 }
564 g:Editors = [
565 'vim',
566 # comment
567 'nano'
568 ]
569 last line
570 END
571 call setline(1, lines)
572 vim9cmd :2,10source
573 call assert_equal(#{pi: 3.12, e: 2.71828}, g:Math)
574 call assert_equal(['vim', 'nano'], g:Editors)
575
Bram Moolenaarc75bca32022-03-27 13:36:50 +0100576 " '<,'> range before the cmd modifier works
577 unlet g:Math
578 unlet g:Editors
579 exe "normal 6GV4j:vim9cmd source\<CR>"
580 call assert_equal(['vim', 'nano'], g:Editors)
581 unlet g:Editors
582
Yegappan Lakshmanan85b43c62022-03-21 19:45:17 +0000583 " test for using try/catch
584 %d _
585 let lines =<< trim END
586 vim9script
587 g:Trace = '1'
588 try
589 a1 = b1
590 catch
591 g:Trace ..= '2'
592 finally
593 g:Trace ..= '3'
594 endtry
595 END
596 call setline(1, lines)
597 source
598 call assert_equal('123', g:Trace)
599
600 " test with the finish command
601 %d _
602 let lines =<< trim END
603 vim9script
604 g:Color = 'red'
605 finish
606 g:Color = 'blue'
607 END
608 call setline(1, lines)
609 source
610 call assert_equal('red', g:Color)
611
Yegappan Lakshmanan35dc1762022-03-22 12:13:54 +0000612 " test for ++clear argument to clear all the functions/variables
613 %d _
614 let lines =<< trim END
615 g:ScriptVarFound = exists("color")
616 g:MyFuncFound = exists('*Myfunc')
617 if g:MyFuncFound
618 finish
619 endif
620 var color = 'blue'
621 def Myfunc()
622 enddef
623 END
624 call setline(1, lines)
625 vim9cmd source
626 call assert_false(g:MyFuncFound)
627 call assert_false(g:ScriptVarFound)
628 vim9cmd source
629 call assert_true(g:MyFuncFound)
630 call assert_true(g:ScriptVarFound)
631 vim9cmd source ++clear
632 call assert_false(g:MyFuncFound)
633 call assert_false(g:ScriptVarFound)
634 vim9cmd source ++clear
635 call assert_false(g:MyFuncFound)
636 call assert_false(g:ScriptVarFound)
637 call assert_fails('vim9cmd source ++clearx', 'E475:')
638 call assert_fails('vim9cmd source ++abcde', 'E484:')
639
Yegappan Lakshmanan36a5b682022-03-19 12:56:51 +0000640 %bw!
641endfunc
642
Bram Moolenaar2bdad612022-03-29 19:52:12 +0100643func Test_source_buffer_long_line()
644 " This was reading past the end of the line.
645 new
646 norm300gr0
647 so
648 bwipe!
Bram Moolenaar4748c4b2022-05-17 17:47:07 +0100649
650 let lines =<< trim END
651 new
652 norm 10a0000000000ΓΈ00000000000
653 norm i0000000000000000000
654 silent! so
655 END
Dominique Pellecaa1d192022-09-28 10:45:15 +0100656 call writefile(lines, 'Xtest.vim', 'D')
Bram Moolenaar4748c4b2022-05-17 17:47:07 +0100657 source Xtest.vim
658 bwipe!
Bram Moolenaar2bdad612022-03-29 19:52:12 +0100659endfunc
660
Bram Moolenaar69082912022-09-22 21:35:19 +0100661func Test_source_buffer_with_NUL_char()
662 " This was trying to use a line below the buffer.
663 let lines =<< trim END
664 if !exists('g:loaded')
665 let g:loaded = 1
666 source
667 endif
668 END
669 " Can't have a NL in heredoc
670 let lines += ["silent! vim9 echo [0 \<NL> ? 'a' : 'b']"]
Dominique Pellecaa1d192022-09-28 10:45:15 +0100671 call writefile(lines, 'XsourceNul', 'D')
Bram Moolenaar69082912022-09-22 21:35:19 +0100672 edit XsourceNul
673 source
674
675 bwipe!
676endfunc
677
Bram Moolenaar2bdad612022-03-29 19:52:12 +0100678
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100679" vim: shiftwidth=2 sts=2 expandtab