123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591 |
- -- TUI acceptance tests.
- -- Uses :terminal as a way to send keys and assert screen state.
- --
- -- "bracketed paste" terminal feature:
- -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode
- local t = require('test.testutil')
- local n = require('test.functional.testnvim')()
- local Screen = require('test.functional.ui.screen')
- local tt = require('test.functional.testterm')
- local eq = t.eq
- local feed_data = tt.feed_data
- local clear = n.clear
- local command = n.command
- local exec = n.exec
- local exec_lua = n.exec_lua
- local testprg = n.testprg
- local retry = t.retry
- local nvim_prog = n.nvim_prog
- local nvim_set = n.nvim_set
- local ok = t.ok
- local read_file = t.read_file
- local fn = n.fn
- local api = n.api
- local is_ci = t.is_ci
- local is_os = t.is_os
- local new_pipename = n.new_pipename
- local set_session = n.set_session
- local write_file = t.write_file
- local eval = n.eval
- local assert_log = t.assert_log
- local testlog = 'Xtest-tui-log'
- if t.skip(is_os('win')) then
- return
- end
- describe('TUI', function()
- local screen --[[@type test.functional.ui.screen]]
- local child_session --[[@type test.Session]]
- local child_exec_lua
- before_each(function()
- clear()
- local child_server = new_pipename()
- screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- nvim_set .. ' notermguicolors laststatus=2 background=dark',
- '--cmd',
- 'colorscheme vim',
- })
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]])
- child_session = n.connect(child_server)
- child_exec_lua = tt.make_lua_executor(child_session)
- end)
- -- Wait for mode in the child Nvim (avoid "typeahead race" #10826).
- local function wait_for_mode(mode)
- retry(nil, nil, function()
- local _, m = child_session:request('nvim_get_mode')
- eq(mode, m.mode)
- end)
- end
- -- Assert buffer contents in the child Nvim.
- local function expect_child_buf_lines(expected)
- assert(type({}) == type(expected))
- retry(nil, nil, function()
- local _, buflines = child_session:request('nvim_buf_get_lines', 0, 0, -1, false)
- eq(expected, buflines)
- end)
- end
- -- Ensure both child client and child server have processed pending events.
- local function poke_both_eventloop()
- child_exec_lua([[
- _G.termresponse = nil
- vim.api.nvim_create_autocmd('TermResponse', {
- once = true,
- callback = function(ev) _G.termresponse = ev.data end,
- })
- ]])
- feed_data('\027P0$r\027\\')
- retry(nil, nil, function()
- eq('\027P0$r', child_exec_lua('return _G.termresponse'))
- end)
- end
- it('rapid resize #7572 #7628', function()
- -- Need buffer rows to provoke the behavior.
- feed_data(':edit test/functional/fixtures/bigfile.txt\n')
- screen:expect([[
- ^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
- 0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
- 0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
- 0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
- {5:test/functional/fixtures/bigfile.txt }|
- :edit test/functional/fixtures/bigfile.txt |
- {3:-- TERMINAL --} |
- ]])
- command('call jobresize(b:terminal_job_id, 58, 9)')
- command('call jobresize(b:terminal_job_id, 62, 13)')
- command('call jobresize(b:terminal_job_id, 100, 42)')
- command('call jobresize(b:terminal_job_id, 37, 1000)')
- -- Resize to <5 columns.
- screen:try_resize(4, 44)
- command('call jobresize(b:terminal_job_id, 4, 1000)')
- -- Resize to 1 row, then to 1 column, then increase rows to 4.
- screen:try_resize(44, 1)
- command('call jobresize(b:terminal_job_id, 44, 1)')
- screen:try_resize(1, 1)
- command('call jobresize(b:terminal_job_id, 1, 1)')
- screen:try_resize(1, 4)
- command('call jobresize(b:terminal_job_id, 1, 4)')
- screen:try_resize(57, 17)
- command('call jobresize(b:terminal_job_id, 57, 17)')
- retry(nil, nil, function()
- eq({ true, 57 }, { child_session:request('nvim_win_get_width', 0) })
- end)
- end)
- it('accepts resize while pager is active', function()
- child_session:request(
- 'nvim_exec2',
- [[
- set more
- func! ManyErr()
- for i in range(20)
- echoerr "FAIL ".i
- endfor
- endfunc
- ]],
- {}
- )
- feed_data(':call ManyErr()\r')
- screen:expect {
- grid = [[
- {8:Error detected while processing function ManyErr:} |
- {11:line 2:} |
- {8:FAIL 0} |
- {8:FAIL 1} |
- {8:FAIL 2} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- screen:try_resize(50, 10)
- screen:expect {
- grid = [[
- :call ManyErr() |
- {8:Error detected while processing function ManyErr:} |
- {11:line 2:} |
- {8:FAIL 0} |
- {8:FAIL 1} |
- {8:FAIL 2} |
- |*2
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('j')
- screen:expect {
- grid = [[
- {8:Error detected while processing function ManyErr:} |
- {11:line 2:} |
- {8:FAIL 0} |
- {8:FAIL 1} |
- {8:FAIL 2} |
- {8:FAIL 3} |
- {8:FAIL 4} |
- {8:FAIL 5} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- screen:try_resize(50, 7)
- screen:expect {
- grid = [[
- {8:FAIL 1} |
- {8:FAIL 2} |
- {8:FAIL 3} |
- {8:FAIL 4} |
- {8:FAIL 5} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- screen:try_resize(50, 5)
- screen:expect {
- grid = [[
- {8:FAIL 3} |
- {8:FAIL 4} |
- {8:FAIL 5} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('g')
- screen:expect {
- grid = [[
- :call ManyErr() |
- {8:Error detected while processing function ManyErr:} |
- {11:line 2:} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- screen:try_resize(50, 10)
- screen:expect {
- grid = [[
- :call ManyErr() |
- {8:Error detected while processing function ManyErr:} |
- {11:line 2:} |
- {8:FAIL 0} |
- {8:FAIL 1} |
- {8:FAIL 2} |
- {8:FAIL 3} |
- {8:FAIL 4} |
- {10:-- More --}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('\003')
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*6
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- it('accepts basic utf-8 input', function()
- feed_data('iabc\ntest1\ntest2')
- screen:expect([[
- abc |
- test1 |
- test2^ |
- {4:~ }|
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027')
- screen:expect([[
- abc |
- test1 |
- test^2 |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('interprets leading <Esc> byte as ALT modifier in normal-mode', function()
- local keys = 'dfghjkl'
- for c in keys:gmatch('.') do
- feed_data(':nnoremap <a-' .. c .. '> ialt-' .. c .. '<cr><esc>\r')
- feed_data('\027' .. c)
- end
- screen:expect([[
- alt-j |
- alt-k |
- alt-l |
- ^ |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('gg')
- screen:expect([[
- ^alt-d |
- alt-f |
- alt-g |
- alt-h |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('interprets ESC+key as ALT chord in i_CTRL-V', function()
- -- Vim represents ALT/META by setting the "high bit" of the modified key:
- -- ALT+j inserts "ê". Nvim does not (#3982).
- feed_data('i\022\027j')
- screen:expect([[
- <M-j>^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('interprets <Esc>[27u as <Esc>', function()
- child_session:request(
- 'nvim_exec2',
- [[
- nnoremap <M-;> <Nop>
- nnoremap <Esc> AESC<Esc>
- nnoremap ; Asemicolon<Esc>
- ]],
- {}
- )
- feed_data('\027[27u;')
- screen:expect([[
- ESCsemicolo^n |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <Esc>; should be recognized as <M-;> when <M-;> is mapped
- feed_data('\027;')
- screen:expect_unchanged()
- end)
- it('interprets <Esc><Nul> as <M-C-Space> #17198', function()
- feed_data('i\022\027\000')
- screen:expect([[
- <M-C-Space>^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('accepts ASCII control sequences', function()
- feed_data('i')
- feed_data('\022\007') -- ctrl+g
- feed_data('\022\022') -- ctrl+v
- feed_data('\022\013') -- ctrl+m
- screen:expect([[
- {6:^G^V^M}^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- local function test_mouse_wheel(esc)
- child_session:request(
- 'nvim_exec2',
- [[
- set number nostartofline nowrap mousescroll=hor:1,ver:1
- call setline(1, repeat([join(range(10), '----')], 10))
- vsplit
- ]],
- {}
- )
- screen:expect([[
- {11: 1 }^0----1----2----3----4│{11: 1 }0----1----2----3----|
- {11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
- {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
- {11: 4 }0----1----2----3----4│{11: 4 }0----1----2----3----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelDown> in active window
- if esc then
- feed_data('\027[<65;8;1M')
- else
- api.nvim_input_mouse('wheel', 'down', '', 0, 0, 7)
- end
- screen:expect([[
- {11: 2 }^0----1----2----3----4│{11: 1 }0----1----2----3----|
- {11: 3 }0----1----2----3----4│{11: 2 }0----1----2----3----|
- {11: 4 }0----1----2----3----4│{11: 3 }0----1----2----3----|
- {11: 5 }0----1----2----3----4│{11: 4 }0----1----2----3----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelDown> in inactive window
- if esc then
- feed_data('\027[<65;48;1M')
- else
- api.nvim_input_mouse('wheel', 'down', '', 0, 0, 47)
- end
- screen:expect([[
- {11: 2 }^0----1----2----3----4│{11: 2 }0----1----2----3----|
- {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
- {11: 4 }0----1----2----3----4│{11: 4 }0----1----2----3----|
- {11: 5 }0----1----2----3----4│{11: 5 }0----1----2----3----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelRight> in active window
- if esc then
- feed_data('\027[<67;8;1M')
- else
- api.nvim_input_mouse('wheel', 'right', '', 0, 0, 7)
- end
- screen:expect([[
- {11: 2 }^----1----2----3----4-│{11: 2 }0----1----2----3----|
- {11: 3 }----1----2----3----4-│{11: 3 }0----1----2----3----|
- {11: 4 }----1----2----3----4-│{11: 4 }0----1----2----3----|
- {11: 5 }----1----2----3----4-│{11: 5 }0----1----2----3----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelRight> in inactive window
- if esc then
- feed_data('\027[<67;48;1M')
- else
- api.nvim_input_mouse('wheel', 'right', '', 0, 0, 47)
- end
- screen:expect([[
- {11: 2 }^----1----2----3----4-│{11: 2 }----1----2----3----4|
- {11: 3 }----1----2----3----4-│{11: 3 }----1----2----3----4|
- {11: 4 }----1----2----3----4-│{11: 4 }----1----2----3----4|
- {11: 5 }----1----2----3----4-│{11: 5 }----1----2----3----4|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelDown> in active window
- if esc then
- feed_data('\027[<69;8;1M')
- else
- api.nvim_input_mouse('wheel', 'down', 'S', 0, 0, 7)
- end
- screen:expect([[
- {11: 5 }^----1----2----3----4-│{11: 2 }----1----2----3----4|
- {11: 6 }----1----2----3----4-│{11: 3 }----1----2----3----4|
- {11: 7 }----1----2----3----4-│{11: 4 }----1----2----3----4|
- {11: 8 }----1----2----3----4-│{11: 5 }----1----2----3----4|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelDown> in inactive window
- if esc then
- feed_data('\027[<69;48;1M')
- else
- api.nvim_input_mouse('wheel', 'down', 'S', 0, 0, 47)
- end
- screen:expect([[
- {11: 5 }^----1----2----3----4-│{11: 5 }----1----2----3----4|
- {11: 6 }----1----2----3----4-│{11: 6 }----1----2----3----4|
- {11: 7 }----1----2----3----4-│{11: 7 }----1----2----3----4|
- {11: 8 }----1----2----3----4-│{11: 8 }----1----2----3----4|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelRight> in active window
- if esc then
- feed_data('\027[<71;8;1M')
- else
- api.nvim_input_mouse('wheel', 'right', 'S', 0, 0, 7)
- end
- screen:expect([[
- {11: 5 }^----6----7----8----9 │{11: 5 }----1----2----3----4|
- {11: 6 }----6----7----8----9 │{11: 6 }----1----2----3----4|
- {11: 7 }----6----7----8----9 │{11: 7 }----1----2----3----4|
- {11: 8 }----6----7----8----9 │{11: 8 }----1----2----3----4|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelRight> in inactive window
- if esc then
- feed_data('\027[<71;48;1M')
- else
- api.nvim_input_mouse('wheel', 'right', 'S', 0, 0, 47)
- end
- screen:expect([[
- {11: 5 }^----6----7----8----9 │{11: 5 }5----6----7----8----|
- {11: 6 }----6----7----8----9 │{11: 6 }5----6----7----8----|
- {11: 7 }----6----7----8----9 │{11: 7 }5----6----7----8----|
- {11: 8 }----6----7----8----9 │{11: 8 }5----6----7----8----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelUp> in active window
- if esc then
- feed_data('\027[<64;8;1M')
- else
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 7)
- end
- screen:expect([[
- {11: 4 }----6----7----8----9 │{11: 5 }5----6----7----8----|
- {11: 5 }^----6----7----8----9 │{11: 6 }5----6----7----8----|
- {11: 6 }----6----7----8----9 │{11: 7 }5----6----7----8----|
- {11: 7 }----6----7----8----9 │{11: 8 }5----6----7----8----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelUp> in inactive window
- if esc then
- feed_data('\027[<64;48;1M')
- else
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 47)
- end
- screen:expect([[
- {11: 4 }----6----7----8----9 │{11: 4 }5----6----7----8----|
- {11: 5 }^----6----7----8----9 │{11: 5 }5----6----7----8----|
- {11: 6 }----6----7----8----9 │{11: 6 }5----6----7----8----|
- {11: 7 }----6----7----8----9 │{11: 7 }5----6----7----8----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelLeft> in active window
- if esc then
- feed_data('\027[<66;8;1M')
- else
- api.nvim_input_mouse('wheel', 'left', '', 0, 0, 7)
- end
- screen:expect([[
- {11: 4 }5----6----7----8----9│{11: 4 }5----6----7----8----|
- {11: 5 }5^----6----7----8----9│{11: 5 }5----6----7----8----|
- {11: 6 }5----6----7----8----9│{11: 6 }5----6----7----8----|
- {11: 7 }5----6----7----8----9│{11: 7 }5----6----7----8----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <ScrollWheelLeft> in inactive window
- if esc then
- feed_data('\027[<66;48;1M')
- else
- api.nvim_input_mouse('wheel', 'left', '', 0, 0, 47)
- end
- screen:expect([[
- {11: 4 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
- {11: 5 }5^----6----7----8----9│{11: 5 }-5----6----7----8---|
- {11: 6 }5----6----7----8----9│{11: 6 }-5----6----7----8---|
- {11: 7 }5----6----7----8----9│{11: 7 }-5----6----7----8---|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelUp> in active window
- if esc then
- feed_data('\027[<68;8;1M')
- else
- api.nvim_input_mouse('wheel', 'up', 'S', 0, 0, 7)
- end
- screen:expect([[
- {11: 1 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
- {11: 2 }5----6----7----8----9│{11: 5 }-5----6----7----8---|
- {11: 3 }5----6----7----8----9│{11: 6 }-5----6----7----8---|
- {11: 4 }5^----6----7----8----9│{11: 7 }-5----6----7----8---|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelUp> in inactive window
- if esc then
- feed_data('\027[<68;48;1M')
- else
- api.nvim_input_mouse('wheel', 'up', 'S', 0, 0, 47)
- end
- screen:expect([[
- {11: 1 }5----6----7----8----9│{11: 1 }-5----6----7----8---|
- {11: 2 }5----6----7----8----9│{11: 2 }-5----6----7----8---|
- {11: 3 }5----6----7----8----9│{11: 3 }-5----6----7----8---|
- {11: 4 }5^----6----7----8----9│{11: 4 }-5----6----7----8---|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelLeft> in active window
- if esc then
- feed_data('\027[<70;8;1M')
- else
- api.nvim_input_mouse('wheel', 'left', 'S', 0, 0, 7)
- end
- screen:expect([[
- {11: 1 }0----1----2----3----4│{11: 1 }-5----6----7----8---|
- {11: 2 }0----1----2----3----4│{11: 2 }-5----6----7----8---|
- {11: 3 }0----1----2----3----4│{11: 3 }-5----6----7----8---|
- {11: 4 }0----1----2----3----^4│{11: 4 }-5----6----7----8---|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- <S-ScrollWheelLeft> in inactive window
- if esc then
- feed_data('\027[<70;48;1M')
- else
- api.nvim_input_mouse('wheel', 'left', 'S', 0, 0, 47)
- end
- screen:expect([[
- {11: 1 }0----1----2----3----4│{11: 1 }0----1----2----3----|
- {11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
- {11: 3 }0----1----2----3----4│{11: 3 }0----1----2----3----|
- {11: 4 }0----1----2----3----^4│{11: 4 }0----1----2----3----|
- {5:[No Name] [+] }{1:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end
- describe('accepts mouse wheel events', function()
- it('(mouse events sent to host)', function()
- test_mouse_wheel(false)
- end)
- it('(escape sequences sent to child)', function()
- test_mouse_wheel(true)
- end)
- end)
- local function test_mouse_popup(esc)
- child_session:request(
- 'nvim_exec2',
- [[
- call setline(1, 'popup menu test')
- set mouse=a mousemodel=popup
- aunmenu PopUp
- " Delete the default MenuPopup event handler.
- autocmd! nvim.popupmenu
- menu PopUp.foo :let g:menustr = 'foo'<CR>
- menu PopUp.bar :let g:menustr = 'bar'<CR>
- menu PopUp.baz :let g:menustr = 'baz'<CR>
- highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse
- highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold
- ]],
- {}
- )
- if esc then
- feed_data('\027[<2;5;1M')
- else
- api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }{13: foo }{4: }|
- {4:~ }{13: bar }{4: }|
- {4:~ }{13: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<2;5;1m')
- else
- api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
- end
- screen:expect_unchanged()
- if esc then
- feed_data('\027[<64;5;1M')
- else
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 4)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }{14: foo }{4: }|
- {4:~ }{13: bar }{4: }|
- {4:~ }{13: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<35;7;4M')
- else
- api.nvim_input_mouse('move', '', '', 0, 3, 6)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }{13: foo }{4: }|
- {4:~ }{13: bar }{4: }|
- {4:~ }{14: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<65;7;4M')
- else
- api.nvim_input_mouse('wheel', 'down', '', 0, 3, 6)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }{13: foo }{4: }|
- {4:~ }{14: bar }{4: }|
- {4:~ }{13: baz }{4: }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<0;7;3M')
- else
- api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }|*3
- {5:[No Name] [+] }|
- :let g:menustr = 'bar' |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<0;7;3m')
- else
- api.nvim_input_mouse('left', 'release', '', 0, 2, 6)
- end
- screen:expect_unchanged()
- if esc then
- feed_data('\027[<2;45;3M')
- else
- api.nvim_input_mouse('right', 'press', '', 0, 2, 44)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }|*2
- {4:~ }{13: foo }{4: }|
- {5:[No Name] [+] }{13: bar }{5: }|
- :let g:menustr = 'bar' {13: baz } |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<34;48;6M')
- else
- api.nvim_input_mouse('right', 'drag', '', 0, 5, 47)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }|*2
- {4:~ }{13: foo }{4: }|
- {5:[No Name] [+] }{13: bar }{5: }|
- :let g:menustr = 'bar' {14: baz } |
- {3:-- TERMINAL --} |
- ]])
- if esc then
- feed_data('\027[<2;48;6m')
- else
- api.nvim_input_mouse('right', 'release', '', 0, 5, 47)
- end
- screen:expect([[
- ^popup menu test |
- {4:~ }|*3
- {5:[No Name] [+] }|
- :let g:menustr = 'baz' |
- {3:-- TERMINAL --} |
- ]])
- end
- describe('mouse events work with right-click menu', function()
- it('(mouse events sent to host)', function()
- test_mouse_popup(false)
- end)
- it('(escape sequences sent to child)', function()
- test_mouse_popup(true)
- end)
- end)
- it('accepts keypad keys from kitty keyboard protocol #19180', function()
- feed_data('i')
- feed_data(fn.nr2char(57399)) -- KP_0
- feed_data(fn.nr2char(57400)) -- KP_1
- feed_data(fn.nr2char(57401)) -- KP_2
- feed_data(fn.nr2char(57402)) -- KP_3
- feed_data(fn.nr2char(57403)) -- KP_4
- feed_data(fn.nr2char(57404)) -- KP_5
- feed_data(fn.nr2char(57405)) -- KP_6
- feed_data(fn.nr2char(57406)) -- KP_7
- feed_data(fn.nr2char(57407)) -- KP_8
- feed_data(fn.nr2char(57408)) -- KP_9
- feed_data(fn.nr2char(57409)) -- KP_DECIMAL
- feed_data(fn.nr2char(57410)) -- KP_DIVIDE
- feed_data(fn.nr2char(57411)) -- KP_MULTIPLY
- feed_data(fn.nr2char(57412)) -- KP_SUBTRACT
- feed_data(fn.nr2char(57413)) -- KP_ADD
- feed_data(fn.nr2char(57414)) -- KP_ENTER
- feed_data(fn.nr2char(57415)) -- KP_EQUAL
- screen:expect([[
- 0123456789./*-+ |
- =^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57417)) -- KP_LEFT
- screen:expect([[
- 0123456789./*-+ |
- ^= |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57418)) -- KP_RIGHT
- screen:expect([[
- 0123456789./*-+ |
- =^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57419)) -- KP_UP
- screen:expect([[
- 0^123456789./*-+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57420)) -- KP_DOWN
- screen:expect([[
- 0123456789./*-+ |
- =^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57425)) -- KP_INSERT
- screen:expect([[
- 0123456789./*-+ |
- =^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- REPLACE --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[27u') -- ESC
- screen:expect([[
- 0123456789./*-+ |
- ^= |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[57417;5u') -- CTRL + KP_LEFT
- screen:expect([[
- ^0123456789./*-+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[57418;2u') -- SHIFT + KP_RIGHT
- screen:expect([[
- 0123456789^./*-+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57426)) -- KP_DELETE
- screen:expect([[
- 0123456789^/*-+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57423)) -- KP_HOME
- screen:expect([[
- ^0123456789/*-+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data(fn.nr2char(57424)) -- KP_END
- screen:expect([[
- 0123456789/*-^+ |
- = |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- child_session:request(
- 'nvim_exec2',
- [[
- tab split
- tabnew
- highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline
- ]],
- {}
- )
- screen:expect([[
- {12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}|
- ^ |
- {4:~ }|*2
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[57421;5u') -- CTRL + KP_PAGE_UP
- screen:expect([[
- {12: + [No Name] }{3: + [No Name] }{12: [No Name] }{1: }{12:X}|
- 0123456789/*-^+ |
- = |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[57422;5u') -- CTRL + KP_PAGE_DOWN
- screen:expect([[
- {12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}|
- ^ |
- {4:~ }|*2
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('supports Super and Meta modifiers', function()
- feed_data('i')
- feed_data('\022\027[106;9u') -- Super + j
- feed_data('\022\027[107;33u') -- Meta + k
- feed_data('\022\027[13;41u') -- Super + Meta + Enter
- feed_data('\022\027[127;48u') -- Shift + Alt + Ctrl + Super + Meta + Backspace
- feed_data('\n')
- feed_data('\022\027[57376;9u') -- Super + F13
- feed_data('\022\027[57377;33u') -- Meta + F14
- feed_data('\022\027[57378;41u') -- Super + Meta + F15
- feed_data('\022\027[57379;48u') -- Shift + Alt + Ctrl + Super + Meta + F16
- screen:expect([[
- <D-j><T-k><T-D-CR><M-T-C-S-D-BS> |
- <D-F13><T-F14><T-D-F15><M-T-C-S-D-F16>^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: Insert mode', function()
- -- "bracketed paste"
- feed_data('i""\027i\027[200~')
- screen:expect([[
- "^" |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('pasted from terminal')
- expect_child_buf_lines({ '"pasted from terminal"' })
- screen:expect([[
- "pasted from terminal^" |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[201~') -- End paste.
- poke_both_eventloop()
- screen:expect_unchanged()
- feed_data('\027[27u') -- ESC: go to Normal mode.
- wait_for_mode('n')
- screen:expect([[
- "pasted from termina^l" |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Dot-repeat/redo.
- feed_data('2.')
- expect_child_buf_lines({ '"pasted from terminapasted from terminalpasted from terminall"' })
- screen:expect([[
- "pasted from terminapasted from terminalpasted fro|
- m termina^ll" |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Undo.
- feed_data('u')
- expect_child_buf_lines({ '"pasted from terminal"' })
- feed_data('u')
- expect_child_buf_lines({ '""' })
- feed_data('u')
- expect_child_buf_lines({ '' })
- end)
- it('paste: select-mode', function()
- feed_data('ithis is line 1\nthis is line 2\nline 3 is here\n\027')
- wait_for_mode('n')
- screen:expect([[
- this is line 1 |
- this is line 2 |
- line 3 is here |
- ^ |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Select-mode. Use <C-n> to move down.
- feed_data('gg04lgh\14\14')
- screen:expect([[
- this{16: is line 1} |
- {16:this is line 2} |
- {16:line}^ 3 is here |
- |
- {5:[No Name] [+] }|
- {3:-- SELECT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[200~')
- feed_data('just paste it™')
- feed_data('\027[201~')
- screen:expect([[
- thisjust paste it^™3 is here |
- |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Undo.
- feed_data('u')
- expect_child_buf_lines {
- 'this is line 1',
- 'this is line 2',
- 'line 3 is here',
- '',
- }
- -- Redo.
- feed_data('\18') -- <C-r>
- expect_child_buf_lines {
- 'thisjust paste it™3 is here',
- '',
- }
- end)
- it('paste: terminal mode', function()
- if is_ci('github') then
- pending('tty-test complains about not owning the terminal -- actions/runner#241')
- end
- screen:set_default_attr_ids({
- [1] = { reverse = true }, -- focused cursor
- [3] = { bold = true },
- [19] = { bold = true, background = 121, foreground = 0 }, -- StatusLineTerm
- })
- child_exec_lua('vim.o.statusline="^^^^^^^"')
- child_exec_lua('vim.cmd.terminal(...)', testprg('tty-test'))
- feed_data('i')
- screen:expect([[
- tty ready |
- ^ |
- |*2
- {19:^^^^^^^ }|
- {3:-- TERMINAL --} |*2
- ]])
- feed_data('\027[200~')
- feed_data('hallo')
- feed_data('\027[201~')
- screen:expect([[
- tty ready |
- hallo^ |
- |*2
- {19:^^^^^^^ }|
- {3:-- TERMINAL --} |*2
- ]])
- end)
- it('paste: normal-mode (+CRLF #10872)', function()
- feed_data(':set ruler | echo')
- wait_for_mode('c')
- feed_data('\n')
- wait_for_mode('n')
- local expected_lf = { 'line 1', 'ESC:\027 / CR: \rx' }
- local expected_crlf = { 'line 1', 'ESC:\027 / CR: ', 'x' }
- local expected_grid1 = [[
- line 1 |
- ESC:{6:^[} / CR: |
- ^x |
- {4:~ }|
- {5:[No Name] [+] 3,1 All}|
- |
- {3:-- TERMINAL --} |
- ]]
- -- "bracketed paste"
- feed_data('\027[200~' .. table.concat(expected_lf, '\n') .. '\027[201~')
- screen:expect(expected_grid1)
- -- Dot-repeat/redo.
- feed_data('.')
- local expected_grid2 = [[
- ESC:{6:^[} / CR: |
- xline 1 |
- ESC:{6:^[} / CR: |
- ^x |
- {5:[No Name] [+] 5,1 Bot}|
- |
- {3:-- TERMINAL --} |
- ]]
- screen:expect(expected_grid2)
- -- Undo.
- feed_data('u')
- expect_child_buf_lines(expected_crlf)
- feed_data('u')
- expect_child_buf_lines({ '' })
- feed_data(':echo')
- wait_for_mode('c')
- feed_data('\n')
- wait_for_mode('n')
- -- CRLF input
- feed_data('\027[200~' .. table.concat(expected_lf, '\r\n') .. '\027[201~')
- screen:expect(expected_grid1)
- expect_child_buf_lines(expected_crlf)
- -- Dot-repeat/redo.
- feed_data('.')
- screen:expect(expected_grid2)
- -- Undo.
- feed_data('u')
- expect_child_buf_lines(expected_crlf)
- feed_data('u')
- expect_child_buf_lines({ '' })
- end)
- it('paste: cmdline-mode inserts 1 line', function()
- feed_data('ifoo\n') -- Insert some text (for dot-repeat later).
- feed_data('\027:""') -- Enter Cmdline-mode.
- feed_data('\027[D') -- <Left> to place cursor between quotes.
- wait_for_mode('c')
- screen:expect([[
- foo |
- |
- {4:~ }|*2
- {5:[No Name] [+] }|
- :"^" |
- {3:-- TERMINAL --} |
- ]])
- -- "bracketed paste"
- feed_data('\027[200~line 1\nline 2\n')
- wait_for_mode('c')
- feed_data('line 3\nline 4\n\027[201~')
- poke_both_eventloop()
- wait_for_mode('c')
- screen:expect([[
- foo |
- |
- {4:~ }|*2
- {5:[No Name] [+] }|
- :"line 1^" |
- {3:-- TERMINAL --} |
- ]])
- -- Dot-repeat/redo.
- feed_data('\027[27u')
- wait_for_mode('n')
- feed_data('.')
- screen:expect([[
- foo |*2
- ^ |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: cmdline-mode collects chunks of unfinished line', function()
- local function expect_cmdline(expected)
- retry(nil, nil, function()
- local _, cmdline = child_session:request('nvim_call_function', 'getcmdline', {})
- eq(expected, cmdline)
- local _, pos = child_session:request('nvim_call_function', 'getcmdpos', {})
- eq(#expected, pos) -- Cursor is just before the last char.
- end)
- end
- feed_data('\027:""') -- Enter Cmdline-mode.
- feed_data('\027[D') -- <Left> to place cursor between quotes.
- expect_cmdline('""')
- feed_data('\027[200~stuff 1 ')
- expect_cmdline('"stuff 1 "')
- -- Discards everything after the first line.
- feed_data('more\nstuff 2\nstuff 3\n')
- expect_cmdline('"stuff 1 more"')
- feed_data('stuff 3')
- expect_cmdline('"stuff 1 more"')
- -- End the paste sequence.
- feed_data('\027[201~')
- poke_both_eventloop()
- expect_cmdline('"stuff 1 more"')
- feed_data(' typed')
- expect_cmdline('"stuff 1 more typed"')
- end)
- it('paste: recovers from vim.paste() failure', function()
- child_exec_lua([[
- _G.save_paste_fn = vim.paste
- -- Stack traces for this test are non-deterministic, so disable them
- _G.debug.traceback = function(msg) return msg end
- vim.paste = function(lines, phase) error("fake fail") end
- ]])
- -- Prepare something for dot-repeat/redo.
- feed_data('ifoo\n\027[27u')
- wait_for_mode('n')
- screen:expect([[
- foo |
- ^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Start pasting...
- feed_data('\027[200~line 1\nline 2\n')
- screen:expect([[
- foo |
- |
- {5: }|
- {8:paste: Error executing lua: [string "<nvim>"]:4: f}|
- {8:ake fail} |
- {10:Press ENTER or type command to continue}^ |
- {3:-- TERMINAL --} |
- ]])
- -- Remaining chunks are discarded after vim.paste() failure.
- feed_data('line 3\nline 4\n')
- feed_data('line 5\nline 6\n')
- feed_data('line 7\nline 8\n')
- -- Stop paste.
- feed_data('\027[201~')
- screen:expect_unchanged()
- feed_data('\n') -- <CR> to dismiss hit-enter prompt
- expect_child_buf_lines({ 'foo', '' })
- -- Dot-repeat/redo is not modified by failed paste.
- feed_data('.')
- screen:expect([[
- foo |*2
- ^ |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Editor should still work after failed/drained paste.
- feed_data('ityped input...\027[27u')
- screen:expect([[
- foo |*2
- typed input..^. |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Paste works if vim.paste() succeeds.
- child_exec_lua([[vim.paste = _G.save_paste_fn]])
- feed_data('\027[200~line A\nline B\n\027[201~')
- screen:expect([[
- foo |
- typed input...line A |
- line B |
- ^ |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: vim.paste() cancel (retval=false) #10865', function()
- -- This test only exercises the "cancel" case. Use-case would be "dangling
- -- paste", but that is not implemented yet. #10865
- child_exec_lua([[
- vim.paste = function(lines, phase) return false end
- ]])
- feed_data('\027[200~line A\nline B\n\027[201~')
- expect_child_buf_lines({ '' })
- feed_data('ifoo\n\027[27u')
- expect_child_buf_lines({ 'foo', '' })
- end)
- it('paste: vim.paste() cancel (retval=false) with streaming #30462', function()
- child_exec_lua([[
- vim.paste = (function(overridden)
- return function(lines, phase)
- for i, line in ipairs(lines) do
- if line:find('!') then
- return false
- end
- end
- return overridden(lines, phase)
- end
- end)(vim.paste)
- ]])
- feed_data('A')
- wait_for_mode('i')
- feed_data('\027[200~aaa')
- expect_child_buf_lines({ 'aaa' })
- feed_data('bbb')
- expect_child_buf_lines({ 'aaabbb' })
- feed_data('ccc!') -- This chunk is cancelled.
- expect_child_buf_lines({ 'aaabbb' })
- feed_data('ddd\027[201~') -- This chunk is ignored.
- poke_both_eventloop()
- expect_child_buf_lines({ 'aaabbb' })
- feed_data('\027[27u')
- wait_for_mode('n')
- feed_data('.') -- Dot-repeat only includes chunks actually pasted.
- expect_child_buf_lines({ 'aaabbbaaabbb' })
- feed_data('$\027[200~eee\027[201~') -- A following paste works normally.
- expect_child_buf_lines({ 'aaabbbaaabbbeee' })
- end)
- it("paste: 'nomodifiable' buffer", function()
- child_exec_lua([[
- vim.bo.modifiable = false
- -- Truncate the error message to hide the line number
- _G.debug.traceback = function(msg) return msg:sub(-49) end
- ]])
- feed_data('\027[200~fail 1\nfail 2\n\027[201~')
- screen:expect([[
- |
- {4:~ }|
- {5: }|
- {8:paste: Error executing lua: Vim:E21: Cannot make c}|
- {8:hanges, 'modifiable' is off} |
- {10:Press ENTER or type command to continue}^ |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\n') -- <Enter> to dismiss hit-enter prompt
- child_exec_lua('vim.bo.modifiable = true')
- feed_data('\027[200~success 1\nsuccess 2\n\027[201~')
- screen:expect([[
- success 1 |
- success 2 |
- ^ |
- {4:~ }|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: exactly 64 bytes #10311', function()
- local expected = string.rep('z', 64)
- feed_data('i')
- wait_for_mode('i')
- -- "bracketed paste"
- feed_data('\027[200~' .. expected .. '\027[201~')
- expect_child_buf_lines({ expected })
- feed_data(' end')
- expected = expected .. ' end'
- screen:expect([[
- zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz|
- zzzzzzzzzzzzzz end^ |
- {4:~ }|*2
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- expect_child_buf_lines({ expected })
- end)
- it('paste: less-than sign in cmdline #11088', function()
- local expected = '<'
- feed_data(':')
- wait_for_mode('c')
- -- "bracketed paste"
- feed_data('\027[200~' .. expected .. '\027[201~')
- screen:expect([[
- |
- {4:~ }|*3
- {5:[No Name] }|
- :<^ |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: big burst of input', function()
- feed_data(':set ruler\n')
- local q = {}
- for i = 1, 3000 do
- q[i] = 'item ' .. tostring(i)
- end
- feed_data('i')
- wait_for_mode('i')
- -- "bracketed paste"
- feed_data('\027[200~' .. table.concat(q, '\n') .. '\027[201~')
- expect_child_buf_lines(q)
- feed_data(' end')
- screen:expect([[
- item 2997 |
- item 2998 |
- item 2999 |
- item 3000 end^ |
- {5:[No Name] [+] 3000,14 Bot}|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[27u') -- ESC: go to Normal mode.
- wait_for_mode('n')
- -- Dot-repeat/redo.
- feed_data('.')
- screen:expect([[
- item 2997 |
- item 2998 |
- item 2999 |
- item 3000 en^dd |
- {5:[No Name] [+] 5999,13 Bot}|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: forwards spurious "start paste" code', function()
- -- If multiple "start paste" sequences are sent without a corresponding
- -- "stop paste" sequence, only the first occurrence should be consumed.
- feed_data('i')
- wait_for_mode('i')
- -- Send the "start paste" sequence.
- feed_data('\027[200~')
- feed_data('\npasted from terminal (1)\n')
- -- Send spurious "start paste" sequence.
- feed_data('\027[200~')
- feed_data('\n')
- -- Send the "stop paste" sequence.
- feed_data('\027[201~')
- screen:expect([[
- |
- pasted from terminal (1) |
- {6:^[}[200~ |
- ^ |
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: ignores spurious "stop paste" code', function()
- -- If "stop paste" sequence is received without a preceding "start paste"
- -- sequence, it should be ignored.
- feed_data('i')
- wait_for_mode('i')
- -- Send "stop paste" sequence.
- feed_data('\027[201~')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: split "start paste" code', function()
- feed_data('i')
- wait_for_mode('i')
- -- Send split "start paste" sequence.
- feed_data('\027[2')
- feed_data('00~pasted from terminal\027[201~')
- screen:expect([[
- pasted from terminal^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: split "stop paste" code', function()
- feed_data('i')
- wait_for_mode('i')
- -- Send split "stop paste" sequence.
- feed_data('\027[200~pasted from terminal\027[20')
- feed_data('1~')
- screen:expect([[
- pasted from terminal^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('paste: streamed paste with isolated "stop paste" code', function()
- child_exec_lua([[
- _G.paste_phases = {}
- vim.paste = (function(overridden)
- return function(lines, phase)
- table.insert(_G.paste_phases, phase)
- overridden(lines, phase)
- end
- end)(vim.paste)
- ]])
- feed_data('i')
- wait_for_mode('i')
- feed_data('\027[200~pasted') -- phase 1
- screen:expect([[
- pasted^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- feed_data(' from terminal') -- phase 2
- screen:expect([[
- pasted from terminal^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- -- Send isolated "stop paste" sequence.
- feed_data('\027[201~') -- phase 3
- poke_both_eventloop()
- screen:expect_unchanged()
- local rv = child_exec_lua('return _G.paste_phases')
- -- In rare cases there may be multiple chunks of phase 2 because of timing.
- eq({ 1, 2, 3 }, { rv[1], rv[2], rv[#rv] })
- end)
- it('allows termguicolors to be set at runtime', function()
- screen:set_option('rgb', true)
- screen:set_default_attr_ids({
- [1] = { reverse = true },
- [2] = { foreground = tonumber('0x4040ff'), fg_indexed = true },
- [3] = { bold = true, reverse = true },
- [4] = { bold = true },
- [5] = { reverse = true, foreground = tonumber('0xe0e000'), fg_indexed = true },
- [6] = { foreground = tonumber('0xe0e000'), fg_indexed = true },
- [7] = { reverse = true, foreground = Screen.colors.SeaGreen4 },
- [8] = { foreground = Screen.colors.SeaGreen4 },
- [9] = { bold = true, foreground = Screen.colors.Blue1 },
- [10] = { foreground = Screen.colors.Blue },
- })
- feed_data(':hi SpecialKey ctermfg=3 guifg=SeaGreen\n')
- feed_data('i')
- feed_data('\022\007') -- ctrl+g
- feed_data('\028\014') -- crtl+\ ctrl+N
- feed_data(':set termguicolors?\n')
- screen:expect([[
- {6:^^G} |
- {2:~ }|*3
- {3:[No Name] [+] }|
- notermguicolors |
- {4:-- TERMINAL --} |
- ]])
- feed_data(':set termguicolors\n')
- screen:expect([[
- {8:^^G} |
- {9:~}{10: }|*3
- {3:[No Name] [+] }|
- :set termguicolors |
- {4:-- TERMINAL --} |
- ]])
- feed_data(':set notermguicolors\n')
- screen:expect([[
- {6:^^G} |
- {2:~ }|*3
- {3:[No Name] [+] }|
- :set notermguicolors |
- {4:-- TERMINAL --} |
- ]])
- end)
- it('forwards :term palette colors with termguicolors', function()
- if is_ci('github') then
- pending('tty-test complains about not owning the terminal -- actions/runner#241')
- end
- screen:set_rgb_cterm(true)
- screen:set_default_attr_ids({
- [1] = { { reverse = true }, { reverse = true } },
- [2] = {
- { bold = true, background = Screen.colors.LightGreen, foreground = Screen.colors.Black },
- { bold = true },
- },
- [3] = { { bold = true }, { bold = true } },
- [4] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
- [5] = { { foreground = tonumber('0xff8000') }, {} },
- [6] = {
- {
- fg_indexed = true,
- bg_indexed = true,
- bold = true,
- background = tonumber('0x66ff99'),
- foreground = Screen.colors.Black,
- },
- { bold = true, background = 121, foreground = 0 },
- },
- [7] = {
- {
- fg_indexed = true,
- bg_indexed = true,
- background = tonumber('0x66ff99'),
- foreground = Screen.colors.Black,
- },
- { background = 121, foreground = 0 },
- },
- })
- child_exec_lua('vim.o.statusline="^^^^^^^"')
- child_exec_lua('vim.o.termguicolors=true')
- child_exec_lua('vim.cmd.terminal(...)', testprg('tty-test'))
- screen:expect {
- grid = [[
- ^tty ready |
- |*3
- {2:^^^^^^^ }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data(
- ':call chansend(&channel, "\\033[38;5;3mtext\\033[38:2:255:128:0mcolor\\033[0;10mtext")\n'
- )
- screen:expect {
- grid = [[
- ^tty ready |
- {4:text}{5:color}text |
- |*2
- {2:^^^^^^^ }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data(':set notermguicolors\n')
- screen:expect {
- grid = [[
- ^tty ready |
- {4:text}colortext |
- |*2
- {6:^^^^^^^}{7: }|
- :set notermguicolors |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- -- Note: libvterm doesn't support colored underline or undercurl.
- it('supports undercurl and underdouble when run in :terminal', function()
- screen:set_default_attr_ids({
- [1] = { reverse = true },
- [2] = { bold = true, reverse = true },
- [3] = { bold = true },
- [4] = { foreground = 12 },
- [5] = { undercurl = true },
- [6] = { underdouble = true },
- })
- child_session:request('nvim_set_hl', 0, 'Visual', { undercurl = true })
- feed_data('ifoobar\027V')
- screen:expect([[
- {5:fooba}^r |
- {4:~ }|*3
- {2:[No Name] [+] }|
- {3:-- VISUAL LINE --} |
- {3:-- TERMINAL --} |
- ]])
- child_session:request('nvim_set_hl', 0, 'Visual', { underdouble = true })
- screen:expect([[
- {6:fooba}^r |
- {4:~ }|*3
- {2:[No Name] [+] }|
- {3:-- VISUAL LINE --} |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('in nvim_list_uis(), sets nvim_set_client_info()', function()
- -- $TERM in :terminal.
- local exp_term = is_os('bsd') and 'builtin_xterm' or 'xterm-256color'
- local ui_chan = 1
- local expected = {
- {
- chan = ui_chan,
- ext_cmdline = false,
- ext_hlstate = false,
- ext_linegrid = true,
- ext_messages = false,
- ext_multigrid = false,
- ext_popupmenu = false,
- ext_tabline = false,
- ext_termcolors = true,
- ext_wildmenu = false,
- height = 6,
- override = false,
- rgb = false,
- stdin_tty = true,
- stdout_tty = true,
- term_background = '',
- term_colors = 256,
- term_name = exp_term,
- width = 50,
- },
- }
- local _, rv = child_session:request('nvim_list_uis')
- eq(expected, rv)
- ---@type table
- local expected_version = child_exec_lua('return vim.version()')
- -- vim.version() returns `prerelease` string. Coerce it to boolean.
- expected_version.prerelease = not not expected_version.prerelease
- local expected_chan_info = {
- client = {
- attributes = {
- license = 'Apache 2',
- -- pid = 5371,
- website = 'https://neovim.io',
- },
- methods = {},
- name = 'nvim-tui',
- type = 'ui',
- version = expected_version,
- },
- id = ui_chan,
- mode = 'rpc',
- stream = 'stdio',
- }
- local status, chan_info = child_session:request('nvim_get_chan_info', ui_chan)
- ok(status)
- local info = chan_info.client
- ok(info.attributes.pid and info.attributes.pid > 0, 'PID', info.attributes.pid or 'nil')
- ok(info.version.major >= 0)
- ok(info.version.minor >= 0)
- ok(info.version.patch >= 0)
- -- Delete variable fields so we can deep-compare.
- info.attributes.pid = nil
- eq(expected_chan_info, chan_info)
- end)
- it('allows grid to assume wider ambiwidth chars than host terminal', function()
- child_session:request(
- 'nvim_buf_set_lines',
- 0,
- 0,
- -1,
- true,
- { ('℃'):rep(60), ('℃'):rep(60) }
- )
- child_session:request('nvim_set_option_value', 'cursorline', true, {})
- child_session:request('nvim_set_option_value', 'list', true, {})
- child_session:request('nvim_set_option_value', 'listchars', 'eol:$', { win = 0 })
- feed_data('gg')
- local singlewidth_screen = [[
- {12:^℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃}|
- {12:℃℃℃℃℃℃℃℃℃℃}{15:$}{12: }|
- ℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃|
- ℃℃℃℃℃℃℃℃℃℃{4:$} |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]]
- -- When grid assumes "℃" to be double-width but host terminal assumes it to be single-width,
- -- the second cell of "℃" is a space and the attributes of the "℃" are applied to it.
- local doublewidth_screen = [[
- {12:^℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ }|
- {12:℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ }|
- {12:℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ }{15:$}{12: }|
- ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ ℃ {4:@@@@}|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]]
- screen:expect(singlewidth_screen)
- child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {})
- screen:expect(doublewidth_screen)
- child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
- screen:expect(singlewidth_screen)
- child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2103, 0x2103, 2 } } })
- screen:expect(doublewidth_screen)
- child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2103, 0x2103, 1 } } })
- screen:expect(singlewidth_screen)
- end)
- it('allows grid to assume wider non-ambiwidth chars than host terminal', function()
- child_session:request(
- 'nvim_buf_set_lines',
- 0,
- 0,
- -1,
- true,
- { ('✓'):rep(60), ('✓'):rep(60) }
- )
- child_session:request('nvim_set_option_value', 'cursorline', true, {})
- child_session:request('nvim_set_option_value', 'list', true, {})
- child_session:request('nvim_set_option_value', 'listchars', 'eol:$', { win = 0 })
- feed_data('gg')
- local singlewidth_screen = [[
- {12:^✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓}|
- {12:✓✓✓✓✓✓✓✓✓✓}{15:$}{12: }|
- ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓|
- ✓✓✓✓✓✓✓✓✓✓{4:$} |
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]]
- -- When grid assumes "✓" to be double-width but host terminal assumes it to be single-width,
- -- the second cell of "✓" is a space and the attributes of the "✓" are applied to it.
- local doublewidth_screen = [[
- {12:^✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }|
- {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }|
- {12:✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ }{15:$}{12: }|
- ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ {4:@@@@}|
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]]
- screen:expect(singlewidth_screen)
- child_session:request('nvim_set_option_value', 'ambiwidth', 'double', {})
- screen:expect_unchanged()
- child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 2 } } })
- screen:expect(doublewidth_screen)
- child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
- screen:expect_unchanged()
- child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2713, 0x2713, 1 } } })
- screen:expect(singlewidth_screen)
- end)
- it('draws correctly when cursor_address overflows #21643', function()
- screen:try_resize(70, 333)
- retry(nil, nil, function()
- eq({ true, 330 }, { child_session:request('nvim_win_get_height', 0) })
- end)
- child_session:request('nvim_set_option_value', 'cursorline', true, {})
- -- Use full screen message so that redrawing afterwards is more deterministic.
- child_session:notify('nvim_command', 'intro')
- screen:expect({ any = 'Nvim is open source and freely distributable' })
- -- Going to top-left corner needs 3 bytes.
- -- Setting underline attribute needs 9 bytes.
- -- A Ꝩ character takes 3 bytes.
- -- The whole line needs 3 + 9 + 3 * 21838 + 3 = 65529 bytes.
- -- The cursor_address that comes after will overflow the 65535-byte buffer.
- local line = ('Ꝩ'):rep(21838) .. '℃'
- child_session:notify('nvim_buf_set_lines', 0, 0, -1, true, { line, 'b' })
- -- Close the :intro message and redraw the lines.
- feed_data('\n')
- screen:expect([[
- {12:^ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ}|
- {12:ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ}|*310
- {12:ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ℃ }|
- b |
- {4:~ }|*17
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('draws correctly when setting title overflows #30793', function()
- screen:try_resize(67, 327)
- retry(nil, nil, function()
- eq({ true, 324 }, { child_session:request('nvim_win_get_height', 0) })
- end)
- child_exec_lua([[
- vim.o.cmdheight = 0
- vim.o.laststatus = 0
- vim.o.ruler = false
- vim.o.showcmd = false
- vim.o.termsync = false
- vim.o.title = true
- ]])
- retry(nil, nil, function()
- eq('[No Name] - Nvim', api.nvim_buf_get_var(0, 'term_title'))
- eq({ true, 326 }, { child_session:request('nvim_win_get_height', 0) })
- end)
- -- Use full screen message so that redrawing afterwards is more deterministic.
- child_session:notify('nvim_command', 'intro')
- screen:expect({ any = 'Nvim is open source and freely distributable' })
- -- Going to top-left corner needs 3 bytes.
- -- A Ꝩ character takes 3 bytes.
- -- The whole line needs 3 + 3 * 21842 = 65529 bytes.
- -- The title will be updated because the buffer is now modified.
- -- The start of the OSC 0 sequence to set title can fit in the 65535-byte buffer,
- -- but the title string cannot.
- local line = ('Ꝩ'):rep(21842)
- child_session:notify('nvim_buf_set_lines', 0, 0, -1, true, { line })
- -- Close the :intro message and redraw the lines.
- feed_data('\n')
- screen:expect([[
- ^ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ|
- ꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨꝨ|*325
- {3:-- TERMINAL --} |
- ]])
- retry(nil, nil, function()
- eq('[No Name] + - Nvim', api.nvim_buf_get_var(0, 'term_title'))
- end)
- end)
- it('visual bell (padding) does not crash #21610', function()
- feed_data ':set visualbell\n'
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- :set visualbell |
- {3:-- TERMINAL --} |
- ]],
- }
- -- move left is enough to invoke the bell
- feed_data 'h'
- -- visual change to show we process events after this
- feed_data 'i'
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- it('no assert failure on deadly signal #21896', function()
- exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
- screen:expect {
- grid = [[
- Vim: Caught deadly signal 'SIGTERM' |
- |*2
- [Process exited 1]^ |
- |*2
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- it('no stack-use-after-scope with cursor color #22432', function()
- screen:set_option('rgb', true)
- command('set termguicolors')
- child_session:request(
- 'nvim_exec2',
- [[
- set tgc
- hi Cursor guifg=Red guibg=Green
- set guicursor=n:block-Cursor/lCursor
- ]],
- {}
- )
- screen:set_default_attr_ids({
- [1] = { reverse = true },
- [2] = { bold = true, foreground = Screen.colors.Blue },
- [3] = { foreground = Screen.colors.Blue },
- [4] = { reverse = true, bold = true },
- [5] = { bold = true },
- })
- screen:expect([[
- ^ |
- {2:~}{3: }|*3
- {4:[No Name] }|
- |
- {5:-- TERMINAL --} |
- ]])
- feed_data('i')
- screen:expect([[
- ^ |
- {2:~}{3: }|*3
- {4:[No Name] }|
- {5:-- INSERT --} |
- {5:-- TERMINAL --} |
- ]])
- end)
- it('redraws on SIGWINCH even if terminal size is unchanged #23411', function()
- child_session:request('nvim_echo', { { 'foo' } }, false, {})
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- foo |
- {3:-- TERMINAL --} |
- ]])
- exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigwinch')]])
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('supports hiding cursor', function()
- child_session:request(
- 'nvim_command',
- "let g:id = jobstart([v:progpath, '--clean', '--headless'])"
- )
- feed_data(':call jobwait([g:id])\n')
- screen:expect([[
- |
- {4:~ }|*3
- {5:[No Name] }|
- :call jobwait([g:id]) |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\003')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- Type :qa and press <Enter> to exit Nvim |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('cursor is not hidden on incsearch with no match', function()
- feed_data('ifoo\027')
- feed_data('/foo')
- screen:expect([[
- {1:foo} |
- {4:~ }|*3
- {5:[No Name] [+] }|
- /foo^ |
- {3:-- TERMINAL --} |
- ]])
- screen:sleep(10)
- feed_data('b')
- screen:expect([[
- foo |
- {4:~ }|*3
- {5:[No Name] [+] }|
- /foob^ |
- {3:-- TERMINAL --} |
- ]])
- screen:sleep(10)
- feed_data('a')
- screen:expect([[
- foo |
- {4:~ }|*3
- {5:[No Name] [+] }|
- /fooba^ |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('emits hyperlinks with OSC 8', function()
- exec_lua([[
- local buf = vim.api.nvim_get_current_buf()
- _G.urls = {}
- vim.api.nvim_create_autocmd('TermRequest', {
- buffer = buf,
- callback = function(args)
- local req = args.data
- if not req then
- return
- end
- local id, url = req:match('\027]8;id=(%d+);(.*)$')
- if id ~= nil and url ~= nil then
- table.insert(_G.urls, { id = tonumber(id), url = url })
- end
- end,
- })
- ]])
- child_exec_lua([[
- vim.api.nvim_buf_set_lines(0, 0, 0, true, {'Hello'})
- local ns = vim.api.nvim_create_namespace('test')
- vim.api.nvim_buf_set_extmark(0, ns, 0, 1, {
- end_col = 3,
- url = 'https://example.com',
- })
- ]])
- retry(nil, 1000, function()
- eq({ { id = 0xE1EA0000, url = 'https://example.com' } }, exec_lua([[return _G.urls]]))
- end)
- end)
- end)
- describe('TUI', function()
- before_each(clear)
- it('resize at startup #17285 #15044 #11330', function()
- local screen = Screen.new(50, 10)
- screen:set_default_attr_ids({
- [1] = { reverse = true },
- [2] = { bold = true, foreground = Screen.colors.Blue },
- [3] = { bold = true },
- [4] = { foreground = tonumber('0x4040ff'), fg_indexed = true },
- [5] = { bold = true, reverse = true },
- [6] = { foreground = Screen.colors.White, background = Screen.colors.DarkGreen },
- })
- fn.jobstart({
- nvim_prog,
- '--clean',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set notermguicolors',
- '--cmd',
- 'let start = reltime() | while v:true | if reltimefloat(reltime(start)) > 2 | break | endif | endwhile',
- }, {
- term = true,
- env = {
- VIMRUNTIME = os.getenv('VIMRUNTIME'),
- },
- })
- exec([[
- sleep 500m
- vs new
- ]])
- screen:expect([[
- ^ │ |
- {2:~ }│{4:~ }|*5
- {2:~ }│{5:[No Name] 0,0-1 All}|
- {2:~ }│ |
- {5:new }{6:{MATCH:<.*[/\]nvim }}|
- |
- ]])
- end)
- -- #28667, #28668
- for _, guicolors in ipairs({ 'notermguicolors', 'termguicolors' }) do
- it('has no black flicker when clearing regions during startup with ' .. guicolors, function()
- local screen = Screen.new(50, 10)
- fn.jobstart({
- nvim_prog,
- '--clean',
- '--cmd',
- 'set ' .. guicolors,
- '--cmd',
- 'sleep 10',
- }, {
- term = true,
- env = {
- VIMRUNTIME = os.getenv('VIMRUNTIME'),
- },
- })
- screen:expect({
- grid = [[
- ^ |
- |*9
- ]],
- intermediate = true,
- })
- screen:try_resize(51, 11)
- screen:expect({
- grid = [[
- ^ |
- |*10
- ]],
- })
- end)
- end
- it('argv[0] can be overridden #23953', function()
- if not exec_lua('return pcall(require, "ffi")') then
- pending('missing LuaJIT FFI')
- end
- local script_file = 'Xargv0.lua'
- write_file(
- script_file,
- [=[
- local ffi = require('ffi')
- ffi.cdef([[int execl(const char *, const char *, ...);]])
- ffi.C.execl(vim.v.progpath, 'Xargv0nvim', '--clean', nil)
- ]=]
- )
- finally(function()
- os.remove(script_file)
- end)
- local screen = tt.setup_child_nvim({ '--clean', '-l', script_file })
- screen:expect {
- grid = [[
- ^ |
- ~ |*3
- [No Name] 0,0-1 All|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data(':put =v:argv + [v:progname]\n')
- screen:expect {
- grid = [[
- Xargv0nvim |
- --embed |
- --clean |
- ^Xargv0nvim |
- [No Name] [+] 5,1 Bot|
- 4 more lines |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- it('with non-tty (pipe) stdout/stderr', function()
- finally(function()
- os.remove('testF')
- end)
- local screen = tt.setup_screen(
- 0,
- ('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
- nvim_prog
- ),
- nil,
- { VIMRUNTIME = os.getenv('VIMRUNTIME') }
- )
- feed_data(':w testF\n:q\n')
- screen:expect([[
- :w testF |
- :q |
- abc |
- |
- [Process exited 0]^ |
- |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('<C-h> #10134', function()
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noruler notermguicolors',
- '--cmd',
- ':nnoremap <C-h> :echomsg "\\<C-h\\>"<CR>',
- })
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- command([[call chansend(b:terminal_job_id, "\<C-h>")]])
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- <C-h> |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('draws line with many trailing spaces correctly #24955', function()
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'set notermguicolors',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'call setline(1, ["1st line" .. repeat(" ", 153), "2nd line"])',
- }, { cols = 80 })
- screen:expect {
- grid = [[
- ^1st line |
- |*2
- 2nd line |
- {5:[No Name] [+] 1,1 All}|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('$')
- screen:expect {
- grid = [[
- 1st line |
- |
- ^ |
- 2nd line |
- {5:[No Name] [+] 1,161 All}|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- it('draws screen lines with leading spaces correctly #29711', function()
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'set foldcolumn=6 | call setline(1, ["", repeat("aabb", 1000)]) | echo 42',
- }, { extra_rows = 10, cols = 66 })
- screen:expect {
- grid = [[
- ^ |
- aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabb|*12
- aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba@@@|
- [No Name] [+] 1,0-1 Top|
- 42 |
- -- TERMINAL -- |
- ]],
- attr_ids = {},
- }
- feed_data('\12') -- Ctrl-L
- -- The first line counts as 3 cells.
- -- For the second line, 6 repeated spaces at the start counts as 2 cells,
- -- so each screen line of the second line counts as 62 cells.
- -- After drawing the first line and 8 screen lines of the second line,
- -- 3 + 8 * 62 = 499 cells have been counted.
- -- The 6 repeated spaces at the start of the next screen line exceeds the
- -- 500-cell limit, so the buffer is flushed after these spaces.
- screen:expect {
- grid = [[
- ^ |
- aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabb|*12
- aabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabbaabba@@@|
- [No Name] [+] 1,0-1 Top|
- |
- -- TERMINAL -- |
- ]],
- attr_ids = {},
- }
- end)
- it('no heap-buffer-overflow when changing &columns', function()
- -- Set a different bg colour and change $TERM to something dumber so the `print_spaces()`
- -- codepath in `clear_region()` is hit.
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'set notermguicolors | highlight Normal ctermbg=red',
- '--cmd',
- 'call setline(1, ["a"->repeat(&columns)])',
- }, { env = { TERM = 'ansi' } })
- screen:expect {
- grid = [[
- ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- ~ |*3
- [No Name] [+] 1,1 All|
- |
- -- TERMINAL -- |
- ]],
- attr_ids = {},
- }
- feed_data(':set columns=12\n')
- screen:expect {
- grid = [[
- ^aaaaaaaaaaaa |
- aaaaaaaaaaaa |*3
- < [+] 1,1 |
- |
- -- TERMINAL -- |
- ]],
- attr_ids = {},
- }
- -- Wider than TUI, so screen state will look weird.
- -- Wait for the statusline to redraw to confirm that the TUI lives and ASAN is happy.
- feed_data(':set columns=99|set stl=redrawn%m\n')
- screen:expect({ any = 'redrawn%[%+%]' })
- end)
- end)
- describe('TUI UIEnter/UILeave', function()
- it('fires exactly once, after VimEnter', function()
- clear()
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile noshowcmd noruler notermguicolors',
- '--cmd',
- 'let g:evs = []',
- '--cmd',
- 'autocmd UIEnter * :call add(g:evs, "UIEnter")',
- '--cmd',
- 'autocmd UILeave * :call add(g:evs, "UILeave")',
- '--cmd',
- 'autocmd VimEnter * :call add(g:evs, "VimEnter")',
- })
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data(':echo g:evs\n')
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- ['VimEnter', 'UIEnter'] |
- {3:-- TERMINAL --} |
- ]],
- }
- end)
- end)
- describe('TUI FocusGained/FocusLost', function()
- local screen
- local child_session
- before_each(function()
- clear()
- local child_server = new_pipename()
- screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile noshowcmd noruler notermguicolors background=dark',
- })
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]])
- child_session = n.connect(child_server)
- child_session:request(
- 'nvim_exec2',
- [[
- autocmd FocusGained * echo 'gained'
- autocmd FocusLost * echo 'lost'
- ]],
- {}
- )
- feed_data('\034\016') -- CTRL-\ CTRL-N
- end)
- it('in normal-mode', function()
- retry(2, 3 * screen.timeout, function()
- feed_data('\027[I')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- gained |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[O')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- lost |
- {3:-- TERMINAL --} |
- ]])
- end)
- end)
- it('in insert-mode', function()
- feed_data(':set noshowmode\r')
- feed_data('i')
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- :set noshowmode |
- {3:-- TERMINAL --} |
- ]],
- }
- retry(2, 3 * screen.timeout, function()
- feed_data('\027[I')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- gained |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[O')
- screen:expect([[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- lost |
- {3:-- TERMINAL --} |
- ]])
- end)
- end)
- -- During cmdline-mode we ignore :echo invoked by timers/events.
- -- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
- it('in cmdline-mode does NOT :echo', function()
- feed_data(':')
- feed_data('\027[I')
- screen:expect([[
- |
- {4:~ }|*3
- {5:[No Name] }|
- :^ |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027[O')
- screen:expect {
- grid = [[
- |
- {4:~ }|*3
- {5:[No Name] }|
- :^ |
- {3:-- TERMINAL --} |
- ]],
- unchanged = true,
- }
- end)
- it('in cmdline-mode', function()
- -- Set up autocmds that modify the buffer, instead of just calling :echo.
- -- This is how we can test handling of focus gained/lost during cmdline-mode.
- -- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
- child_session:request(
- 'nvim_exec2',
- [[
- autocmd!
- autocmd FocusLost * call append(line('$'), 'lost')
- autocmd FocusGained * call append(line('$'), 'gained')
- ]],
- {}
- )
- retry(2, 3 * screen.timeout, function()
- -- Enter cmdline-mode.
- feed_data(':')
- screen:sleep(1)
- -- Send focus lost/gained termcodes.
- feed_data('\027[O')
- feed_data('\027[I')
- screen:sleep(1)
- -- Exit cmdline-mode. Redraws from timers/events are blocked during
- -- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode.
- feed_data('\n')
- screen:expect { any = 'lost' .. (' '):rep(46) .. '|\ngained' }
- end)
- end)
- it('in terminal-mode', function()
- feed_data(':set shell=' .. testprg('shell-test') .. ' shellcmdflag=EXE\n')
- feed_data(':set noshowmode laststatus=0\n')
- feed_data(':terminal zia\n')
- -- Wait for terminal to be ready.
- screen:expect {
- grid = [[
- ^ready $ zia |
- |
- [Process exited 0] |
- |*2
- :terminal zia |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('\027[I')
- screen:expect {
- grid = [[
- ^ready $ zia |
- |
- [Process exited 0] |
- |*2
- gained |
- {3:-- TERMINAL --} |
- ]],
- timeout = (4 * screen.timeout),
- }
- feed_data('\027[O')
- screen:expect([[
- ^ready $ zia |
- |
- [Process exited 0] |
- |*2
- lost |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('in press-enter prompt', function()
- feed_data(":echom 'msg1'|echom 'msg2'|echom 'msg3'|echom 'msg4'|echom 'msg5'\n")
- -- Execute :messages to provoke the press-enter prompt.
- feed_data(':messages\n')
- screen:expect {
- grid = [[
- msg1 |
- msg2 |
- msg3 |
- msg4 |
- msg5 |
- {10:Press ENTER or type command to continue}^ |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('\027[I')
- feed_data('\027[I')
- screen:expect {
- grid = [[
- msg1 |
- msg2 |
- msg3 |
- msg4 |
- msg5 |
- {10:Press ENTER or type command to continue}^ |
- {3:-- TERMINAL --} |
- ]],
- unchanged = true,
- }
- end)
- end)
- -- These tests require `tt` because --headless/--embed
- -- does not initialize the TUI.
- describe("TUI 't_Co' (terminal colors)", function()
- local screen
- local function assert_term_colors(term, colorterm, maxcolors)
- clear({ env = { TERM = term }, args = {} })
- screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- nvim_set .. ' notermguicolors',
- }, {
- env = {
- LANG = 'C',
- TERM = term or '',
- COLORTERM = colorterm or '',
- },
- })
- local tline
- if maxcolors == 8 then
- tline = '{9:~ }'
- elseif maxcolors == 16 then
- tline = '~ '
- else
- tline = '{4:~ }'
- end
- screen:expect(string.format(
- [[
- ^ |
- %s|*4
- |
- {3:-- TERMINAL --} |
- ]],
- tline
- ))
- feed_data(':echo &t_Co\n')
- screen:expect(string.format(
- [[
- ^ |
- %s|*4
- %-3s |
- {3:-- TERMINAL --} |
- ]],
- tline,
- tostring(maxcolors and maxcolors or '')
- ))
- end
- -- ansi and no terminal type at all:
- it('no TERM uses 8 colors', function()
- assert_term_colors(nil, nil, 8)
- end)
- it('TERM=ansi no COLORTERM uses 8 colors', function()
- assert_term_colors('ansi', nil, 8)
- end)
- it('TERM=ansi with COLORTERM=anything-no-number uses 16 colors', function()
- assert_term_colors('ansi', 'yet-another-term', 16)
- end)
- it('unknown TERM COLORTERM with 256 in name uses 256 colors', function()
- assert_term_colors('ansi', 'yet-another-term-256color', 256)
- end)
- it('TERM=ansi-256color sets 256 colours', function()
- assert_term_colors('ansi-256color', nil, 256)
- end)
- -- Unknown terminal types:
- it('unknown TERM no COLORTERM sets 8 colours', function()
- assert_term_colors('yet-another-term', nil, 8)
- end)
- it('unknown TERM with COLORTERM=anything-no-number uses 16 colors', function()
- assert_term_colors('yet-another-term', 'yet-another-term', 16)
- end)
- it('unknown TERM with 256 in name sets 256 colours', function()
- assert_term_colors('yet-another-term-256color', nil, 256)
- end)
- it('unknown TERM COLORTERM with 256 in name uses 256 colors', function()
- assert_term_colors('yet-another-term', 'yet-another-term-256color', 256)
- end)
- -- Linux kernel terminal emulator:
- it('TERM=linux uses 256 colors', function()
- assert_term_colors('linux', nil, 256)
- end)
- it('TERM=linux-16color uses 256 colors', function()
- assert_term_colors('linux-16color', nil, 256)
- end)
- it('TERM=linux-256color uses 256 colors', function()
- assert_term_colors('linux-256color', nil, 256)
- end)
- -- screen:
- --
- -- FreeBSD falls back to the built-in screen-256colour entry.
- -- Linux and MacOS have a screen entry in external terminfo with 8 colours,
- -- which is raised to 16 by COLORTERM.
- it('TERM=screen no COLORTERM uses 8/256 colors', function()
- if is_os('freebsd') then
- assert_term_colors('screen', nil, 256)
- else
- assert_term_colors('screen', nil, 8)
- end
- end)
- it('TERM=screen COLORTERM=screen uses 16/256 colors', function()
- if is_os('freebsd') then
- assert_term_colors('screen', 'screen', 256)
- else
- assert_term_colors('screen', 'screen', 16)
- end
- end)
- it('TERM=screen COLORTERM=screen-256color uses 256 colors', function()
- assert_term_colors('screen', 'screen-256color', 256)
- end)
- it('TERM=screen-256color no COLORTERM uses 256 colors', function()
- assert_term_colors('screen-256color', nil, 256)
- end)
- -- tmux:
- --
- -- FreeBSD and MacOS fall back to the built-in tmux-256colour entry.
- -- Linux has a tmux entry in external terminfo with 8 colours,
- -- which is raised to 256.
- it('TERM=tmux no COLORTERM uses 256 colors', function()
- assert_term_colors('tmux', nil, 256)
- end)
- it('TERM=tmux COLORTERM=tmux uses 256 colors', function()
- assert_term_colors('tmux', 'tmux', 256)
- end)
- it('TERM=tmux COLORTERM=tmux-256color uses 256 colors', function()
- assert_term_colors('tmux', 'tmux-256color', 256)
- end)
- it('TERM=tmux-256color no COLORTERM uses 256 colors', function()
- assert_term_colors('tmux-256color', nil, 256)
- end)
- -- xterm and imitators:
- it('TERM=xterm uses 256 colors', function()
- assert_term_colors('xterm', nil, 256)
- end)
- it('TERM=xterm COLORTERM=gnome-terminal uses 256 colors', function()
- assert_term_colors('xterm', 'gnome-terminal', 256)
- end)
- it('TERM=xterm COLORTERM=mate-terminal uses 256 colors', function()
- assert_term_colors('xterm', 'mate-terminal', 256)
- end)
- it('TERM=xterm-256color uses 256 colors', function()
- assert_term_colors('xterm-256color', nil, 256)
- end)
- -- rxvt and stterm:
- --
- -- FreeBSD and MacOS fall back to the built-in rxvt-256color and
- -- st-256colour entries.
- -- Linux has an rxvt, an st, and an st-16color entry in external terminfo
- -- with 8, 8, and 16 colours respectively, which are raised to 256.
- it('TERM=rxvt no COLORTERM uses 256 colors', function()
- assert_term_colors('rxvt', nil, 256)
- end)
- it('TERM=rxvt COLORTERM=rxvt uses 256 colors', function()
- assert_term_colors('rxvt', 'rxvt', 256)
- end)
- it('TERM=rxvt-256color uses 256 colors', function()
- assert_term_colors('rxvt-256color', nil, 256)
- end)
- it('TERM=st no COLORTERM uses 256 colors', function()
- assert_term_colors('st', nil, 256)
- end)
- it('TERM=st COLORTERM=st uses 256 colors', function()
- assert_term_colors('st', 'st', 256)
- end)
- it('TERM=st COLORTERM=st-256color uses 256 colors', function()
- assert_term_colors('st', 'st-256color', 256)
- end)
- it('TERM=st-16color no COLORTERM uses 8/256 colors', function()
- assert_term_colors('st', nil, 256)
- end)
- it('TERM=st-16color COLORTERM=st uses 16/256 colors', function()
- assert_term_colors('st', 'st', 256)
- end)
- it('TERM=st-16color COLORTERM=st-256color uses 256 colors', function()
- assert_term_colors('st', 'st-256color', 256)
- end)
- it('TERM=st-256color uses 256 colors', function()
- assert_term_colors('st-256color', nil, 256)
- end)
- -- gnome and vte:
- --
- -- FreeBSD and MacOS fall back to the built-in vte-256color entry.
- -- Linux has a gnome, a vte, a gnome-256color, and a vte-256color entry in
- -- external terminfo with 8, 8, 256, and 256 colours respectively, which are
- -- raised to 256.
- it('TERM=gnome no COLORTERM uses 256 colors', function()
- assert_term_colors('gnome', nil, 256)
- end)
- it('TERM=gnome COLORTERM=gnome uses 256 colors', function()
- assert_term_colors('gnome', 'gnome', 256)
- end)
- it('TERM=gnome COLORTERM=gnome-256color uses 256 colors', function()
- assert_term_colors('gnome', 'gnome-256color', 256)
- end)
- it('TERM=gnome-256color uses 256 colors', function()
- assert_term_colors('gnome-256color', nil, 256)
- end)
- it('TERM=vte no COLORTERM uses 256 colors', function()
- assert_term_colors('vte', nil, 256)
- end)
- it('TERM=vte COLORTERM=vte uses 256 colors', function()
- assert_term_colors('vte', 'vte', 256)
- end)
- it('TERM=vte COLORTERM=vte-256color uses 256 colors', function()
- assert_term_colors('vte', 'vte-256color', 256)
- end)
- it('TERM=vte-256color uses 256 colors', function()
- assert_term_colors('vte-256color', nil, 256)
- end)
- -- others:
- -- TODO(blueyed): this is made pending, since it causes failure + later hang
- -- when using non-compatible libvterm (#9494/#10179).
- pending('TERM=interix uses 8 colors', function()
- assert_term_colors('interix', nil, 8)
- end)
- it('TERM=iTerm.app uses 256 colors', function()
- assert_term_colors('iTerm.app', nil, 256)
- end)
- it('TERM=iterm uses 256 colors', function()
- assert_term_colors('iterm', nil, 256)
- end)
- end)
- -- These tests require `tt` because --headless/--embed
- -- does not initialize the TUI.
- describe("TUI 'term' option", function()
- local screen
- local function assert_term(term_envvar, term_expected)
- clear()
- screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- nvim_set .. ' notermguicolors',
- }, {
- env = {
- LANG = 'C',
- TERM = term_envvar or '',
- },
- })
- local full_timeout = screen.timeout
- retry(nil, 2 * full_timeout, function() -- Wait for TUI thread to set 'term'.
- feed_data(":echo 'term='.(&term)\n")
- screen:expect { any = 'term=' .. term_expected, timeout = 250 }
- end)
- end
- it('gets builtin term if $TERM is invalid', function()
- assert_term('foo', 'builtin_ansi')
- end)
- it('gets system-provided term if $TERM is valid', function()
- if is_os('openbsd') then
- assert_term('xterm', 'xterm')
- elseif is_os('bsd') then -- BSD lacks terminfo, builtin is always used.
- assert_term('xterm', 'builtin_xterm')
- elseif is_os('mac') then
- local status, _ = pcall(assert_term, 'xterm', 'xterm')
- if not status then
- pending('macOS: unibilium could not find terminfo')
- end
- else
- assert_term('xterm', 'xterm')
- end
- end)
- it('builtin terms', function()
- -- These non-standard terminfos are always builtin.
- assert_term('win32con', 'builtin_win32con')
- assert_term('conemu', 'builtin_conemu')
- assert_term('vtpcon', 'builtin_vtpcon')
- end)
- end)
- -- These tests require `tt` because --headless/--embed
- -- does not initialize the TUI.
- describe('TUI', function()
- local screen
- local logfile = 'Xtest_tui_verbose_log'
- after_each(function()
- os.remove(logfile)
- end)
- -- Runs (child) `nvim` in a TTY (:terminal), to start the builtin TUI.
- local function nvim_tui(extra_args)
- clear()
- screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- nvim_set .. ' notermguicolors',
- extra_args,
- }, {
- env = {
- LANG = 'C',
- },
- })
- end
- it('-V3log logs terminfo values', function()
- nvim_tui('-V3' .. logfile)
- -- Wait for TUI to start.
- feed_data('Gitext')
- screen:expect([[
- text^ |
- {4:~ }|*4
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]])
- retry(nil, 3000, function() -- Wait for log file to be flushed.
- local log = read_file('Xtest_tui_verbose_log') or ''
- eq('--- Terminal info --- {{{\n', string.match(log, '%-%-%- Terminal.-\n')) -- }}}
- ok(#log > 50)
- end)
- end)
- it('does not crash on large inputs #26099', function()
- nvim_tui()
- screen:expect([[
- ^ |
- {4:~ }|*4
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data(string.format('\027]52;c;%s\027\\', string.rep('A', 8192)))
- screen:expect {
- grid = [[
- ^ |
- {4:~ }|*4
- |
- {3:-- TERMINAL --} |
- ]],
- unchanged = true,
- }
- end)
- it('queries the terminal for truecolor support', function()
- clear()
- exec_lua([[
- vim.api.nvim_create_autocmd('TermRequest', {
- callback = function(args)
- local req = args.data
- local payload = req:match('^\027P%+q([%x;]+)$')
- if payload then
- local t = {}
- for cap in vim.gsplit(payload, ';') do
- local resp = string.format('\027P1+r%s\027\\', payload)
- vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
- t[vim.text.hexdecode(cap)] = true
- end
- vim.g.xtgettcap = t
- return true
- end
- end,
- })
- ]])
- local child_server = new_pipename()
- screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- }, {
- env = {
- VIMRUNTIME = os.getenv('VIMRUNTIME'),
- -- Force COLORTERM to be unset and use a TERM that does not contain Tc or RGB in terminfo.
- -- This will force the nested nvim instance to query with XTGETTCAP
- COLORTERM = '',
- TERM = 'xterm-256colors',
- },
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, 1000, function()
- eq({
- Tc = true,
- RGB = true,
- setrgbf = true,
- setrgbb = true,
- }, eval("get(g:, 'xtgettcap', '')"))
- eq({ true, 1 }, { child_session:request('nvim_eval', '&termguicolors') })
- end)
- end)
- it('does not query the terminal for truecolor support if $COLORTERM is set', function()
- clear()
- exec_lua([[
- vim.api.nvim_create_autocmd('TermRequest', {
- callback = function(args)
- local req = args.data
- vim.g.termrequest = req
- local xtgettcap = req:match('^\027P%+q([%x;]+)$')
- if xtgettcap then
- local t = {}
- for cap in vim.gsplit(xtgettcap, ';') do
- local resp = string.format('\027P1+r%s\027\\', xtgettcap)
- vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
- t[vim.text.hexdecode(cap)] = true
- end
- vim.g.xtgettcap = t
- return true
- elseif req:match('^\027P$qm\027\\$') then
- vim.g.decrqss = true
- end
- end,
- })
- ]])
- local child_server = new_pipename()
- screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- }, {
- env = {
- VIMRUNTIME = os.getenv('VIMRUNTIME'),
- -- With COLORTERM=256, Nvim should not query the terminal and should not set 'tgc'
- COLORTERM = '256',
- TERM = 'xterm-256colors',
- },
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, 1000, function()
- local xtgettcap = eval("get(g:, 'xtgettcap', {})")
- eq(nil, xtgettcap['Tc'])
- eq(nil, xtgettcap['RGB'])
- eq(nil, xtgettcap['setrgbf'])
- eq(nil, xtgettcap['setrgbb'])
- eq(0, eval([[get(g:, 'decrqss')]]))
- eq({ true, 0 }, { child_session:request('nvim_eval', '&termguicolors') })
- end)
- end)
- it('queries the terminal for OSC 52 support', function()
- clear()
- exec_lua([[
- vim.api.nvim_create_autocmd('TermRequest', {
- callback = function(args)
- local req = args.data
- local payload = req:match('^\027P%+q([%x;]+)$')
- if payload and vim.text.hexdecode(payload) == 'Ms' then
- local resp = string.format('\027P1+r%s=%s\027\\', payload, vim.text.hexencode('\027]52;;\027\\'))
- vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
- return true
- end
- end,
- })
- ]])
- local child_server = new_pipename()
- screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- -- Use --clean instead of -u NONE to load the osc52 plugin
- '--clean',
- }, {
- env = {
- VIMRUNTIME = os.getenv('VIMRUNTIME'),
- },
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, 1000, function()
- eq({ true, { osc52 = true } }, { child_session:request('nvim_eval', 'g:termfeatures') })
- end)
- end)
- end)
- describe('TUI bg color', function()
- before_each(clear)
- it('is properly set in a nested Nvim instance when background=dark', function()
- command('highlight clear Normal')
- command('set background=dark') -- set outer Nvim background
- local child_server = new_pipename()
- local screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile',
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, nil, function()
- eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') })
- end)
- end)
- it('is properly set in a nested Nvim instance when background=light', function()
- command('highlight clear Normal')
- command('set background=light') -- set outer Nvim background
- local child_server = new_pipename()
- local screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile',
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, nil, function()
- eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') })
- end)
- end)
- it('queries the terminal for background color', function()
- exec_lua([[
- vim.api.nvim_create_autocmd('TermRequest', {
- callback = function(args)
- local req = args.data
- if req == '\027]11;?' then
- vim.g.oscrequest = true
- return true
- end
- end,
- })
- ]])
- tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile',
- })
- retry(nil, 1000, function()
- eq(true, eval("get(g:, 'oscrequest', v:false)"))
- end)
- end)
- it('triggers OptionSet from automatic background processing', function()
- local screen = tt.setup_child_nvim({
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile',
- '-c',
- 'autocmd OptionSet background echo "did OptionSet, yay!"',
- })
- screen:expect([[
- ^ |
- {3:~} |*3
- {5:[No Name] 0,0-1 All}|
- did OptionSet, yay! |
- {3:-- TERMINAL --} |
- ]])
- end)
- it('sends theme update notifications when background changes #31652', function()
- command('set background=dark') -- set outer Nvim background
- local child_server = new_pipename()
- local screen = tt.setup_child_nvim({
- '--listen',
- child_server,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- 'set noswapfile',
- })
- screen:expect({ any = '%[No Name%]' })
- local child_session = n.connect(child_server)
- retry(nil, nil, function()
- eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') })
- end)
- command('set background=light') -- set outer Nvim background
- retry(nil, nil, function()
- eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') })
- end)
- end)
- end)
- -- These tests require `tt` because --headless/--embed
- -- does not initialize the TUI.
- describe('TUI as a client', function()
- after_each(function()
- os.remove(testlog)
- end)
- it('connects to remote instance (with its own TUI)', function()
- local server_super = n.new_session(false)
- local client_super = n.new_session(true)
- set_session(server_super)
- local server_pipe = new_pipename()
- local screen_server = tt.setup_child_nvim({
- '--listen',
- server_pipe,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- nvim_set .. ' notermguicolors laststatus=2 background=dark',
- })
- feed_data('iHello, World')
- screen_server:expect {
- grid = [[
- Hello, World^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('\027')
- screen_server:expect {
- grid = [[
- Hello, Worl^d |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- set_session(client_super)
- local screen_client = tt.setup_child_nvim({
- '--server',
- server_pipe,
- '--remote-ui',
- })
- screen_client:expect {
- grid = [[
- Hello, Worl^d |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- -- grid smaller than containing terminal window is cleared properly
- feed_data(":call setline(1,['a'->repeat(&columns)]->repeat(&lines))\n")
- feed_data('0:set lines=3\n')
- screen_server:expect {
- grid = [[
- ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {5:[No Name] [+] }|
- |*4
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data(':q!\n')
- server_super:close()
- client_super:close()
- end)
- it('connects to remote instance (--headless)', function()
- local server = n.new_session(false)
- local client_super = n.new_session(true, { env = { NVIM_LOG_FILE = testlog } })
- set_session(server)
- local server_pipe = api.nvim_get_vvar('servername')
- server:request('nvim_input', 'iHalloj!<Esc>')
- server:request('nvim_command', 'set notermguicolors')
- set_session(client_super)
- local screen_client = tt.setup_child_nvim({
- '--server',
- server_pipe,
- '--remote-ui',
- })
- screen_client:expect {
- grid = [[
- Halloj^! |
- {4:~ }|*4
- |
- {3:-- TERMINAL --} |
- ]],
- }
- -- No heap-use-after-free when receiving UI events after deadly signal #22184
- server:request('nvim_input', ('a'):rep(1000))
- exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
- screen_client:expect {
- grid = [[
- Vim: Caught deadly signal 'SIGTERM' |
- |*2
- [Process exited 1]^ |
- |*2
- {3:-- TERMINAL --} |
- ]],
- }
- eq(0, api.nvim_get_vvar('shell_error'))
- -- exits on input eof #22244
- fn.system({ nvim_prog, '--server', server_pipe, '--remote-ui' })
- eq(1, api.nvim_get_vvar('shell_error'))
- client_super:close()
- server:close()
- if is_os('mac') then
- assert_log('uv_tty_set_mode failed: Unknown system error %-102', testlog)
- end
- end)
- it('throws error when no server exists', function()
- clear()
- local screen = tt.setup_child_nvim({
- '--server',
- '127.0.0.1:2436546',
- '--remote-ui',
- }, { cols = 60 })
- screen:expect([[
- Remote ui failed to start: {MATCH:.*}|
- |
- [Process exited 1]^ |
- |*3
- {3:-- TERMINAL --} |
- ]])
- end)
- local function test_remote_tui_quit(status)
- local server_super = n.new_session(false)
- local client_super = n.new_session(true)
- set_session(server_super)
- local server_pipe = new_pipename()
- local screen_server = tt.setup_child_nvim({
- '--listen',
- server_pipe,
- '-u',
- 'NONE',
- '-i',
- 'NONE',
- '--cmd',
- 'colorscheme vim',
- '--cmd',
- nvim_set .. ' notermguicolors laststatus=2 background=dark',
- })
- screen_server:expect {
- grid = [[
- ^ |
- {4:~ }|*3
- {5:[No Name] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('iHello, World')
- screen_server:expect {
- grid = [[
- Hello, World^ |
- {4:~ }|*3
- {5:[No Name] [+] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]],
- }
- feed_data('\027')
- screen_server:expect {
- grid = [[
- Hello, Worl^d |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- set_session(client_super)
- local screen_client = tt.setup_child_nvim({
- '--server',
- server_pipe,
- '--remote-ui',
- })
- screen_client:expect {
- grid = [[
- Hello, Worl^d |
- {4:~ }|*3
- {5:[No Name] [+] }|
- |
- {3:-- TERMINAL --} |
- ]],
- }
- -- quitting the server
- set_session(server_super)
- feed_data(status and ':' .. status .. 'cquit!\n' or ':quit!\n')
- status = status and status or 0
- screen_server:expect {
- grid = [[
- |
- [Process exited ]] .. status .. [[]^ {MATCH:%s+}|
- |*4
- {3:-- TERMINAL --} |
- ]],
- }
- -- assert that client has exited
- screen_client:expect {
- grid = [[
- |
- [Process exited ]] .. status .. [[]^ {MATCH:%s+}|
- |*4
- {3:-- TERMINAL --} |
- ]],
- }
- server_super:close()
- client_super:close()
- end
- describe('exits when server quits', function()
- it('with :quit', function()
- test_remote_tui_quit()
- end)
- it('with :cquit', function()
- test_remote_tui_quit(42)
- end)
- end)
- end)
|