startup_spec.lua 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local assert_alive = n.assert_alive
  5. local assert_log = t.assert_log
  6. local clear = n.clear
  7. local command = n.command
  8. local ok = t.ok
  9. local eq = t.eq
  10. local matches = t.matches
  11. local eval = n.eval
  12. local exec = n.exec
  13. local exec_capture = n.exec_capture
  14. local exec_lua = n.exec_lua
  15. local feed = n.feed
  16. local fn = n.fn
  17. local pesc = vim.pesc
  18. local mkdir = t.mkdir
  19. local mkdir_p = n.mkdir_p
  20. local nvim_prog = n.nvim_prog
  21. local nvim_set = n.nvim_set
  22. local read_file = t.read_file
  23. local retry = t.retry
  24. local rmdir = n.rmdir
  25. local sleep = vim.uv.sleep
  26. local startswith = vim.startswith
  27. local write_file = t.write_file
  28. local api = n.api
  29. local is_os = t.is_os
  30. local dedent = t.dedent
  31. local tbl_map = vim.tbl_map
  32. local tbl_filter = vim.tbl_filter
  33. local endswith = vim.endswith
  34. local check_close = n.check_close
  35. local testlog = 'Xtest-startupspec-log'
  36. describe('startup', function()
  37. it('--clean', function()
  38. clear()
  39. matches(
  40. vim.pesc(t.fix_slashes(fn.stdpath('config'))),
  41. t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
  42. )
  43. clear('--clean')
  44. ok(
  45. not t.fix_slashes(api.nvim_get_option_value('runtimepath', {}))
  46. :match(vim.pesc(t.fix_slashes(fn.stdpath('config'))))
  47. )
  48. end)
  49. it('prevents remote UI infinite loop', function()
  50. clear()
  51. local screen
  52. screen = Screen.new(84, 3)
  53. fn.termopen({ nvim_prog, '-u', 'NONE', '--server', eval('v:servername'), '--remote-ui' })
  54. screen:expect([[
  55. ^Cannot attach UI of :terminal child to its parent. (Unset $NVIM to skip this check) |
  56. |*2
  57. ]])
  58. end)
  59. it('--startuptime', function()
  60. local testfile = 'Xtest_startuptime'
  61. finally(function()
  62. os.remove(testfile)
  63. end)
  64. clear({ args = { '--startuptime', testfile } })
  65. assert_log('Embedded', testfile, 100)
  66. assert_log('sourcing', testfile, 100)
  67. assert_log("require%('vim%._editor'%)", testfile, 100)
  68. end)
  69. it('--startuptime does not crash on error #31125', function()
  70. eq(
  71. "E484: Can't open file .",
  72. fn.system({
  73. nvim_prog,
  74. '-u',
  75. 'NONE',
  76. '-i',
  77. 'NONE',
  78. '--headless',
  79. '--startuptime',
  80. '.',
  81. '-c',
  82. '42cquit',
  83. })
  84. )
  85. eq(42, api.nvim_get_vvar('shell_error'))
  86. end)
  87. it('-D does not hang #12647', function()
  88. clear()
  89. local screen
  90. screen = Screen.new(60, 7)
  91. -- not the same colors on windows for some reason
  92. screen._default_attr_ids = nil
  93. local id = fn.termopen({
  94. nvim_prog,
  95. '-u',
  96. 'NONE',
  97. '-i',
  98. 'NONE',
  99. '--cmd',
  100. 'set noruler',
  101. '-D',
  102. }, {
  103. env = {
  104. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  105. },
  106. })
  107. screen:expect({ any = pesc('Entering Debug mode. Type "cont" to continue.') })
  108. fn.chansend(id, 'cont\n')
  109. screen:expect([[
  110. ^ |
  111. ~ |*3
  112. [No Name] |
  113. |*2
  114. ]])
  115. end)
  116. it(':filetype detect enables filetype detection with -u NONE', function()
  117. clear()
  118. eq('filetype detection:OFF plugin:OFF indent:OFF', exec_capture('filetype'))
  119. command('filetype detect')
  120. eq('filetype detection:ON plugin:OFF indent:OFF', exec_capture('filetype'))
  121. end)
  122. end)
  123. describe('startup', function()
  124. before_each(clear)
  125. after_each(function()
  126. check_close()
  127. os.remove(testlog)
  128. end)
  129. describe('-l Lua', function()
  130. local function assert_l_out(expected, nvim_args, lua_args, script, input)
  131. local args = { nvim_prog }
  132. vim.list_extend(args, nvim_args or {})
  133. vim.list_extend(args, { '-l', (script or 'test/functional/fixtures/startup.lua') })
  134. vim.list_extend(args, lua_args or {})
  135. local out = fn.system(args, input):gsub('\r\n', '\n')
  136. return eq(dedent(expected), out)
  137. end
  138. it('failure modes', function()
  139. -- nvim -l <empty>
  140. matches('nvim%.?e?x?e?: Argument missing after: "%-l"', fn.system({ nvim_prog, '-l' }))
  141. eq(1, eval('v:shell_error'))
  142. end)
  143. it('os.exit() sets Nvim exitcode', function()
  144. -- tricky: LeakSanitizer triggers on os.exit() and disrupts the return value, disable it
  145. exec_lua [[
  146. local asan_options = os.getenv('ASAN_OPTIONS') or ''
  147. if asan_options ~= '' then
  148. asan_options = asan_options .. ':'
  149. end
  150. vim.uv.os_setenv('ASAN_OPTIONS', asan_options .. ':detect_leaks=0')
  151. ]]
  152. -- nvim -l foo.lua -arg1 -- a b c
  153. assert_l_out(
  154. [[
  155. bufs:
  156. nvim args: 7
  157. lua args: { "-arg1", "--exitcode", "73", "--arg2",
  158. [0] = "test/functional/fixtures/startup.lua"
  159. }]],
  160. {},
  161. { '-arg1', '--exitcode', '73', '--arg2' }
  162. )
  163. eq(73, eval('v:shell_error'))
  164. end)
  165. it('Lua-error sets Nvim exitcode', function()
  166. eq(0, eval('v:shell_error'))
  167. matches(
  168. 'E5113: .* my pearls!!',
  169. fn.system({ nvim_prog, '-l', 'test/functional/fixtures/startup-fail.lua' })
  170. )
  171. eq(1, eval('v:shell_error'))
  172. matches(
  173. 'E5113: .* %[string "error%("whoa"%)"%]:1: whoa',
  174. fn.system({ nvim_prog, '-l', '-' }, 'error("whoa")')
  175. )
  176. eq(1, eval('v:shell_error'))
  177. end)
  178. it('executes stdin "-"', function()
  179. assert_l_out(
  180. 'arg0=- args=2 whoa\n',
  181. nil,
  182. { 'arg1', 'arg 2' },
  183. '-',
  184. "print(('arg0=%s args=%d %s'):format(_G.arg[0], #_G.arg, 'whoa'))"
  185. )
  186. assert_l_out(
  187. 'biiig input: 1000042\n',
  188. nil,
  189. nil,
  190. '-',
  191. ('print("biiig input: "..("%s"):len())'):format(string.rep('x', (1000 * 1000) + 42))
  192. )
  193. eq(0, eval('v:shell_error'))
  194. end)
  195. it('does not truncate long print() message', function()
  196. assert_l_out(('k'):rep(1234) .. '\n', nil, nil, '-', "print(('k'):rep(1234))")
  197. end)
  198. it('does not add newline when unnecessary', function()
  199. assert_l_out('', nil, nil, '-', '')
  200. assert_l_out('foobar\n', nil, nil, '-', [[print('foobar\n')]])
  201. end)
  202. it('sets _G.arg', function()
  203. -- nvim -l foo.lua
  204. assert_l_out(
  205. [[
  206. bufs:
  207. nvim args: 3
  208. lua args: {
  209. [0] = "test/functional/fixtures/startup.lua"
  210. }
  211. ]],
  212. {},
  213. {}
  214. )
  215. eq(0, eval('v:shell_error'))
  216. -- nvim -l foo.lua [args]
  217. assert_l_out(
  218. [[
  219. bufs:
  220. nvim args: 7
  221. lua args: { "-arg1", "--arg2", "--", "arg3",
  222. [0] = "test/functional/fixtures/startup.lua"
  223. }
  224. ]],
  225. {},
  226. { '-arg1', '--arg2', '--', 'arg3' }
  227. )
  228. eq(0, eval('v:shell_error'))
  229. -- nvim file1 file2 -l foo.lua -arg1 -- file3 file4
  230. assert_l_out(
  231. [[
  232. bufs: file1 file2
  233. nvim args: 10
  234. lua args: { "-arg1", "arg 2", "--", "file3", "file4",
  235. [0] = "test/functional/fixtures/startup.lua"
  236. }
  237. ]],
  238. { 'file1', 'file2' },
  239. { '-arg1', 'arg 2', '--', 'file3', 'file4' }
  240. )
  241. eq(0, eval('v:shell_error'))
  242. -- nvim -l foo.lua <vim args>
  243. assert_l_out(
  244. [[
  245. bufs:
  246. nvim args: 5
  247. lua args: { "-c", "set wrap?",
  248. [0] = "test/functional/fixtures/startup.lua"
  249. }
  250. ]],
  251. {},
  252. { '-c', 'set wrap?' }
  253. )
  254. eq(0, eval('v:shell_error'))
  255. -- nvim <vim args> -l foo.lua <vim args>
  256. assert_l_out(
  257. [[
  258. wrap
  259. bufs:
  260. nvim args: 7
  261. lua args: { "-c", "set wrap?",
  262. [0] = "test/functional/fixtures/startup.lua"
  263. }
  264. ]],
  265. { '-c', 'set wrap?' },
  266. { '-c', 'set wrap?' }
  267. )
  268. eq(0, eval('v:shell_error'))
  269. end)
  270. it('disables swapfile/shada/config/plugins', function()
  271. assert_l_out(
  272. 'updatecount=0 shadafile=NONE loadplugins=false scripts=1\n',
  273. nil,
  274. nil,
  275. '-',
  276. [[print(('updatecount=%d shadafile=%s loadplugins=%s scripts=%d'):format(
  277. vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]]
  278. )
  279. end)
  280. end)
  281. it('--cmd/-c/+ do not truncate long Lua print() message with --headless', function()
  282. local out = fn.system({
  283. nvim_prog,
  284. '-u',
  285. 'NONE',
  286. '-i',
  287. 'NONE',
  288. '--headless',
  289. '--cmd',
  290. 'lua print(("A"):rep(1234))',
  291. '-c',
  292. 'lua print(("B"):rep(1234))',
  293. '+lua print(("C"):rep(1234))',
  294. '+q',
  295. })
  296. eq(('A'):rep(1234) .. '\r\n' .. ('B'):rep(1234) .. '\r\n' .. ('C'):rep(1234), out)
  297. end)
  298. it('pipe at both ends: has("ttyin")==0 has("ttyout")==0', function()
  299. -- system() puts a pipe at both ends.
  300. local out = fn.system({
  301. nvim_prog,
  302. '-u',
  303. 'NONE',
  304. '-i',
  305. 'NONE',
  306. '--headless',
  307. '--cmd',
  308. nvim_set,
  309. '-c',
  310. [[echo has('ttyin') has('ttyout')]],
  311. '+q',
  312. })
  313. eq('0 0', out)
  314. end)
  315. it('with --embed: has("ttyin")==0 has("ttyout")==0', function()
  316. local screen = Screen.new(25, 3)
  317. -- Remote UI connected by --embed.
  318. -- TODO: a lot of tests in this file already use the new default color scheme.
  319. -- once we do the batch update of tests to use it, remove this workaround
  320. screen._default_attr_ids = nil
  321. command([[echo has('ttyin') has('ttyout')]])
  322. screen:expect([[
  323. ^ |
  324. ~ |
  325. 0 0 |
  326. ]])
  327. end)
  328. it('in a TTY: has("ttyin")==1 has("ttyout")==1', function()
  329. local screen = Screen.new(25, 4)
  330. screen._default_attr_ids = nil
  331. if is_os('win') then
  332. command([[set shellcmdflag=/s\ /c shellxquote=\"]])
  333. end
  334. -- Running in :terminal
  335. fn.termopen({
  336. nvim_prog,
  337. '-u',
  338. 'NONE',
  339. '-i',
  340. 'NONE',
  341. '--cmd',
  342. nvim_set,
  343. '-c',
  344. 'echo has("ttyin") has("ttyout")',
  345. }, {
  346. env = {
  347. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  348. },
  349. })
  350. screen:expect([[
  351. ^ |
  352. ~ |
  353. 1 1 |
  354. |
  355. ]])
  356. end)
  357. it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
  358. clear({ env = { NVIM_LOG_FILE = testlog } })
  359. if is_os('win') then
  360. command([[set shellcmdflag=/s\ /c shellxquote=\"]])
  361. end
  362. os.remove('Xtest_startup_ttyout')
  363. finally(function()
  364. os.remove('Xtest_startup_ttyout')
  365. end)
  366. -- Running in :terminal
  367. fn.termopen(
  368. (
  369. [["%s" -u NONE -i NONE --cmd "%s"]]
  370. .. [[ -c "call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')"]]
  371. .. [[ -c q | cat -v]]
  372. ):format(nvim_prog, nvim_set),
  373. {
  374. env = {
  375. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  376. },
  377. }
  378. )
  379. retry(nil, 3000, function()
  380. sleep(1)
  381. eq(
  382. '1\n0\n', -- stdin is a TTY, stdout is a pipe
  383. read_file('Xtest_startup_ttyout')
  384. )
  385. end)
  386. end)
  387. it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
  388. clear({ env = { NVIM_LOG_FILE = testlog } })
  389. if is_os('win') then
  390. command([[set shellcmdflag=/s\ /c shellxquote=\"]])
  391. end
  392. os.remove('Xtest_startup_ttyout')
  393. finally(function()
  394. os.remove('Xtest_startup_ttyout')
  395. end)
  396. -- Running in :terminal
  397. fn.termopen(
  398. (
  399. [[echo foo | ]] -- Input from a pipe.
  400. .. [["%s" -u NONE -i NONE --cmd "%s"]]
  401. .. [[ -c "call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')"]]
  402. .. [[ -c q -- -]]
  403. ):format(nvim_prog, nvim_set),
  404. {
  405. env = {
  406. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  407. },
  408. }
  409. )
  410. retry(nil, 3000, function()
  411. sleep(1)
  412. eq(
  413. '0\n1\n', -- stdin is a pipe, stdout is a TTY
  414. read_file('Xtest_startup_ttyout')
  415. )
  416. end)
  417. end)
  418. it('input from pipe (implicit) #7679', function()
  419. clear({ env = { NVIM_LOG_FILE = testlog } })
  420. local screen = Screen.new(25, 4)
  421. screen._default_attr_ids = nil
  422. if is_os('win') then
  423. command([[set shellcmdflag=/s\ /c shellxquote=\"]])
  424. end
  425. -- Running in :terminal
  426. fn.termopen(
  427. (
  428. [[echo foo | ]]
  429. .. [["%s" -u NONE -i NONE --cmd "%s"]]
  430. .. [[ -c "echo has('ttyin') has('ttyout')"]]
  431. ):format(nvim_prog, nvim_set),
  432. {
  433. env = {
  434. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  435. },
  436. }
  437. )
  438. screen:expect([[
  439. ^foo |
  440. ~ |
  441. 0 1 |
  442. |
  443. ]])
  444. if not is_os('win') then
  445. assert_log('Failed to get flags on descriptor 3: Bad file descriptor', testlog, 100)
  446. end
  447. end)
  448. it('input from pipe + file args #7679', function()
  449. eq(
  450. 'ohyeah\r\n0 0 bufs=3',
  451. fn.system({
  452. nvim_prog,
  453. '-n',
  454. '-u',
  455. 'NONE',
  456. '-i',
  457. 'NONE',
  458. '--headless',
  459. '+.print',
  460. "+echo has('ttyin') has('ttyout') 'bufs='.bufnr('$')",
  461. '+qall!',
  462. '-',
  463. 'test/functional/fixtures/tty-test.c',
  464. 'test/functional/fixtures/shell-test.c',
  465. }, { 'ohyeah', '' })
  466. )
  467. end)
  468. it('if stdin is empty: selects buffer 2, deletes buffer 1 #8561', function()
  469. eq(
  470. '\r\n 2 %a "file1" line 0\r\n 3 "file2" line 0',
  471. fn.system({
  472. nvim_prog,
  473. '-n',
  474. '-u',
  475. 'NONE',
  476. '-i',
  477. 'NONE',
  478. '--headless',
  479. '+ls!',
  480. '+qall!',
  481. '-',
  482. 'file1',
  483. 'file2',
  484. }, { '' })
  485. )
  486. end)
  487. it('stdin with -es/-Es #7679', function()
  488. local input = { 'append', 'line1', 'line2', '.', '%print', '' }
  489. local inputstr = table.concat(input, '\n')
  490. --
  491. -- -Es: read stdin as text
  492. --
  493. eq(
  494. 'partylikeits1999\n',
  495. fn.system({
  496. nvim_prog,
  497. '-n',
  498. '-u',
  499. 'NONE',
  500. '-i',
  501. 'NONE',
  502. '-Es',
  503. '+.print',
  504. 'test/functional/fixtures/tty-test.c',
  505. }, { 'partylikeits1999', '' })
  506. )
  507. eq(inputstr, fn.system({ nvim_prog, '-i', 'NONE', '-Es', '+%print', '-' }, input))
  508. -- with `-u NORC`
  509. eq(
  510. 'thepartycontinues\n',
  511. fn.system({ nvim_prog, '-n', '-u', 'NORC', '-Es', '+.print' }, { 'thepartycontinues', '' })
  512. )
  513. -- without `-u`
  514. eq(
  515. 'thepartycontinues\n',
  516. fn.system({ nvim_prog, '-n', '-Es', '+.print' }, { 'thepartycontinues', '' })
  517. )
  518. --
  519. -- -es: read stdin as ex-commands
  520. --
  521. eq(
  522. ' encoding=utf-8\n',
  523. fn.system({
  524. nvim_prog,
  525. '-n',
  526. '-u',
  527. 'NONE',
  528. '-i',
  529. 'NONE',
  530. '-es',
  531. 'test/functional/fixtures/tty-test.c',
  532. }, { 'set encoding', '' })
  533. )
  534. eq('line1\nline2\n', fn.system({ nvim_prog, '-i', 'NONE', '-es', '-' }, input))
  535. -- with `-u NORC`
  536. eq(
  537. ' encoding=utf-8\n',
  538. fn.system({ nvim_prog, '-n', '-u', 'NORC', '-es' }, { 'set encoding', '' })
  539. )
  540. -- without `-u`
  541. eq(' encoding=utf-8\n', fn.system({ nvim_prog, '-n', '-es' }, { 'set encoding', '' }))
  542. end)
  543. it('-es/-Es disables swapfile, user config #8540', function()
  544. for _, arg in ipairs({ '-es', '-Es' }) do
  545. local out = fn.system({
  546. nvim_prog,
  547. arg,
  548. '+set swapfile? updatecount? shadafile?',
  549. '+put =map(getscriptinfo(), {-> v:val.name})',
  550. '+%print',
  551. })
  552. local line1 = string.match(out, '^.-\n')
  553. -- updatecount=0 means swapfile was disabled.
  554. eq(' swapfile updatecount=0 shadafile=\n', line1)
  555. -- Standard plugins were loaded, but not user config.
  556. ok(string.find(out, 'man.lua') ~= nil)
  557. ok(string.find(out, 'init.vim') == nil)
  558. end
  559. end)
  560. it('fails on --embed with -es/-Es/-l', function()
  561. matches(
  562. 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
  563. fn.system({ nvim_prog, '--embed', '-es' })
  564. )
  565. matches(
  566. 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
  567. fn.system({ nvim_prog, '--embed', '-Es' })
  568. )
  569. matches(
  570. 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
  571. fn.system({ nvim_prog, '--embed', '-l', 'foo.lua' })
  572. )
  573. end)
  574. it('ENTER dismisses early message #7967', function()
  575. local screen
  576. screen = Screen.new(60, 6)
  577. screen._default_attr_ids = nil
  578. local id = fn.termopen({
  579. nvim_prog,
  580. '-u',
  581. 'NONE',
  582. '-i',
  583. 'NONE',
  584. '--cmd',
  585. 'set noruler',
  586. '--cmd',
  587. 'let g:foo = g:bar',
  588. }, {
  589. env = {
  590. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  591. },
  592. })
  593. screen:expect([[
  594. ^ |
  595. |
  596. Error detected while processing pre-vimrc command line: |
  597. E121: Undefined variable: g:bar |
  598. Press ENTER or type command to continue |
  599. |
  600. ]])
  601. fn.chansend(id, '\n')
  602. screen:expect([[
  603. ^ |
  604. ~ |*2
  605. [No Name] |
  606. |*2
  607. ]])
  608. end)
  609. it('-r works without --headless in PTY #23294', function()
  610. exec([[
  611. func Normalize(data) abort
  612. " Windows: remove ^M and term escape sequences
  613. return map(a:data, 'substitute(substitute(v:val, "\r", "", "g"), "\x1b\\%(\\]\\d\\+;.\\{-}\x07\\|\\[.\\{-}[\x40-\x7E]\\)", "", "g")')
  614. endfunc
  615. func OnOutput(id, data, event) dict
  616. let g:stdout = Normalize(a:data)
  617. endfunc
  618. call jobstart([v:progpath, '-u', 'NONE', '-i', 'NONE', '-r'], {
  619. \ 'pty': v:true,
  620. \ 'stdout_buffered': v:true,
  621. \ 'on_stdout': function('OnOutput'),
  622. \ })
  623. ]])
  624. retry(nil, nil, function()
  625. eq('Swap files found:', eval('g:stdout[0]'))
  626. end)
  627. end)
  628. it('fixed hang issue with --headless (#11386)', function()
  629. local expected = ''
  630. local period = 100
  631. for i = 1, period - 1 do
  632. expected = expected .. i .. '\r\n'
  633. end
  634. expected = expected .. period
  635. eq(
  636. expected,
  637. -- FIXME(codehex): We should really set a timeout for the system function.
  638. -- If this test fails, there will be a waiting input state.
  639. fn.system({
  640. nvim_prog,
  641. '-u',
  642. 'NONE',
  643. '-c',
  644. 'for i in range(1, 100) | echo i | endfor | quit',
  645. '--headless',
  646. })
  647. )
  648. end)
  649. it('get command line arguments from v:argv', function()
  650. local out = fn.system({
  651. nvim_prog,
  652. '-u',
  653. 'NONE',
  654. '-i',
  655. 'NONE',
  656. '--headless',
  657. '--cmd',
  658. nvim_set,
  659. '-c',
  660. [[echo v:argv[-1:] len(v:argv) > 1]],
  661. '+q',
  662. })
  663. eq("['+q'] 1", out)
  664. end)
  665. end)
  666. describe('startup', function()
  667. it('-e/-E interactive #7679', function()
  668. clear('-e')
  669. local screen = Screen.new(25, 3)
  670. feed("put ='from -e'<CR>")
  671. screen:expect([[
  672. :put ='from -e' |
  673. from -e |
  674. :^ |
  675. ]])
  676. clear('-E')
  677. screen = Screen.new(25, 3)
  678. feed("put ='from -E'<CR>")
  679. screen:expect([[
  680. :put ='from -E' |
  681. from -E |
  682. :^ |
  683. ]])
  684. end)
  685. it('-e sets ex mode', function()
  686. clear('-e')
  687. local screen = Screen.new(25, 3)
  688. -- Verify we set the proper mode both before and after :vi.
  689. feed('put =mode(1)<CR>vi<CR>:put =mode(1)<CR>')
  690. screen:expect([[
  691. cv |
  692. ^n |
  693. :put =mode(1) |
  694. ]])
  695. eq('cv\n', fn.system({ nvim_prog, '-n', '-es' }, { 'put =mode(1)', 'print', '' }))
  696. end)
  697. it('-d does not diff non-arglist windows #13720 #21289', function()
  698. write_file(
  699. 'Xdiff.vim',
  700. [[
  701. let bufnr = nvim_create_buf(0, 1)
  702. let config = {
  703. \ 'relative': 'editor',
  704. \ 'focusable': v:false,
  705. \ 'width': 1,
  706. \ 'height': 1,
  707. \ 'row': 3,
  708. \ 'col': 3
  709. \ }
  710. autocmd WinEnter * call nvim_open_win(bufnr, v:false, config)]]
  711. )
  712. finally(function()
  713. os.remove('Xdiff.vim')
  714. end)
  715. clear { args = { '-u', 'Xdiff.vim', '-d', 'Xdiff.vim', 'Xdiff.vim' } }
  716. eq(true, api.nvim_get_option_value('diff', { win = fn.win_getid(1) }))
  717. eq(true, api.nvim_get_option_value('diff', { win = fn.win_getid(2) }))
  718. local float_win = fn.win_getid(3)
  719. eq('editor', api.nvim_win_get_config(float_win).relative)
  720. eq(false, api.nvim_get_option_value('diff', { win = float_win }))
  721. end)
  722. it('does not crash if --embed is given twice', function()
  723. clear { args = { '--embed' } }
  724. assert_alive()
  725. end)
  726. it('does not crash when expanding cdpath during early_init', function()
  727. clear { env = { CDPATH = '~doesnotexist' } }
  728. assert_alive()
  729. eq(',~doesnotexist', eval('&cdpath'))
  730. end)
  731. it("sets 'shortmess' when loading other tabs", function()
  732. clear({ args = { '-p', 'a', 'b', 'c' } })
  733. local screen = Screen.new(25, 4)
  734. screen:expect({
  735. grid = [[
  736. {1: a }{2: b c }{3: }{2:X}|
  737. ^ |
  738. {4:~ }|
  739. |
  740. ]],
  741. attr_ids = {
  742. [1] = { bold = true },
  743. [2] = { background = Screen.colors.LightGrey, underline = true },
  744. [3] = { reverse = true },
  745. [4] = { bold = true, foreground = Screen.colors.Blue1 },
  746. },
  747. })
  748. end)
  749. end)
  750. describe('startup', function()
  751. local function pack_clear(cmd)
  752. -- add packages after config dir in rtp but before config/after
  753. clear {
  754. args = {
  755. '--cmd',
  756. 'set packpath=test/functional/fixtures',
  757. '--cmd',
  758. 'let paths=split(&rtp, ",")',
  759. '--cmd',
  760. 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")',
  761. '--cmd',
  762. cmd,
  763. },
  764. env = { XDG_CONFIG_HOME = 'test/functional/fixtures/' },
  765. args_rm = { 'runtimepath' },
  766. }
  767. end
  768. it('handles &packpath during startup', function()
  769. pack_clear [[
  770. let g:x = bar#test()
  771. let g:y = leftpad#pad("heyya")
  772. ]]
  773. eq(-3, eval 'g:x')
  774. eq(' heyya', eval 'g:y')
  775. pack_clear [[ lua _G.y = require'bar'.doit() _G.z = require'leftpad''howdy' ]]
  776. eq({ 9003, '\thowdy' }, exec_lua [[ return { _G.y, _G.z } ]])
  777. end)
  778. it('handles require from &packpath in an async handler', function()
  779. -- NO! you cannot just speed things up by calling async functions during startup!
  780. -- It doesn't make anything actually faster! NOOOO!
  781. pack_clear [[ lua require'async_leftpad'('brrrr', 'async_res') ]]
  782. -- haha, async leftpad go brrrrr
  783. eq('\tbrrrr', exec_lua [[ return _G.async_res ]])
  784. end)
  785. it('handles :packadd during startup', function()
  786. -- control group: opt/bonus is not available by default
  787. pack_clear [[
  788. try
  789. let g:x = bonus#secret()
  790. catch
  791. let g:err = v:exception
  792. endtry
  793. ]]
  794. eq('Vim(let):E117: Unknown function: bonus#secret', eval 'g:err')
  795. pack_clear [[ lua _G.test = {pcall(function() require'bonus'.launch() end)} ]]
  796. eq(
  797. { false, [[[string ":lua"]:1: module 'bonus' not found:]] },
  798. exec_lua [[ _G.test[2] = string.gsub(_G.test[2], '[\r\n].*', '') return _G.test ]]
  799. )
  800. -- ok, time to launch the nukes:
  801. pack_clear [[ packadd! bonus | let g:x = bonus#secret() ]]
  802. eq('halloj', eval 'g:x')
  803. pack_clear [[ packadd! bonus | lua _G.y = require'bonus'.launch() ]]
  804. eq('CPE 1704 TKS', exec_lua [[ return _G.y ]])
  805. end)
  806. it('handles the correct order with start packages and after/', function()
  807. pack_clear [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]
  808. eq(
  809. { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
  810. exec_lua [[ return _G.test_loadorder ]]
  811. )
  812. end)
  813. it('handles the correct order with start packages and after/ after startup', function()
  814. pack_clear [[ lua _G.test_loadorder = {} ]]
  815. command [[ runtime! filen.lua ]]
  816. eq(
  817. { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
  818. exec_lua [[ return _G.test_loadorder ]]
  819. )
  820. end)
  821. it('handles the correct order with globpath(&rtp, ...)', function()
  822. pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
  823. command [[
  824. for x in globpath(&rtp, "filen.lua",1,1)
  825. call v:lua.dofile(x)
  826. endfor
  827. ]]
  828. eq(
  829. { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
  830. exec_lua [[ return _G.test_loadorder ]]
  831. )
  832. local rtp = api.nvim_get_option_value('rtp', {})
  833. ok(
  834. startswith(
  835. rtp,
  836. 'test/functional/fixtures/nvim,test/functional/fixtures/pack/*/start/*,test/functional/fixtures/start/*,test/functional/fixtures,test/functional/fixtures/middle,'
  837. ),
  838. 'startswith(…)',
  839. 'rtp=' .. rtp
  840. )
  841. end)
  842. it('handles the correct order with opt packages and after/', function()
  843. pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]]
  844. eq({
  845. 'ordinary',
  846. 'SuperSpecial',
  847. 'FANCY',
  848. 'mittel',
  849. 'FANCY after',
  850. 'SuperSpecial after',
  851. 'ordinary after',
  852. }, exec_lua [[ return _G.test_loadorder ]])
  853. end)
  854. it('handles the correct order with opt packages and after/ after startup', function()
  855. pack_clear [[ lua _G.test_loadorder = {} ]]
  856. command [[
  857. packadd! superspecial
  858. runtime! filen.lua
  859. ]]
  860. eq({
  861. 'ordinary',
  862. 'SuperSpecial',
  863. 'FANCY',
  864. 'mittel',
  865. 'FANCY after',
  866. 'SuperSpecial after',
  867. 'ordinary after',
  868. }, exec_lua [[ return _G.test_loadorder ]])
  869. end)
  870. it('handles the correct order with opt packages and globpath(&rtp, ...)', function()
  871. pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
  872. command [[
  873. packadd! superspecial
  874. for x in globpath(&rtp, "filen.lua",1,1)
  875. call v:lua.dofile(x)
  876. endfor
  877. ]]
  878. eq({
  879. 'ordinary',
  880. 'SuperSpecial',
  881. 'FANCY',
  882. 'mittel',
  883. 'SuperSpecial after',
  884. 'FANCY after',
  885. 'ordinary after',
  886. }, exec_lua [[ return _G.test_loadorder ]])
  887. end)
  888. it('handles the correct order with a package that changes packpath', function()
  889. pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! funky\nruntime! filen.lua" ]]
  890. eq(
  891. { 'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
  892. exec_lua [[ return _G.test_loadorder ]]
  893. )
  894. eq({ 'ordinary', 'funky!', 'mittel', 'ordinary after' }, exec_lua [[ return _G.nested_order ]])
  895. end)
  896. it('handles the correct order when prepending packpath', function()
  897. clear {
  898. args = {
  899. '--cmd',
  900. 'set packpath^=test/functional/fixtures',
  901. '--cmd',
  902. [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]],
  903. },
  904. env = { XDG_CONFIG_HOME = 'test/functional/fixtures/' },
  905. }
  906. eq(
  907. { 'ordinary', 'FANCY', 'FANCY after', 'ordinary after' },
  908. exec_lua [[ return _G.test_loadorder ]]
  909. )
  910. end)
  911. it('window widths are correct when modelines set &columns with tabpages', function()
  912. write_file('Xtab1.noft', 'vim: columns=81')
  913. write_file('Xtab2.noft', 'vim: columns=81')
  914. finally(function()
  915. os.remove('Xtab1.noft')
  916. os.remove('Xtab2.noft')
  917. end)
  918. clear({ args = { '-p', 'Xtab1.noft', 'Xtab2.noft' } })
  919. eq(81, api.nvim_win_get_width(0))
  920. command('tabnext')
  921. eq(81, api.nvim_win_get_width(0))
  922. end)
  923. end)
  924. describe('sysinit', function()
  925. local xdgdir = 'Xxdg'
  926. local vimdir = 'Xvim'
  927. local xhome = 'Xhome'
  928. local pathsep = n.get_pathsep()
  929. before_each(function()
  930. rmdir(xdgdir)
  931. rmdir(vimdir)
  932. rmdir(xhome)
  933. mkdir(xdgdir)
  934. mkdir(xdgdir .. pathsep .. 'nvim')
  935. write_file(
  936. table.concat({ xdgdir, 'nvim', 'sysinit.vim' }, pathsep),
  937. [[
  938. let g:loaded = get(g:, "loaded", 0) + 1
  939. let g:xdg = 1
  940. ]]
  941. )
  942. mkdir(vimdir)
  943. write_file(
  944. table.concat({ vimdir, 'sysinit.vim' }, pathsep),
  945. [[
  946. let g:loaded = get(g:, "loaded", 0) + 1
  947. let g:vim = 1
  948. ]]
  949. )
  950. mkdir(xhome)
  951. end)
  952. after_each(function()
  953. rmdir(xdgdir)
  954. rmdir(vimdir)
  955. rmdir(xhome)
  956. end)
  957. it('prefers XDG_CONFIG_DIRS over VIM', function()
  958. clear {
  959. args = { '--cmd', 'set nomore undodir=. directory=. belloff=' },
  960. args_rm = { '-u', '--cmd' },
  961. env = { HOME = xhome, XDG_CONFIG_DIRS = xdgdir, VIM = vimdir },
  962. }
  963. eq(
  964. 'loaded 1 xdg 1 vim 0',
  965. eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')
  966. )
  967. end)
  968. it('uses VIM if XDG_CONFIG_DIRS unset', function()
  969. clear {
  970. args = { '--cmd', 'set nomore undodir=. directory=. belloff=' },
  971. args_rm = { '-u', '--cmd' },
  972. env = { HOME = xhome, XDG_CONFIG_DIRS = '', VIM = vimdir },
  973. }
  974. eq(
  975. 'loaded 1 xdg 0 vim 1',
  976. eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')
  977. )
  978. end)
  979. end)
  980. describe('user config init', function()
  981. local xhome = 'Xhome'
  982. local pathsep = n.get_pathsep()
  983. local xconfig = xhome .. pathsep .. 'Xconfig'
  984. local xdata = xhome .. pathsep .. 'Xdata'
  985. local init_lua_path = table.concat({ xconfig, 'nvim', 'init.lua' }, pathsep)
  986. local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
  987. before_each(function()
  988. rmdir(xhome)
  989. mkdir_p(xconfig .. pathsep .. 'nvim')
  990. mkdir_p(xdata)
  991. write_file(
  992. init_lua_path,
  993. [[
  994. vim.g.lua_rc = 1
  995. ]]
  996. )
  997. end)
  998. after_each(function()
  999. rmdir(xhome)
  1000. end)
  1001. it('loads init.lua from XDG config home by default', function()
  1002. clear { args_rm = { '-u' }, env = xenv }
  1003. eq(1, eval('g:lua_rc'))
  1004. eq(fn.fnamemodify(init_lua_path, ':p'), eval('$MYVIMRC'))
  1005. end)
  1006. describe('loads existing', function()
  1007. local exrc_path = '.exrc'
  1008. local xstate = 'Xstate'
  1009. local xstateenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata, XDG_STATE_HOME = xstate }
  1010. local function setup_exrc_file(filename)
  1011. exrc_path = filename
  1012. if string.find(exrc_path, '%.lua$') then
  1013. write_file(
  1014. exrc_path,
  1015. string.format(
  1016. [[
  1017. vim.g.exrc_file = "%s"
  1018. ]],
  1019. exrc_path
  1020. )
  1021. )
  1022. else
  1023. write_file(
  1024. exrc_path,
  1025. string.format(
  1026. [[
  1027. let g:exrc_file = "%s"
  1028. ]],
  1029. exrc_path
  1030. )
  1031. )
  1032. end
  1033. end
  1034. before_each(function()
  1035. write_file(
  1036. init_lua_path,
  1037. [[
  1038. vim.o.exrc = true
  1039. vim.g.exrc_file = '---'
  1040. ]]
  1041. )
  1042. mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
  1043. end)
  1044. after_each(function()
  1045. os.remove(exrc_path)
  1046. rmdir(xstate)
  1047. end)
  1048. for _, filename in ipairs({ '.exrc', '.nvimrc', '.nvim.lua' }) do
  1049. it(filename .. ' in cwd', function()
  1050. setup_exrc_file(filename)
  1051. clear { args_rm = { '-u' }, env = xstateenv }
  1052. -- The 'exrc' file is not trusted, and the prompt is skipped because there is no UI.
  1053. eq('---', eval('g:exrc_file'))
  1054. local screen = Screen.new(50, 8)
  1055. screen._default_attr_ids = nil
  1056. fn.termopen({ nvim_prog }, {
  1057. env = {
  1058. VIMRUNTIME = os.getenv('VIMRUNTIME'),
  1059. },
  1060. })
  1061. screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:') })
  1062. -- `i` to enter Terminal mode, `a` to allow
  1063. feed('ia')
  1064. screen:expect([[
  1065. |
  1066. ~ |*4
  1067. [No Name] 0,0-1 All|
  1068. |
  1069. -- TERMINAL -- |
  1070. ]])
  1071. feed(':echo g:exrc_file<CR>')
  1072. screen:expect(string.format(
  1073. [[
  1074. |
  1075. ~ |*4
  1076. [No Name] 0,0-1 All|
  1077. %s%s|
  1078. -- TERMINAL -- |
  1079. ]],
  1080. filename,
  1081. string.rep(' ', 50 - #filename)
  1082. ))
  1083. clear { args_rm = { '-u' }, env = xstateenv }
  1084. -- The 'exrc' file is now trusted.
  1085. eq(filename, eval('g:exrc_file'))
  1086. end)
  1087. end
  1088. end)
  1089. describe('with explicitly provided config', function()
  1090. local custom_lua_path = table.concat({ xhome, 'custom.lua' }, pathsep)
  1091. before_each(function()
  1092. write_file(
  1093. custom_lua_path,
  1094. [[
  1095. vim.g.custom_lua_rc = 1
  1096. ]]
  1097. )
  1098. end)
  1099. it('loads custom lua config and does not set $MYVIMRC', function()
  1100. clear { args = { '-u', custom_lua_path }, env = xenv }
  1101. eq(1, eval('g:custom_lua_rc'))
  1102. eq('', eval('$MYVIMRC'))
  1103. end)
  1104. end)
  1105. describe('VIMRC also exists', function()
  1106. before_each(function()
  1107. write_file(
  1108. table.concat({ xconfig, 'nvim', 'init.vim' }, pathsep),
  1109. [[
  1110. let g:vim_rc = 1
  1111. ]]
  1112. )
  1113. end)
  1114. it('loads default lua config, but shows an error', function()
  1115. clear { args_rm = { '-u' }, env = xenv }
  1116. feed('<cr><c-c>') -- Dismiss "Conflicting config …" message.
  1117. eq(1, eval('g:lua_rc'))
  1118. matches('^E5422: Conflicting configs', exec_capture('messages'))
  1119. end)
  1120. end)
  1121. end)
  1122. describe('runtime:', function()
  1123. local xhome = 'Xhome'
  1124. local pathsep = n.get_pathsep()
  1125. local xconfig = xhome .. pathsep .. 'Xconfig'
  1126. local xdata = xhome .. pathsep .. 'Xdata'
  1127. local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
  1128. setup(function()
  1129. rmdir(xhome)
  1130. mkdir_p(xconfig .. pathsep .. 'nvim')
  1131. mkdir_p(xdata)
  1132. end)
  1133. teardown(function()
  1134. rmdir(xhome)
  1135. end)
  1136. it('loads plugin/*.lua from XDG config home', function()
  1137. local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
  1138. local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
  1139. mkdir_p(plugin_folder_path)
  1140. finally(function()
  1141. rmdir(plugin_folder_path)
  1142. end)
  1143. write_file(plugin_file_path, [[ vim.g.lua_plugin = 1 ]])
  1144. clear { args_rm = { '-u' }, env = xenv }
  1145. eq(1, eval('g:lua_plugin'))
  1146. end)
  1147. it('loads plugin/*.lua from start packages', function()
  1148. local plugin_path =
  1149. table.concat({ xconfig, 'nvim', 'pack', 'category', 'start', 'test_plugin' }, pathsep)
  1150. local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
  1151. local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
  1152. local profiler_file = 'test_startuptime.log'
  1153. mkdir_p(plugin_folder_path)
  1154. finally(function()
  1155. os.remove(profiler_file)
  1156. rmdir(plugin_path)
  1157. end)
  1158. write_file(plugin_file_path, [[vim.g.lua_plugin = 2]])
  1159. clear { args_rm = { '-u' }, args = { '--startuptime', profiler_file }, env = xenv }
  1160. eq(2, eval('g:lua_plugin'))
  1161. -- Check if plugin_file_path is listed in getscriptinfo()
  1162. local scripts = tbl_map(function(s)
  1163. return s.name
  1164. end, fn.getscriptinfo())
  1165. ok(#tbl_filter(function(s)
  1166. return endswith(s, plugin_file_path)
  1167. end, scripts) > 0)
  1168. -- Check if plugin_file_path is listed in startup profile
  1169. local profile_reader = io.open(profiler_file, 'r')
  1170. local profile_log = profile_reader:read('*a')
  1171. profile_reader:close()
  1172. ok(profile_log:find(plugin_file_path) ~= nil)
  1173. end)
  1174. it('loads plugin/*.lua from site packages', function()
  1175. local nvimdata = is_os('win') and 'nvim-data' or 'nvim'
  1176. local plugin_path =
  1177. table.concat({ xdata, nvimdata, 'site', 'pack', 'xa', 'start', 'yb' }, pathsep)
  1178. local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
  1179. local plugin_after_path = table.concat({ plugin_path, 'after', 'plugin' }, pathsep)
  1180. local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
  1181. local plugin_after_file_path = table.concat({ plugin_after_path, 'helloo.lua' }, pathsep)
  1182. mkdir_p(plugin_folder_path)
  1183. mkdir_p(plugin_after_path)
  1184. finally(function()
  1185. rmdir(plugin_path)
  1186. end)
  1187. write_file(plugin_file_path, [[table.insert(_G.lista, "unos")]])
  1188. write_file(plugin_after_file_path, [[table.insert(_G.lista, "dos")]])
  1189. clear { args_rm = { '-u' }, args = { '--cmd', 'lua _G.lista = {}' }, env = xenv }
  1190. eq({ 'unos', 'dos' }, exec_lua 'return _G.lista')
  1191. end)
  1192. it('no crash setting &rtp in plugins with :packloadall called before #18315', function()
  1193. local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
  1194. mkdir_p(plugin_folder_path)
  1195. finally(function()
  1196. rmdir(plugin_folder_path)
  1197. end)
  1198. write_file(
  1199. table.concat({ plugin_folder_path, 'plugin.vim' }, pathsep),
  1200. [[
  1201. let &runtimepath = &runtimepath
  1202. let g:vim_plugin = 1
  1203. ]]
  1204. )
  1205. write_file(
  1206. table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep),
  1207. [[
  1208. vim.o.runtimepath = vim.o.runtimepath
  1209. vim.g.lua_plugin = 1
  1210. ]]
  1211. )
  1212. clear { args_rm = { '-u' }, args = { '--cmd', 'packloadall' }, env = xenv }
  1213. eq(1, eval('g:vim_plugin'))
  1214. eq(1, eval('g:lua_plugin'))
  1215. end)
  1216. it("loads ftdetect/*.{vim,lua} respecting 'rtp' order", function()
  1217. local rtp_folder = table.concat({ xconfig, 'nvim' }, pathsep)
  1218. local after_rtp_folder = table.concat({ rtp_folder, 'after' }, pathsep)
  1219. local ftdetect_folder = table.concat({ rtp_folder, 'ftdetect' }, pathsep)
  1220. local after_ftdetect_folder = table.concat({ after_rtp_folder, 'ftdetect' }, pathsep)
  1221. mkdir_p(ftdetect_folder)
  1222. mkdir_p(after_ftdetect_folder)
  1223. finally(function()
  1224. rmdir(ftdetect_folder)
  1225. rmdir(after_ftdetect_folder)
  1226. end)
  1227. write_file(table.concat({ rtp_folder, 'scripts.vim' }, pathsep), [[let g:aseq ..= 'S']])
  1228. write_file(table.concat({ after_rtp_folder, 'scripts.vim' }, pathsep), [[let g:aseq ..= 's']])
  1229. -- A .lua file is loaded after a .vim file if they only differ in extension.
  1230. -- All files in after/ftdetect/ are loaded after all files in ftdetect/.
  1231. write_file(
  1232. table.concat({ ftdetect_folder, 'new-ft.vim' }, pathsep),
  1233. [[
  1234. let g:seq ..= 'A'
  1235. autocmd BufRead,BufNewFile FTDETECT let g:aseq ..= 'A'
  1236. ]]
  1237. )
  1238. write_file(
  1239. table.concat({ ftdetect_folder, 'new-ft.lua' }, pathsep),
  1240. [[
  1241. vim.g.seq = vim.g.seq .. 'B'
  1242. vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
  1243. pattern = 'FTDETECT',
  1244. command = "let g:aseq ..= 'B'",
  1245. })
  1246. ]]
  1247. )
  1248. write_file(
  1249. table.concat({ after_ftdetect_folder, 'new-ft.vim' }, pathsep),
  1250. [[
  1251. let g:seq ..= 'a'
  1252. autocmd BufRead,BufNewFile FTDETECT let g:aseq ..= 'a'
  1253. ]]
  1254. )
  1255. write_file(
  1256. table.concat({ after_ftdetect_folder, 'new-ft.lua' }, pathsep),
  1257. [[
  1258. vim.g.seq = vim.g.seq .. 'b'
  1259. vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
  1260. pattern = 'FTDETECT',
  1261. command = "let g:aseq ..= 'b'",
  1262. })
  1263. ]]
  1264. )
  1265. clear { args_rm = { '-u' }, args = { '--cmd', 'let g:seq = ""' }, env = xenv }
  1266. eq('ABab', eval('g:seq'))
  1267. command('let g:aseq = ""')
  1268. command('edit FTDETECT')
  1269. eq('SsABab', eval('g:aseq'))
  1270. end)
  1271. end)
  1272. describe('user session', function()
  1273. local xhome = 'Xhome'
  1274. local pathsep = n.get_pathsep()
  1275. local session_file = table.concat({ xhome, 'session.lua' }, pathsep)
  1276. before_each(function()
  1277. rmdir(xhome)
  1278. mkdir(xhome)
  1279. write_file(
  1280. session_file,
  1281. [[
  1282. vim.g.lua_session = 1
  1283. ]]
  1284. )
  1285. end)
  1286. after_each(function()
  1287. rmdir(xhome)
  1288. end)
  1289. it('loads session from the provided lua file', function()
  1290. clear { args = { '-S', session_file }, env = { HOME = xhome } }
  1291. eq(1, eval('g:lua_session'))
  1292. end)
  1293. end)
  1294. describe('inccommand on ex mode', function()
  1295. it('should not preview', function()
  1296. clear()
  1297. local screen
  1298. screen = Screen.new(60, 10)
  1299. local id = fn.termopen({
  1300. nvim_prog,
  1301. '-u',
  1302. 'NONE',
  1303. '-i',
  1304. 'NONE',
  1305. '-c',
  1306. 'set termguicolors background=dark',
  1307. '-E',
  1308. 'test/README.md',
  1309. }, {
  1310. env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
  1311. })
  1312. fn.chansend(id, '%s/N')
  1313. screen:expect {
  1314. grid = [[
  1315. {1:^ }|
  1316. {1: }|*6
  1317. {1:Entering Ex mode. Type "visual" to go to Normal mode. }|
  1318. {1::%s/N }|
  1319. |
  1320. ]],
  1321. attr_ids = {
  1322. [1] = {
  1323. background = Screen.colors.NvimDarkGrey2,
  1324. foreground = Screen.colors.NvimLightGrey2,
  1325. },
  1326. },
  1327. }
  1328. end)
  1329. end)