18a7d6542SBram Moolenaar" Test various aspects of the Vim9 script language.
28a7d6542SBram Moolenaar
3673660abSBram Moolenaarsource check.vim
4ad39c094SBram Moolenaarsource view_util.vim
5673660abSBram Moolenaar
68a7d6542SBram Moolenaar" Check that "lines" inside ":def" results in an "error" message.
78a7d6542SBram Moolenaarfunc CheckDefFailure(lines, error)
8978d170bSBram Moolenaar  call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
98a7d6542SBram Moolenaar  call assert_fails('so Xdef', a:error, a:lines)
108a7d6542SBram Moolenaar  call delete('Xdef')
118a7d6542SBram Moolenaarendfunc
128a7d6542SBram Moolenaar
138a7d6542SBram Moolenaarfunc CheckScriptFailure(lines, error)
148a7d6542SBram Moolenaar  call writefile(a:lines, 'Xdef')
158a7d6542SBram Moolenaar  call assert_fails('so Xdef', a:error, a:lines)
168a7d6542SBram Moolenaar  call delete('Xdef')
178a7d6542SBram Moolenaarendfunc
188a7d6542SBram Moolenaar
198a7d6542SBram Moolenaardef Test_syntax()
208a7d6542SBram Moolenaar  let var = 234
218a7d6542SBram Moolenaar  let other: list<string> = ['asdf']
228a7d6542SBram Moolenaarenddef
238a7d6542SBram Moolenaar
248a7d6542SBram Moolenaarfunc Test_def_basic()
258a7d6542SBram Moolenaar  def SomeFunc(): string
268a7d6542SBram Moolenaar    return 'yes'
278a7d6542SBram Moolenaar  enddef
288a7d6542SBram Moolenaar  call assert_equal('yes', SomeFunc())
298a7d6542SBram Moolenaarendfunc
308a7d6542SBram Moolenaar
316e587dcbSBram Moolenaarlet s:appendToMe = 'xxx'
326e587dcbSBram Moolenaarlet s:addToMe = 111
33401d9ffbSBram Moolenaarlet g:existing = 'yes'
346e587dcbSBram Moolenaar
358a7d6542SBram Moolenaardef Test_assignment()
368a7d6542SBram Moolenaar  let bool1: bool = true
378a7d6542SBram Moolenaar  assert_equal(v:true, bool1)
388a7d6542SBram Moolenaar  let bool2: bool = false
398a7d6542SBram Moolenaar  assert_equal(v:false, bool2)
408a7d6542SBram Moolenaar
410c2ca58eSBram Moolenaar  let list1: list<bool> = [false, true, false]
428a7d6542SBram Moolenaar  let list2: list<number> = [1, 2, 3]
430c2ca58eSBram Moolenaar  let list3: list<string> = ['sdf', 'asdf']
440c2ca58eSBram Moolenaar  let list4: list<any> = ['yes', true, 1234]
450c2ca58eSBram Moolenaar  let list5: list<blob> = [0z01, 0z02]
468a7d6542SBram Moolenaar
47436472f5SBram Moolenaar  let listS: list<string> = []
48436472f5SBram Moolenaar  let listN: list<number> = []
498a7d6542SBram Moolenaar
500c2ca58eSBram Moolenaar  let dict1: dict<bool> = #{one: false, two: true}
518a7d6542SBram Moolenaar  let dict2: dict<number> = #{one: 1, two: 2}
520c2ca58eSBram Moolenaar  let dict3: dict<string> = #{key: 'value'}
530c2ca58eSBram Moolenaar  let dict4: dict<any> = #{one: 1, two: '2'}
540c2ca58eSBram Moolenaar  let dict5: dict<blob> = #{one: 0z01, tw: 0z02}
55b283a8a6SBram Moolenaar
56401d9ffbSBram Moolenaar  g:newvar = 'new'
57401d9ffbSBram Moolenaar  assert_equal('new', g:newvar)
58401d9ffbSBram Moolenaar
59401d9ffbSBram Moolenaar  assert_equal('yes', g:existing)
60401d9ffbSBram Moolenaar  g:existing = 'no'
61401d9ffbSBram Moolenaar  assert_equal('no', g:existing)
62401d9ffbSBram Moolenaar
63b283a8a6SBram Moolenaar  v:char = 'abc'
646e587dcbSBram Moolenaar  assert_equal('abc', v:char)
65b283a8a6SBram Moolenaar
66b283a8a6SBram Moolenaar  $ENVVAR = 'foobar'
676e587dcbSBram Moolenaar  assert_equal('foobar', $ENVVAR)
68b283a8a6SBram Moolenaar  $ENVVAR = ''
696e587dcbSBram Moolenaar
70fd1823e0SBram Moolenaar  s:appendToMe ..= 'yyy'
71fd1823e0SBram Moolenaar  assert_equal('xxxyyy', s:appendToMe)
72fd1823e0SBram Moolenaar  s:addToMe += 222
73fd1823e0SBram Moolenaar  assert_equal(333, s:addToMe)
740bbf722aSBram Moolenaar  s:newVar = 'new'
750bbf722aSBram Moolenaar  assert_equal('new', s:newVar)
768a7d6542SBram Moolenaarenddef
778a7d6542SBram Moolenaar
788a7d6542SBram Moolenaarfunc Test_assignment_failure()
798a7d6542SBram Moolenaar  call CheckDefFailure(['let var=234'], 'E1004:')
808a7d6542SBram Moolenaar  call CheckDefFailure(['let var =234'], 'E1004:')
818a7d6542SBram Moolenaar  call CheckDefFailure(['let var= 234'], 'E1004:')
828a7d6542SBram Moolenaar
838a7d6542SBram Moolenaar  call CheckDefFailure(['let true = 1'], 'E1034:')
848a7d6542SBram Moolenaar  call CheckDefFailure(['let false = 1'], 'E1034:')
858a7d6542SBram Moolenaar
868a7d6542SBram Moolenaar  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
878a7d6542SBram Moolenaar  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
888a7d6542SBram Moolenaar
898a7d6542SBram Moolenaar  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
908a7d6542SBram Moolenaar  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
918a7d6542SBram Moolenaar
928a7d6542SBram Moolenaar  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
938a7d6542SBram Moolenaar  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
948a7d6542SBram Moolenaarendfunc
958a7d6542SBram Moolenaar
968a7d6542SBram Moolenaarfunc Test_const()
978a7d6542SBram Moolenaar  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
988a7d6542SBram Moolenaar  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
998a7d6542SBram Moolenaar  call CheckDefFailure(['const two'], 'E1021:')
1008a7d6542SBram Moolenaarendfunc
1018a7d6542SBram Moolenaar
1028a7d6542SBram Moolenaardef Test_block()
1038a7d6542SBram Moolenaar  let outer = 1
1048a7d6542SBram Moolenaar  {
1058a7d6542SBram Moolenaar    let inner = 2
1068a7d6542SBram Moolenaar    assert_equal(1, outer)
1078a7d6542SBram Moolenaar    assert_equal(2, inner)
1088a7d6542SBram Moolenaar  }
1098a7d6542SBram Moolenaar  assert_equal(1, outer)
1108a7d6542SBram Moolenaarenddef
1118a7d6542SBram Moolenaar
1128a7d6542SBram Moolenaarfunc Test_block_failure()
1138a7d6542SBram Moolenaar  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
1148a7d6542SBram Moolenaarendfunc
1158a7d6542SBram Moolenaar
1168a7d6542SBram Moolenaardef ReturnString(): string
1178a7d6542SBram Moolenaar  return 'string'
1188a7d6542SBram Moolenaarenddef
1198a7d6542SBram Moolenaar
1208a7d6542SBram Moolenaardef ReturnNumber(): number
1218a7d6542SBram Moolenaar  return 123
1228a7d6542SBram Moolenaarenddef
1238a7d6542SBram Moolenaar
12409f28f49SBram Moolenaarlet g:notNumber = 'string'
12509f28f49SBram Moolenaar
12609f28f49SBram Moolenaardef ReturnGlobal(): number
12709f28f49SBram Moolenaar  return g:notNumber
12809f28f49SBram Moolenaarenddef
12909f28f49SBram Moolenaar
1308a7d6542SBram Moolenaardef Test_return_string()
1318a7d6542SBram Moolenaar  assert_equal('string', ReturnString())
1328a7d6542SBram Moolenaar  assert_equal(123, ReturnNumber())
13309f28f49SBram Moolenaar  assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string')
1348a7d6542SBram Moolenaarenddef
1358a7d6542SBram Moolenaar
1368a7d6542SBram Moolenaarfunc Increment()
1378a7d6542SBram Moolenaar  let g:counter += 1
1388a7d6542SBram Moolenaarendfunc
1398a7d6542SBram Moolenaar
1408a7d6542SBram Moolenaardef Test_call_ufunc_count()
1418a7d6542SBram Moolenaar  g:counter = 1
1428a7d6542SBram Moolenaar  Increment()
1438a7d6542SBram Moolenaar  Increment()
1448a7d6542SBram Moolenaar  Increment()
1458a7d6542SBram Moolenaar  " works with and without :call
1468a7d6542SBram Moolenaar  assert_equal(4, g:counter)
147b283a8a6SBram Moolenaar  call assert_equal(4, g:counter)
1488a7d6542SBram Moolenaar  unlet g:counter
1498a7d6542SBram Moolenaarenddef
1508a7d6542SBram Moolenaar
1518a7d6542SBram Moolenaardef MyVarargs(arg: string, ...rest: list<string>): string
1528a7d6542SBram Moolenaar  let res = arg
1538a7d6542SBram Moolenaar  for s in rest
1548a7d6542SBram Moolenaar    res ..= ',' .. s
1558a7d6542SBram Moolenaar  endfor
1568a7d6542SBram Moolenaar  return res
1578a7d6542SBram Moolenaarenddef
1588a7d6542SBram Moolenaar
1598a7d6542SBram Moolenaardef Test_call_varargs()
1608a7d6542SBram Moolenaar  assert_equal('one', MyVarargs('one'))
1618a7d6542SBram Moolenaar  assert_equal('one,two', MyVarargs('one', 'two'))
1628a7d6542SBram Moolenaar  assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
1638a7d6542SBram Moolenaarenddef
1648a7d6542SBram Moolenaar
165170fcfcfSBram Moolenaardef MyDefaultArgs(name = 'string'): string
166170fcfcfSBram Moolenaar  return name
167170fcfcfSBram Moolenaarenddef
168170fcfcfSBram Moolenaar
169170fcfcfSBram Moolenaardef Test_call_default_args()
170170fcfcfSBram Moolenaar  assert_equal('string', MyDefaultArgs())
171170fcfcfSBram Moolenaar  assert_equal('one', MyDefaultArgs('one'))
172170fcfcfSBram Moolenaar  assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
173170fcfcfSBram Moolenaarenddef
174170fcfcfSBram Moolenaar
175170fcfcfSBram Moolenaarfunc Test_call_default_args_from_func()
176170fcfcfSBram Moolenaar  call assert_equal('string', MyDefaultArgs())
177170fcfcfSBram Moolenaar  call assert_equal('one', MyDefaultArgs('one'))
178170fcfcfSBram Moolenaar  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
179170fcfcfSBram Moolenaarendfunc
180170fcfcfSBram Moolenaar
181b35efa5eSBram Moolenaarfunc TakesOneArg(arg)
182b35efa5eSBram Moolenaar  echo a:arg
183b35efa5eSBram Moolenaarendfunc
184b35efa5eSBram Moolenaar
185b35efa5eSBram Moolenaardef Test_call_wrong_arg_count()
186b35efa5eSBram Moolenaar  call CheckDefFailure(['TakesOneArg()'], 'E119:')
187b35efa5eSBram Moolenaar  call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
188b35efa5eSBram Moolenaarenddef
189b35efa5eSBram Moolenaar
190170fcfcfSBram Moolenaar" Default arg and varargs
191170fcfcfSBram Moolenaardef MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
192170fcfcfSBram Moolenaar  let res = one .. ',' .. two
193170fcfcfSBram Moolenaar  for s in rest
194170fcfcfSBram Moolenaar    res ..= ',' .. s
195170fcfcfSBram Moolenaar  endfor
196170fcfcfSBram Moolenaar  return res
197170fcfcfSBram Moolenaarenddef
198170fcfcfSBram Moolenaar
199170fcfcfSBram Moolenaardef Test_call_def_varargs()
200170fcfcfSBram Moolenaar  call assert_fails('call MyDefVarargs()', 'E119:')
201170fcfcfSBram Moolenaar  assert_equal('one,foo', MyDefVarargs('one'))
202170fcfcfSBram Moolenaar  assert_equal('one,two', MyDefVarargs('one', 'two'))
203170fcfcfSBram Moolenaar  assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
204170fcfcfSBram Moolenaarenddef
205170fcfcfSBram Moolenaar
206b35efa5eSBram Moolenaardef Test_call_func_defined_later()
207b35efa5eSBram Moolenaar  call assert_equal('one', DefinedLater('one'))
208b35efa5eSBram Moolenaar  call assert_fails('call NotDefined("one")', 'E117:')
209b35efa5eSBram Moolenaarenddef
210170fcfcfSBram Moolenaar
211b35efa5eSBram Moolenaarfunc DefinedLater(arg)
21226e117e9SBram Moolenaar  return a:arg
21326e117e9SBram Moolenaarendfunc
21426e117e9SBram Moolenaar
215*7eeefd4aSBram Moolenaardef FuncWithForwardCall()
216*7eeefd4aSBram Moolenaar  return DefinedEvenLater("yes")
217*7eeefd4aSBram Moolenaarenddef
218*7eeefd4aSBram Moolenaar
219*7eeefd4aSBram Moolenaardef DefinedEvenLater(arg: string): string
220*7eeefd4aSBram Moolenaar  return arg
221*7eeefd4aSBram Moolenaarenddef
222*7eeefd4aSBram Moolenaar
223*7eeefd4aSBram Moolenaardef Test_error_in_nested_function()
224*7eeefd4aSBram Moolenaar  " Error in called function requires unwinding the call stack.
225*7eeefd4aSBram Moolenaar  assert_fails('call FuncWithForwardCall()', 'E1029')
226*7eeefd4aSBram Moolenaarenddef
227*7eeefd4aSBram Moolenaar
2288a7d6542SBram Moolenaardef Test_return_type_wrong()
229978d170bSBram Moolenaar  CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
230978d170bSBram Moolenaar  CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
231978d170bSBram Moolenaar  CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
232978d170bSBram Moolenaar  CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
2338a7d6542SBram Moolenaarenddef
2348a7d6542SBram Moolenaar
235bfe12043SBram Moolenaardef Test_arg_type_wrong()
236bfe12043SBram Moolenaar  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
237bfe12043SBram Moolenaarenddef
238bfe12043SBram Moolenaar
2398a7d6542SBram Moolenaardef Test_try_catch()
2408a7d6542SBram Moolenaar  let l = []
2418a7d6542SBram Moolenaar  try
2428a7d6542SBram Moolenaar    add(l, '1')
2438a7d6542SBram Moolenaar    throw 'wrong'
2448a7d6542SBram Moolenaar    add(l, '2')
2458a7d6542SBram Moolenaar  catch
2468a7d6542SBram Moolenaar    add(l, v:exception)
2478a7d6542SBram Moolenaar  finally
2488a7d6542SBram Moolenaar    add(l, '3')
2498a7d6542SBram Moolenaar  endtry
2508a7d6542SBram Moolenaar  assert_equal(['1', 'wrong', '3'], l)
2518a7d6542SBram Moolenaarenddef
2528a7d6542SBram Moolenaar
253257cc5eeSBram Moolenaardef ThrowFromDef()
254257cc5eeSBram Moolenaar  throw 'getout'
255257cc5eeSBram Moolenaarenddef
256257cc5eeSBram Moolenaar
257257cc5eeSBram Moolenaarfunc CatchInFunc()
258257cc5eeSBram Moolenaar  try
259257cc5eeSBram Moolenaar    call ThrowFromDef()
260257cc5eeSBram Moolenaar  catch
261257cc5eeSBram Moolenaar    let g:thrown_func = v:exception
262257cc5eeSBram Moolenaar  endtry
263257cc5eeSBram Moolenaarendfunc
264257cc5eeSBram Moolenaar
265257cc5eeSBram Moolenaardef CatchInDef()
266257cc5eeSBram Moolenaar  try
267257cc5eeSBram Moolenaar    ThrowFromDef()
268257cc5eeSBram Moolenaar  catch
269257cc5eeSBram Moolenaar    g:thrown_def = v:exception
270257cc5eeSBram Moolenaar  endtry
271257cc5eeSBram Moolenaarenddef
272257cc5eeSBram Moolenaar
273f575adffSBram Moolenaardef ReturnFinally(): string
274f575adffSBram Moolenaar  try
275f575adffSBram Moolenaar    return 'intry'
276f575adffSBram Moolenaar  finally
277f575adffSBram Moolenaar    g:in_finally = 'finally'
278f575adffSBram Moolenaar  endtry
279f575adffSBram Moolenaar  return 'end'
280f575adffSBram Moolenaarenddef
281f575adffSBram Moolenaar
282257cc5eeSBram Moolenaardef Test_try_catch_nested()
283257cc5eeSBram Moolenaar  CatchInFunc()
284257cc5eeSBram Moolenaar  assert_equal('getout', g:thrown_func)
285257cc5eeSBram Moolenaar
286257cc5eeSBram Moolenaar  CatchInDef()
287257cc5eeSBram Moolenaar  assert_equal('getout', g:thrown_def)
288f575adffSBram Moolenaar
289f575adffSBram Moolenaar  assert_equal('intry', ReturnFinally())
290f575adffSBram Moolenaar  assert_equal('finally', g:in_finally)
291f575adffSBram Moolenaarenddef
292f575adffSBram Moolenaar
293f575adffSBram Moolenaardef Test_try_catch_match()
294f575adffSBram Moolenaar  let seq = 'a'
295f575adffSBram Moolenaar  try
296f575adffSBram Moolenaar    throw 'something'
297f575adffSBram Moolenaar  catch /nothing/
298f575adffSBram Moolenaar    seq ..= 'x'
299f575adffSBram Moolenaar  catch /some/
300f575adffSBram Moolenaar    seq ..= 'b'
301f575adffSBram Moolenaar  catch /asdf/
302f575adffSBram Moolenaar    seq ..= 'x'
303f575adffSBram Moolenaar  finally
304f575adffSBram Moolenaar    seq ..= 'c'
305f575adffSBram Moolenaar  endtry
306f575adffSBram Moolenaar  assert_equal('abc', seq)
307257cc5eeSBram Moolenaarenddef
308257cc5eeSBram Moolenaar
3098a7d6542SBram Moolenaarlet s:export_script_lines =<< trim END
3108a7d6542SBram Moolenaar  vim9script
3118a7d6542SBram Moolenaar  let name: string = 'bob'
3128a7d6542SBram Moolenaar  def Concat(arg: string): string
3138a7d6542SBram Moolenaar    return name .. arg
3148a7d6542SBram Moolenaar  enddef
3158a7d6542SBram Moolenaar  let g:result = Concat('bie')
3168a7d6542SBram Moolenaar  let g:localname = name
3178a7d6542SBram Moolenaar
3188a7d6542SBram Moolenaar  export const CONST = 1234
3198a7d6542SBram Moolenaar  export let exported = 9876
3206e587dcbSBram Moolenaar  export let exp_name = 'John'
3218a7d6542SBram Moolenaar  export def Exported(): string
3228a7d6542SBram Moolenaar    return 'Exported'
3238a7d6542SBram Moolenaar  enddef
3248a7d6542SBram MoolenaarEND
3258a7d6542SBram Moolenaar
3268a7d6542SBram Moolenaardef Test_vim9script()
3278a7d6542SBram Moolenaar  let import_script_lines =<< trim END
3288a7d6542SBram Moolenaar    vim9script
3298a7d6542SBram Moolenaar    import {exported, Exported} from './Xexport.vim'
3308a7d6542SBram Moolenaar    g:imported = exported
3316e587dcbSBram Moolenaar    exported += 3
3326e587dcbSBram Moolenaar    g:imported_added = exported
3338a7d6542SBram Moolenaar    g:imported_func = Exported()
3346e587dcbSBram Moolenaar
3356e587dcbSBram Moolenaar    import {exp_name} from './Xexport.vim'
3366e587dcbSBram Moolenaar    g:imported_name = exp_name
3376e587dcbSBram Moolenaar    exp_name ..= ' Doe'
3386e587dcbSBram Moolenaar    g:imported_name_appended = exp_name
3398a7d6542SBram Moolenaar  END
3408a7d6542SBram Moolenaar
3418a7d6542SBram Moolenaar  writefile(import_script_lines, 'Ximport.vim')
3428a7d6542SBram Moolenaar  writefile(s:export_script_lines, 'Xexport.vim')
3438a7d6542SBram Moolenaar
3448a7d6542SBram Moolenaar  source Ximport.vim
3458a7d6542SBram Moolenaar
3468a7d6542SBram Moolenaar  assert_equal('bobbie', g:result)
3478a7d6542SBram Moolenaar  assert_equal('bob', g:localname)
3488a7d6542SBram Moolenaar  assert_equal(9876, g:imported)
3496e587dcbSBram Moolenaar  assert_equal(9879, g:imported_added)
3508a7d6542SBram Moolenaar  assert_equal('Exported', g:imported_func)
3516e587dcbSBram Moolenaar  assert_equal('John', g:imported_name)
3526e587dcbSBram Moolenaar  assert_equal('John Doe', g:imported_name_appended)
3538a7d6542SBram Moolenaar  assert_false(exists('g:name'))
3548a7d6542SBram Moolenaar
3558a7d6542SBram Moolenaar  unlet g:result
3568a7d6542SBram Moolenaar  unlet g:localname
3578a7d6542SBram Moolenaar  unlet g:imported
3586e587dcbSBram Moolenaar  unlet g:imported_added
3598a7d6542SBram Moolenaar  unlet g:imported_func
3606e587dcbSBram Moolenaar  unlet g:imported_name g:imported_name_appended
3618a7d6542SBram Moolenaar  delete('Ximport.vim')
362f2d5c240SBram Moolenaar
363f2d5c240SBram Moolenaar  let import_star_as_lines =<< trim END
364f2d5c240SBram Moolenaar    vim9script
365f2d5c240SBram Moolenaar    import * as Export from './Xexport.vim'
366f2d5c240SBram Moolenaar    def UseExport()
367f2d5c240SBram Moolenaar      g:imported = Export.exported
368f2d5c240SBram Moolenaar    enddef
369f2d5c240SBram Moolenaar    UseExport()
370f2d5c240SBram Moolenaar  END
371f2d5c240SBram Moolenaar  writefile(import_star_as_lines, 'Ximport.vim')
372f2d5c240SBram Moolenaar  source Ximport.vim
373f2d5c240SBram Moolenaar  assert_equal(9876, g:imported)
374f2d5c240SBram Moolenaar
375f2d5c240SBram Moolenaar  let import_star_lines =<< trim END
376f2d5c240SBram Moolenaar    vim9script
377f2d5c240SBram Moolenaar    import * from './Xexport.vim'
378f2d5c240SBram Moolenaar    g:imported = exported
379f2d5c240SBram Moolenaar  END
380f2d5c240SBram Moolenaar  writefile(import_star_lines, 'Ximport.vim')
381f2d5c240SBram Moolenaar  assert_fails('source Ximport.vim', 'E1045:')
382f2d5c240SBram Moolenaar
383fa29c8abSBram Moolenaar  " try to import something that exists but is not exported
384fa29c8abSBram Moolenaar  let import_not_exported_lines =<< trim END
385fa29c8abSBram Moolenaar    vim9script
386fa29c8abSBram Moolenaar    import name from './Xexport.vim'
387fa29c8abSBram Moolenaar  END
388fa29c8abSBram Moolenaar  writefile(import_not_exported_lines, 'Ximport.vim')
389fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1049:')
390fa29c8abSBram Moolenaar
391fa29c8abSBram Moolenaar  " import a very long name, requires making a copy
392fa29c8abSBram Moolenaar  let import_long_name_lines =<< trim END
393fa29c8abSBram Moolenaar    vim9script
394fa29c8abSBram Moolenaar    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
395fa29c8abSBram Moolenaar  END
396fa29c8abSBram Moolenaar  writefile(import_long_name_lines, 'Ximport.vim')
397fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1048:')
398fa29c8abSBram Moolenaar
399fa29c8abSBram Moolenaar  let import_no_from_lines =<< trim END
400fa29c8abSBram Moolenaar    vim9script
401fa29c8abSBram Moolenaar    import name './Xexport.vim'
402fa29c8abSBram Moolenaar  END
403fa29c8abSBram Moolenaar  writefile(import_no_from_lines, 'Ximport.vim')
404fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1070:')
405fa29c8abSBram Moolenaar
406fa29c8abSBram Moolenaar  let import_invalid_string_lines =<< trim END
407fa29c8abSBram Moolenaar    vim9script
408fa29c8abSBram Moolenaar    import name from Xexport.vim
409fa29c8abSBram Moolenaar  END
410fa29c8abSBram Moolenaar  writefile(import_invalid_string_lines, 'Ximport.vim')
411fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1071:')
412fa29c8abSBram Moolenaar
413fa29c8abSBram Moolenaar  let import_wrong_name_lines =<< trim END
414fa29c8abSBram Moolenaar    vim9script
415fa29c8abSBram Moolenaar    import name from './XnoExport.vim'
416fa29c8abSBram Moolenaar  END
417fa29c8abSBram Moolenaar  writefile(import_wrong_name_lines, 'Ximport.vim')
418fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1053:')
419fa29c8abSBram Moolenaar
420fa29c8abSBram Moolenaar  let import_missing_comma_lines =<< trim END
421fa29c8abSBram Moolenaar    vim9script
422fa29c8abSBram Moolenaar    import {exported name} from './Xexport.vim'
423fa29c8abSBram Moolenaar  END
424fa29c8abSBram Moolenaar  writefile(import_missing_comma_lines, 'Ximport.vim')
425fa29c8abSBram Moolenaar  assert_fails('source Ximport.vim', 'E1046:')
426fa29c8abSBram Moolenaar
427f2d5c240SBram Moolenaar  delete('Ximport.vim')
4288a7d6542SBram Moolenaar  delete('Xexport.vim')
4298a7d6542SBram Moolenaar
430750802b5SBram Moolenaar  " Check that in a Vim9 script 'cpo' is set to the Vim default.
431750802b5SBram Moolenaar  set cpo&vi
432750802b5SBram Moolenaar  let cpo_before = &cpo
433750802b5SBram Moolenaar  let lines =<< trim END
434750802b5SBram Moolenaar    vim9script
435750802b5SBram Moolenaar    g:cpo_in_vim9script = &cpo
436750802b5SBram Moolenaar  END
437750802b5SBram Moolenaar  writefile(lines, 'Xvim9_script')
438750802b5SBram Moolenaar  source Xvim9_script
439750802b5SBram Moolenaar  assert_equal(cpo_before, &cpo)
440750802b5SBram Moolenaar  set cpo&vim
441750802b5SBram Moolenaar  assert_equal(&cpo, g:cpo_in_vim9script)
442750802b5SBram Moolenaar  delete('Xvim9_script')
443750802b5SBram Moolenaarenddef
444750802b5SBram Moolenaar
445750802b5SBram Moolenaardef Test_vim9script_fails()
4468a7d6542SBram Moolenaar  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
4478a7d6542SBram Moolenaar  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
448750802b5SBram Moolenaar  CheckScriptFailure(['export let some = 123'], 'E1042:')
449f2d5c240SBram Moolenaar  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
450750802b5SBram Moolenaar  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
451750802b5SBram Moolenaar  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
452750802b5SBram Moolenaar
453750802b5SBram Moolenaar  assert_fails('vim9script', 'E1038')
454750802b5SBram Moolenaar  assert_fails('export something', 'E1042')
4558a7d6542SBram Moolenaarenddef
4568a7d6542SBram Moolenaar
4578a7d6542SBram Moolenaardef Test_vim9script_call()
4588a7d6542SBram Moolenaar  let lines =<< trim END
4598a7d6542SBram Moolenaar    vim9script
4608a7d6542SBram Moolenaar    let var = ''
4618a7d6542SBram Moolenaar    def MyFunc(arg: string)
4628a7d6542SBram Moolenaar       var = arg
4638a7d6542SBram Moolenaar    enddef
4648a7d6542SBram Moolenaar    MyFunc('foobar')
4658a7d6542SBram Moolenaar    assert_equal('foobar', var)
4668a7d6542SBram Moolenaar
4678a7d6542SBram Moolenaar    let str = 'barfoo'
4688a7d6542SBram Moolenaar    str->MyFunc()
4698a7d6542SBram Moolenaar    assert_equal('barfoo', var)
4708a7d6542SBram Moolenaar
4718a7d6542SBram Moolenaar    let g:value = 'value'
4728a7d6542SBram Moolenaar    g:value->MyFunc()
4738a7d6542SBram Moolenaar    assert_equal('value', var)
4748a7d6542SBram Moolenaar
4758a7d6542SBram Moolenaar    let listvar = []
4768a7d6542SBram Moolenaar    def ListFunc(arg: list<number>)
4778a7d6542SBram Moolenaar       listvar = arg
4788a7d6542SBram Moolenaar    enddef
4798a7d6542SBram Moolenaar    [1, 2, 3]->ListFunc()
4808a7d6542SBram Moolenaar    assert_equal([1, 2, 3], listvar)
4818a7d6542SBram Moolenaar
4828a7d6542SBram Moolenaar    let dictvar = {}
4838a7d6542SBram Moolenaar    def DictFunc(arg: dict<number>)
4848a7d6542SBram Moolenaar       dictvar = arg
4858a7d6542SBram Moolenaar    enddef
4868a7d6542SBram Moolenaar    {'a': 1, 'b': 2}->DictFunc()
4878a7d6542SBram Moolenaar    assert_equal(#{a: 1, b: 2}, dictvar)
4888a7d6542SBram Moolenaar    #{a: 3, b: 4}->DictFunc()
4898a7d6542SBram Moolenaar    assert_equal(#{a: 3, b: 4}, dictvar)
4900c6ceaf9SBram Moolenaar
4910c6ceaf9SBram Moolenaar    ('text')->MyFunc()
4920c6ceaf9SBram Moolenaar    assert_equal('text', var)
4930c6ceaf9SBram Moolenaar    ("some")->MyFunc()
4940c6ceaf9SBram Moolenaar    assert_equal('some', var)
4958a7d6542SBram Moolenaar  END
4968a7d6542SBram Moolenaar  writefile(lines, 'Xcall.vim')
4978a7d6542SBram Moolenaar  source Xcall.vim
4988a7d6542SBram Moolenaar  delete('Xcall.vim')
4998a7d6542SBram Moolenaarenddef
5008a7d6542SBram Moolenaar
5018a7d6542SBram Moolenaardef Test_vim9script_call_fail_decl()
5028a7d6542SBram Moolenaar  let lines =<< trim END
5038a7d6542SBram Moolenaar    vim9script
5048a7d6542SBram Moolenaar    let var = ''
5058a7d6542SBram Moolenaar    def MyFunc(arg: string)
5068a7d6542SBram Moolenaar       let var = 123
5078a7d6542SBram Moolenaar    enddef
5088a7d6542SBram Moolenaar  END
5098a7d6542SBram Moolenaar  writefile(lines, 'Xcall_decl.vim')
5108a7d6542SBram Moolenaar  assert_fails('source Xcall_decl.vim', 'E1054:')
5118a7d6542SBram Moolenaar  delete('Xcall_decl.vim')
5128a7d6542SBram Moolenaarenddef
5138a7d6542SBram Moolenaar
5148a7d6542SBram Moolenaardef Test_vim9script_call_fail_const()
5158a7d6542SBram Moolenaar  let lines =<< trim END
5168a7d6542SBram Moolenaar    vim9script
5178a7d6542SBram Moolenaar    const var = ''
5188a7d6542SBram Moolenaar    def MyFunc(arg: string)
5198a7d6542SBram Moolenaar       var = 'asdf'
5208a7d6542SBram Moolenaar    enddef
5218a7d6542SBram Moolenaar  END
5228a7d6542SBram Moolenaar  writefile(lines, 'Xcall_const.vim')
5238a7d6542SBram Moolenaar  assert_fails('source Xcall_const.vim', 'E46:')
5248a7d6542SBram Moolenaar  delete('Xcall_const.vim')
5258a7d6542SBram Moolenaarenddef
5268a7d6542SBram Moolenaar
5278a7d6542SBram Moolenaardef Test_vim9script_reload()
5288a7d6542SBram Moolenaar  let lines =<< trim END
5298a7d6542SBram Moolenaar    vim9script
5308a7d6542SBram Moolenaar    const var = ''
5318a7d6542SBram Moolenaar    let valone = 1234
5328a7d6542SBram Moolenaar    def MyFunc(arg: string)
5338a7d6542SBram Moolenaar       valone = 5678
5348a7d6542SBram Moolenaar    enddef
5358a7d6542SBram Moolenaar  END
5368a7d6542SBram Moolenaar  let morelines =<< trim END
5378a7d6542SBram Moolenaar    let valtwo = 222
5388a7d6542SBram Moolenaar    export def GetValtwo(): number
5398a7d6542SBram Moolenaar      return valtwo
5408a7d6542SBram Moolenaar    enddef
5418a7d6542SBram Moolenaar  END
5428a7d6542SBram Moolenaar  writefile(lines + morelines, 'Xreload.vim')
5438a7d6542SBram Moolenaar  source Xreload.vim
5448a7d6542SBram Moolenaar  source Xreload.vim
5458a7d6542SBram Moolenaar  source Xreload.vim
5468a7d6542SBram Moolenaar
5478a7d6542SBram Moolenaar  let testlines =<< trim END
5488a7d6542SBram Moolenaar    vim9script
5498a7d6542SBram Moolenaar    def TheFunc()
5508a7d6542SBram Moolenaar      import GetValtwo from './Xreload.vim'
5518a7d6542SBram Moolenaar      assert_equal(222, GetValtwo())
5528a7d6542SBram Moolenaar    enddef
5538a7d6542SBram Moolenaar    TheFunc()
5548a7d6542SBram Moolenaar  END
5558a7d6542SBram Moolenaar  writefile(testlines, 'Ximport.vim')
5568a7d6542SBram Moolenaar  source Ximport.vim
5578a7d6542SBram Moolenaar
5588a7d6542SBram Moolenaar  " test that when not using "morelines" valtwo is still defined
5598a7d6542SBram Moolenaar  " need to source Xreload.vim again, import doesn't reload a script
5608a7d6542SBram Moolenaar  writefile(lines, 'Xreload.vim')
5618a7d6542SBram Moolenaar  source Xreload.vim
5628a7d6542SBram Moolenaar  source Ximport.vim
5638a7d6542SBram Moolenaar
5648a7d6542SBram Moolenaar  " cannot declare a var twice
5658a7d6542SBram Moolenaar  lines =<< trim END
5668a7d6542SBram Moolenaar    vim9script
5678a7d6542SBram Moolenaar    let valone = 1234
5688a7d6542SBram Moolenaar    let valone = 5678
5698a7d6542SBram Moolenaar  END
5708a7d6542SBram Moolenaar  writefile(lines, 'Xreload.vim')
5718a7d6542SBram Moolenaar  assert_fails('source Xreload.vim', 'E1041:')
5728a7d6542SBram Moolenaar
5738a7d6542SBram Moolenaar  delete('Xreload.vim')
5748a7d6542SBram Moolenaar  delete('Ximport.vim')
5758a7d6542SBram Moolenaarenddef
5768a7d6542SBram Moolenaar
5778a7d6542SBram Moolenaardef Test_import_absolute()
5788a7d6542SBram Moolenaar  let import_lines = [
5798a7d6542SBram Moolenaar        \ 'vim9script',
5808a7d6542SBram Moolenaar        \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
581b283a8a6SBram Moolenaar        \ 'def UseExported()',
5828a7d6542SBram Moolenaar        \ '  g:imported_abs = exported',
5834e12a5dfSBram Moolenaar        \ '  exported = 8888',
5844e12a5dfSBram Moolenaar        \ '  g:imported_after = exported',
585b283a8a6SBram Moolenaar        \ 'enddef',
586b283a8a6SBram Moolenaar        \ 'UseExported()',
5874e12a5dfSBram Moolenaar        \ 'g:import_disassembled = execute("disass UseExported")',
5888a7d6542SBram Moolenaar        \ ]
5898a7d6542SBram Moolenaar  writefile(import_lines, 'Ximport_abs.vim')
5908a7d6542SBram Moolenaar  writefile(s:export_script_lines, 'Xexport_abs.vim')
5918a7d6542SBram Moolenaar
5928a7d6542SBram Moolenaar  source Ximport_abs.vim
5938a7d6542SBram Moolenaar
5948a7d6542SBram Moolenaar  assert_equal(9876, g:imported_abs)
5954e12a5dfSBram Moolenaar  assert_equal(8888, g:imported_after)
596b283a8a6SBram Moolenaar  assert_match('<SNR>\d\+_UseExported.*'
597b283a8a6SBram Moolenaar        \ .. 'g:imported_abs = exported.*'
598b283a8a6SBram Moolenaar        \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
5994e12a5dfSBram Moolenaar        \ .. '1 STOREG g:imported_abs.*'
6004e12a5dfSBram Moolenaar        \ .. 'exported = 8888.*'
6014e12a5dfSBram Moolenaar        \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
6024e12a5dfSBram Moolenaar        \ .. 'g:imported_after = exported.*'
6034e12a5dfSBram Moolenaar        \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
6044e12a5dfSBram Moolenaar        \ .. '5 STOREG g:imported_after.*'
6054e12a5dfSBram Moolenaar        \, g:import_disassembled)
6068a7d6542SBram Moolenaar  unlet g:imported_abs
6074e12a5dfSBram Moolenaar  unlet g:import_disassembled
6088a7d6542SBram Moolenaar
6098a7d6542SBram Moolenaar  delete('Ximport_abs.vim')
6108a7d6542SBram Moolenaar  delete('Xexport_abs.vim')
6118a7d6542SBram Moolenaarenddef
6128a7d6542SBram Moolenaar
6138a7d6542SBram Moolenaardef Test_import_rtp()
6148a7d6542SBram Moolenaar  let import_lines = [
6158a7d6542SBram Moolenaar        \ 'vim9script',
6168a7d6542SBram Moolenaar        \ 'import exported from "Xexport_rtp.vim"',
6178a7d6542SBram Moolenaar        \ 'g:imported_rtp = exported',
6188a7d6542SBram Moolenaar        \ ]
6198a7d6542SBram Moolenaar  writefile(import_lines, 'Ximport_rtp.vim')
6208a7d6542SBram Moolenaar  mkdir('import')
6218a7d6542SBram Moolenaar  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
6228a7d6542SBram Moolenaar
6238a7d6542SBram Moolenaar  let save_rtp = &rtp
6248a7d6542SBram Moolenaar  &rtp = getcwd()
6258a7d6542SBram Moolenaar  source Ximport_rtp.vim
6268a7d6542SBram Moolenaar  &rtp = save_rtp
6278a7d6542SBram Moolenaar
6288a7d6542SBram Moolenaar  assert_equal(9876, g:imported_rtp)
6298a7d6542SBram Moolenaar  unlet g:imported_rtp
6308a7d6542SBram Moolenaar
6318a7d6542SBram Moolenaar  delete('Ximport_rtp.vim')
6328a7d6542SBram Moolenaar  delete('import/Xexport_rtp.vim')
6338a7d6542SBram Moolenaar  delete('import', 'd')
6348a7d6542SBram Moolenaarenddef
6358a7d6542SBram Moolenaar
6368a7d6542SBram Moolenaardef Test_fixed_size_list()
6378a7d6542SBram Moolenaar  " will be allocated as one piece of memory, check that changes work
6388a7d6542SBram Moolenaar  let l = [1, 2, 3, 4]
6398a7d6542SBram Moolenaar  l->remove(0)
6408a7d6542SBram Moolenaar  l->add(5)
6418a7d6542SBram Moolenaar  l->insert(99, 1)
6420f18b6d1SBram Moolenaar  assert_equal([2, 99, 3, 4, 5], l)
6438a7d6542SBram Moolenaarenddef
6448a7d6542SBram Moolenaar
645673660abSBram Moolenaar" Test that inside :function a Python function can be defined, :def is not
646673660abSBram Moolenaar" recognized.
647673660abSBram Moolenaarfunc Test_function_python()
648673660abSBram Moolenaar  CheckFeature python3
649673660abSBram Moolenaar  let py = 'python3'
650673660abSBram Moolenaar  execute py "<< EOF"
651673660abSBram Moolenaardef do_something():
652673660abSBram Moolenaar  return 1
653673660abSBram MoolenaarEOF
654673660abSBram Moolenaarendfunc
655673660abSBram Moolenaar
656158906cfSBram Moolenaardef IfElse(what: number): string
657158906cfSBram Moolenaar  let res = ''
658158906cfSBram Moolenaar  if what == 1
659158906cfSBram Moolenaar    res = "one"
660158906cfSBram Moolenaar  elseif what == 2
661158906cfSBram Moolenaar    res = "two"
662a259d8d3SBram Moolenaar  else
663158906cfSBram Moolenaar    res = "three"
664a259d8d3SBram Moolenaar  endif
665158906cfSBram Moolenaar  return res
666a259d8d3SBram Moolenaarenddef
667a259d8d3SBram Moolenaar
668158906cfSBram Moolenaardef Test_if_elseif_else()
669158906cfSBram Moolenaar  assert_equal('one', IfElse(1))
670158906cfSBram Moolenaar  assert_equal('two', IfElse(2))
671158906cfSBram Moolenaar  assert_equal('three', IfElse(3))
6720f18b6d1SBram Moolenaarenddef
6730f18b6d1SBram Moolenaar
67463ce4849SBram Moolenaardef Test_delfunc()
67563ce4849SBram Moolenaar  let lines =<< trim END
67663ce4849SBram Moolenaar    vim9script
67763ce4849SBram Moolenaar    def GoneSoon()
67863ce4849SBram Moolenaar      echo 'hello'
67963ce4849SBram Moolenaar    enddef
68063ce4849SBram Moolenaar
68163ce4849SBram Moolenaar    def CallGoneSoon()
68263ce4849SBram Moolenaar      GoneSoon()
68363ce4849SBram Moolenaar    enddef
68463ce4849SBram Moolenaar
68563ce4849SBram Moolenaar    delfunc GoneSoon
68663ce4849SBram Moolenaar    CallGoneSoon()
68763ce4849SBram Moolenaar  END
68863ce4849SBram Moolenaar  writefile(lines, 'XToDelFunc')
68963ce4849SBram Moolenaar  assert_fails('so XToDelFunc', 'E933')
69063ce4849SBram Moolenaar  assert_fails('so XToDelFunc', 'E933')
69163ce4849SBram Moolenaar
69263ce4849SBram Moolenaar  delete('XToDelFunc')
69363ce4849SBram Moolenaarenddef
69463ce4849SBram Moolenaar
6955b1c8fe3SBram Moolenaardef Test_substitute_cmd()
6965b1c8fe3SBram Moolenaar  new
6975b1c8fe3SBram Moolenaar  setline(1, 'something')
6985b1c8fe3SBram Moolenaar  :substitute(some(other(
6995b1c8fe3SBram Moolenaar  assert_equal('otherthing', getline(1))
70083f37b91SBram Moolenaar  bwipe!
70183f37b91SBram Moolenaar
70283f37b91SBram Moolenaar  " also when the context is Vim9 script
70383f37b91SBram Moolenaar  let lines =<< trim END
70483f37b91SBram Moolenaar    vim9script
70583f37b91SBram Moolenaar    new
70683f37b91SBram Moolenaar    setline(1, 'something')
70783f37b91SBram Moolenaar    :substitute(some(other(
70883f37b91SBram Moolenaar    assert_equal('otherthing', getline(1))
70983f37b91SBram Moolenaar    bwipe!
71083f37b91SBram Moolenaar  END
71183f37b91SBram Moolenaar  writefile(lines, 'Xvim9lines')
71283f37b91SBram Moolenaar  source Xvim9lines
71383f37b91SBram Moolenaar
71483f37b91SBram Moolenaar  delete('Xvim9lines')
7155b1c8fe3SBram Moolenaarenddef
7165b1c8fe3SBram Moolenaar
717ad39c094SBram Moolenaardef Test_execute_cmd()
718ad39c094SBram Moolenaar  new
719ad39c094SBram Moolenaar  setline(1, 'default')
720ad39c094SBram Moolenaar  execute 'call setline(1, "execute-string")'
721ad39c094SBram Moolenaar  assert_equal('execute-string', getline(1))
722ad39c094SBram Moolenaar  let cmd1 = 'call setline(1,'
723ad39c094SBram Moolenaar  let cmd2 = '"execute-var")'
724ad39c094SBram Moolenaar  execute cmd1 cmd2
725ad39c094SBram Moolenaar  assert_equal('execute-var', getline(1))
726ad39c094SBram Moolenaar  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
727ad39c094SBram Moolenaar  assert_equal('execute-var-string', getline(1))
728ad39c094SBram Moolenaar  let cmd_first = 'call '
729ad39c094SBram Moolenaar  let cmd_last = 'setline(1, "execute-var-var")'
730ad39c094SBram Moolenaar  execute cmd_first .. cmd_last
731ad39c094SBram Moolenaar  assert_equal('execute-var-var', getline(1))
732ad39c094SBram Moolenaar  bwipe!
733ad39c094SBram Moolenaarenddef
734ad39c094SBram Moolenaar
735ad39c094SBram Moolenaardef Test_echo_cmd()
736ad39c094SBram Moolenaar  echo 'something'
737ad39c094SBram Moolenaar  assert_match('^something$', Screenline(&lines))
738ad39c094SBram Moolenaar
739ad39c094SBram Moolenaar  let str1 = 'some'
740ad39c094SBram Moolenaar  let str2 = 'more'
741ad39c094SBram Moolenaar  echo str1 str2
742ad39c094SBram Moolenaar  assert_match('^some more$', Screenline(&lines))
743ad39c094SBram Moolenaarenddef
744ad39c094SBram Moolenaar
7458a7d6542SBram Moolenaar
7468a7d6542SBram Moolenaar" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
747