messages_spec.lua 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear, feed = n.clear, n.feed
  5. local eval = n.eval
  6. local eq = t.eq
  7. local neq = t.neq
  8. local command = n.command
  9. local set_method_error = n.set_method_error
  10. local api = n.api
  11. local async_meths = n.async_meths
  12. local test_build_dir = t.paths.test_build_dir
  13. local nvim_prog = n.nvim_prog
  14. local testprg = n.testprg
  15. local exec = n.exec
  16. local exec_capture = n.exec_capture
  17. local exc_exec = n.exc_exec
  18. local exec_lua = n.exec_lua
  19. local poke_eventloop = n.poke_eventloop
  20. local assert_alive = n.assert_alive
  21. local retry = t.retry
  22. local is_os = t.is_os
  23. local fn = n.fn
  24. local skip = t.skip
  25. describe('ui/ext_messages', function()
  26. local screen
  27. local fname = 'Xtest_functional_ui_messages_spec'
  28. before_each(function()
  29. clear()
  30. screen = Screen.new(25, 5, { rgb = true, ext_messages = true, ext_popupmenu = true })
  31. screen:add_extra_attr_ids {
  32. [100] = { undercurl = true, special = Screen.colors.Red },
  33. }
  34. end)
  35. after_each(function()
  36. os.remove(fname)
  37. end)
  38. it('msg_clear follows msg_show kind of confirm', function()
  39. feed('iline 1<esc>')
  40. feed(':call confirm("test")<cr>')
  41. screen:expect({
  42. grid = [[
  43. line ^1 |
  44. {1:~ }|*4
  45. ]],
  46. cmdline = {
  47. {
  48. content = { { '' } },
  49. hl_id = 10,
  50. pos = 0,
  51. prompt = '[O]k: ',
  52. },
  53. },
  54. messages = {
  55. {
  56. content = { { '\ntest\n', 6, 10 } },
  57. history = false,
  58. kind = 'confirm',
  59. },
  60. },
  61. })
  62. feed('<cr>')
  63. screen:expect({
  64. grid = [[
  65. line ^1 |
  66. {1:~ }|*4
  67. ]],
  68. cmdline = { { abort = false } },
  69. })
  70. end)
  71. it('msg_show kinds', function()
  72. feed('iline 1\nline 2<esc>')
  73. -- confirm is now cmdline prompt
  74. feed(':echo confirm("test")<cr>')
  75. screen:expect({
  76. grid = [[
  77. line 1 |
  78. line ^2 |
  79. {1:~ }|*3
  80. ]],
  81. cmdline = {
  82. {
  83. content = { { '' } },
  84. hl_id = 10,
  85. pos = 0,
  86. prompt = '[O]k: ',
  87. },
  88. },
  89. messages = {
  90. {
  91. content = { { '\ntest\n', 6, 10 } },
  92. history = false,
  93. kind = 'confirm',
  94. },
  95. },
  96. })
  97. feed('<cr>')
  98. screen:expect({
  99. grid = [[
  100. line 1 |
  101. line ^2 |
  102. {1:~ }|*3
  103. ]],
  104. cmdline = { { abort = false } },
  105. messages = {
  106. {
  107. content = { { '\ntest\n', 6, 10 } },
  108. history = false,
  109. kind = 'confirm',
  110. },
  111. {
  112. content = { { '1' } },
  113. history = false,
  114. kind = 'echo',
  115. },
  116. {
  117. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  118. history = false,
  119. kind = 'return_prompt',
  120. },
  121. },
  122. })
  123. feed('<cr>')
  124. -- :substitute confirm is now cmdline prompt
  125. feed(':%s/i/X/gc<cr>')
  126. screen:expect({
  127. grid = [[
  128. l{2:^i}ne 1 |
  129. l{10:i}ne 2 |
  130. {1:~ }|*3
  131. ]],
  132. cmdline = {
  133. {
  134. content = { { '' } },
  135. hl_id = 18,
  136. pos = 0,
  137. prompt = 'replace with X? (y)es/(n)o/(a)ll/(q)uit/(l)ast/scroll up(^E)/down(^Y)',
  138. },
  139. },
  140. })
  141. feed('nq')
  142. -- kind=wmsg (editing readonly file)
  143. command('write ' .. fname)
  144. command('set readonly nohls')
  145. feed('G$x')
  146. screen:expect({
  147. grid = [[
  148. line 1 |
  149. line^ |
  150. {1:~ }|*3
  151. ]],
  152. cmdline = { { abort = false } },
  153. messages = {
  154. {
  155. content = { { 'W10: Warning: Changing a readonly file', 19, 26 } },
  156. history = true,
  157. kind = 'wmsg',
  158. },
  159. },
  160. })
  161. -- kind=wmsg ('wrapscan' after search reaches EOF)
  162. feed('uG$/i<cr>')
  163. screen:expect {
  164. grid = [[
  165. l^ine 1 |
  166. line 2 |
  167. {1:~ }|*3
  168. ]],
  169. cmdline = { { abort = false } },
  170. messages = {
  171. {
  172. content = { { 'search hit BOTTOM, continuing at TOP', 19, 26 } },
  173. history = true,
  174. kind = 'wmsg',
  175. },
  176. },
  177. }
  178. -- kind=emsg after :throw
  179. feed(':throw "foo"<cr>')
  180. screen:expect {
  181. cmdline = { { abort = false } },
  182. messages = {
  183. {
  184. content = { { 'Error detected while processing :', 9, 6 } },
  185. history = true,
  186. kind = 'emsg',
  187. },
  188. {
  189. content = { { 'E605: Exception not caught: foo', 9, 6 } },
  190. history = true,
  191. kind = 'emsg',
  192. },
  193. {
  194. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  195. history = false,
  196. kind = 'return_prompt',
  197. },
  198. },
  199. }
  200. -- kind=quickfix after :cnext
  201. feed('<c-c>')
  202. command("caddexpr [expand('%').':1:line1',expand('%').':2:line2']")
  203. feed(':cnext<cr>')
  204. screen:expect {
  205. grid = [[
  206. line 1 |
  207. ^line 2 |
  208. {1:~ }|*3
  209. ]],
  210. cmdline = { { abort = false } },
  211. messages = {
  212. {
  213. content = { { '(2 of 2): line2' } },
  214. history = true,
  215. kind = 'quickfix',
  216. },
  217. },
  218. }
  219. -- search_cmd
  220. feed('?line<cr>')
  221. screen:expect({
  222. grid = [[
  223. ^line 1 |
  224. line 2 |
  225. {1:~ }|*3
  226. ]],
  227. cmdline = { { abort = false } },
  228. messages = {
  229. {
  230. content = { { '?line ' } },
  231. history = false,
  232. kind = 'search_cmd',
  233. },
  234. },
  235. })
  236. -- highlight
  237. feed(':filter character highlight<CR>')
  238. screen:expect({
  239. cmdline = { { abort = false } },
  240. messages = {
  241. {
  242. content = {
  243. { '\n@character ' },
  244. { 'xxx', 26, 150 },
  245. { ' ' },
  246. { 'links to', 18, 5 },
  247. { ' Character\n@character.special ' },
  248. { 'xxx', 16, 151 },
  249. { ' ' },
  250. { 'links to', 18, 5 },
  251. { ' SpecialChar' },
  252. },
  253. history = false,
  254. kind = 'list_cmd',
  255. },
  256. },
  257. })
  258. -- undo
  259. feed('uu')
  260. screen:expect({
  261. grid = [[
  262. ^ |
  263. {1:~ }|*4
  264. ]],
  265. messages = {
  266. {
  267. content = { { 'Already at oldest change' } },
  268. history = true,
  269. kind = 'undo',
  270. },
  271. },
  272. })
  273. feed('<C-r><C-r><C-r>')
  274. screen:expect({
  275. grid = [[
  276. line 1 |
  277. line^ |
  278. {1:~ }|*3
  279. ]],
  280. messages = {
  281. {
  282. content = { { 'Already at newest change' } },
  283. history = true,
  284. kind = 'undo',
  285. },
  286. },
  287. })
  288. -- kind=completion
  289. command('set noshowmode')
  290. feed('i<C-n>')
  291. screen:expect({
  292. messages = {
  293. {
  294. content = { { 'The only match' } },
  295. history = false,
  296. kind = 'completion',
  297. },
  298. },
  299. })
  300. feed('<Esc>')
  301. command('set showmode')
  302. -- kind=echoerr for nvim_echo() err
  303. feed(':call nvim_echo([["Error"], ["Message", "Special"]], 1, #{ err:1 })<CR>')
  304. screen:expect({
  305. cmdline = { { abort = false } },
  306. messages = {
  307. {
  308. content = { { 'Error', 9, 6 }, { 'Message', 16, 99 } },
  309. history = true,
  310. kind = 'echoerr',
  311. },
  312. },
  313. })
  314. -- kind=verbose for nvim_echo() verbose
  315. feed(':call nvim_echo([["Verbose Message"]], 1, #{ verbose:1 })<CR>')
  316. screen:expect({
  317. cmdline = { { abort = false } },
  318. messages = {
  319. {
  320. content = { { 'Verbose Message' } },
  321. history = true,
  322. kind = 'verbose',
  323. },
  324. },
  325. })
  326. -- kind=verbose for :verbose messages
  327. feed(':1verbose filter Diff[AC] hi<CR>')
  328. screen:expect({
  329. cmdline = { { abort = false } },
  330. messages = {
  331. {
  332. content = {
  333. { '\nDiffAdd ' },
  334. { 'xxx', 22, 30 },
  335. { ' ' },
  336. { 'ctermbg=', 18, 5 },
  337. { '81 ' },
  338. { 'guibg=', 18, 5 },
  339. { 'LightBlue' },
  340. },
  341. history = false,
  342. kind = 'list_cmd',
  343. },
  344. {
  345. content = { { '\n\tLast set from Lua (run Nvim with -V1 for more details)' } },
  346. history = false,
  347. kind = 'verbose',
  348. },
  349. {
  350. content = {
  351. { '\nDiffChange ' },
  352. { 'xxx', 4, 31 },
  353. { ' ' },
  354. { 'ctermbg=', 18, 5 },
  355. { '225 ' },
  356. { 'guibg=', 18, 5 },
  357. { 'LightMagenta' },
  358. },
  359. history = false,
  360. kind = 'list_cmd',
  361. },
  362. {
  363. content = { { '\n\tLast set from Lua (run Nvim with -V1 for more details)' } },
  364. history = false,
  365. kind = 'verbose',
  366. },
  367. {
  368. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  369. history = false,
  370. kind = 'return_prompt',
  371. },
  372. },
  373. })
  374. -- kind=shell for :!cmd messages
  375. local cmd = t.is_os('win') and 'echo stdout& echo stderr>&2& exit 3'
  376. or '{ echo stdout; echo stderr >&2; exit 3; }'
  377. feed(('<CR>:!%s<CR>'):format(cmd))
  378. screen:expect({
  379. cmdline = { { abort = false } },
  380. messages = {
  381. {
  382. content = { { (':!%s\r\n[No write since last change]\n'):format(cmd) } },
  383. history = false,
  384. kind = '',
  385. },
  386. {
  387. content = { { ('stdout%s\n'):format(t.is_os('win') and '\r' or '') } },
  388. history = false,
  389. kind = 'shell_out',
  390. },
  391. {
  392. content = { { ('stderr%s\n'):format(t.is_os('win') and '\r' or ''), 9, 6 } },
  393. history = false,
  394. kind = 'shell_err',
  395. },
  396. {
  397. content = { { '\nshell returned 3\n\n' } },
  398. history = false,
  399. kind = 'shell_ret',
  400. },
  401. {
  402. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  403. history = false,
  404. kind = 'return_prompt',
  405. },
  406. },
  407. })
  408. end)
  409. it(':echoerr', function()
  410. feed(':echoerr "raa"<cr>')
  411. screen:expect {
  412. grid = [[
  413. ^ |
  414. {1:~ }|*4
  415. ]],
  416. cmdline = { { abort = false } },
  417. messages = {
  418. {
  419. content = { { 'raa', 9, 6 } },
  420. history = true,
  421. kind = 'echoerr',
  422. },
  423. },
  424. }
  425. -- cmdline in a later input cycle clears error message
  426. feed(':')
  427. screen:expect {
  428. grid = [[
  429. ^ |
  430. {1:~ }|*4
  431. ]],
  432. cmdline = { {
  433. firstc = ':',
  434. content = { { '' } },
  435. pos = 0,
  436. } },
  437. }
  438. feed('echoerr "bork" | echoerr "fail"<cr>')
  439. screen:expect {
  440. grid = [[
  441. ^ |
  442. {1:~ }|*4
  443. ]],
  444. cmdline = { { abort = false } },
  445. messages = {
  446. {
  447. content = { { 'bork', 9, 6 } },
  448. history = true,
  449. kind = 'echoerr',
  450. },
  451. {
  452. content = { { 'fail', 9, 6 } },
  453. history = true,
  454. kind = 'echoerr',
  455. },
  456. {
  457. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  458. history = false,
  459. kind = 'return_prompt',
  460. },
  461. },
  462. }
  463. feed(':echoerr "extrafail"<cr>')
  464. screen:expect {
  465. grid = [[
  466. ^ |
  467. {1:~ }|*4
  468. ]],
  469. cmdline = { { abort = false } },
  470. messages = {
  471. {
  472. content = { { 'bork', 9, 6 } },
  473. history = true,
  474. kind = 'echoerr',
  475. },
  476. {
  477. content = { { 'fail', 9, 6 } },
  478. history = true,
  479. kind = 'echoerr',
  480. },
  481. {
  482. content = { { 'extrafail', 9, 6 } },
  483. history = true,
  484. kind = 'echoerr',
  485. },
  486. {
  487. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  488. history = false,
  489. kind = 'return_prompt',
  490. },
  491. },
  492. }
  493. feed('<cr>')
  494. screen:expect {
  495. grid = [[
  496. ^ |
  497. {1:~ }|*4
  498. ]],
  499. }
  500. -- cmdline without interleaving wait/display keeps the error message
  501. feed(':echoerr "problem" | let x = input("foo> ")<cr>')
  502. screen:expect {
  503. grid = [[
  504. ^ |
  505. {1:~ }|*4
  506. ]],
  507. messages = {
  508. {
  509. content = { { 'problem', 9, 6 } },
  510. history = true,
  511. kind = 'echoerr',
  512. },
  513. },
  514. cmdline = {
  515. {
  516. prompt = 'foo> ',
  517. hl_id = 0,
  518. content = { { '' } },
  519. pos = 0,
  520. },
  521. },
  522. }
  523. feed('solution<cr>')
  524. screen:expect {
  525. grid = [[
  526. ^ |
  527. {1:~ }|*4
  528. ]],
  529. cmdline = { { abort = false } },
  530. }
  531. eq('solution', eval('x'))
  532. feed(':messages<cr>')
  533. screen:expect {
  534. grid = [[
  535. ^ |
  536. {1:~ }|*4
  537. ]],
  538. cmdline = { { abort = false } },
  539. msg_history = {
  540. { kind = 'echoerr', content = { { 'raa', 9, 6 } } },
  541. { kind = 'echoerr', content = { { 'bork', 9, 6 } } },
  542. { kind = 'echoerr', content = { { 'fail', 9, 6 } } },
  543. { kind = 'echoerr', content = { { 'extrafail', 9, 6 } } },
  544. { kind = 'echoerr', content = { { 'problem', 9, 6 } } },
  545. },
  546. messages = {
  547. {
  548. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  549. history = false,
  550. kind = 'return_prompt',
  551. },
  552. },
  553. }
  554. feed '<cr>'
  555. screen:expect {
  556. grid = [[
  557. ^ |
  558. {1:~ }|*4
  559. ]],
  560. }
  561. end)
  562. it(':echoerr multiline', function()
  563. exec_lua([[vim.g.multi = table.concat({ "bork", "fail" }, "\n")]])
  564. feed(':echoerr g:multi<cr>')
  565. screen:expect {
  566. grid = [[
  567. ^ |
  568. {1:~ }|*4
  569. ]],
  570. cmdline = { { abort = false } },
  571. messages = {
  572. {
  573. content = { { 'bork\nfail', 9, 6 } },
  574. history = true,
  575. kind = 'echoerr',
  576. },
  577. },
  578. }
  579. feed(':messages<cr>')
  580. screen:expect {
  581. grid = [[
  582. ^ |
  583. {1:~ }|*4
  584. ]],
  585. cmdline = { { abort = false } },
  586. messages = {
  587. {
  588. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  589. history = false,
  590. kind = 'return_prompt',
  591. },
  592. },
  593. msg_history = {
  594. {
  595. content = { { 'bork\nfail', 9, 6 } },
  596. kind = 'echoerr',
  597. },
  598. },
  599. }
  600. end)
  601. it('shortmess-=S', function()
  602. command('set shortmess-=S')
  603. feed('iline 1\nline 2<esc>')
  604. feed('/line<cr>')
  605. screen:expect {
  606. grid = [[
  607. {10:^line} 1 |
  608. {10:line} 2 |
  609. {1:~ }|*3
  610. ]],
  611. cmdline = { { abort = false } },
  612. messages = {
  613. { content = { { '/line W [1/2]' } }, kind = 'search_count', history = false },
  614. },
  615. }
  616. feed('n')
  617. screen:expect {
  618. grid = [[
  619. {10:line} 1 |
  620. {10:^line} 2 |
  621. {1:~ }|*3
  622. ]],
  623. messages = {
  624. { content = { { '/line [2/2]' } }, kind = 'search_count', history = false },
  625. },
  626. }
  627. end)
  628. it("doesn't crash with column adjustment #10069", function()
  629. feed(':let [x,y] = [1,2]<cr>')
  630. feed(':let x y<cr>')
  631. screen:expect {
  632. grid = [[
  633. ^ |
  634. {1:~ }|*4
  635. ]],
  636. cmdline = { { abort = false } },
  637. messages = {
  638. { content = { { 'x #1' } }, kind = 'list_cmd', history = false },
  639. { content = { { 'y #2' } }, kind = 'list_cmd', history = false },
  640. {
  641. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  642. history = false,
  643. kind = 'return_prompt',
  644. },
  645. },
  646. }
  647. end)
  648. it('&showmode', function()
  649. command('imap <f2> <cmd>echomsg "stuff"<cr>')
  650. feed('i')
  651. screen:expect {
  652. grid = [[
  653. ^ |
  654. {1:~ }|*4
  655. ]],
  656. showmode = { { '-- INSERT --', 5, 11 } },
  657. }
  658. feed('alphpabet<cr>alphanum<cr>')
  659. screen:expect {
  660. grid = [[
  661. alphpabet |
  662. alphanum |
  663. ^ |
  664. {1:~ }|*2
  665. ]],
  666. showmode = { { '-- INSERT --', 5, 11 } },
  667. }
  668. feed('<c-x>')
  669. screen:expect {
  670. grid = [[
  671. alphpabet |
  672. alphanum |
  673. ^ |
  674. {1:~ }|*2
  675. ]],
  676. showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5, 11 } },
  677. }
  678. feed('<c-p>')
  679. screen:expect {
  680. grid = [[
  681. alphpabet |
  682. alphanum |
  683. alphanum^ |
  684. {1:~ }|*2
  685. ]],
  686. popupmenu = {
  687. anchor = { 1, 2, 0 },
  688. items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
  689. pos = 1,
  690. },
  691. showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } },
  692. }
  693. -- echomsg and showmode don't overwrite each other, this is the same
  694. -- as the TUI behavior with cmdheight=2 or larger.
  695. feed('<f2>')
  696. screen:expect {
  697. grid = [[
  698. alphpabet |
  699. alphanum |
  700. alphanum^ |
  701. {1:~ }|*2
  702. ]],
  703. popupmenu = {
  704. anchor = { 1, 2, 0 },
  705. items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
  706. pos = 1,
  707. },
  708. messages = {
  709. {
  710. content = { { 'stuff' } },
  711. history = true,
  712. kind = 'echomsg',
  713. },
  714. },
  715. showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 1 of 2', 6, 18 } },
  716. }
  717. feed('<c-p>')
  718. screen:expect {
  719. grid = [[
  720. alphpabet |
  721. alphanum |
  722. alphpabet^ |
  723. {1:~ }|*2
  724. ]],
  725. popupmenu = {
  726. anchor = { 1, 2, 0 },
  727. items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
  728. pos = 0,
  729. },
  730. messages = {
  731. {
  732. content = { { 'stuff' } },
  733. history = true,
  734. kind = 'echomsg',
  735. },
  736. },
  737. showmode = { { '-- Keyword Local completion (^N^P) ', 5, 11 }, { 'match 2 of 2', 6, 18 } },
  738. }
  739. feed('<esc>:messages<cr>')
  740. screen:expect {
  741. grid = [[
  742. alphpabet |
  743. alphanum |
  744. alphpabe^t |
  745. {1:~ }|*2
  746. ]],
  747. cmdline = { { abort = false } },
  748. msg_history = { {
  749. content = { { 'stuff' } },
  750. kind = 'echomsg',
  751. } },
  752. messages = {
  753. {
  754. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  755. history = false,
  756. kind = 'return_prompt',
  757. },
  758. },
  759. }
  760. end)
  761. it('&showmode with macro-recording message', function()
  762. feed('qq')
  763. screen:expect {
  764. grid = [[
  765. ^ |
  766. {1:~ }|*4
  767. ]],
  768. showmode = { { 'recording @q', 5, 11 } },
  769. }
  770. feed('i')
  771. screen:expect {
  772. grid = [[
  773. ^ |
  774. {1:~ }|*4
  775. ]],
  776. showmode = { { '-- INSERT --recording @q', 5, 11 } },
  777. }
  778. feed('<esc>')
  779. screen:expect {
  780. grid = [[
  781. ^ |
  782. {1:~ }|*4
  783. ]],
  784. showmode = { { 'recording @q', 5, 11 } },
  785. }
  786. feed('q')
  787. screen:expect([[
  788. ^ |
  789. {1:~ }|*4
  790. ]])
  791. end)
  792. it('shows macro-recording message with &noshowmode', function()
  793. command('set noshowmode')
  794. feed('qq')
  795. -- also check mode to avoid immediate success
  796. screen:expect {
  797. grid = [[
  798. ^ |
  799. {1:~ }|*4
  800. ]],
  801. showmode = { { 'recording @q', 5, 11 } },
  802. mode = 'normal',
  803. }
  804. feed('i')
  805. screen:expect {
  806. grid = [[
  807. ^ |
  808. {1:~ }|*4
  809. ]],
  810. showmode = { { 'recording @q', 5, 11 } },
  811. mode = 'insert',
  812. }
  813. feed('<esc>')
  814. screen:expect {
  815. grid = [[
  816. ^ |
  817. {1:~ }|*4
  818. ]],
  819. showmode = { { 'recording @q', 5, 11 } },
  820. mode = 'normal',
  821. }
  822. feed('q')
  823. screen:expect {
  824. grid = [[
  825. ^ |
  826. {1:~ }|*4
  827. ]],
  828. mode = 'normal',
  829. }
  830. end)
  831. it('supports &showcmd and &ruler', function()
  832. command('set showcmd ruler')
  833. command('hi link MsgArea ErrorMsg')
  834. screen:expect({
  835. grid = [[
  836. ^ |
  837. {1:~ }|*4
  838. ]],
  839. ruler = { { '0,0-1 All', 9, 61 } },
  840. })
  841. command('hi clear MsgArea')
  842. feed('i')
  843. screen:expect {
  844. grid = [[
  845. ^ |
  846. {1:~ }|*4
  847. ]],
  848. showmode = { { '-- INSERT --', 5, 11 } },
  849. ruler = { { '0,1 All' } },
  850. }
  851. feed('abcde<cr>12345<esc>')
  852. screen:expect {
  853. grid = [[
  854. abcde |
  855. 1234^5 |
  856. {1:~ }|*3
  857. ]],
  858. ruler = { { '2,5 All' } },
  859. }
  860. feed('d')
  861. screen:expect {
  862. grid = [[
  863. abcde |
  864. 1234^5 |
  865. {1:~ }|*3
  866. ]],
  867. showcmd = { { 'd' } },
  868. ruler = { { '2,5 All' } },
  869. }
  870. feed('<esc>^')
  871. screen:expect {
  872. grid = [[
  873. abcde |
  874. ^12345 |
  875. {1:~ }|*3
  876. ]],
  877. ruler = { { '2,1 All' } },
  878. }
  879. feed('<c-v>k2l')
  880. screen:expect({
  881. grid = [[
  882. {17:ab}^cde |
  883. {17:123}45 |
  884. {1:~ }|*3
  885. ]],
  886. showmode = { { '-- VISUAL BLOCK --', 5, 11 } },
  887. showcmd = { { '2x3' } },
  888. ruler = { { '1,3 All' } },
  889. })
  890. feed('o<esc>d')
  891. screen:expect {
  892. grid = [[
  893. abcde |
  894. ^12345 |
  895. {1:~ }|*3
  896. ]],
  897. showcmd = { { 'd' } },
  898. ruler = { { '2,1 All' } },
  899. }
  900. feed('i')
  901. screen:expect {
  902. grid = [[
  903. abcde |
  904. ^12345 |
  905. {1:~ }|*3
  906. ]],
  907. showcmd = { { 'di' } },
  908. ruler = { { '2,1 All' } },
  909. }
  910. feed('w')
  911. screen:expect {
  912. grid = [[
  913. abcde |
  914. ^ |
  915. {1:~ }|*3
  916. ]],
  917. ruler = { { '2,0-1 All' } },
  918. }
  919. -- when ruler is part of statusline it is not externalized.
  920. -- this will be added as part of future ext_statusline support
  921. command('set laststatus=2')
  922. screen:expect([[
  923. abcde |
  924. ^ |
  925. {1:~ }|*2
  926. {3:<o Name] [+] 2,0-1 All}|
  927. ]])
  928. end)
  929. it('keeps history of message of different kinds', function()
  930. feed(':echomsg "howdy"<cr>')
  931. screen:expect {
  932. grid = [[
  933. ^ |
  934. {1:~ }|*4
  935. ]],
  936. cmdline = { { abort = false } },
  937. messages = {
  938. {
  939. content = { { 'howdy' } },
  940. history = true,
  941. kind = 'echomsg',
  942. },
  943. },
  944. }
  945. -- always test a message without kind. If this one gets promoted to a
  946. -- category, add a new message without kind.
  947. feed('<c-c>')
  948. screen:expect {
  949. grid = [[
  950. ^ |
  951. {1:~ }|*4
  952. ]],
  953. messages = {
  954. {
  955. content = { { 'Type :qa and press <Enter> to exit Nvim' } },
  956. history = true,
  957. kind = '',
  958. },
  959. },
  960. }
  961. feed(':echoerr "bork"<cr>')
  962. screen:expect {
  963. grid = [[
  964. ^ |
  965. {1:~ }|*4
  966. ]],
  967. cmdline = { { abort = false } },
  968. messages = {
  969. {
  970. content = { { 'bork', 9, 6 } },
  971. history = true,
  972. kind = 'echoerr',
  973. },
  974. },
  975. }
  976. feed(':echo "xyz"<cr>')
  977. screen:expect {
  978. grid = [[
  979. ^ |
  980. {1:~ }|*4
  981. ]],
  982. cmdline = { { abort = false } },
  983. messages = {
  984. {
  985. content = { { 'xyz' } },
  986. history = false,
  987. kind = 'echo',
  988. },
  989. },
  990. }
  991. feed(':call nosuchfunction()<cr>')
  992. screen:expect {
  993. grid = [[
  994. ^ |
  995. {1:~ }|*4
  996. ]],
  997. cmdline = { { abort = false } },
  998. messages = {
  999. {
  1000. content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } },
  1001. history = true,
  1002. kind = 'emsg',
  1003. },
  1004. },
  1005. }
  1006. feed(':messages<cr>')
  1007. screen:expect {
  1008. grid = [[
  1009. ^ |
  1010. {1:~ }|*4
  1011. ]],
  1012. cmdline = { { abort = false } },
  1013. msg_history = {
  1014. { kind = 'echomsg', content = { { 'howdy' } } },
  1015. { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } },
  1016. { kind = 'echoerr', content = { { 'bork', 9, 6 } } },
  1017. { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9, 6 } } },
  1018. },
  1019. messages = {
  1020. {
  1021. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  1022. history = false,
  1023. kind = 'return_prompt',
  1024. },
  1025. },
  1026. }
  1027. end)
  1028. it("implies ext_cmdline but allows changing 'cmdheight'", function()
  1029. eq(0, eval('&cmdheight'))
  1030. feed(':set cmdheight=1')
  1031. screen:expect {
  1032. grid = [[
  1033. ^ |
  1034. {1:~ }|*4
  1035. ]],
  1036. cmdline = {
  1037. {
  1038. content = { { 'set cmdheight=1' } },
  1039. firstc = ':',
  1040. pos = 15,
  1041. },
  1042. },
  1043. }
  1044. feed('<cr>')
  1045. screen:expect({
  1046. grid = [[
  1047. ^ |
  1048. {1:~ }|*3
  1049. |
  1050. ]],
  1051. cmdline = { { abort = false } },
  1052. })
  1053. eq(1, eval('&cmdheight'))
  1054. feed(':set cmdheight=0')
  1055. screen:expect {
  1056. grid = [[
  1057. ^ |
  1058. {1:~ }|*3
  1059. |
  1060. ]],
  1061. cmdline = {
  1062. {
  1063. content = { { 'set cmdheight=0' } },
  1064. firstc = ':',
  1065. pos = 15,
  1066. },
  1067. },
  1068. }
  1069. feed('<cr>')
  1070. screen:expect({
  1071. grid = [[
  1072. ^ |
  1073. {1:~ }|*4
  1074. ]],
  1075. cmdline = { { abort = false } },
  1076. })
  1077. eq(0, eval('&cmdheight'))
  1078. end)
  1079. it('supports multiline messages from lua', function()
  1080. feed(':lua error("such\\nmultiline\\nerror")<cr>')
  1081. screen:expect {
  1082. grid = [[
  1083. ^ |
  1084. {1:~ }|*4
  1085. ]],
  1086. cmdline = { { abort = false } },
  1087. messages = {
  1088. {
  1089. content = {
  1090. {
  1091. [[E5108: Error executing lua [string ":lua"]:1: such
  1092. multiline
  1093. error
  1094. stack traceback:
  1095. [C]: in function 'error'
  1096. [string ":lua"]:1: in main chunk]],
  1097. 9,
  1098. 6,
  1099. },
  1100. },
  1101. history = true,
  1102. kind = 'lua_error',
  1103. },
  1104. },
  1105. }
  1106. end)
  1107. it('supports multiline messages from rpc', function()
  1108. feed(':call rpcrequest(1, "test_method")<cr>')
  1109. screen:expect {
  1110. grid = [[
  1111. ^ |
  1112. {1:~ }|*4
  1113. ]],
  1114. cmdline = { { abort = false } },
  1115. messages = {
  1116. {
  1117. content = {
  1118. { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 6 },
  1119. },
  1120. history = true,
  1121. kind = 'rpc_error',
  1122. },
  1123. },
  1124. request_cb = function(name)
  1125. if name == 'test_method' then
  1126. set_method_error('complete\nerror\n\nmessage')
  1127. end
  1128. end,
  1129. }
  1130. end)
  1131. it('supports multiline messages for :map', function()
  1132. command('mapclear')
  1133. command('nmap Y y$')
  1134. command('nmap Q @@')
  1135. command('nnoremap j k')
  1136. feed(':map<cr>')
  1137. screen:expect {
  1138. cmdline = { { abort = false } },
  1139. messages = {
  1140. {
  1141. content = {
  1142. { '\nn Q @@\nn Y y$\nn j ' },
  1143. { '*', 18, 1 },
  1144. { ' k' },
  1145. },
  1146. history = false,
  1147. kind = 'list_cmd',
  1148. },
  1149. },
  1150. }
  1151. end)
  1152. it('wildmode=list', function()
  1153. screen:try_resize(25, 7)
  1154. screen:set_option('ext_popupmenu', false)
  1155. command('set wildmenu wildmode=list')
  1156. feed(':set wildm<tab>')
  1157. screen:expect {
  1158. grid = [[
  1159. ^ |
  1160. {1:~ }|*6
  1161. ]],
  1162. messages = {
  1163. {
  1164. content = { { 'wildmenu wildmode\n' } },
  1165. history = false,
  1166. kind = 'wildlist',
  1167. },
  1168. },
  1169. cmdline = {
  1170. {
  1171. firstc = ':',
  1172. content = { { 'set wildm' } },
  1173. pos = 9,
  1174. },
  1175. },
  1176. }
  1177. end)
  1178. it('hides prompt_for_number messages', function()
  1179. command('set spell')
  1180. feed('ihelllo<esc>')
  1181. feed('z=')
  1182. screen:expect({
  1183. grid = [[
  1184. {100:^helllo} |
  1185. {1:~ }|*4
  1186. ]],
  1187. cmdline = {
  1188. {
  1189. content = { { '' } },
  1190. hl_id = 0,
  1191. pos = 0,
  1192. prompt = 'Type number and <Enter> or click with the mouse (q or empty cancels):',
  1193. },
  1194. },
  1195. messages = {
  1196. {
  1197. content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
  1198. history = false,
  1199. kind = 'list_cmd',
  1200. },
  1201. },
  1202. })
  1203. feed('1')
  1204. screen:expect({
  1205. grid = [[
  1206. {100:^helllo} |
  1207. {1:~ }|*4
  1208. ]],
  1209. cmdline = {
  1210. {
  1211. content = { { '1' } },
  1212. hl_id = 0,
  1213. pos = 1,
  1214. prompt = 'Type number and <Enter> or click with the mouse (q or empty cancels):',
  1215. },
  1216. },
  1217. messages = {
  1218. {
  1219. content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\n' } },
  1220. history = false,
  1221. kind = 'list_cmd',
  1222. },
  1223. },
  1224. })
  1225. feed('<cr>')
  1226. screen:expect({
  1227. grid = [[
  1228. ^Hello |
  1229. {1:~ }|*4
  1230. ]],
  1231. cmdline = { { abort = false } },
  1232. })
  1233. end)
  1234. it('supports nvim_echo messages with multiple attrs', function()
  1235. async_meths.nvim_echo(
  1236. { { 'wow, ', 'Search' }, { 'such\n\nvery ', 'ErrorMsg' }, { 'color', 'LineNr' } },
  1237. true,
  1238. {}
  1239. )
  1240. screen:expect {
  1241. grid = [[
  1242. ^ |
  1243. {1:~ }|*4
  1244. ]],
  1245. messages = {
  1246. {
  1247. content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
  1248. history = true,
  1249. kind = 'echomsg',
  1250. },
  1251. },
  1252. }
  1253. feed ':ls<cr>'
  1254. screen:expect {
  1255. grid = [[
  1256. ^ |
  1257. {1:~ }|*4
  1258. ]],
  1259. cmdline = { { abort = false } },
  1260. messages = {
  1261. {
  1262. content = { { '\n 1 %a "[No Name]" line 1' } },
  1263. kind = 'list_cmd',
  1264. history = false,
  1265. },
  1266. },
  1267. }
  1268. feed ':messages<cr>'
  1269. screen:expect {
  1270. grid = [[
  1271. ^ |
  1272. {1:~ }|*4
  1273. ]],
  1274. cmdline = { { abort = false } },
  1275. messages = {
  1276. {
  1277. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  1278. history = false,
  1279. kind = 'return_prompt',
  1280. },
  1281. },
  1282. msg_history = {
  1283. {
  1284. content = { { 'wow, ', 10, 8 }, { 'such\n\nvery ', 9, 6 }, { 'color', 8, 12 } },
  1285. kind = 'echomsg',
  1286. },
  1287. },
  1288. }
  1289. feed '<cr>'
  1290. screen:expect {
  1291. grid = [[
  1292. ^ |
  1293. {1:~ }|*4
  1294. ]],
  1295. }
  1296. end)
  1297. it('does not truncate messages', function()
  1298. command('write ' .. fname)
  1299. screen:expect({
  1300. messages = {
  1301. {
  1302. content = { { string.format('"%s" [New] 0L, 0B written', fname) } },
  1303. kind = 'bufwrite',
  1304. history = true,
  1305. },
  1306. },
  1307. })
  1308. end)
  1309. it('does not do showmode unnecessarily #29086', function()
  1310. local screen_showmode = screen._handle_msg_showmode
  1311. local showmode = 0
  1312. screen._handle_msg_showmode = function(...)
  1313. screen_showmode(...)
  1314. showmode = showmode + 1
  1315. end
  1316. screen:expect({
  1317. grid = [[
  1318. ^ |
  1319. {1:~ }|*4
  1320. ]],
  1321. })
  1322. eq(showmode, 1)
  1323. end)
  1324. it('emits single message for multiline print())', function()
  1325. exec_lua([[print("foo\nbar\nbaz")]])
  1326. screen:expect({
  1327. messages = {
  1328. {
  1329. content = { { 'foo\nbar\nbaz' } },
  1330. history = true,
  1331. kind = 'lua_print',
  1332. },
  1333. },
  1334. })
  1335. exec_lua([[print(vim.inspect({ foo = "bar" }))]])
  1336. screen:expect({
  1337. grid = [[
  1338. ^ |
  1339. {1:~ }|*4
  1340. ]],
  1341. messages = {
  1342. {
  1343. content = { { '{\n foo = "bar"\n}' } },
  1344. history = true,
  1345. kind = 'lua_print',
  1346. },
  1347. },
  1348. })
  1349. exec_lua([[vim.print({ foo = "bar" })]])
  1350. screen:expect_unchanged()
  1351. end)
  1352. it('ruler redraw does not crash due to double grid_line_start()', function()
  1353. exec_lua([[
  1354. local ns = vim.api.nvim_create_namespace('')
  1355. vim.ui_attach(ns, { ext_messages = true }, function(event, ...)
  1356. if event == 'msg_ruler' then
  1357. vim.api.nvim__redraw({ flush = true })
  1358. end
  1359. end)
  1360. vim.o.ruler = true
  1361. vim.o.laststatus = 0
  1362. ]])
  1363. feed('i')
  1364. n.assert_alive()
  1365. end)
  1366. it(':digraph contains newlines', function()
  1367. command('digraph')
  1368. screen:expect({
  1369. condition = function()
  1370. local nl = 0
  1371. eq('list_cmd', screen.messages[1].kind)
  1372. for _, chunk in ipairs(screen.messages[1].content) do
  1373. nl = nl + (chunk[2]:find('\n') and 1 or 0)
  1374. end
  1375. eq(682, nl)
  1376. screen.messages = {}
  1377. end,
  1378. })
  1379. end)
  1380. end)
  1381. describe('ui/builtin messages', function()
  1382. local screen
  1383. before_each(function()
  1384. clear()
  1385. screen = Screen.new(60, 7, { rgb = true, ext_popupmenu = true })
  1386. screen:add_extra_attr_ids {
  1387. [100] = { background = Screen.colors.LightRed },
  1388. [101] = { background = Screen.colors.Grey20 },
  1389. [102] = { foreground = Screen.colors.Magenta1, bold = true },
  1390. }
  1391. end)
  1392. it('supports multiline messages from rpc', function()
  1393. feed(':call rpcrequest(1, "test_method")<cr>')
  1394. screen:expect {
  1395. grid = [[
  1396. {3: }|
  1397. {9:Error invoking 'test_method' on channel 1:} |
  1398. {9:complete} |
  1399. {9:error} |
  1400. |
  1401. {9:message} |
  1402. {6:Press ENTER or type command to continue}^ |
  1403. ]],
  1404. request_cb = function(name)
  1405. if name == 'test_method' then
  1406. set_method_error('complete\nerror\n\nmessage')
  1407. end
  1408. end,
  1409. }
  1410. end)
  1411. it(':hi Group output', function()
  1412. screen:try_resize(70, 7)
  1413. feed(':hi ErrorMsg<cr>')
  1414. screen:expect([[
  1415. |
  1416. {1:~ }|*2
  1417. {3: }|
  1418. :hi ErrorMsg |
  1419. ErrorMsg {9:xxx} {18:ctermfg=}15 {18:ctermbg=}1 {18:guifg=}White {18:guibg=}Red |
  1420. {6:Press ENTER or type command to continue}^ |
  1421. ]])
  1422. feed('<cr>')
  1423. screen:try_resize(30, 7)
  1424. feed(':hi ErrorMsg<cr>')
  1425. screen:expect([[
  1426. :hi ErrorMsg |
  1427. ErrorMsg {9:xxx} {18:ctermfg=}15 |
  1428. {18:ctermbg=}1 |
  1429. {18:guifg=}White|
  1430. {18:guibg=}Red |
  1431. {6:Press ENTER or type command to}|
  1432. {6: continue}^ |
  1433. ]])
  1434. feed('<cr>')
  1435. -- screen size doesn't affect internal output #10285
  1436. eq('ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red', exec_capture('hi ErrorMsg'))
  1437. end)
  1438. it(':syntax list langGroup output', function()
  1439. command('syntax on')
  1440. exec([[
  1441. syn match vimComment excludenl +\s"[^\-:.%#=*].*$+lc=1 contains=@vimCommentGroup,vimCommentString
  1442. syn match vimComment +\<endif\s\+".*$+lc=5 contains=@vimCommentGroup,vimCommentString
  1443. syn match vimComment +\<else\s\+".*$+lc=4 contains=@vimCommentGroup,vimCommentString
  1444. hi link vimComment Comment
  1445. ]])
  1446. screen:try_resize(110, 7)
  1447. feed(':syntax list vimComment<cr>')
  1448. screen:expect([[
  1449. {102:--- Syntax items ---} |
  1450. vimComment {18:xxx} {18:match} /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 {18:excludenl} {18:contains}=@vimCommentGroup,vimCommentString |
  1451. |
  1452. {18:match} /\<endif\s\+".*$/ms=s+5,lc=5 {18:contains}=@vimCommentGroup,vimCommentString |
  1453. {18:match} /\<else\s\+".*$/ms=s+4,lc=4 {18:contains}=@vimCommentGroup,vimCommentString |
  1454. {18:links to} Comment |
  1455. {6:Press ENTER or type command to continue}^ |
  1456. ]])
  1457. feed('<cr>')
  1458. screen:try_resize(55, 7)
  1459. feed(':syntax list vimComment<cr>')
  1460. screen:expect([[
  1461. |
  1462. {18:match} /\<endif\s\+".*$/ms=s+5,lc=5 |
  1463. {18:contains}=@vimCommentGroup,vimCommentString |
  1464. {18:match} /\<else\s\+".*$/ms=s+4,lc=4 {18:c}|
  1465. {18:ontains}=@vimCommentGroup,vimCommentString |
  1466. {18:links to} Comment |
  1467. {6:Press ENTER or type command to continue}^ |
  1468. ]])
  1469. feed('<cr>')
  1470. -- ignore final whitespace inside string
  1471. -- luacheck: push ignore
  1472. eq(
  1473. [[--- Syntax items ---
  1474. vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vimCommentGroup,vimCommentString
  1475. match /\<endif\s\+".*$/ms=s+5,lc=5 contains=@vimCommentGroup,vimCommentString
  1476. match /\<else\s\+".*$/ms=s+4,lc=4 contains=@vimCommentGroup,vimCommentString
  1477. links to Comment]],
  1478. exec_capture('syntax list vimComment')
  1479. )
  1480. -- luacheck: pop
  1481. end)
  1482. it('no empty line after :silent #12099', function()
  1483. exec([[
  1484. func T1()
  1485. silent !echo
  1486. echo "message T1"
  1487. endfunc
  1488. func T2()
  1489. silent lua print("lua message")
  1490. echo "message T2"
  1491. endfunc
  1492. func T3()
  1493. silent call nvim_out_write("api message\n")
  1494. echo "message T3"
  1495. endfunc
  1496. ]])
  1497. feed(':call T1()<CR>')
  1498. screen:expect {
  1499. grid = [[
  1500. ^ |
  1501. {1:~ }|*5
  1502. message T1 |
  1503. ]],
  1504. }
  1505. feed(':call T2()<CR>')
  1506. screen:expect {
  1507. grid = [[
  1508. ^ |
  1509. {1:~ }|*5
  1510. message T2 |
  1511. ]],
  1512. }
  1513. feed(':call T3()<CR>')
  1514. screen:expect {
  1515. grid = [[
  1516. ^ |
  1517. {1:~ }|*5
  1518. message T3 |
  1519. ]],
  1520. }
  1521. end)
  1522. it('supports ruler with laststatus=0', function()
  1523. command('set ruler laststatus=0')
  1524. screen:expect {
  1525. grid = [[
  1526. ^ |
  1527. {1:~ }|*5
  1528. 0,0-1 All |
  1529. ]],
  1530. }
  1531. command('hi MsgArea guibg=#333333')
  1532. screen:expect {
  1533. grid = [[
  1534. ^ |
  1535. {1:~ }|*5
  1536. {101: 0,0-1 All }|
  1537. ]],
  1538. }
  1539. command('set rulerformat=%15(%c%V\\ %p%%%)')
  1540. screen:expect {
  1541. grid = [[
  1542. ^ |
  1543. {1:~ }|*5
  1544. {101: 0,0-1 100% }|
  1545. ]],
  1546. }
  1547. end)
  1548. it('supports echo with CRLF line separators', function()
  1549. feed(':echo "line 1\\r\\nline 2"<cr>')
  1550. screen:expect {
  1551. grid = [[
  1552. |
  1553. {1:~ }|*2
  1554. {3: }|
  1555. line 1 |
  1556. line 2 |
  1557. {6:Press ENTER or type command to continue}^ |
  1558. ]],
  1559. }
  1560. feed('<cr>:echo "abc\\rz"<cr>')
  1561. screen:expect {
  1562. grid = [[
  1563. ^ |
  1564. {1:~ }|*5
  1565. zbc |
  1566. ]],
  1567. }
  1568. end)
  1569. it('redraws UPD_NOT_VALID correctly after message', function()
  1570. -- edge case: only one window was set UPD_NOT_VALID. Original report
  1571. -- used :make, but fake it using one command to set the current
  1572. -- window UPD_NOT_VALID and another to show a long message.
  1573. command('set more')
  1574. feed(':new<cr><c-w><c-w>')
  1575. screen:expect {
  1576. grid = [[
  1577. |
  1578. {1:~ }|
  1579. {2:[No Name] }|
  1580. ^ |
  1581. {1:~ }|
  1582. {3:[No Name] }|
  1583. :new |
  1584. ]],
  1585. }
  1586. feed(':set colorcolumn=10 | digraphs<cr>')
  1587. screen:expect {
  1588. grid = [[
  1589. :set colorcolumn=10 | digraphs |
  1590. NU {18:^@} 10 SH {18:^A} 1 SX {18:^B} 2 EX {18:^C} 3 |
  1591. ET {18:^D} 4 EQ {18:^E} 5 AK {18:^F} 6 BL {18:^G} 7 |
  1592. BS {18:^H} 8 HT {18:^I} 9 LF {18:^@} 10 VT {18:^K} 11 |
  1593. FF {18:^L} 12 CR {18:^M} 13 SO {18:^N} 14 SI {18:^O} 15 |
  1594. DL {18:^P} 16 D1 {18:^Q} 17 D2 {18:^R} 18 D3 {18:^S} 19 |
  1595. {6:-- More --}^ |
  1596. ]],
  1597. }
  1598. feed('q')
  1599. screen:expect {
  1600. grid = [[
  1601. |
  1602. {1:~ }|
  1603. {2:[No Name] }|
  1604. ^ {100: } |
  1605. {1:~ }|
  1606. {3:[No Name] }|
  1607. |
  1608. ]],
  1609. }
  1610. -- edge case: just covers statusline
  1611. feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>')
  1612. screen:expect {
  1613. grid = [[
  1614. {9:E5108: Error executing lua [string ":lua"]:1: x} |
  1615. |
  1616. {9:x} |
  1617. {9:stack traceback:} |
  1618. {9: [C]: in function 'error'} |
  1619. {9: [string ":lua"]:1: in main chunk} |
  1620. {6:Press ENTER or type command to continue}^ |
  1621. ]],
  1622. }
  1623. feed('<cr>')
  1624. screen:expect {
  1625. grid = [[
  1626. |
  1627. {1:~ }|
  1628. {2:[No Name] }|
  1629. ^ {100: } |
  1630. {1:~ }|
  1631. {3:[No Name] }|
  1632. |
  1633. ]],
  1634. }
  1635. -- edge case: just covers lowest window line
  1636. feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>')
  1637. screen:expect {
  1638. grid = [[
  1639. {9:E5108: Error executing lua [string ":lua"]:1: x} |
  1640. |*2
  1641. {9:x} |
  1642. {9:stack traceback:} |
  1643. {9: [C]: in function 'error'} |
  1644. {6:-- More --}^ |
  1645. ]],
  1646. }
  1647. feed('<cr>')
  1648. screen:expect {
  1649. grid = [[
  1650. |*2
  1651. {9:x} |
  1652. {9:stack traceback:} |
  1653. {9: [C]: in function 'error'} |
  1654. {9: [string ":lua"]:1: in main chunk} |
  1655. {6:Press ENTER or type command to continue}^ |
  1656. ]],
  1657. }
  1658. end)
  1659. it('supports nvim_echo messages with multiple attrs', function()
  1660. async_meths.nvim_echo(
  1661. { { 'wow, ', 'Search' }, { 'such\n\nvery ', 'ErrorMsg' }, { 'color', 'LineNr' } },
  1662. true,
  1663. {}
  1664. )
  1665. screen:expect {
  1666. grid = [[
  1667. |
  1668. {1:~ }|
  1669. {3: }|
  1670. {10:wow, }{9:such} |
  1671. |
  1672. {9:very }{8:color} |
  1673. {6:Press ENTER or type command to continue}^ |
  1674. ]],
  1675. }
  1676. feed '<cr>'
  1677. screen:expect {
  1678. grid = [[
  1679. ^ |
  1680. {1:~ }|*5
  1681. |
  1682. ]],
  1683. }
  1684. feed ':messages<cr>'
  1685. screen:expect {
  1686. grid = [[
  1687. |
  1688. {1:~ }|
  1689. {3: }|
  1690. {10:wow, }{9:such} |
  1691. |
  1692. {9:very }{8:color} |
  1693. {6:Press ENTER or type command to continue}^ |
  1694. ]],
  1695. }
  1696. end)
  1697. it('supports nvim_echo messages with emoji', function()
  1698. -- stylua: ignore
  1699. async_meths.nvim_echo(
  1700. { { 'wow, 🏳️‍⚧️🧑‍🌾❤️😂🏴‍☠️\nvariant ❤️ one\nvariant ❤ two' } }, true, {}
  1701. )
  1702. screen:expect([[
  1703. |
  1704. {1:~ }|
  1705. {3: }|
  1706. wow, 🏳️‍⚧️🧑‍🌾❤️😂🏴‍☠️ |
  1707. variant ❤️ one |
  1708. variant ❤ two |
  1709. {6:Press ENTER or type command to continue}^ |
  1710. ]])
  1711. feed '<cr>'
  1712. screen:expect([[
  1713. ^ |
  1714. {1:~ }|*5
  1715. |
  1716. ]])
  1717. feed ':messages<cr>'
  1718. screen:expect([[
  1719. |
  1720. {1:~ }|
  1721. {3: }|
  1722. wow, 🏳️‍⚧️🧑‍🌾❤️😂🏴‍☠️ |
  1723. variant ❤️ one |
  1724. variant ❤ two |
  1725. {6:Press ENTER or type command to continue}^ |
  1726. ]])
  1727. end)
  1728. it('prints lines in Ex mode correctly with a burst of carriage returns #19341', function()
  1729. command('set number')
  1730. api.nvim_buf_set_lines(0, 0, 0, true, { 'aaa', 'bbb', 'ccc' })
  1731. feed('gggQ<CR><CR>1<CR><CR>vi')
  1732. screen:expect([[
  1733. Entering Ex mode. Type "visual" to go to Normal mode. |
  1734. {8: 2 }bbb |
  1735. {8: 3 }ccc |
  1736. :1 |
  1737. {8: 1 }aaa |
  1738. {8: 2 }bbb |
  1739. :vi^ |
  1740. ]])
  1741. feed('<CR>')
  1742. screen:expect([[
  1743. {8: 1 }aaa |
  1744. {8: 2 }^bbb |
  1745. {8: 3 }ccc |
  1746. {8: 4 } |
  1747. {1:~ }|*2
  1748. |
  1749. ]])
  1750. end)
  1751. describe('echo messages are shown when immediately followed by', function()
  1752. --- @param to_block string command to cause a blocking wait
  1753. --- @param to_unblock number|string number: timeout for blocking screen
  1754. --- string: keys to stop the blocking wait
  1755. local function test_flush_before_block(to_block, to_unblock)
  1756. local timeout = type(to_unblock) == 'number' and to_unblock or nil
  1757. exec(([[
  1758. func PrintAndWait()
  1759. echon "aaa\nbbb"
  1760. %s
  1761. echon "\nccc"
  1762. endfunc
  1763. ]]):format(to_block))
  1764. feed(':call PrintAndWait()<CR>')
  1765. screen:expect {
  1766. grid = [[
  1767. |
  1768. {1:~ }|*3
  1769. {3: }|
  1770. aaa |
  1771. bbb^ |
  1772. ]],
  1773. timeout = timeout,
  1774. }
  1775. if type(to_unblock) == 'string' then
  1776. feed(to_unblock)
  1777. end
  1778. screen:expect {
  1779. grid = [[
  1780. |
  1781. {1:~ }|
  1782. {3: }|
  1783. aaa |
  1784. bbb |
  1785. ccc |
  1786. {6:Press ENTER or type command to continue}^ |
  1787. ]],
  1788. }
  1789. end
  1790. it('getchar()', function()
  1791. test_flush_before_block([[call getchar()]], 'k')
  1792. end)
  1793. it('wait()', function()
  1794. test_flush_before_block([[call wait(300, '0')]], 100)
  1795. end)
  1796. it('lua vim.wait()', function()
  1797. test_flush_before_block([[lua vim.wait(300, function() end)]], 100)
  1798. end)
  1799. end)
  1800. it('consecutive calls to win_move_statusline() work after multiline message #21014', function()
  1801. async_meths.nvim_exec(
  1802. [[
  1803. echo "\n"
  1804. call win_move_statusline(0, -4)
  1805. call win_move_statusline(0, 4)
  1806. ]],
  1807. false
  1808. )
  1809. screen:expect([[
  1810. |
  1811. {1:~ }|*3
  1812. {3: }|
  1813. |
  1814. {6:Press ENTER or type command to continue}^ |
  1815. ]])
  1816. feed('<CR>')
  1817. screen:expect([[
  1818. ^ |
  1819. {1:~ }|*5
  1820. |
  1821. ]])
  1822. eq(1, api.nvim_get_option_value('cmdheight', {}))
  1823. end)
  1824. it('using nvim_echo in VimResized does not cause hit-enter prompt #26139', function()
  1825. command([[au VimResized * lua vim.api.nvim_echo({ { '123456' } }, true, {})]])
  1826. screen:try_resize(60, 5)
  1827. screen:expect([[
  1828. ^ |
  1829. {1:~ }|*3
  1830. |
  1831. ]])
  1832. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1833. end)
  1834. it('bottom of screen is cleared after increasing &cmdheight #20360', function()
  1835. command('set laststatus=2')
  1836. screen:expect([[
  1837. ^ |
  1838. {1:~ }|*4
  1839. {3:[No Name] }|
  1840. |
  1841. ]])
  1842. command('set cmdheight=4')
  1843. screen:expect([[
  1844. ^ |
  1845. {1:~ }|
  1846. {3:[No Name] }|
  1847. |*4
  1848. ]])
  1849. end)
  1850. it('supports :intro with cmdheight=0 #26505', function()
  1851. screen:try_resize(80, 24)
  1852. command('set cmdheight=0')
  1853. feed(':intro<CR>')
  1854. screen:expect([[
  1855. |*5
  1856. {MATCH:.*}|
  1857. |
  1858. Nvim is open source and freely distributable |
  1859. https://neovim.io/#chat |
  1860. |
  1861. type :help nvim{18:<Enter>} if you are new! |
  1862. type :checkhealth{18:<Enter>} to optimize Nvim |
  1863. type :q{18:<Enter>} to exit |
  1864. type :help{18:<Enter>} for help |
  1865. |
  1866. {MATCH: +}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}|
  1867. |
  1868. Help poor children in Uganda! |
  1869. type :help iccf{18:<Enter>} for information |
  1870. |*2
  1871. {3: }|
  1872. |
  1873. {6:Press ENTER or type command to continue}^ |
  1874. ]])
  1875. feed('<CR>')
  1876. assert_alive()
  1877. end)
  1878. end)
  1879. it('calling screenstring() after redrawing between messages without UI #20999', function()
  1880. clear()
  1881. exec([[
  1882. echo repeat('a', 100)
  1883. redraw
  1884. echo "\n"
  1885. call screenstring(1, 1)
  1886. ]])
  1887. assert_alive()
  1888. end)
  1889. describe('ui/ext_messages', function()
  1890. local screen
  1891. before_each(function()
  1892. clear { args_rm = { '--headless' }, args = { '--cmd', 'set shortmess-=I' } }
  1893. screen = Screen.new(80, 24, { rgb = true, ext_messages = true, ext_popupmenu = true })
  1894. end)
  1895. it('supports intro screen', function()
  1896. -- intro message is not externalized. But check that it still works.
  1897. -- Note parts of it depends on version or is indeterministic. We ignore those parts.
  1898. local introscreen = [[
  1899. ^ |
  1900. {1:~ }|*4
  1901. {MATCH:.*}|
  1902. {1:~ }|
  1903. {1:~ }Nvim is open source and freely distributable{1: }|
  1904. {1:~ }https://neovim.io/#chat{1: }|
  1905. {1:~ }|
  1906. {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }|
  1907. {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }|
  1908. {1:~ }type :q{18:<Enter>} to exit {1: }|
  1909. {1:~ }type :help{18:<Enter>} for help {1: }|
  1910. {1:~ }|
  1911. {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}|
  1912. {1:~ }|
  1913. {1:~ }Help poor children in Uganda!{1: }|
  1914. {1:~ }type :help iccf{18:<Enter>} for information {1: }|
  1915. {1:~ }|*5
  1916. ]]
  1917. local showmode = { { '-- INSERT --', 5, 11 } }
  1918. screen:expect(introscreen)
  1919. -- <c-l> (same as :mode) does _not_ clear intro message
  1920. feed('<c-l>i')
  1921. screen:expect { grid = introscreen, showmode = showmode }
  1922. -- opening a float without focus also does not
  1923. local win = api.nvim_open_win(api.nvim_create_buf(false, false), false, {
  1924. relative = 'editor',
  1925. height = 1,
  1926. width = 5,
  1927. row = 1,
  1928. col = 5,
  1929. })
  1930. screen:expect {
  1931. grid = [[
  1932. ^ |
  1933. {1:~ }{4: }{1: }|
  1934. {1:~ }|*3
  1935. {MATCH:.*}|
  1936. {1:~ }|
  1937. {1:~ }Nvim is open source and freely distributable{1: }|
  1938. {1:~ }https://neovim.io/#chat{1: }|
  1939. {1:~ }|
  1940. {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }|
  1941. {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }|
  1942. {1:~ }type :q{18:<Enter>} to exit {1: }|
  1943. {1:~ }type :help{18:<Enter>} for help {1: }|
  1944. {1:~ }|
  1945. {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}|
  1946. {1:~ }|
  1947. {1:~ }Help poor children in Uganda!{1: }|
  1948. {1:~ }type :help iccf{18:<Enter>} for information {1: }|
  1949. {1:~ }|*5
  1950. ]],
  1951. showmode = showmode,
  1952. }
  1953. api.nvim_win_close(win, true)
  1954. screen:expect { grid = introscreen, showmode = showmode }
  1955. -- but editing text does..
  1956. feed('x')
  1957. screen:expect {
  1958. grid = [[
  1959. x^ |
  1960. {1:~ }|*23
  1961. ]],
  1962. showmode = showmode,
  1963. }
  1964. feed('<esc>:intro<cr>')
  1965. screen:expect {
  1966. grid = [[
  1967. ^ |
  1968. |*4
  1969. {MATCH:.*}|
  1970. |
  1971. Nvim is open source and freely distributable |
  1972. https://neovim.io/#chat |
  1973. |
  1974. type :help nvim{18:<Enter>} if you are new! |
  1975. type :checkhealth{18:<Enter>} to optimize Nvim |
  1976. type :q{18:<Enter>} to exit |
  1977. type :help{18:<Enter>} for help |
  1978. |
  1979. {MATCH: +}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}|
  1980. |
  1981. Help poor children in Uganda! |
  1982. type :help iccf{18:<Enter>} for information |
  1983. |*5
  1984. ]],
  1985. cmdline = { { abort = false } },
  1986. messages = {
  1987. {
  1988. content = { { 'Press ENTER or type command to continue', 6, 18 } },
  1989. history = false,
  1990. kind = 'return_prompt',
  1991. },
  1992. },
  1993. }
  1994. feed('<cr>')
  1995. screen:expect {
  1996. grid = [[
  1997. ^x |
  1998. {1:~ }|*23
  1999. ]],
  2000. }
  2001. end)
  2002. it('clears intro screen when new buffer is active', function()
  2003. api.nvim_set_current_buf(api.nvim_create_buf(true, false))
  2004. screen:expect {
  2005. grid = [[
  2006. ^ |
  2007. {1:~ }|*23
  2008. ]],
  2009. }
  2010. end)
  2011. it('clears intro screen when new buffer is active in floating window', function()
  2012. local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 }
  2013. api.nvim_open_win(api.nvim_create_buf(false, false), true, win_opts)
  2014. screen:expect {
  2015. grid = [[
  2016. |
  2017. {1:~ }{4:^ }{1: }|
  2018. {1:~ }|*22
  2019. ]],
  2020. }
  2021. end)
  2022. it('clears intro screen when initial buffer is active in floating window', function()
  2023. local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 }
  2024. api.nvim_open_win(api.nvim_get_current_buf(), true, win_opts)
  2025. screen:expect {
  2026. grid = [[
  2027. |
  2028. {1:~ }{4:^ }{1: }|
  2029. {1:~ }|*22
  2030. ]],
  2031. }
  2032. end)
  2033. it('clears intro screen when initial window is converted to be floating', function()
  2034. exec_lua([[
  2035. local init_win_id = vim.api.nvim_get_current_win()
  2036. vim.cmd('split')
  2037. local win_opts = { relative = 'editor', height = 1, width = 5, row = 1, col = 5 }
  2038. vim.api.nvim_win_set_config(init_win_id, win_opts)
  2039. vim.api.nvim_set_current_win(init_win_id)
  2040. ]])
  2041. screen:expect {
  2042. grid = [[
  2043. |
  2044. {1:~ }{4:^ }{1: }|
  2045. {1:~ }|*21
  2046. {2:[No Name] }|
  2047. ]],
  2048. }
  2049. end)
  2050. it('supports global statusline', function()
  2051. feed(':set laststatus=3<cr>')
  2052. feed(':sp<cr>')
  2053. feed(':set cmdheight<cr>')
  2054. screen:expect({
  2055. grid = [[
  2056. ^ |
  2057. {1:~ }|*10
  2058. ────────────────────────────────────────────────────────────────────────────────|
  2059. |
  2060. {1:~ }|*10
  2061. {3:[No Name] }|
  2062. ]],
  2063. cmdline = { { abort = false } },
  2064. messages = {
  2065. { content = { { ' cmdheight=0' } }, kind = 'list_cmd', history = false },
  2066. },
  2067. })
  2068. feed('<c-w>+')
  2069. feed(':set laststatus<cr>')
  2070. screen:expect({
  2071. grid = [[
  2072. ^ |
  2073. {1:~ }|*11
  2074. ────────────────────────────────────────────────────────────────────────────────|
  2075. |
  2076. {1:~ }|*9
  2077. {3:[No Name] }|
  2078. ]],
  2079. cmdline = { { abort = false } },
  2080. messages = {
  2081. { content = { { ' laststatus=3' } }, kind = 'list_cmd', history = false },
  2082. },
  2083. })
  2084. feed(':set mouse=a<cr>')
  2085. api.nvim_input_mouse('left', 'press', '', 0, 12, 10)
  2086. poke_eventloop()
  2087. api.nvim_input_mouse('left', 'drag', '', 0, 11, 10)
  2088. feed('<c-l>')
  2089. feed(':set cmdheight<cr>')
  2090. screen:expect({
  2091. grid = [[
  2092. ^ |
  2093. {1:~ }|*10
  2094. ────────────────────────────────────────────────────────────────────────────────|
  2095. |
  2096. {1:~ }|*10
  2097. {3:[No Name] }|
  2098. ]],
  2099. cmdline = { { abort = false } },
  2100. messages = {
  2101. { content = { { ' cmdheight=0' } }, kind = 'list_cmd', history = false },
  2102. },
  2103. })
  2104. end)
  2105. end)
  2106. it('ui/ext_multigrid supports intro screen', function()
  2107. clear { args_rm = { '--headless' }, args = { '--cmd', 'set shortmess-=I' } }
  2108. local screen = Screen.new(80, 24, { rgb = true, ext_multigrid = true })
  2109. screen:expect {
  2110. grid = [[
  2111. ## grid 1
  2112. [2:--------------------------------------------------------------------------------]|*23
  2113. [3:--------------------------------------------------------------------------------]|
  2114. ## grid 2
  2115. ^ |
  2116. {1:~ }|*4
  2117. {MATCH:.*}|
  2118. {1:~ }|
  2119. {1:~ }Nvim is open source and freely distributable{1: }|
  2120. {1:~ }https://neovim.io/#chat{1: }|
  2121. {1:~ }|
  2122. {1:~ }type :help nvim{18:<Enter>} if you are new! {1: }|
  2123. {1:~ }type :checkhealth{18:<Enter>} to optimize Nvim{1: }|
  2124. {1:~ }type :q{18:<Enter>} to exit {1: }|
  2125. {1:~ }type :help{18:<Enter>} for help {1: }|
  2126. {1:~ }|
  2127. {1:~{MATCH: +}}type :help news{18:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}|
  2128. {1:~ }|
  2129. {1:~ }Help poor children in Uganda!{1: }|
  2130. {1:~ }type :help iccf{18:<Enter>} for information {1: }|
  2131. {1:~ }|*4
  2132. ## grid 3
  2133. |
  2134. ]],
  2135. win_viewport = {
  2136. [2] = {
  2137. win = 1000,
  2138. topline = 0,
  2139. botline = 2,
  2140. curline = 0,
  2141. curcol = 0,
  2142. linecount = 1,
  2143. sum_scroll_delta = 0,
  2144. },
  2145. },
  2146. }
  2147. feed 'ix'
  2148. screen:expect {
  2149. grid = [[
  2150. ## grid 1
  2151. [2:--------------------------------------------------------------------------------]|*23
  2152. [3:--------------------------------------------------------------------------------]|
  2153. ## grid 2
  2154. x^ |
  2155. {1:~ }|*22
  2156. ## grid 3
  2157. {5:-- INSERT --} |
  2158. ]],
  2159. win_viewport = {
  2160. [2] = {
  2161. win = 1000,
  2162. topline = 0,
  2163. botline = 2,
  2164. curline = 0,
  2165. curcol = 1,
  2166. linecount = 1,
  2167. sum_scroll_delta = 0,
  2168. },
  2169. },
  2170. }
  2171. end)
  2172. describe('ui/msg_puts_printf', function()
  2173. it('output multibyte characters correctly', function()
  2174. local screen
  2175. local cmd = ''
  2176. local locale_dir = test_build_dir .. '/share/locale/ja/LC_MESSAGES'
  2177. clear({ env = { LANG = 'ja_JP.UTF-8' } })
  2178. screen = Screen.new(25, 5)
  2179. if is_os('win') then
  2180. if os.execute('chcp 932 > NUL 2>&1') ~= 0 then
  2181. pending('missing japanese language features', function() end)
  2182. return
  2183. else
  2184. cmd = 'chcp 932 > NUL & '
  2185. end
  2186. else
  2187. if exc_exec('lang ja_JP.UTF-8') ~= 0 then
  2188. pending('Locale ja_JP.UTF-8 not supported', function() end)
  2189. return
  2190. end
  2191. end
  2192. os.execute('cmake -E make_directory ' .. locale_dir)
  2193. os.execute(
  2194. 'cmake -E copy ' .. test_build_dir .. '/src/nvim/po/ja.mo ' .. locale_dir .. '/nvim.mo'
  2195. )
  2196. cmd = cmd .. '"' .. nvim_prog .. '" -u NONE -i NONE -Es -V1'
  2197. command([[call jobstart(']] .. cmd .. [[',{'term':v:true})]])
  2198. screen:expect([[
  2199. ^Exモードに入ります。ノー |
  2200. マルモードに戻るには "vis|
  2201. ual" と入力してください。|
  2202. : |
  2203. |
  2204. ]])
  2205. os.execute('cmake -E remove_directory ' .. test_build_dir .. '/share')
  2206. end)
  2207. end)
  2208. describe('pager', function()
  2209. local screen
  2210. before_each(function()
  2211. clear()
  2212. screen = Screen.new(35, 8)
  2213. screen:set_default_attr_ids({
  2214. [1] = { bold = true, foreground = Screen.colors.Blue1 },
  2215. [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
  2216. [3] = {
  2217. foreground = Screen.colors.Grey100,
  2218. background = Screen.colors.Red,
  2219. special = Screen.colors.Yellow,
  2220. },
  2221. [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
  2222. [5] = { special = Screen.colors.Yellow },
  2223. [6] = { special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4 },
  2224. [7] = { foreground = Screen.colors.Grey0, background = Screen.colors.Grey100 },
  2225. [8] = { foreground = Screen.colors.Gray90, background = Screen.colors.Grey100 },
  2226. [9] = { foreground = tonumber('0x00000c'), background = Screen.colors.Grey100 },
  2227. [10] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff') },
  2228. [11] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0x2b8452') },
  2229. [12] = { bold = true, reverse = true },
  2230. })
  2231. command('set more')
  2232. exec_lua(
  2233. '_G.x = ...',
  2234. [[
  2235. Lorem ipsum dolor sit amet, consectetur
  2236. adipisicing elit, sed do eiusmod tempor
  2237. incididunt ut labore et dolore magna aliqua.
  2238. Ut enim ad minim veniam, quis nostrud xercitation
  2239. ullamco laboris nisi ut
  2240. aliquip ex ea commodo consequat.]]
  2241. )
  2242. end)
  2243. it('can be quit with echon', function()
  2244. screen:try_resize(25, 5)
  2245. feed(':echon join(map(range(0, &lines*10), "v:val"), "\\n")<cr>')
  2246. screen:expect {
  2247. grid = [[
  2248. 0 |
  2249. 1 |
  2250. 2 |
  2251. 3 |
  2252. {4:-- More --}^ |
  2253. ]],
  2254. }
  2255. feed('q')
  2256. screen:expect {
  2257. grid = [[
  2258. ^ |
  2259. {1:~ }|*3
  2260. |
  2261. ]],
  2262. }
  2263. end)
  2264. it('can be quit with Lua #11224 #16537', function()
  2265. screen:try_resize(40, 5)
  2266. feed(':lua for i=0,10 do print(i) end<cr>')
  2267. screen:expect {
  2268. grid = [[
  2269. 0 |
  2270. 1 |
  2271. 2 |
  2272. 3 |
  2273. {4:-- More --}^ |
  2274. ]],
  2275. }
  2276. feed('q')
  2277. screen:expect {
  2278. grid = [[
  2279. ^ |
  2280. {1:~ }|*3
  2281. |
  2282. ]],
  2283. }
  2284. feed(':mess<cr>')
  2285. screen:expect {
  2286. grid = [[
  2287. 0 |
  2288. 1 |
  2289. 2 |
  2290. 3 |
  2291. {4:-- More --}^ |
  2292. ]],
  2293. }
  2294. feed('G')
  2295. screen:expect {
  2296. grid = [[
  2297. 7 |
  2298. 8 |
  2299. 9 |
  2300. 10 |
  2301. {4:Press ENTER or type command to continue}^ |
  2302. ]],
  2303. }
  2304. feed('<cr>')
  2305. end)
  2306. it('handles wrapped lines with line scroll', function()
  2307. feed(':lua error(_G.x)<cr>')
  2308. screen:expect {
  2309. grid = [[
  2310. {2:E5108: Error executing lua [string }|
  2311. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2312. {2:et, consectetur} |
  2313. {2:adipisicing elit, sed do eiusmod te}|
  2314. {2:mpor} |
  2315. {2:incididunt ut labore et dolore magn}|
  2316. {2:a aliqua.} |
  2317. {4:-- More --}^ |
  2318. ]],
  2319. }
  2320. feed('j')
  2321. screen:expect {
  2322. grid = [[
  2323. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2324. {2:et, consectetur} |
  2325. {2:adipisicing elit, sed do eiusmod te}|
  2326. {2:mpor} |
  2327. {2:incididunt ut labore et dolore magn}|
  2328. {2:a aliqua.} |
  2329. {2:Ut enim ad minim veniam, quis nostr}|
  2330. {4:-- More --}^ |
  2331. ]],
  2332. }
  2333. feed('k')
  2334. screen:expect {
  2335. grid = [[
  2336. {2:E5108: Error executing lua [string }|
  2337. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2338. {2:et, consectetur} |
  2339. {2:adipisicing elit, sed do eiusmod te}|
  2340. {2:mpor} |
  2341. {2:incididunt ut labore et dolore magn}|
  2342. {2:a aliqua.} |
  2343. {4:-- More --}^ |
  2344. ]],
  2345. }
  2346. feed('j')
  2347. screen:expect {
  2348. grid = [[
  2349. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2350. {2:et, consectetur} |
  2351. {2:adipisicing elit, sed do eiusmod te}|
  2352. {2:mpor} |
  2353. {2:incididunt ut labore et dolore magn}|
  2354. {2:a aliqua.} |
  2355. {2:Ut enim ad minim veniam, quis nostr}|
  2356. {4:-- More --}^ |
  2357. ]],
  2358. }
  2359. end)
  2360. it('handles wrapped lines with page scroll', function()
  2361. feed(':lua error(_G.x)<cr>')
  2362. screen:expect {
  2363. grid = [[
  2364. {2:E5108: Error executing lua [string }|
  2365. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2366. {2:et, consectetur} |
  2367. {2:adipisicing elit, sed do eiusmod te}|
  2368. {2:mpor} |
  2369. {2:incididunt ut labore et dolore magn}|
  2370. {2:a aliqua.} |
  2371. {4:-- More --}^ |
  2372. ]],
  2373. }
  2374. feed('d')
  2375. screen:expect {
  2376. grid = [[
  2377. {2:mpor} |
  2378. {2:incididunt ut labore et dolore magn}|
  2379. {2:a aliqua.} |
  2380. {2:Ut enim ad minim veniam, quis nostr}|
  2381. {2:ud xercitation} |
  2382. {2:ullamco laboris nisi ut} |
  2383. {2:aliquip ex ea commodo consequat.} |
  2384. {4:-- More --}^ |
  2385. ]],
  2386. }
  2387. feed('u')
  2388. screen:expect {
  2389. grid = [[
  2390. {2:E5108: Error executing lua [string }|
  2391. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2392. {2:et, consectetur} |
  2393. {2:adipisicing elit, sed do eiusmod te}|
  2394. {2:mpor} |
  2395. {2:incididunt ut labore et dolore magn}|
  2396. {2:a aliqua.} |
  2397. {4:-- More --}^ |
  2398. ]],
  2399. }
  2400. feed('d')
  2401. screen:expect {
  2402. grid = [[
  2403. {2:mpor} |
  2404. {2:incididunt ut labore et dolore magn}|
  2405. {2:a aliqua.} |
  2406. {2:Ut enim ad minim veniam, quis nostr}|
  2407. {2:ud xercitation} |
  2408. {2:ullamco laboris nisi ut} |
  2409. {2:aliquip ex ea commodo consequat.} |
  2410. {4:-- More --}^ |
  2411. ]],
  2412. }
  2413. end)
  2414. it('handles wrapped lines with line scroll and MsgArea highlight', function()
  2415. command('hi MsgArea guisp=Yellow')
  2416. feed(':lua error(_G.x)<cr>')
  2417. screen:expect {
  2418. grid = [[
  2419. {3:E5108: Error executing lua [string }|
  2420. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2421. {3:et, consectetur}{5: }|
  2422. {3:adipisicing elit, sed do eiusmod te}|
  2423. {3:mpor}{5: }|
  2424. {3:incididunt ut labore et dolore magn}|
  2425. {3:a aliqua.}{5: }|
  2426. {6:-- More --}{5:^ }|
  2427. ]],
  2428. }
  2429. feed('j')
  2430. screen:expect {
  2431. grid = [[
  2432. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2433. {3:et, consectetur}{5: }|
  2434. {3:adipisicing elit, sed do eiusmod te}|
  2435. {3:mpor}{5: }|
  2436. {3:incididunt ut labore et dolore magn}|
  2437. {3:a aliqua.}{5: }|
  2438. {3:Ut enim ad minim veniam, quis nostr}|
  2439. {6:-- More --}{5:^ }|
  2440. ]],
  2441. }
  2442. feed('k')
  2443. screen:expect {
  2444. grid = [[
  2445. {3:E5108: Error executing lua [string }|
  2446. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2447. {3:et, consectetur}{5: }|
  2448. {3:adipisicing elit, sed do eiusmod te}|
  2449. {3:mpor}{5: }|
  2450. {3:incididunt ut labore et dolore magn}|
  2451. {3:a aliqua.}{5: }|
  2452. {6:-- More --}{5:^ }|
  2453. ]],
  2454. }
  2455. feed('j')
  2456. screen:expect {
  2457. grid = [[
  2458. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2459. {3:et, consectetur}{5: }|
  2460. {3:adipisicing elit, sed do eiusmod te}|
  2461. {3:mpor}{5: }|
  2462. {3:incididunt ut labore et dolore magn}|
  2463. {3:a aliqua.}{5: }|
  2464. {3:Ut enim ad minim veniam, quis nostr}|
  2465. {6:-- More --}{5:^ }|
  2466. ]],
  2467. }
  2468. end)
  2469. it('handles wrapped lines with page scroll and MsgArea highlight', function()
  2470. command('hi MsgArea guisp=Yellow')
  2471. feed(':lua error(_G.x)<cr>')
  2472. screen:expect {
  2473. grid = [[
  2474. {3:E5108: Error executing lua [string }|
  2475. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2476. {3:et, consectetur}{5: }|
  2477. {3:adipisicing elit, sed do eiusmod te}|
  2478. {3:mpor}{5: }|
  2479. {3:incididunt ut labore et dolore magn}|
  2480. {3:a aliqua.}{5: }|
  2481. {6:-- More --}{5:^ }|
  2482. ]],
  2483. }
  2484. feed('d')
  2485. screen:expect {
  2486. grid = [[
  2487. {3:mpor}{5: }|
  2488. {3:incididunt ut labore et dolore magn}|
  2489. {3:a aliqua.}{5: }|
  2490. {3:Ut enim ad minim veniam, quis nostr}|
  2491. {3:ud xercitation}{5: }|
  2492. {3:ullamco laboris nisi ut}{5: }|
  2493. {3:aliquip ex ea commodo consequat.}{5: }|
  2494. {6:-- More --}{5:^ }|
  2495. ]],
  2496. }
  2497. feed('u')
  2498. screen:expect {
  2499. grid = [[
  2500. {3:E5108: Error executing lua [string }|
  2501. {3:":lua"]:1: Lorem ipsum dolor sit am}|
  2502. {3:et, consectetur}{5: }|
  2503. {3:adipisicing elit, sed do eiusmod te}|
  2504. {3:mpor}{5: }|
  2505. {3:incididunt ut labore et dolore magn}|
  2506. {3:a aliqua.}{5: }|
  2507. {6:-- More --}{5:^ }|
  2508. ]],
  2509. }
  2510. feed('d')
  2511. screen:expect {
  2512. grid = [[
  2513. {3:mpor}{5: }|
  2514. {3:incididunt ut labore et dolore magn}|
  2515. {3:a aliqua.}{5: }|
  2516. {3:Ut enim ad minim veniam, quis nostr}|
  2517. {3:ud xercitation}{5: }|
  2518. {3:ullamco laboris nisi ut}{5: }|
  2519. {3:aliquip ex ea commodo consequat.}{5: }|
  2520. {6:-- More --}{5:^ }|
  2521. ]],
  2522. }
  2523. end)
  2524. it('preserves MsgArea highlighting after more prompt', function()
  2525. screen:try_resize(70, 6)
  2526. command('hi MsgArea guisp=Yellow')
  2527. command('map x Lorem ipsum labore et dolore magna aliqua')
  2528. command('map y adipisicing elit')
  2529. command('map z incididunt ut')
  2530. command('map a labore et dolore')
  2531. command('map b ex ea commodo')
  2532. command('map xx yy')
  2533. command('map xy yz')
  2534. feed(':map<cr>')
  2535. screen:expect {
  2536. grid = [[
  2537. {5: a labore et dolore }|
  2538. {5: b ex ea commodo }|
  2539. {5: xy yz }|
  2540. {5: xx yy }|
  2541. {5: x Lorem ipsum labore et dolore magna aliqua }|
  2542. {6:-- More --}{5:^ }|
  2543. ]],
  2544. }
  2545. feed('j')
  2546. screen:expect {
  2547. grid = [[
  2548. {5: b ex ea commodo }|
  2549. {5: xy yz }|
  2550. {5: xx yy }|
  2551. {5: x Lorem ipsum labore et dolore magna aliqua }|
  2552. {5: y adipisicing elit }|
  2553. {6:-- More --}{5:^ }|
  2554. ]],
  2555. }
  2556. feed('j')
  2557. screen:expect {
  2558. grid = [[
  2559. {5: xy yz }|
  2560. {5: xx yy }|
  2561. {5: x Lorem ipsum labore et dolore magna aliqua }|
  2562. {5: y adipisicing elit }|
  2563. {5: z incididunt ut }|
  2564. {6:Press ENTER or type command to continue}{5:^ }|
  2565. ]],
  2566. }
  2567. end)
  2568. it('clears "-- more --" message', function()
  2569. command('hi MsgArea guisp=Yellow blend=10')
  2570. feed(':echon join(range(20), "\\n")<cr>')
  2571. screen:expect {
  2572. grid = [[
  2573. {7:0}{8: }|
  2574. {9:1}{10: }|
  2575. {9:2}{10: }|
  2576. {9:3}{10: }|
  2577. {9:4}{10: }|
  2578. {9:5}{10: }|
  2579. {9:6}{10: }|
  2580. {11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
  2581. ]],
  2582. }
  2583. feed('j')
  2584. screen:expect {
  2585. grid = [[
  2586. {7:1}{8: }|
  2587. {9:2}{10: }|
  2588. {9:3}{10: }|
  2589. {9:4}{10: }|
  2590. {9:5}{10: }|
  2591. {9:6}{10: }|
  2592. {9:7}{10: }|
  2593. {11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
  2594. ]],
  2595. }
  2596. feed('k')
  2597. screen:expect {
  2598. grid = [[
  2599. {7:0}{8: }|
  2600. {9:1}{10: }|
  2601. {9:2}{10: }|
  2602. {9:3}{10: }|
  2603. {9:4}{10: }|
  2604. {9:5}{10: }|
  2605. {9:6}{10: }|
  2606. {11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
  2607. ]],
  2608. }
  2609. feed('j')
  2610. screen:expect {
  2611. grid = [[
  2612. {7:1}{8: }|
  2613. {9:2}{10: }|
  2614. {9:3}{10: }|
  2615. {9:4}{10: }|
  2616. {9:5}{10: }|
  2617. {9:6}{10: }|
  2618. {9:7}{10: }|
  2619. {11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
  2620. ]],
  2621. }
  2622. end)
  2623. it('with :!cmd does not crash on resize', function()
  2624. skip(fn.executable('sleep') == 0, 'missing "sleep" command')
  2625. feed(':!sleep 1<cr>')
  2626. screen:expect {
  2627. grid = [[
  2628. |
  2629. {1:~ }|*4
  2630. {12: }|
  2631. :!sleep 1 |
  2632. |
  2633. ]],
  2634. }
  2635. -- not processed while command is executing
  2636. async_meths.nvim_ui_try_resize(35, 5)
  2637. -- TODO(bfredl): ideally it should be processed just
  2638. -- before the "press ENTER" prompt though
  2639. screen:expect {
  2640. grid = [[
  2641. |
  2642. {1:~ }|*2
  2643. {12: }|
  2644. :!sleep 1 |
  2645. |
  2646. {4:Press ENTER or type command to cont}|
  2647. {4:inue}^ |
  2648. ]],
  2649. }
  2650. feed('<cr>')
  2651. screen:expect {
  2652. grid = [[
  2653. ^ |
  2654. {1:~ }|*3
  2655. |
  2656. ]],
  2657. }
  2658. end)
  2659. it('can be resized', function()
  2660. feed(':lua error(_G.x)<cr>')
  2661. screen:expect {
  2662. grid = [[
  2663. {2:E5108: Error executing lua [string }|
  2664. {2:":lua"]:1: Lorem ipsum dolor sit am}|
  2665. {2:et, consectetur} |
  2666. {2:adipisicing elit, sed do eiusmod te}|
  2667. {2:mpor} |
  2668. {2:incididunt ut labore et dolore magn}|
  2669. {2:a aliqua.} |
  2670. {4:-- More --}^ |
  2671. ]],
  2672. }
  2673. -- responds to resize, but text is not reflown
  2674. screen:try_resize(45, 5)
  2675. screen:expect {
  2676. grid = [[
  2677. {2:adipisicing elit, sed do eiusmod te} |
  2678. {2:mpor} |
  2679. {2:incididunt ut labore et dolore magn} |
  2680. {2:a aliqua.} |
  2681. {4:-- More --}^ |
  2682. ]],
  2683. }
  2684. -- can create empty space, as the command hasn't output the text below yet.
  2685. -- text is not reflown; existing lines get cut
  2686. screen:try_resize(30, 12)
  2687. screen:expect {
  2688. grid = [[
  2689. :lua error(_G.x) |
  2690. {2:E5108: Error executing lua [st}|
  2691. {2:":lua"]:1: Lorem ipsum dolor s}|
  2692. {2:et, consectetur} |
  2693. {2:adipisicing elit, sed do eiusm}|
  2694. {2:mpore} |
  2695. {2:incididunt ut labore et dolore}|
  2696. {2:a aliqua.} |
  2697. |*3
  2698. {4:-- More --}^ |
  2699. ]],
  2700. }
  2701. -- continues in a mostly consistent state, but only new lines are
  2702. -- wrapped at the new screen size.
  2703. feed('<cr>')
  2704. screen:expect {
  2705. grid = [[
  2706. {2:E5108: Error executing lua [st}|
  2707. {2:":lua"]:1: Lorem ipsum dolor s}|
  2708. {2:et, consectetur} |
  2709. {2:adipisicing elit, sed do eiusm}|
  2710. {2:mpore} |
  2711. {2:incididunt ut labore et dolore}|
  2712. {2:a aliqua.} |
  2713. {2:Ut enim ad minim veniam, quis }|
  2714. {2:nostrud xercitation} |
  2715. {2:ullamco laboris nisi ut} |
  2716. {2:aliquip ex ea commodo consequa}|
  2717. {4:-- More --}^ |
  2718. ]],
  2719. }
  2720. feed('<cr>')
  2721. screen:expect {
  2722. grid = [[
  2723. {2:":lua"]:1: Lorem ipsum dolor s}|
  2724. {2:et, consectetur} |
  2725. {2:adipisicing elit, sed do eiusm}|
  2726. {2:mpore} |
  2727. {2:incididunt ut labore et dolore}|
  2728. {2:a aliqua.} |
  2729. {2:Ut enim ad minim veniam, quis }|
  2730. {2:nostrud xercitation} |
  2731. {2:ullamco laboris nisi ut} |
  2732. {2:aliquip ex ea commodo consequa}|
  2733. {2:t.} |
  2734. {4:-- More --}^ |
  2735. ]],
  2736. }
  2737. feed('q')
  2738. screen:expect {
  2739. grid = [[
  2740. ^ |
  2741. {1:~ }|*10
  2742. |
  2743. ]],
  2744. }
  2745. end)
  2746. it('with cmdheight=0 does not crash with g<', function()
  2747. command('set cmdheight=0')
  2748. feed(':ls<cr>')
  2749. screen:expect {
  2750. grid = [[
  2751. |
  2752. {1:~ }|
  2753. {12: }|
  2754. :ls |
  2755. 1 %a "[No Name]" |
  2756. line 1 |
  2757. {4:Press ENTER or type command to cont}|
  2758. {4:inue}^ |
  2759. ]],
  2760. }
  2761. feed('<cr>')
  2762. screen:expect {
  2763. grid = [[
  2764. ^ |
  2765. {1:~ }|*7
  2766. ]],
  2767. }
  2768. feed('g<lt>')
  2769. screen:expect {
  2770. grid = [[
  2771. |
  2772. {1:~ }|
  2773. {12: }|
  2774. :ls |
  2775. 1 %a "[No Name]" |
  2776. line 1 |
  2777. {4:Press ENTER or type command to cont}|
  2778. {4:inue}^ |
  2779. ]],
  2780. }
  2781. feed('<cr>')
  2782. screen:expect {
  2783. grid = [[
  2784. ^ |
  2785. {1:~ }|*7
  2786. ]],
  2787. }
  2788. end)
  2789. it('g< shows blank line from :echo properly', function()
  2790. screen:try_resize(60, 8)
  2791. feed([[:echo 1 | echo "\n" | echo 2<CR>]])
  2792. screen:expect([[
  2793. |
  2794. {1:~ }|*2
  2795. {12: }|
  2796. 1 |
  2797. |
  2798. 2 |
  2799. {4:Press ENTER or type command to continue}^ |
  2800. ]])
  2801. feed('<CR>')
  2802. screen:expect([[
  2803. ^ |
  2804. {1:~ }|*6
  2805. |
  2806. ]])
  2807. feed('g<lt>')
  2808. screen:expect([[
  2809. |
  2810. {1:~ }|
  2811. {12: }|
  2812. :echo 1 | echo "\n" | echo 2 |
  2813. 1 |
  2814. |
  2815. 2 |
  2816. {4:Press ENTER or type command to continue}^ |
  2817. ]])
  2818. feed('<CR>')
  2819. screen:expect([[
  2820. ^ |
  2821. {1:~ }|*6
  2822. |
  2823. ]])
  2824. end)
  2825. it('scrolling works properly when :echo output ends with newline', function()
  2826. screen:try_resize(60, 6)
  2827. feed([[:echo range(100)->join("\n") .. "\n"<CR>]])
  2828. screen:expect([[
  2829. 0 |
  2830. 1 |
  2831. 2 |
  2832. 3 |
  2833. 4 |
  2834. {4:-- More --}^ |
  2835. ]])
  2836. feed('G')
  2837. screen:expect([[
  2838. 96 |
  2839. 97 |
  2840. 98 |
  2841. 99 |
  2842. |
  2843. {4:Press ENTER or type command to continue}^ |
  2844. ]])
  2845. for _ = 1, 3 do
  2846. feed('k')
  2847. screen:expect([[
  2848. 95 |
  2849. 96 |
  2850. 97 |
  2851. 98 |
  2852. 99 |
  2853. {4:-- More --}^ |
  2854. ]])
  2855. feed('k')
  2856. screen:expect([[
  2857. 94 |
  2858. 95 |
  2859. 96 |
  2860. 97 |
  2861. 98 |
  2862. {4:-- More --}^ |
  2863. ]])
  2864. feed('j')
  2865. screen:expect([[
  2866. 95 |
  2867. 96 |
  2868. 97 |
  2869. 98 |
  2870. 99 |
  2871. {4:-- More --}^ |
  2872. ]])
  2873. feed('j')
  2874. screen:expect([[
  2875. 96 |
  2876. 97 |
  2877. 98 |
  2878. 99 |
  2879. |
  2880. {4:-- More --}^ |
  2881. ]])
  2882. feed('j')
  2883. screen:expect([[
  2884. 96 |
  2885. 97 |
  2886. 98 |
  2887. 99 |
  2888. |
  2889. {4:Press ENTER or type command to continue}^ |
  2890. ]])
  2891. end
  2892. end)
  2893. it('scrolling works properly when :!cmd output ends with newline #27902', function()
  2894. screen:try_resize(60, 6)
  2895. api.nvim_set_option_value('shell', testprg('shell-test'), {})
  2896. api.nvim_set_option_value('shellcmdflag', 'REP 100', {})
  2897. api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes
  2898. feed([[:!foo<CR>]])
  2899. screen:expect([[
  2900. 96: foo |
  2901. 97: foo |
  2902. 98: foo |
  2903. 99: foo |
  2904. |
  2905. {4:Press ENTER or type command to continue}^ |
  2906. ]])
  2907. for _ = 1, 3 do
  2908. feed('k')
  2909. screen:expect([[
  2910. 95: foo |
  2911. 96: foo |
  2912. 97: foo |
  2913. 98: foo |
  2914. 99: foo |
  2915. {4:-- More --}^ |
  2916. ]])
  2917. feed('k')
  2918. screen:expect([[
  2919. 94: foo |
  2920. 95: foo |
  2921. 96: foo |
  2922. 97: foo |
  2923. 98: foo |
  2924. {4:-- More --}^ |
  2925. ]])
  2926. feed('j')
  2927. screen:expect([[
  2928. 95: foo |
  2929. 96: foo |
  2930. 97: foo |
  2931. 98: foo |
  2932. 99: foo |
  2933. {4:-- More --}^ |
  2934. ]])
  2935. feed('j')
  2936. screen:expect([[
  2937. 96: foo |
  2938. 97: foo |
  2939. 98: foo |
  2940. 99: foo |
  2941. |
  2942. {4:-- More --}^ |
  2943. ]])
  2944. feed('j')
  2945. screen:expect([[
  2946. 96: foo |
  2947. 97: foo |
  2948. 98: foo |
  2949. 99: foo |
  2950. |
  2951. {4:Press ENTER or type command to continue}^ |
  2952. ]])
  2953. end
  2954. end)
  2955. end)
  2956. it('pager works in headless mode with UI attached', function()
  2957. skip(is_os('win'))
  2958. clear()
  2959. local child_server = assert(n.new_pipename())
  2960. fn.jobstart({ nvim_prog, '--clean', '--headless', '--listen', child_server })
  2961. retry(nil, nil, function()
  2962. neq(nil, vim.uv.fs_stat(child_server))
  2963. end)
  2964. local child_session = n.connect(child_server)
  2965. local child_screen = Screen.new(40, 6, nil, child_session)
  2966. child_screen._default_attr_ids = nil -- TODO: unskip with new color scheme
  2967. child_session:notify('nvim_command', [[echo range(100)->join("\n")]])
  2968. child_screen:expect([[
  2969. 0 |
  2970. 1 |
  2971. 2 |
  2972. 3 |
  2973. 4 |
  2974. -- More --^ |
  2975. ]])
  2976. child_session:request('nvim_input', 'G')
  2977. child_screen:expect([[
  2978. 95 |
  2979. 96 |
  2980. 97 |
  2981. 98 |
  2982. 99 |
  2983. Press ENTER or type command to continue^ |
  2984. ]])
  2985. child_session:request('nvim_input', 'g')
  2986. child_screen:expect([[
  2987. 0 |
  2988. 1 |
  2989. 2 |
  2990. 3 |
  2991. 4 |
  2992. -- More --^ |
  2993. ]])
  2994. end)