decorations_spec.lua 246 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear = n.clear
  5. local feed = n.feed
  6. local insert = n.insert
  7. local exec_lua = n.exec_lua
  8. local exec = n.exec
  9. local expect_events = t.expect_events
  10. local api = n.api
  11. local fn = n.fn
  12. local command = n.command
  13. local eq = t.eq
  14. local assert_alive = n.assert_alive
  15. local pcall_err = t.pcall_err
  16. describe('decorations providers', function()
  17. local screen
  18. before_each(function()
  19. clear()
  20. screen = Screen.new(40, 8)
  21. screen:set_default_attr_ids {
  22. [1] = {bold=true, foreground=Screen.colors.Blue};
  23. [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
  24. [3] = {foreground = Screen.colors.Brown};
  25. [4] = {foreground = Screen.colors.Blue1};
  26. [5] = {foreground = Screen.colors.Magenta};
  27. [6] = {bold = true, foreground = Screen.colors.Brown};
  28. [7] = {background = Screen.colors.Gray90};
  29. [8] = {bold = true, reverse = true};
  30. [9] = {reverse = true};
  31. [10] = {italic = true, background = Screen.colors.Magenta};
  32. [11] = {foreground = Screen.colors.Red, background = tonumber('0x005028')};
  33. [12] = {foreground = tonumber('0x990000')};
  34. [13] = {background = Screen.colors.LightBlue};
  35. [14] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue};
  36. [15] = {special = Screen.colors.Blue, undercurl = true},
  37. [16] = {special = Screen.colors.Red, undercurl = true},
  38. [17] = {foreground = Screen.colors.Red},
  39. [18] = {bold = true, foreground = Screen.colors.SeaGreen};
  40. [19] = {bold = true};
  41. }
  42. end)
  43. local mulholland = [[
  44. // just to see if there was an accident
  45. // on Mulholland Drive
  46. try_start();
  47. bufref_T save_buf;
  48. switch_buffer(&save_buf, buf);
  49. posp = getmark(mark, false);
  50. restore_buffer(&save_buf); ]]
  51. local function setup_provider(code)
  52. return exec_lua ([[
  53. local api = vim.api
  54. _G.ns1 = api.nvim_create_namespace "ns1"
  55. ]] .. (code or [[
  56. beamtrace = {}
  57. local function on_do(kind, ...)
  58. table.insert(beamtrace, {kind, ...})
  59. end
  60. ]]) .. [[
  61. api.nvim_set_decoration_provider(_G.ns1, {
  62. on_start = on_do; on_buf = on_do;
  63. on_win = on_do; on_line = on_do;
  64. on_end = on_do; _on_spell_nav = on_do;
  65. })
  66. return _G.ns1
  67. ]])
  68. end
  69. local function check_trace(expected)
  70. local actual = exec_lua [[ local b = beamtrace beamtrace = {} return b ]]
  71. expect_events(expected, actual, "beam trace")
  72. end
  73. it('does not OOM when inserting, rather than appending, to the decoration provider vector', function()
  74. -- Add a dummy decoration provider with a larger ns id than what setup_provider() creates.
  75. -- This forces get_decor_provider() to insert into the providers vector,
  76. -- rather than append, which used to spin in an infinite loop allocating
  77. -- memory until nvim crashed/was killed.
  78. setup_provider([[
  79. local ns2 = api.nvim_create_namespace "ns2"
  80. api.nvim_set_decoration_provider(ns2, {})
  81. ]])
  82. assert_alive()
  83. end)
  84. it('leave a trace', function()
  85. insert(mulholland)
  86. setup_provider()
  87. screen:expect{grid=[[
  88. // just to see if there was an accident |
  89. // on Mulholland Drive |
  90. try_start(); |
  91. bufref_T save_buf; |
  92. switch_buffer(&save_buf, buf); |
  93. posp = getmark(mark, false); |
  94. restore_buffer(&save_buf);^ |
  95. |
  96. ]]}
  97. check_trace {
  98. { "start", 4 };
  99. { "win", 1000, 1, 0, 6 };
  100. { "line", 1000, 1, 0 };
  101. { "line", 1000, 1, 1 };
  102. { "line", 1000, 1, 2 };
  103. { "line", 1000, 1, 3 };
  104. { "line", 1000, 1, 4 };
  105. { "line", 1000, 1, 5 };
  106. { "line", 1000, 1, 6 };
  107. { "end", 4 };
  108. }
  109. feed "iü<esc>"
  110. screen:expect{grid=[[
  111. // just to see if there was an accident |
  112. // on Mulholland Drive |
  113. try_start(); |
  114. bufref_T save_buf; |
  115. switch_buffer(&save_buf, buf); |
  116. posp = getmark(mark, false); |
  117. restore_buffer(&save_buf);^ü |
  118. |
  119. ]]}
  120. check_trace {
  121. { "start", 5 };
  122. { "buf", 1, 5 };
  123. { "win", 1000, 1, 0, 6 };
  124. { "line", 1000, 1, 6 };
  125. { "end", 5 };
  126. }
  127. end)
  128. it('can have single provider', function()
  129. insert(mulholland)
  130. setup_provider [[
  131. local hl = api.nvim_get_hl_id_by_name "ErrorMsg"
  132. local test_ns = api.nvim_create_namespace "mulholland"
  133. function on_do(event, ...)
  134. if event == "line" then
  135. local win, buf, line = ...
  136. api.nvim_buf_set_extmark(buf, test_ns, line, line,
  137. { end_line = line, end_col = line+1,
  138. hl_group = hl,
  139. ephemeral = true
  140. })
  141. end
  142. end
  143. ]]
  144. screen:expect{grid=[[
  145. {2:/}/ just to see if there was an accident |
  146. /{2:/} on Mulholland Drive |
  147. tr{2:y}_start(); |
  148. buf{2:r}ef_T save_buf; |
  149. swit{2:c}h_buffer(&save_buf, buf); |
  150. posp {2:=} getmark(mark, false); |
  151. restor{2:e}_buffer(&save_buf);^ |
  152. |
  153. ]]}
  154. end)
  155. it('can indicate spellchecked points', function()
  156. exec [[
  157. set spell
  158. set spelloptions=noplainbuffer
  159. syntax off
  160. ]]
  161. insert [[
  162. I am well written text.
  163. i am not capitalized.
  164. I am a speling mistakke.
  165. ]]
  166. setup_provider [[
  167. local ns = api.nvim_create_namespace "spell"
  168. beamtrace = {}
  169. local function on_do(kind, ...)
  170. if kind == 'win' or kind == 'spell' then
  171. api.nvim_buf_set_extmark(0, ns, 0, 0, {
  172. end_row = 2,
  173. end_col = 23,
  174. spell = true,
  175. priority = 20,
  176. ephemeral = true
  177. })
  178. end
  179. table.insert(beamtrace, {kind, ...})
  180. end
  181. ]]
  182. check_trace {
  183. { "start", 5 };
  184. { "win", 1000, 1, 0, 3 };
  185. { "line", 1000, 1, 0 };
  186. { "line", 1000, 1, 1 };
  187. { "line", 1000, 1, 2 };
  188. { "line", 1000, 1, 3 };
  189. { "end", 5 };
  190. }
  191. feed "gg0"
  192. screen:expect{grid=[[
  193. ^I am well written text. |
  194. {15:i} am not capitalized. |
  195. I am a {16:speling} {16:mistakke}. |
  196. |
  197. {1:~ }|*3
  198. |
  199. ]]}
  200. feed "]s"
  201. check_trace {
  202. { "spell", 1000, 1, 1, 0, 1, -1 };
  203. }
  204. screen:expect{grid=[[
  205. I am well written text. |
  206. {15:^i} am not capitalized. |
  207. I am a {16:speling} {16:mistakke}. |
  208. |
  209. {1:~ }|*3
  210. |
  211. ]]}
  212. feed "]s"
  213. check_trace {
  214. { "spell", 1000, 1, 2, 7, 2, -1 };
  215. }
  216. screen:expect{grid=[[
  217. I am well written text. |
  218. {15:i} am not capitalized. |
  219. I am a {16:^speling} {16:mistakke}. |
  220. |
  221. {1:~ }|*3
  222. |
  223. ]]}
  224. -- spell=false with higher priority does disable spell
  225. local ns = api.nvim_create_namespace "spell"
  226. local id = api.nvim_buf_set_extmark(0, ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
  227. screen:expect{grid=[[
  228. I am well written text. |
  229. i am not capitalized. |
  230. I am a ^speling mistakke. |
  231. |
  232. {1:~ }|*3
  233. |
  234. ]]}
  235. feed "]s"
  236. screen:expect{grid=[[
  237. I am well written text. |
  238. i am not capitalized. |
  239. I am a ^speling mistakke. |
  240. |
  241. {1:~ }|*3
  242. {17:search hit BOTTOM, continuing at TOP} |
  243. ]]}
  244. command('echo ""')
  245. -- spell=false with lower priority doesn't disable spell
  246. api.nvim_buf_set_extmark(0, ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false })
  247. screen:expect{grid=[[
  248. I am well written text. |
  249. {15:i} am not capitalized. |
  250. I am a {16:^speling} {16:mistakke}. |
  251. |
  252. {1:~ }|*3
  253. |
  254. ]]}
  255. feed "]s"
  256. screen:expect{grid=[[
  257. I am well written text. |
  258. {15:i} am not capitalized. |
  259. I am a {16:speling} {16:^mistakke}. |
  260. |
  261. {1:~ }|*3
  262. |
  263. ]]}
  264. end)
  265. it('can predefine highlights', function()
  266. screen:try_resize(40, 16)
  267. insert(mulholland)
  268. exec [[
  269. 3
  270. set ft=c
  271. syntax on
  272. set number cursorline
  273. split
  274. ]]
  275. local ns1 = setup_provider()
  276. for k,v in pairs {
  277. LineNr = {italic=true, bg="Magenta"};
  278. Comment = {fg="#FF0000", bg = 80*256+40};
  279. CursorLine = {link="ErrorMsg"};
  280. } do api.nvim_set_hl(ns1, k, v) end
  281. screen:expect{grid=[[
  282. {3: 1 }{4:// just to see if there was an accid}|
  283. {3: }{4:ent} |
  284. {3: 2 }{4:// on Mulholland Drive} |
  285. {6: 3 }{7:^try_start(); }|
  286. {3: 4 }bufref_T save_buf; |
  287. {3: 5 }switch_buffer(&save_buf, buf); |
  288. {3: 6 }posp = getmark(mark, {5:false}); |
  289. {8:[No Name] [+] }|
  290. {3: 2 }{4:// on Mulholland Drive} |
  291. {6: 3 }{7:try_start(); }|
  292. {3: 4 }bufref_T save_buf; |
  293. {3: 5 }switch_buffer(&save_buf, buf); |
  294. {3: 6 }posp = getmark(mark, {5:false}); |
  295. {3: 7 }restore_buffer(&save_buf); |
  296. {9:[No Name] [+] }|
  297. |
  298. ]]}
  299. api.nvim_set_hl_ns(ns1)
  300. screen:expect{grid=[[
  301. {10: 1 }{11:// just to see if there was an accid}|
  302. {10: }{11:ent} |
  303. {10: 2 }{11:// on Mulholland Drive} |
  304. {6: 3 }{2:^try_start(); }|
  305. {10: 4 }bufref_T save_buf; |
  306. {10: 5 }switch_buffer(&save_buf, buf); |
  307. {10: 6 }posp = getmark(mark, {5:false}); |
  308. {8:[No Name] [+] }|
  309. {10: 2 }{11:// on Mulholland Drive} |
  310. {6: 3 }{2:try_start(); }|
  311. {10: 4 }bufref_T save_buf; |
  312. {10: 5 }switch_buffer(&save_buf, buf); |
  313. {10: 6 }posp = getmark(mark, {5:false}); |
  314. {10: 7 }restore_buffer(&save_buf); |
  315. {9:[No Name] [+] }|
  316. |
  317. ]]}
  318. exec_lua [[
  319. local api = vim.api
  320. local thewin = api.nvim_get_current_win()
  321. local ns2 = api.nvim_create_namespace 'ns2'
  322. api.nvim_set_decoration_provider (ns2, {
  323. on_win = function (_, win, buf)
  324. api.nvim_set_hl_ns_fast(win == thewin and _G.ns1 or ns2)
  325. end;
  326. })
  327. ]]
  328. screen:expect{grid=[[
  329. {10: 1 }{11:// just to see if there was an accid}|
  330. {10: }{11:ent} |
  331. {10: 2 }{11:// on Mulholland Drive} |
  332. {6: 3 }{2:^try_start(); }|
  333. {10: 4 }bufref_T save_buf; |
  334. {10: 5 }switch_buffer(&save_buf, buf); |
  335. {10: 6 }posp = getmark(mark, {5:false}); |
  336. {8:[No Name] [+] }|
  337. {3: 2 }{4:// on Mulholland Drive} |
  338. {6: 3 }{7:try_start(); }|
  339. {3: 4 }bufref_T save_buf; |
  340. {3: 5 }switch_buffer(&save_buf, buf); |
  341. {3: 6 }posp = getmark(mark, {5:false}); |
  342. {3: 7 }restore_buffer(&save_buf); |
  343. {9:[No Name] [+] }|
  344. |
  345. ]]}
  346. end)
  347. it('can break an existing link', function()
  348. insert(mulholland)
  349. local ns1 = setup_provider()
  350. exec [[
  351. highlight OriginalGroup guifg='#990000'
  352. highlight link LinkGroup OriginalGroup
  353. ]]
  354. api.nvim_buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
  355. screen:expect{grid=[[
  356. // just to see if there was an accident |
  357. // on Mulholland Drive |
  358. try_start(); {12:- not red} |
  359. bufref_T save_buf; |
  360. switch_buffer(&save_buf, buf); |
  361. posp = getmark(mark, false); |
  362. restore_buffer(&save_buf);^ |
  363. |
  364. ]]}
  365. api.nvim_set_hl(ns1, 'LinkGroup', {fg = 'Blue'})
  366. api.nvim_set_hl_ns(ns1)
  367. screen:expect{grid=[[
  368. // just to see if there was an accident |
  369. // on Mulholland Drive |
  370. try_start(); {4:- not red} |
  371. bufref_T save_buf; |
  372. switch_buffer(&save_buf, buf); |
  373. posp = getmark(mark, false); |
  374. restore_buffer(&save_buf);^ |
  375. |
  376. ]]}
  377. end)
  378. it("with 'default': do not break an existing link", function()
  379. insert(mulholland)
  380. local ns1 = setup_provider()
  381. exec [[
  382. highlight OriginalGroup guifg='#990000'
  383. highlight link LinkGroup OriginalGroup
  384. ]]
  385. api.nvim_buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
  386. screen:expect{grid=[[
  387. // just to see if there was an accident |
  388. // on Mulholland Drive |
  389. try_start(); {12:- not red} |
  390. bufref_T save_buf; |
  391. switch_buffer(&save_buf, buf); |
  392. posp = getmark(mark, false); |
  393. restore_buffer(&save_buf);^ |
  394. |
  395. ]]}
  396. api.nvim_set_hl(ns1, 'LinkGroup', {fg = 'Blue', default=true})
  397. api.nvim_set_hl_ns(ns1)
  398. feed 'k'
  399. screen:expect{grid=[[
  400. // just to see if there was an accident |
  401. // on Mulholland Drive |
  402. try_start(); {12:- not red} |
  403. bufref_T save_buf; |
  404. switch_buffer(&save_buf, buf); |
  405. posp = getmark(mark, false^); |
  406. restore_buffer(&save_buf); |
  407. |
  408. ]]}
  409. end)
  410. it('can have virtual text', function()
  411. insert(mulholland)
  412. setup_provider [[
  413. local hl = api.nvim_get_hl_id_by_name "ErrorMsg"
  414. local test_ns = api.nvim_create_namespace "mulholland"
  415. function on_do(event, ...)
  416. if event == "line" then
  417. local win, buf, line = ...
  418. api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
  419. virt_text = {{'+', 'ErrorMsg'}};
  420. virt_text_pos='overlay';
  421. ephemeral = true;
  422. })
  423. end
  424. end
  425. ]]
  426. screen:expect{grid=[[
  427. {2:+}/ just to see if there was an accident |
  428. {2:+}/ on Mulholland Drive |
  429. {2:+}ry_start(); |
  430. {2:+}ufref_T save_buf; |
  431. {2:+}witch_buffer(&save_buf, buf); |
  432. {2:+}osp = getmark(mark, false); |
  433. {2:+}estore_buffer(&save_buf);^ |
  434. |
  435. ]]}
  436. end)
  437. it('can have virtual text of the style: right_align', function()
  438. insert(mulholland)
  439. setup_provider [[
  440. local hl = api.nvim_get_hl_id_by_name "ErrorMsg"
  441. local test_ns = api.nvim_create_namespace "mulholland"
  442. function on_do(event, ...)
  443. if event == "line" then
  444. local win, buf, line = ...
  445. api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
  446. virt_text = {{'+'}, {string.rep(' ', line+1), 'ErrorMsg'}};
  447. virt_text_pos='right_align';
  448. ephemeral = true;
  449. })
  450. end
  451. end
  452. ]]
  453. screen:expect{grid=[[
  454. // just to see if there was an acciden+{2: }|
  455. // on Mulholland Drive +{2: }|
  456. try_start(); +{2: }|
  457. bufref_T save_buf; +{2: }|
  458. switch_buffer(&save_buf, buf); +{2: }|
  459. posp = getmark(mark, false); +{2: }|
  460. restore_buffer(&save_buf);^ +{2: }|
  461. |
  462. ]]}
  463. end)
  464. it('virtual text works with wrapped lines', function()
  465. insert(mulholland)
  466. feed('ggJj3JjJ')
  467. setup_provider [[
  468. local hl = api.nvim_get_hl_id_by_name "ErrorMsg"
  469. local test_ns = api.nvim_create_namespace "mulholland"
  470. function on_do(event, ...)
  471. if event == "line" then
  472. local win, buf, line = ...
  473. api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
  474. virt_text = {{string.rep('/', line+1), 'ErrorMsg'}};
  475. virt_text_pos='eol';
  476. ephemeral = true;
  477. })
  478. api.nvim_buf_set_extmark(buf, test_ns, line, 6, {
  479. virt_text = {{string.rep('*', line+1), 'ErrorMsg'}};
  480. virt_text_pos='overlay';
  481. ephemeral = true;
  482. })
  483. api.nvim_buf_set_extmark(buf, test_ns, line, 39, {
  484. virt_text = {{string.rep('!', line+1), 'ErrorMsg'}};
  485. virt_text_win_col=20;
  486. ephemeral = true;
  487. })
  488. api.nvim_buf_set_extmark(buf, test_ns, line, 40, {
  489. virt_text = {{string.rep('?', line+1), 'ErrorMsg'}};
  490. virt_text_win_col=10;
  491. ephemeral = true;
  492. })
  493. api.nvim_buf_set_extmark(buf, test_ns, line, 40, {
  494. virt_text = {{string.rep(';', line+1), 'ErrorMsg'}};
  495. virt_text_pos='overlay';
  496. ephemeral = true;
  497. })
  498. api.nvim_buf_set_extmark(buf, test_ns, line, 40, {
  499. virt_text = {{'+'}, {string.rep(' ', line+1), 'ErrorMsg'}};
  500. virt_text_pos='right_align';
  501. ephemeral = true;
  502. })
  503. end
  504. end
  505. ]]
  506. screen:expect{grid=[[
  507. // jus{2:*} to see if th{2:!}re was an accident |
  508. {2:;}n Mulholl{2:?}nd Drive {2:/} +{2: }|
  509. try_st{2:**}t(); bufref_{2:!!}save_buf; switch_b|
  510. {2:;;}fer(&sav{2:??}buf, buf); {2://} +{2: }|
  511. posp ={2:***}tmark(mark,{2:!!!}lse);^ restore_buf|
  512. {2:;;;}(&save_{2:???}); {2:///} +{2: }|
  513. {1:~ }|
  514. |
  515. ]]}
  516. command('setlocal breakindent breakindentopt=shift:2')
  517. screen:expect{grid=[[
  518. // jus{2:*} to see if th{2:!}re was an accident |
  519. {2:;}n Mulho{2:?}land Drive {2:/} +{2: }|
  520. try_st{2:**}t(); bufref_{2:!!}save_buf; switch_b|
  521. {2:;;}fer(&s{2:??}e_buf, buf); {2://} +{2: }|
  522. posp ={2:***}tmark(mark,{2:!!!}lse);^ restore_buf|
  523. {2:;;;}(&sav{2:???}uf); {2:///} +{2: }|
  524. {1:~ }|
  525. |
  526. ]]}
  527. end)
  528. it('can highlight beyond EOL', function()
  529. insert(mulholland)
  530. setup_provider [[
  531. local test_ns = api.nvim_create_namespace "veberod"
  532. function on_do(event, ...)
  533. if event == "line" then
  534. local win, buf, line = ...
  535. if string.find(api.nvim_buf_get_lines(buf, line, line+1, true)[1], "buf") then
  536. api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
  537. end_line = line+1;
  538. hl_group = 'DiffAdd';
  539. hl_eol = true;
  540. ephemeral = true;
  541. })
  542. end
  543. end
  544. end
  545. ]]
  546. screen:expect{grid=[[
  547. // just to see if there was an accident |
  548. // on Mulholland Drive |
  549. try_start(); |
  550. {13:bufref_T save_buf; }|
  551. {13:switch_buffer(&save_buf, buf); }|
  552. posp = getmark(mark, false); |
  553. {13:restore_buffer(&save_buf);^ }|
  554. |
  555. ]]}
  556. end)
  557. it('can create and remove signs when CursorMoved autocommand validates botline #18661', function()
  558. exec_lua([[
  559. local lines = {}
  560. for i = 1, 200 do
  561. lines[i] = 'hello' .. tostring(i)
  562. end
  563. vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
  564. ]])
  565. setup_provider([[
  566. local function on_do(kind, winid, bufnr, topline, botline)
  567. if kind == 'win' then
  568. if topline < 100 and botline > 100 then
  569. api.nvim_buf_set_extmark(bufnr, ns1, 99, -1, { sign_text = 'X' })
  570. else
  571. api.nvim_buf_clear_namespace(bufnr, ns1, 0, -1)
  572. end
  573. end
  574. end
  575. ]])
  576. command([[autocmd CursorMoved * call line('w$')]])
  577. api.nvim_win_set_cursor(0, {100, 0})
  578. screen:expect([[
  579. {14: }hello97 |
  580. {14: }hello98 |
  581. {14: }hello99 |
  582. {14:X }^hello100 |
  583. {14: }hello101 |
  584. {14: }hello102 |
  585. {14: }hello103 |
  586. |
  587. ]])
  588. api.nvim_win_set_cursor(0, {1, 0})
  589. screen:expect([[
  590. ^hello1 |
  591. hello2 |
  592. hello3 |
  593. hello4 |
  594. hello5 |
  595. hello6 |
  596. hello7 |
  597. |
  598. ]])
  599. end)
  600. it('does allow removing extmarks during on_line callbacks', function()
  601. exec_lua([[
  602. eok = true
  603. ]])
  604. setup_provider([[
  605. local function on_do(kind, winid, bufnr, topline, botline)
  606. if kind == 'line' then
  607. api.nvim_buf_set_extmark(bufnr, ns1, 1, -1, { sign_text = 'X' })
  608. eok = pcall(api.nvim_buf_clear_namespace, bufnr, ns1, 0, -1)
  609. end
  610. end
  611. ]])
  612. exec_lua([[
  613. assert(eok == true)
  614. ]])
  615. end)
  616. it('on_line is invoked only for buffer lines', function()
  617. insert(mulholland)
  618. command('vnew')
  619. insert(mulholland)
  620. feed('dd')
  621. command('windo diffthis')
  622. exec_lua([[
  623. out_of_bound = false
  624. ]])
  625. setup_provider([[
  626. local function on_do(kind, _, bufnr, row)
  627. if kind == 'line' then
  628. if not api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] then
  629. out_of_bound = true
  630. end
  631. end
  632. end
  633. ]])
  634. feed('<C-e>')
  635. exec_lua([[
  636. assert(out_of_bound == false)
  637. ]])
  638. end)
  639. it('errors gracefully', function()
  640. insert(mulholland)
  641. setup_provider [[
  642. function on_do(...)
  643. error "Foo"
  644. end
  645. ]]
  646. screen:expect{grid=[[
  647. {2:Error in decoration provider ns1.start:} |
  648. {2:Error executing lua: [string "<nvim>"]:4}|
  649. {2:: Foo} |
  650. {2:stack traceback:} |
  651. {2: [C]: in function 'error'} |
  652. {2: [string "<nvim>"]:4: in function}|
  653. {2: <[string "<nvim>"]:3>} |
  654. {18:Press ENTER or type command to continue}^ |
  655. ]]}
  656. end)
  657. it('can add new providers during redraw #26652', function()
  658. setup_provider [[
  659. local ns = api.nvim_create_namespace('test_no_add')
  660. function on_do(...)
  661. api.nvim_set_decoration_provider(ns, {})
  662. end
  663. ]]
  664. n.assert_alive()
  665. end)
  666. it('is not invoked repeatedly in Visual mode with vim.schedule() #20235', function()
  667. exec_lua([[_G.cnt = 0]])
  668. setup_provider([[
  669. function on_do(event, ...)
  670. if event == 'win' then
  671. vim.schedule(function() end)
  672. _G.cnt = _G.cnt + 1
  673. end
  674. end
  675. ]])
  676. feed('v')
  677. screen:expect([[
  678. ^ |
  679. {1:~ }|*6
  680. {19:-- VISUAL --} |
  681. ]])
  682. eq(2, exec_lua([[return _G.cnt]]))
  683. end)
  684. it('can do large changes to the marktree', function()
  685. insert("line1 with a lot of text\nline2 with a lot of text")
  686. setup_provider([[
  687. function on_do(event, _, _, row)
  688. if event == 'win' or (event == 'line' and row == 1) then
  689. vim.api.nvim_buf_clear_namespace(0, ns1, 0, -1)
  690. for i = 0,1 do
  691. for j = 0,23 do
  692. vim.api.nvim_buf_set_extmark(0, ns1, i, j, {hl_group='ErrorMsg', end_col = j+1})
  693. end
  694. end
  695. end
  696. end
  697. ]])
  698. -- Doesn't crash when modifying the marktree between line1 and line2
  699. screen:expect([[
  700. {2:line1 with a lot of text} |
  701. {2:line2 with a lot of tex^t} |
  702. {1:~ }|*5
  703. |
  704. ]])
  705. end)
  706. end)
  707. local example_text = [[
  708. for _,item in ipairs(items) do
  709. local text, hl_id_cell, count = unpack(item)
  710. if hl_id_cell ~= nil then
  711. hl_id = hl_id_cell
  712. end
  713. for _ = 1, (count or 1) do
  714. local cell = line[colpos]
  715. cell.text = text
  716. cell.hl_id = hl_id
  717. colpos = colpos+1
  718. end
  719. end]]
  720. describe('extmark decorations', function()
  721. local screen, ns
  722. before_each( function()
  723. clear()
  724. screen = Screen.new(50, 15)
  725. screen:set_default_attr_ids {
  726. [1] = {bold=true, foreground=Screen.colors.Blue};
  727. [2] = {foreground = Screen.colors.Brown};
  728. [3] = {bold = true, foreground = Screen.colors.SeaGreen};
  729. [4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
  730. [5] = {foreground = Screen.colors.Brown, bold = true};
  731. [6] = {foreground = Screen.colors.DarkCyan};
  732. [7] = {foreground = Screen.colors.Grey0, background = tonumber('0xff4c4c')};
  733. [8] = {foreground = tonumber('0x180606'), background = tonumber('0xff4c4c')};
  734. [9] = {foreground = tonumber('0xe40c0c'), background = tonumber('0xff4c4c'), bold = true};
  735. [10] = {foreground = tonumber('0xb20000'), background = tonumber('0xff4c4c')};
  736. [11] = {blend = 30, background = Screen.colors.Red1};
  737. [12] = {foreground = Screen.colors.Brown, blend = 30, background = Screen.colors.Red1, bold = true};
  738. [13] = {foreground = Screen.colors.Fuchsia};
  739. [14] = {background = Screen.colors.Red1, foreground = Screen.colors.Black};
  740. [15] = {background = Screen.colors.Red1, foreground = tonumber('0xb20000')};
  741. [16] = {blend = 30, background = Screen.colors.Red1, foreground = Screen.colors.Magenta1};
  742. [17] = {bold = true, foreground = Screen.colors.Brown, background = Screen.colors.LightGrey};
  743. [18] = {background = Screen.colors.LightGrey};
  744. [19] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGrey};
  745. [20] = {foreground = tonumber('0x180606'), background = tonumber('0xf13f3f')};
  746. [21] = {foreground = Screen.colors.Gray0, background = tonumber('0xf13f3f')};
  747. [22] = {foreground = tonumber('0xb20000'), background = tonumber('0xf13f3f')};
  748. [23] = {foreground = Screen.colors.Magenta1, background = Screen.colors.LightGrey};
  749. [24] = {bold = true};
  750. [25] = {background = Screen.colors.LightRed};
  751. [26] = {background = Screen.colors.DarkGrey, foreground = Screen.colors.LightGrey};
  752. [27] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Black};
  753. [28] = {underline = true, foreground = Screen.colors.SlateBlue};
  754. [29] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGrey, underline = true};
  755. [30] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGrey, underline = true};
  756. [31] = {underline = true, foreground = Screen.colors.DarkCyan};
  757. [32] = {underline = true};
  758. [33] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey};
  759. [34] = {background = Screen.colors.Yellow};
  760. [35] = {background = Screen.colors.Yellow, bold = true, foreground = Screen.colors.Blue};
  761. [36] = {foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Red};
  762. [37] = {background = Screen.colors.WebGray, foreground = Screen.colors.DarkBlue};
  763. [38] = {background = Screen.colors.LightBlue};
  764. [39] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true};
  765. [40] = {reverse = true};
  766. [41] = {bold = true, reverse = true};
  767. [42] = {undercurl = true, special = Screen.colors.Red};
  768. [43] = {background = Screen.colors.Yellow, undercurl = true, special = Screen.colors.Red};
  769. [44] = {background = Screen.colors.LightMagenta};
  770. }
  771. ns = api.nvim_create_namespace 'test'
  772. end)
  773. it('empty virtual text at eol should not break colorcolumn #17860', function()
  774. insert(example_text)
  775. feed('gg')
  776. command('set colorcolumn=40')
  777. screen:expect([[
  778. ^for _,item in ipairs(items) do {25: } |
  779. local text, hl_id_cell, count = unp{25:a}ck(item) |
  780. if hl_id_cell ~= nil then {25: } |
  781. hl_id = hl_id_cell {25: } |
  782. end {25: } |
  783. for _ = 1, (count or 1) do {25: } |
  784. local cell = line[colpos] {25: } |
  785. cell.text = text {25: } |
  786. cell.hl_id = hl_id {25: } |
  787. colpos = colpos+1 {25: } |
  788. end {25: } |
  789. end {25: } |
  790. {1:~ }|*2
  791. |
  792. ]])
  793. api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_text={{''}}, virt_text_pos='eol'})
  794. screen:expect_unchanged()
  795. end)
  796. it('can have virtual text of overlay position', function()
  797. insert(example_text)
  798. feed 'gg'
  799. for i = 1,9 do
  800. api.nvim_buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
  801. if i == 3 or (i >= 6 and i <= 9) then
  802. api.nvim_buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
  803. end
  804. end
  805. api.nvim_buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
  806. -- can "float" beyond end of line
  807. api.nvim_buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
  808. -- bound check: right edge of window
  809. api.nvim_buf_set_extmark(0, ns, 2, 26, { virt_text={{'bork bork bork'}, {(' bork'):rep(10), 'ErrorMsg'}}, virt_text_pos='overlay'})
  810. -- empty virt_text should not change anything
  811. api.nvim_buf_set_extmark(0, ns, 6, 16, { virt_text={{''}}, virt_text_pos='overlay'})
  812. screen:expect{grid=[[
  813. ^for _,item in ipairs(items) do |
  814. {2:|} local text, hl_id_cell, count = unpack(item) |
  815. {2:|} if hl_id_cell ~= nil tbork bork bork{4: bork bork}|
  816. {2:|} {1:|} hl_id = hl_id_cell |
  817. {2:|} end |
  818. {2:|} for _ = 1, (count or 1) {4:loopy} |
  819. {2:|} {1:|} local cell = line[colpos] |
  820. {2:|} {1:|} cell.text = text |
  821. {2:|} {1:|} cell.hl_id = hl_id |
  822. {2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
  823. end |
  824. end |
  825. {1:~ }|*2
  826. |
  827. ]]}
  828. -- handles broken lines
  829. screen:try_resize(22, 25)
  830. screen:expect{grid=[[
  831. ^for _,item in ipairs(i|
  832. tems) do |
  833. {2:|} local text, hl_id_|
  834. cell, count = unpack(i|
  835. tem) |
  836. {2:|} if hl_id_cell ~= n|
  837. il tbork bork bork{4: bor}|
  838. {2:|} {1:|} hl_id = hl_id_|
  839. cell |
  840. {2:|} end |
  841. {2:|} for _ = 1, (count |
  842. or 1) {4:loopy} |
  843. {2:|} {1:|} local cell = l|
  844. ine[colpos] |
  845. {2:|} {1:|} cell.text = te|
  846. xt |
  847. {2:|} {1:|} cell.hl_id = h|
  848. l_id |
  849. {2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
  850. s+1 |
  851. end |
  852. end |
  853. {1:~ }|*2
  854. |
  855. ]]}
  856. -- truncating in the middle of a char leaves a space
  857. api.nvim_buf_set_lines(0, 0, 1, true, {'for _,item in ipairs(items) do -- 古古古'})
  858. api.nvim_buf_set_lines(0, 10, 12, true, {' end -- ??????????', 'end -- ?古古古古?古古'})
  859. api.nvim_buf_set_extmark(0, ns, 0, 35, { virt_text={{'A', 'ErrorMsg'}, {'AA'}}, virt_text_pos='overlay'})
  860. api.nvim_buf_set_extmark(0, ns, 10, 19, { virt_text={{'口口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
  861. api.nvim_buf_set_extmark(0, ns, 11, 21, { virt_text={{'口口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
  862. api.nvim_buf_set_extmark(0, ns, 11, 8, { virt_text={{'口口', 'ErrorMsg'}}, virt_text_pos='overlay'})
  863. screen:expect{grid=[[
  864. ^for _,item in ipairs(i|
  865. tems) do -- {4:A}AA 古 |
  866. {2:|} local text, hl_id_|
  867. cell, count = unpack(i|
  868. tem) |
  869. {2:|} if hl_id_cell ~= n|
  870. il tbork bork bork{4: bor}|
  871. {2:|} {1:|} hl_id = hl_id_|
  872. cell |
  873. {2:|} end |
  874. {2:|} for _ = 1, (count |
  875. or 1) {4:loopy} |
  876. {2:|} {1:|} local cell = l|
  877. ine[colpos] |
  878. {2:|} {1:|} cell.text = te|
  879. xt |
  880. {2:|} {1:|} cell.hl_id = h|
  881. l_id |
  882. {2:|} {1:|} cofoo{3:bar}{4:!!}olpo|
  883. s+1 |
  884. end -- ???????{4:口 }|
  885. end -- {4:口口} 古古{4:口口 }|
  886. {1:~ }|*2
  887. |
  888. ]]}
  889. screen:try_resize(82, 13)
  890. screen:expect{grid=[[
  891. ^for _,item in ipairs(items) do -- {4:A}AA 古 |
  892. {2:|} local text, hl_id_cell, count = unpack(item) |
  893. {2:|} if hl_id_cell ~= nil tbork bork bork{4: bork bork bork bork bork bork bork bork b}|
  894. {2:|} {1:|} hl_id = hl_id_cell |
  895. {2:|} end |
  896. {2:|} for _ = 1, (count or 1) {4:loopy} |
  897. {2:|} {1:|} local cell = line[colpos] |
  898. {2:|} {1:|} cell.text = text |
  899. {2:|} {1:|} cell.hl_id = hl_id |
  900. {2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
  901. end -- ???????{4:口口口} |
  902. end -- {4:口口} 古古{4:口口口} |
  903. |
  904. ]]}
  905. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  906. screen:expect{grid=[[
  907. ^for _,item in ipairs(items) do -- 古古古 |
  908. local text, hl_id_cell, count = unpack(item) |
  909. if hl_id_cell ~= nil then |
  910. hl_id = hl_id_cell |
  911. end |
  912. for _ = 1, (count or 1) do |
  913. local cell = line[colpos] |
  914. cell.text = text |
  915. cell.hl_id = hl_id |
  916. colpos = colpos+1 |
  917. end -- ?????????? |
  918. end -- ?古古古古?古古 |
  919. |
  920. ]]}
  921. end)
  922. it('overlay virtual text works with wrapped lines #25158', function()
  923. screen:try_resize(50, 6)
  924. insert(('ab'):rep(100))
  925. for i = 0, 9 do
  926. api.nvim_buf_set_extmark(0, ns, 0, 42 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay'})
  927. api.nvim_buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
  928. end
  929. screen:expect{grid=[[
  930. ababababababababababababababababababababab{4:01234567}|
  931. {4:89}abababababababababababababababababababa{4:012345678}|
  932. {4:9}babababababababababababababababababababababababab|
  933. ababababababababababababababababababababababababa^b|
  934. {1:~ }|
  935. |
  936. ]]}
  937. command('set showbreak=++')
  938. screen:expect{grid=[[
  939. ababababababababababababababababababababab{4:01234567}|
  940. {1:++}{4:89}abababababababababababababababababababa{4:0123456}|
  941. {1:++}{4:789}babababababababababababababababababababababab|
  942. {1:++}abababababababababababababababababababababababab|
  943. {1:++}ababa^b |
  944. |
  945. ]]}
  946. feed('2gkvg0')
  947. screen:expect{grid=[[
  948. ababababababababababababababababababababab{4:01234567}|
  949. {1:++}{4:89}abababababababababababababababababababa{4:0123456}|
  950. {1:++}^a{27:babab}ababababababababababababababababababababab|
  951. {1:++}abababababababababababababababababababababababab|
  952. {1:++}ababab |
  953. {24:-- VISUAL --} |
  954. ]]}
  955. feed('o')
  956. screen:expect{grid=[[
  957. ababababababababababababababababababababab{4:01234567}|
  958. {1:++}{4:89}abababababababababababababababababababa{4:0123456}|
  959. {1:++}{27:ababa}^bababababababababababababababababababababab|
  960. {1:++}abababababababababababababababababababababababab|
  961. {1:++}ababab |
  962. {24:-- VISUAL --} |
  963. ]]}
  964. feed('gk')
  965. screen:expect{grid=[[
  966. ababababababababababababababababababababab{4:01234567}|
  967. {1:++}{4:89}aba^b{27:ababababababababababababababababababababab}|
  968. {1:++}{27:a}{4:89}babababababababababababababababababababababab|
  969. {1:++}abababababababababababababababababababababababab|
  970. {1:++}ababab |
  971. {24:-- VISUAL --} |
  972. ]]}
  973. feed('o')
  974. screen:expect{grid=[[
  975. ababababababababababababababababababababab{4:01234567}|
  976. {1:++}{4:89}aba{27:bababababababababababababababababababababab}|
  977. {1:++}^a{4:89}babababababababababababababababababababababab|
  978. {1:++}abababababababababababababababababababababababab|
  979. {1:++}ababab |
  980. {24:-- VISUAL --} |
  981. ]]}
  982. feed('<Esc>$')
  983. command('set number showbreak=')
  984. screen:expect{grid=[[
  985. {2: 1 }ababababababababababababababababababababab{4:0123}|
  986. {2: }{4:456789}abababababababababababababababababababa{4:0}|
  987. {2: }{4:123456789}babababababababababababababababababab|
  988. {2: }ababababababababababababababababababababababab|
  989. {2: }abababababababa^b |
  990. |
  991. ]]}
  992. command('set cpoptions+=n')
  993. screen:expect{grid=[[
  994. {2: 1 }ababababababababababababababababababababab{4:0123}|
  995. {4:456789}abababababababababababababababababababa{4:01234}|
  996. {4:56789}babababababababababababababababababababababab|
  997. ababababababababababababababababababababababababab|
  998. aba^b |
  999. |
  1000. ]]}
  1001. feed('0g$hi<Tab>')
  1002. screen:expect{grid=[[
  1003. {2: 1 }ababababababababababababababababababababab{4:01} |
  1004. {4:^23456789}abababababababababababababababababababa{4:0}|
  1005. {4:123456789}babababababababababababababababababababab|
  1006. ababababababababababababababababababababababababab|
  1007. abababab |
  1008. {24:-- INSERT --} |
  1009. ]]}
  1010. end)
  1011. it('virt_text_hide hides overlay virtual text when extmark is off-screen', function()
  1012. screen:try_resize(50, 3)
  1013. command('set nowrap')
  1014. api.nvim_buf_set_lines(0, 0, -1, true, {'-- ' .. ('…'):rep(57)})
  1015. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text={{'?????', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
  1016. api.nvim_buf_set_extmark(0, ns, 0, 123, { virt_text={{'!!!!!', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
  1017. screen:expect{grid=[[
  1018. {4:^?????}……………………………………………………………………………………………………{4:!!!!!}……|
  1019. {1:~ }|
  1020. |
  1021. ]]}
  1022. feed('40zl')
  1023. screen:expect{grid=[[
  1024. ^………{4:!!!!!}……………………………… |
  1025. {1:~ }|
  1026. |
  1027. ]]}
  1028. feed('3zl')
  1029. screen:expect{grid=[[
  1030. {4:^!!!!!}……………………………… |
  1031. {1:~ }|
  1032. |
  1033. ]]}
  1034. feed('7zl')
  1035. screen:expect{grid=[[
  1036. ^………………………… |
  1037. {1:~ }|
  1038. |
  1039. ]]}
  1040. command('set wrap smoothscroll')
  1041. screen:expect{grid=[[
  1042. {4:?????}……………………………………………………………………………………………………{4:!!!!!}……|
  1043. ^………………………… |
  1044. |
  1045. ]]}
  1046. feed('<C-E>')
  1047. screen:expect{grid=[[
  1048. {1:<<<}………………^… |
  1049. {1:~ }|
  1050. |
  1051. ]]}
  1052. screen:try_resize(40, 3)
  1053. screen:expect{grid=[[
  1054. {1:<<<}{4:!!!!!}……………………………^… |
  1055. {1:~ }|
  1056. |
  1057. ]]}
  1058. feed('<C-Y>')
  1059. screen:expect{grid=[[
  1060. {4:?????}……………………………………………………………………………………………|
  1061. ………{4:!!!!!}……………………………^… |
  1062. |
  1063. ]]}
  1064. end)
  1065. it('overlay virtual text works on and after a TAB #24022', function()
  1066. screen:try_resize(40, 3)
  1067. api.nvim_buf_set_lines(0, 0, -1, true, {'\t\tline 1'})
  1068. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
  1069. api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = {{'BB', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
  1070. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
  1071. screen:expect{grid=[[
  1072. {34:AA} ^ {34:BB} {34:CC}ne 1 |
  1073. {1:~ }|
  1074. |
  1075. ]]}
  1076. command('setlocal list listchars=tab:<->')
  1077. screen:expect{grid=[[
  1078. {35:^AA}{1:----->}{35:BB}{1:----->}{34:CC}ne 1 |
  1079. {1:~ }|
  1080. |
  1081. ]]}
  1082. end)
  1083. it('can have virtual text of overlay position and styling', function()
  1084. insert(example_text)
  1085. feed 'gg'
  1086. command 'set ft=lua'
  1087. command 'syntax on'
  1088. screen:expect{grid=[[
  1089. {5:^for} _,item {5:in} {6:ipairs}(items) {5:do} |
  1090. {5:local} text, hl_id_cell, count {5:=} unpack(item) |
  1091. {5:if} hl_id_cell {5:~=} {13:nil} {5:then} |
  1092. hl_id {5:=} hl_id_cell |
  1093. {5:end} |
  1094. {5:for} _ {5:=} {13:1}, (count {5:or} {13:1}) {5:do} |
  1095. {5:local} cell {5:=} line[colpos] |
  1096. cell.text {5:=} text |
  1097. cell.hl_id {5:=} hl_id |
  1098. colpos {5:=} colpos{5:+}{13:1} |
  1099. {5:end} |
  1100. {5:end} |
  1101. {1:~ }|*2
  1102. |
  1103. ]]}
  1104. command 'hi Blendy guibg=Red blend=30'
  1105. command 'hi! Visual guifg=NONE guibg=LightGrey'
  1106. api.nvim_buf_set_extmark(0, ns, 1, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend'})
  1107. api.nvim_buf_set_extmark(0, ns, 2, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine'})
  1108. api.nvim_buf_set_extmark(0, ns, 3, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace'})
  1109. api.nvim_buf_set_extmark(0, ns, 4, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend', virt_text_hide=true})
  1110. api.nvim_buf_set_extmark(0, ns, 5, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine', virt_text_hide=true})
  1111. api.nvim_buf_set_extmark(0, ns, 6, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace', virt_text_hide=true})
  1112. screen:expect{grid=[[
  1113. {5:^for} _,item {5:in} {6:ipairs}(items) {5:do} |
  1114. {5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count {5:=} unpack(item) |
  1115. {5:i}{12:c}{11:ombining col}{12:or} {13:nil} {5:then} |
  1116. {11:replacing color}d_cell |
  1117. {5:e}{8:bl}{7:endy}{10: }{7:text}{10: }{7:-}{10: }{7:here} |
  1118. {5:f}{12:co}{11:mbi}{12:n}{11:i}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
  1119. {11:replacing color} line[colpos] |
  1120. cell.text {5:=} text |
  1121. cell.hl_id {5:=} hl_id |
  1122. colpos {5:=} colpos{5:+}{13:1} |
  1123. {5:end} |
  1124. {5:end} |
  1125. {1:~ }|*2
  1126. |
  1127. ]]}
  1128. feed 'V5G'
  1129. screen:expect{grid=[[
  1130. {17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} |
  1131. {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count }{17:=}{18: unpack(item)} |
  1132. {18: }{17:i}{12:c}{11:ombining col}{12:or}{18: }{23:nil}{18: }{17:then} |
  1133. {18: }{11:replacing color}{18:d_cell} |
  1134. {18: }{5:^e}{17:nd} |
  1135. {5:f}{12:co}{11:mbi}{12:n}{11:i}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
  1136. {11:replacing color} line[colpos] |
  1137. cell.text {5:=} text |
  1138. cell.hl_id {5:=} hl_id |
  1139. colpos {5:=} colpos{5:+}{13:1} |
  1140. {5:end} |
  1141. {5:end} |
  1142. {1:~ }|*2
  1143. {24:-- VISUAL LINE --} |
  1144. ]]}
  1145. feed 'jj'
  1146. screen:expect{grid=[[
  1147. {17:for}{18: _,item }{17:in}{18: }{19:ipairs}{18:(items) }{17:do} |
  1148. {18: }{17:l}{20:blen}{21:dy}{22:e}{21:text}{22:h}{21:-}{22:_}{21:here}{18:ell, count }{17:=}{18: unpack(item)} |
  1149. {18: }{17:i}{12:c}{11:ombining col}{12:or}{18: }{23:nil}{18: }{17:then} |
  1150. {18: }{11:replacing color}{18:d_cell} |
  1151. {18: }{17:end} |
  1152. {18: }{17:for}{18: _ }{17:=}{18: }{23:1}{18:, (count }{17:or}{18: }{23:1}{18:) }{17:do} |
  1153. {18: }^ {18: }{17:local}{18: cell }{17:=}{18: line[colpos]} |
  1154. cell.text {5:=} text |
  1155. cell.hl_id {5:=} hl_id |
  1156. colpos {5:=} colpos{5:+}{13:1} |
  1157. {5:end} |
  1158. {5:end} |
  1159. {1:~ }|*2
  1160. {24:-- VISUAL LINE --} |
  1161. ]]}
  1162. end)
  1163. it('can have virtual text of right_align and fixed win_col position', function()
  1164. insert(example_text)
  1165. feed 'gg'
  1166. api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
  1167. api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text={{'VERY', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
  1168. api.nvim_buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
  1169. api.nvim_buf_set_extmark(0, ns, 2, 10, { virt_text={{'MUCH', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
  1170. api.nvim_buf_set_extmark(0, ns, 3, 14, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
  1171. api.nvim_buf_set_extmark(0, ns, 3, 14, { virt_text={{'ERROR', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
  1172. api.nvim_buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'})
  1173. api.nvim_buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_pos='right_align', hl_mode='blend'})
  1174. -- empty virt_text should not change anything
  1175. api.nvim_buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_win_col=14, hl_mode='blend'})
  1176. api.nvim_buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_pos='right_align', hl_mode='blend'})
  1177. screen:expect{grid=[[
  1178. ^for _,item in ipairs(items) do |
  1179. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1180. if hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1181. hl_id = hl_id_cell {4:Error} {4:ERROR}|
  1182. end |
  1183. for _ = 1, (count or 1) do |
  1184. local cell = line[colpos] |
  1185. {1:-} cell.text = text {1:-}|
  1186. cell.hl_id = hl_id |
  1187. colpos = colpos+1 |
  1188. end |
  1189. end |
  1190. {1:~ }|*2
  1191. |
  1192. ]]}
  1193. feed '3G12|i<cr><esc>'
  1194. screen:expect{grid=[[
  1195. for _,item in ipairs(items) do |
  1196. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1197. if hl_i {4:Much} {4:MUCH}|
  1198. ^d_cell ~= nil then |
  1199. hl_id = hl_id_cell {4:Error} {4:ERROR}|
  1200. end |
  1201. for _ = 1, (count or 1) do |
  1202. local cell = line[colpos] |
  1203. {1:-} cell.text = text {1:-}|
  1204. cell.hl_id = hl_id |
  1205. colpos = colpos+1 |
  1206. end |
  1207. end |
  1208. {1:~ }|
  1209. |
  1210. ]]}
  1211. feed 'u:<cr>'
  1212. screen:expect{grid=[[
  1213. for _,item in ipairs(items) do |
  1214. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1215. if hl_i^d_cell ~= nil then {4:Much} {4:MUCH}|
  1216. hl_id = hl_id_cell {4:Error} {4:ERROR}|
  1217. end |
  1218. for _ = 1, (count or 1) do |
  1219. local cell = line[colpos] |
  1220. {1:-} cell.text = text {1:-}|
  1221. cell.hl_id = hl_id |
  1222. colpos = colpos+1 |
  1223. end |
  1224. end |
  1225. {1:~ }|*2
  1226. : |
  1227. ]]}
  1228. feed '8|i<cr><esc>'
  1229. screen:expect{grid=[[
  1230. for _,item in ipairs(items) do |
  1231. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1232. if |
  1233. ^hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1234. hl_id = hl_id_cell {4:Error} {4:ERROR}|
  1235. end |
  1236. for _ = 1, (count or 1) do |
  1237. local cell = line[colpos] |
  1238. {1:-} cell.text = text {1:-}|
  1239. cell.hl_id = hl_id |
  1240. colpos = colpos+1 |
  1241. end |
  1242. end |
  1243. {1:~ }|
  1244. |
  1245. ]]}
  1246. feed 'jI-- <esc>..........'
  1247. screen:expect{grid=[[
  1248. for _,item in ipairs(items) do |
  1249. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1250. if |
  1251. hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1252. --^ -- -- -- -- -- -- --{4:Error}- -- hl_i{4:ERROR}|
  1253. l_id_cell |
  1254. end |
  1255. for _ = 1, (count or 1) do |
  1256. local cell = line[colpos] |
  1257. {1:-} cell.text = text {1:-}|
  1258. cell.hl_id = hl_id |
  1259. colpos = colpos+1 |
  1260. end |
  1261. end |
  1262. |
  1263. ]]}
  1264. api.nvim_buf_set_extmark(0, ns, 4, 50, { virt_text={{'EOL', 'NonText'}} })
  1265. screen:expect{grid=[[
  1266. for _,item in ipairs(items) do |
  1267. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1268. if |
  1269. hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1270. --^ -- -- -- -- -- -- --{4:Error}- -- hl_i{4:ERROR}|
  1271. l_id_cell {1:EOL} |
  1272. end |
  1273. for _ = 1, (count or 1) do |
  1274. local cell = line[colpos] |
  1275. {1:-} cell.text = text {1:-}|
  1276. cell.hl_id = hl_id |
  1277. colpos = colpos+1 |
  1278. end |
  1279. end |
  1280. |
  1281. ]]}
  1282. feed '.'
  1283. screen:expect{grid=[[
  1284. for _,item in ipairs(items) do |
  1285. local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
  1286. if |
  1287. hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1288. --^ -- -- -- -- -- -- -- -- -- -- -- hl_id |
  1289. = hl_id_cell {1:EOL} {4:Error} {4:ERROR}|
  1290. end |
  1291. for _ = 1, (count or 1) do |
  1292. local cell = line[colpos] |
  1293. {1:-} cell.text = text {1:-}|
  1294. cell.hl_id = hl_id |
  1295. colpos = colpos+1 |
  1296. end |
  1297. end |
  1298. |
  1299. ]]}
  1300. command 'set number'
  1301. screen:expect{grid=[[
  1302. {2: 1 }for _,item in ipairs(items) do |
  1303. {2: 2 } local text, hl_id_cell, cou{4:Very} unpack{4:VERY}|
  1304. {2: }m) |
  1305. {2: 3 } if |
  1306. {2: 4 }hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1307. {2: 5 } --^ -- -- -- -- -- -- -- -- -- -- -- hl|
  1308. {2: }_id = hl_id_cell {1:EOL} {4:Error} {4:ERROR}|
  1309. {2: 6 } end |
  1310. {2: 7 } for _ = 1, (count or 1) do |
  1311. {2: 8 } local cell = line[colpos] |
  1312. {2: 9 } {1:-} cell.text = text {1:-}|
  1313. {2: 10 } cell.hl_id = hl_id |
  1314. {2: 11 } colpos = colpos+1 |
  1315. {2: 12 } end |
  1316. |
  1317. ]]}
  1318. command 'set cpoptions+=n'
  1319. screen:expect{grid=[[
  1320. {2: 1 }for _,item in ipairs(items) do |
  1321. {2: 2 } local text, hl_id_cell, cou{4:Very} unpack{4:VERY}|
  1322. m) |
  1323. {2: 3 } if |
  1324. {2: 4 }hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1325. {2: 5 } --^ -- -- -- -- -- -- -- -- -- -- -- hl|
  1326. _id = hl_id_cell {1:EOL} {4:Error} {4:ERROR}|
  1327. {2: 6 } end |
  1328. {2: 7 } for _ = 1, (count or 1) do |
  1329. {2: 8 } local cell = line[colpos] |
  1330. {2: 9 } {1:-} cell.text = text {1:-}|
  1331. {2: 10 } cell.hl_id = hl_id |
  1332. {2: 11 } colpos = colpos+1 |
  1333. {2: 12 } end |
  1334. |
  1335. ]]}
  1336. command 'set cpoptions-=n nowrap'
  1337. screen:expect{grid=[[
  1338. {2: 1 }for _,item in ipairs(items) do |
  1339. {2: 2 } local text, hl_id_cell, cou{4:Very} unpack{4:VERY}|
  1340. {2: 3 } if |
  1341. {2: 4 }hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1342. {2: 5 } --^ -- -- -- -- -- -- --{4:Error}- -- {4:ERROR}|
  1343. {2: 6 } end |
  1344. {2: 7 } for _ = 1, (count or 1) do |
  1345. {2: 8 } local cell = line[colpos] |
  1346. {2: 9 } {1:-} cell.text = text {1:-}|
  1347. {2: 10 } cell.hl_id = hl_id |
  1348. {2: 11 } colpos = colpos+1 |
  1349. {2: 12 } end |
  1350. {2: 13 }end |
  1351. {1:~ }|
  1352. |
  1353. ]]}
  1354. feed '12zl'
  1355. screen:expect{grid=[[
  1356. {2: 1 }n ipairs(items) do |
  1357. {2: 2 }xt, hl_id_cell, count = unpack({4:Very}) {4:VERY}|
  1358. {2: 3 } |
  1359. {2: 4 }= nil then {4:Much} {4:MUCH}|
  1360. {2: 5 }^- -- -- -- -- -- -- -- -- -- --{4:Error}d = h{4:ERROR}|
  1361. {2: 6 } |
  1362. {2: 7 }1, (count or 1) do |
  1363. {2: 8 }l cell = line[colpos] |
  1364. {2: 9 }.tex{1:-} = text {1:-}|
  1365. {2: 10 }.hl_id = hl_id |
  1366. {2: 11 }os = colpos+1 |
  1367. {2: 12 } |
  1368. {2: 13 } |
  1369. {1:~ }|
  1370. |
  1371. ]]}
  1372. feed('fhi<Tab>')
  1373. screen:expect{grid=[[
  1374. {2: 1 }n ipairs(items) do |
  1375. {2: 2 }xt, hl_id_cell, count = unpack({4:Very}) {4:VERY}|
  1376. {2: 3 } |
  1377. {2: 4 }= nil then {4:Much} {4:MUCH}|
  1378. {2: 5 }- -- -- -- -- -- -- -- -- -- --{4:Error}^hl_id{4:ERROR}|
  1379. {2: 6 } |
  1380. {2: 7 }1, (count or 1) do |
  1381. {2: 8 }l cell = line[colpos] |
  1382. {2: 9 }.tex{1:-} = text {1:-}|
  1383. {2: 10 }.hl_id = hl_id |
  1384. {2: 11 }os = colpos+1 |
  1385. {2: 12 } |
  1386. {2: 13 } |
  1387. {1:~ }|
  1388. {24:-- INSERT --} |
  1389. ]]}
  1390. feed('<Esc>0')
  1391. screen:expect{grid=[[
  1392. {2: 1 }for _,item in ipairs(items) do |
  1393. {2: 2 } local text, hl_id_cell, cou{4:Very} unpack{4:VERY}|
  1394. {2: 3 } if |
  1395. {2: 4 }hl_id_cell ~= nil then {4:Much} {4:MUCH}|
  1396. {2: 5 }^ -- -- -- -- -- -- -- --{4:Error}- -- {4:ERROR}|
  1397. {2: 6 } end |
  1398. {2: 7 } for _ = 1, (count or 1) do |
  1399. {2: 8 } local cell = line[colpos] |
  1400. {2: 9 } {1:-} cell.text = text {1:-}|
  1401. {2: 10 } cell.hl_id = hl_id |
  1402. {2: 11 } colpos = colpos+1 |
  1403. {2: 12 } end |
  1404. {2: 13 }end |
  1405. {1:~ }|
  1406. |
  1407. ]]}
  1408. end)
  1409. it('virtual text win_col out of window does not break display #25645', function()
  1410. screen:try_resize(51, 6)
  1411. command('vnew')
  1412. api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 50) })
  1413. screen:expect{grid=[[
  1414. ^aaaaaaaaaaaaaaaaaaaaaaaaa│ |
  1415. aaaaaaaaaaaaaaaaaaaaaaaaa│{1:~ }|
  1416. {1:~ }│{1:~ }|*2
  1417. {41:[No Name] [+] }{40:[No Name] }|
  1418. |
  1419. ]]}
  1420. local extmark_opts = { virt_text_win_col = 35, virt_text = { { ' ', 'Comment' } } }
  1421. api.nvim_buf_set_extmark(0, ns, 0, 0, extmark_opts)
  1422. screen:expect_unchanged()
  1423. assert_alive()
  1424. end)
  1425. it('can have virtual text on folded line', function()
  1426. insert([[
  1427. 11111
  1428. 22222
  1429. 33333]])
  1430. command('1,2fold')
  1431. screen:try_resize(50, 3)
  1432. feed('zb')
  1433. -- XXX: the behavior of overlay virtual text at non-zero column is strange:
  1434. -- 1. With 'wrap' it is never shown.
  1435. -- 2. With 'nowrap' it is shown only if the extmark is hidden before leftcol.
  1436. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'overlay' })
  1437. api.nvim_buf_set_extmark(0, ns, 0, 5, { virt_text = {{'BB', 'Underlined'}}, hl_mode = 'combine', virt_text_win_col = 10 })
  1438. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'right_align' })
  1439. screen:expect{grid=[[
  1440. {29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|
  1441. 3333^3 |
  1442. |
  1443. ]]}
  1444. command('set nowrap')
  1445. screen:expect_unchanged()
  1446. feed('zl')
  1447. screen:expect{grid=[[
  1448. {29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|
  1449. 333^3 |
  1450. |
  1451. ]]}
  1452. feed('zl')
  1453. screen:expect{grid=[[
  1454. {29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|
  1455. 33^3 |
  1456. |
  1457. ]]}
  1458. feed('zl')
  1459. screen:expect{grid=[[
  1460. {29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|
  1461. 3^3 |
  1462. |
  1463. ]]}
  1464. end)
  1465. it('virtual text works below diff filler lines', function()
  1466. screen:try_resize(53, 8)
  1467. insert([[
  1468. aaaaa
  1469. bbbbb
  1470. ccccc
  1471. ddddd
  1472. eeeee]])
  1473. command('rightbelow vnew')
  1474. insert([[
  1475. bbbbb
  1476. ccccc
  1477. ddddd
  1478. eeeee]])
  1479. command('windo diffthis')
  1480. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, virt_text_pos = 'overlay' })
  1481. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB', 'Underlined'}}, virt_text_win_col = 10 })
  1482. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CC', 'Underlined'}}, virt_text_pos = 'right_align' })
  1483. screen:expect{grid=[[
  1484. {37: }{38:aaaaa }│{37: }{39:------------------------}|
  1485. {37: }bbbbb │{37: }{28:AA}bbb {28:BB} {28:CC}|
  1486. {37: }ccccc │{37: }ccccc |
  1487. {37: }ddddd │{37: }ddddd |
  1488. {37: }eeeee │{37: }eeee^e |
  1489. {1:~ }│{1:~ }|
  1490. {40:[No Name] [+] }{41:[No Name] [+] }|
  1491. |
  1492. ]]}
  1493. command('windo set wrap')
  1494. screen:expect_unchanged()
  1495. end)
  1496. it('can have virtual text which combines foreground and background groups', function()
  1497. screen:try_resize(20, 5)
  1498. screen:set_default_attr_ids {
  1499. [1] = {bold=true, foreground=Screen.colors.Blue};
  1500. [2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
  1501. [3] = {background = tonumber('0x123456'), foreground = tonumber('0xcccccc')};
  1502. [4] = {background = tonumber('0x234567'), foreground = tonumber('0xbbbbbb')};
  1503. [5] = {background = tonumber('0x234567'), foreground = tonumber('0xcccccc')};
  1504. [6] = {bold = true, foreground = tonumber('0xcccccc'), background = tonumber('0x234567')};
  1505. }
  1506. exec [[
  1507. hi BgOne guibg=#123456
  1508. hi BgTwo guibg=#234567
  1509. hi FgEin guifg=#bbbbbb
  1510. hi FgZwei guifg=#cccccc
  1511. hi VeryBold gui=bold
  1512. ]]
  1513. insert('##')
  1514. local vt = {
  1515. {'a', {'BgOne', 'FgEin'}};
  1516. {'b', {'BgOne', 'FgZwei'}};
  1517. {'c', {'BgTwo', 'FgEin'}};
  1518. {'d', {'BgTwo', 'FgZwei'}};
  1519. {'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
  1520. }
  1521. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'eol' })
  1522. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'right_align' })
  1523. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'inline' })
  1524. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = { vt, vt } })
  1525. screen:expect{grid=[[
  1526. {2:a}{3:b}{4:c}{5:d}{6:X}#^# {2:a}{3:b}{4:c}{5:d}{6:X} {2:a}{3:b}{4:c}{5:d}{6:X}|
  1527. {2:a}{3:b}{4:c}{5:d}{6:X} |*2
  1528. {1:~ }|
  1529. |
  1530. ]]}
  1531. end)
  1532. it('does not crash when deleting a cleared buffer #15212', function()
  1533. exec_lua [[
  1534. ns = vim.api.nvim_create_namespace("myplugin")
  1535. vim.api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{"a"}}, end_col = 0})
  1536. ]]
  1537. screen:expect{grid=[[
  1538. ^ a |
  1539. {1:~ }|*13
  1540. |
  1541. ]]}
  1542. exec_lua [[
  1543. vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1544. vim.cmd("bdelete")
  1545. ]]
  1546. screen:expect{grid=[[
  1547. ^ |
  1548. {1:~ }|*13
  1549. |
  1550. ]]}
  1551. assert_alive()
  1552. end)
  1553. it('conceal with conceal char #19007', function()
  1554. screen:try_resize(50, 5)
  1555. insert('foo\n')
  1556. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='X'})
  1557. command('set conceallevel=2')
  1558. screen:expect([[
  1559. {26:X} |
  1560. ^ |
  1561. {1:~ }|*2
  1562. |
  1563. ]])
  1564. command('set conceallevel=1')
  1565. screen:expect_unchanged()
  1566. eq("conceal char has to be printable", pcall_err(api.nvim_buf_set_extmark, 0, ns, 0, 0, {end_col=0, end_row=2, conceal='\255'}))
  1567. end)
  1568. it('conceal with composed conceal char', function()
  1569. screen:try_resize(50, 5)
  1570. insert('foo\n')
  1571. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='ẍ̲'})
  1572. command('set conceallevel=2')
  1573. screen:expect([[
  1574. {26:ẍ̲} |
  1575. ^ |
  1576. {1:~ }|*2
  1577. |
  1578. ]])
  1579. command('set conceallevel=1')
  1580. screen:expect_unchanged()
  1581. -- this is rare, but could happen. Save at least the first codepoint
  1582. api.nvim__invalidate_glyph_cache()
  1583. screen:expect{grid=[[
  1584. {26:x} |
  1585. ^ |
  1586. {1:~ }|*2
  1587. |
  1588. ]]}
  1589. end)
  1590. it('conceal without conceal char #24782', function()
  1591. screen:try_resize(50, 5)
  1592. insert('foobar\n')
  1593. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=3, conceal=''})
  1594. command('set listchars=conceal:?')
  1595. command('let &conceallevel=1')
  1596. screen:expect([[
  1597. {26:?}bar |
  1598. ^ |
  1599. {1:~ }|*2
  1600. |
  1601. ]])
  1602. command('let &conceallevel=2')
  1603. screen:expect([[
  1604. bar |
  1605. ^ |
  1606. {1:~ }|*2
  1607. |
  1608. ]])
  1609. end)
  1610. it('conceal works just before truncated double-width char #21486', function()
  1611. screen:try_resize(40, 4)
  1612. api.nvim_buf_set_lines(0, 0, -1, true, {'', ('a'):rep(37) .. '<>古'})
  1613. api.nvim_buf_set_extmark(0, ns, 1, 37, {end_col=39, conceal=''})
  1614. command('setlocal conceallevel=2')
  1615. screen:expect{grid=[[
  1616. ^ |
  1617. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:>} |
  1618. 古 |
  1619. |
  1620. ]]}
  1621. feed('j')
  1622. screen:expect{grid=[[
  1623. |
  1624. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<>{1:>}|
  1625. 古 |
  1626. |
  1627. ]]}
  1628. end)
  1629. it('redraws properly when adding/removing conceal on non-current line', function()
  1630. screen:try_resize(50, 5)
  1631. api.nvim_buf_set_lines(0, 0, -1, true, {'abcd', 'efgh','ijkl', 'mnop'})
  1632. command('setlocal conceallevel=2')
  1633. screen:expect{grid=[[
  1634. ^abcd |
  1635. efgh |
  1636. ijkl |
  1637. mnop |
  1638. |
  1639. ]]}
  1640. api.nvim_buf_set_extmark(0, ns, 2, 1, {end_col=3, conceal=''})
  1641. screen:expect{grid=[[
  1642. ^abcd |
  1643. efgh |
  1644. il |
  1645. mnop |
  1646. |
  1647. ]]}
  1648. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1649. screen:expect{grid=[[
  1650. ^abcd |
  1651. efgh |
  1652. ijkl |
  1653. mnop |
  1654. |
  1655. ]]}
  1656. end)
  1657. it('avoids redraw issue #20651', function()
  1658. exec_lua[[
  1659. vim.cmd.normal'10oXXX'
  1660. vim.cmd.normal'gg'
  1661. local ns = vim.api.nvim_create_namespace('ns')
  1662. local bufnr = vim.api.nvim_create_buf(false, true)
  1663. vim.api.nvim_open_win(bufnr, false, { relative = 'win', height = 1, width = 1, row = 0, col = 0 })
  1664. vim.api.nvim_create_autocmd('CursorMoved', { callback = function()
  1665. local row = vim.api.nvim_win_get_cursor(0)[1] - 1
  1666. vim.api.nvim_buf_set_extmark(0, ns, row, 0, { id = 1 })
  1667. vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, {})
  1668. vim.schedule(function()
  1669. vim.api.nvim_buf_set_extmark(0, ns, row, 0, {
  1670. id = 1,
  1671. virt_text = {{'HELLO', 'Normal'}},
  1672. })
  1673. end)
  1674. end
  1675. })
  1676. ]]
  1677. for _ = 1, 3 do
  1678. vim.uv.sleep(10)
  1679. feed 'j'
  1680. end
  1681. screen:expect{grid=[[
  1682. {44: } |
  1683. XXX |*2
  1684. ^XXX HELLO |
  1685. XXX |*7
  1686. {1:~ }|*3
  1687. |
  1688. ]]}
  1689. end)
  1690. it('underline attribute with higher priority takes effect #22371', function()
  1691. screen:try_resize(50, 3)
  1692. insert('aaabbbaaa')
  1693. exec([[
  1694. hi TestUL gui=underline guifg=Blue
  1695. hi TestUC gui=undercurl guisp=Red
  1696. hi TestBold gui=bold
  1697. ]])
  1698. screen:set_default_attr_ids({
  1699. [0] = {bold = true, foreground = Screen.colors.Blue};
  1700. [1] = {underline = true, foreground = Screen.colors.Blue};
  1701. [2] = {undercurl = true, special = Screen.colors.Red};
  1702. [3] = {underline = true, foreground = Screen.colors.Blue, special = Screen.colors.Red};
  1703. [4] = {undercurl = true, foreground = Screen.colors.Blue, special = Screen.colors.Red};
  1704. [5] = {bold = true, underline = true, foreground = Screen.colors.Blue};
  1705. [6] = {bold = true, undercurl = true, special = Screen.colors.Red};
  1706. })
  1707. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 20 })
  1708. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 30 })
  1709. screen:expect([[
  1710. {1:aaa}{4:bbb}{1:aa^a} |
  1711. {0:~ }|
  1712. |
  1713. ]])
  1714. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1715. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 20 })
  1716. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 30 })
  1717. screen:expect([[
  1718. {2:aaa}{3:bbb}{2:aa^a} |
  1719. {0:~ }|
  1720. |
  1721. ]])
  1722. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1723. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 30 })
  1724. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 20 })
  1725. screen:expect([[
  1726. {1:aaa}{3:bbb}{1:aa^a} |
  1727. {0:~ }|
  1728. |
  1729. ]])
  1730. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1731. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 30 })
  1732. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 20 })
  1733. screen:expect([[
  1734. {2:aaa}{4:bbb}{2:aa^a} |
  1735. {0:~ }|
  1736. |
  1737. ]])
  1738. -- When only one highlight group has an underline attribute, it should always take effect.
  1739. for _, d in ipairs({-5, 5}) do
  1740. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1741. screen:expect([[
  1742. aaabbbaa^a |
  1743. {0:~ }|
  1744. |
  1745. ]])
  1746. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 25 + d })
  1747. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
  1748. screen:expect([[
  1749. {1:aaa}{5:bbb}{1:aa^a} |
  1750. {0:~ }|
  1751. |
  1752. ]])
  1753. end
  1754. for _, d in ipairs({-5, 5}) do
  1755. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1756. screen:expect([[
  1757. aaabbbaa^a |
  1758. {0:~ }|
  1759. |
  1760. ]])
  1761. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 25 + d })
  1762. api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
  1763. screen:expect([[
  1764. {2:aaa}{6:bbb}{2:aa^a} |
  1765. {0:~ }|
  1766. |
  1767. ]])
  1768. end
  1769. end)
  1770. it('highlight is combined with syntax and sign linehl #20004', function()
  1771. screen:try_resize(50, 3)
  1772. insert([[
  1773. function Func()
  1774. end]])
  1775. feed('gg')
  1776. command('set ft=lua')
  1777. command('syntax on')
  1778. command('hi default MyMark guibg=LightGrey')
  1779. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 3, hl_mode = 'combine', hl_group = 'MyMark' })
  1780. command('hi default MyLine gui=underline')
  1781. command('sign define CurrentLine linehl=MyLine')
  1782. fn.sign_place(6, 'Test', 'CurrentLine', '', { lnum = 1 })
  1783. screen:expect{grid=[[
  1784. {30:^fun}{31:ction}{32: Func() }|
  1785. {6:end} |
  1786. |
  1787. ]]}
  1788. end)
  1789. it('highlight works after TAB with sidescroll #14201', function()
  1790. screen:try_resize(50, 3)
  1791. command('set nowrap')
  1792. api.nvim_buf_set_lines(0, 0, -1, true, {'\tword word word word'})
  1793. api.nvim_buf_set_extmark(0, ns, 0, 1, { end_col = 3, hl_group = 'ErrorMsg' })
  1794. screen:expect{grid=[[
  1795. ^ {4:wo}rd word word word |
  1796. {1:~ }|
  1797. |
  1798. ]]}
  1799. feed('7zl')
  1800. screen:expect{grid=[[
  1801. {4:^wo}rd word word word |
  1802. {1:~ }|
  1803. |
  1804. ]]}
  1805. feed('zl')
  1806. screen:expect{grid=[[
  1807. {4:^wo}rd word word word |
  1808. {1:~ }|
  1809. |
  1810. ]]}
  1811. feed('zl')
  1812. screen:expect{grid=[[
  1813. {4:^o}rd word word word |
  1814. {1:~ }|
  1815. |
  1816. ]]}
  1817. end)
  1818. it('highlights the beginning of a TAB char correctly #23734', function()
  1819. screen:try_resize(50, 3)
  1820. api.nvim_buf_set_lines(0, 0, -1, true, {'this is the\ttab'})
  1821. api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 15, hl_group = 'ErrorMsg' })
  1822. screen:expect{grid=[[
  1823. ^this is the{4: tab} |
  1824. {1:~ }|
  1825. |
  1826. ]]}
  1827. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  1828. api.nvim_buf_set_extmark(0, ns, 0, 12, { end_col = 15, hl_group = 'ErrorMsg' })
  1829. screen:expect{grid=[[
  1830. ^this is the {4:tab} |
  1831. {1:~ }|
  1832. |
  1833. ]]}
  1834. end)
  1835. it('highlight applies to a full TAB on line with matches #20885', function()
  1836. screen:try_resize(50, 3)
  1837. api.nvim_buf_set_lines(0, 0, -1, true, {'\t-- match1', ' -- match2'})
  1838. fn.matchadd('NonText', 'match')
  1839. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 1, end_col = 0, hl_group = 'Search' })
  1840. api.nvim_buf_set_extmark(0, ns, 1, 0, { end_row = 2, end_col = 0, hl_group = 'Search' })
  1841. screen:expect{grid=[[
  1842. {34: ^ -- }{35:match}{34:1} |
  1843. {34: -- }{35:match}{34:2} |
  1844. |
  1845. ]]}
  1846. end)
  1847. it('highlight applies to a full TAB in visual block mode', function()
  1848. screen:try_resize(50, 8)
  1849. command('hi! Visual guifg=NONE guibg=LightGrey')
  1850. api.nvim_buf_set_lines(0, 0, -1, true, {'asdf', '\tasdf', '\tasdf', '\tasdf', 'asdf'})
  1851. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 5, end_col = 0, hl_group = 'Underlined'})
  1852. screen:expect([[
  1853. {28:^asdf} |
  1854. {28: asdf} |*3
  1855. {28:asdf} |
  1856. {1:~ }|*2
  1857. |
  1858. ]])
  1859. feed('<C-V>Gll')
  1860. screen:expect([[
  1861. {29:asd}{28:f} |
  1862. {29: }{28: asdf} |*3
  1863. {29:as}{28:^df} |
  1864. {1:~ }|*2
  1865. {24:-- VISUAL BLOCK --} |
  1866. ]])
  1867. end)
  1868. it('highlight works properly with multibyte text and spell #26771', function()
  1869. insert('口口\n')
  1870. screen:try_resize(50, 3)
  1871. api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 3, hl_group = 'Search' })
  1872. screen:expect([[
  1873. {34:口}口 |
  1874. ^ |
  1875. |
  1876. ]])
  1877. command('setlocal spell')
  1878. screen:expect([[
  1879. {43:口}{42:口} |
  1880. ^ |
  1881. |
  1882. ]])
  1883. end)
  1884. it('supports multiline highlights', function()
  1885. insert(example_text)
  1886. feed 'gg'
  1887. for _,i in ipairs {1,2,3,5,6,7} do
  1888. for _,j in ipairs {2,5,10,15} do
  1889. api.nvim_buf_set_extmark(0, ns, i, j, { end_col=j+2, hl_group = 'NonText'})
  1890. end
  1891. end
  1892. screen:expect{grid=[[
  1893. ^for _,item in ipairs(items) do |
  1894. {1: }l{1:oc}al {1:te}xt,{1: h}l_id_cell, count = unpack(item) |
  1895. {1: }i{1:f }hl_{1:id}_ce{1:ll} ~= nil then |
  1896. {1: } {1: } hl{1:_i}d ={1: h}l_id_cell |
  1897. end |
  1898. {1: }f{1:or} _ {1:= }1, {1:(c}ount or 1) do |
  1899. {1: } {1: } lo{1:ca}l c{1:el}l = line[colpos] |
  1900. {1: } {1: } ce{1:ll}.te{1:xt} = text |
  1901. cell.hl_id = hl_id |
  1902. colpos = colpos+1 |
  1903. end |
  1904. end |
  1905. {1:~ }|*2
  1906. |
  1907. ]]}
  1908. feed'5<c-e>'
  1909. screen:expect{grid=[[
  1910. ^ {1: }f{1:or} _ {1:= }1, {1:(c}ount or 1) do |
  1911. {1: } {1: } lo{1:ca}l c{1:el}l = line[colpos] |
  1912. {1: } {1: } ce{1:ll}.te{1:xt} = text |
  1913. cell.hl_id = hl_id |
  1914. colpos = colpos+1 |
  1915. end |
  1916. end |
  1917. {1:~ }|*7
  1918. |
  1919. ]]}
  1920. api.nvim_buf_set_extmark(0, ns, 1, 0, { end_line=8, end_col=10, hl_group = 'ErrorMsg'})
  1921. screen:expect{grid=[[
  1922. {4:^ }{36: }{4:f}{36:or}{4: _ }{36:= }{4:1, }{36:(c}{4:ount or 1) do} |
  1923. {4: }{36: }{4: }{36: }{4: lo}{36:ca}{4:l c}{36:el}{4:l = line[colpos]} |
  1924. {4: }{36: }{4: }{36: }{4: ce}{36:ll}{4:.te}{36:xt}{4: = text} |
  1925. {4: ce}ll.hl_id = hl_id |
  1926. colpos = colpos+1 |
  1927. end |
  1928. end |
  1929. {1:~ }|*7
  1930. |
  1931. ]]}
  1932. end)
  1933. local function with_undo_restore(val)
  1934. screen:try_resize(50, 5)
  1935. insert(example_text)
  1936. feed'gg'
  1937. api.nvim_buf_set_extmark(0, ns, 0, 6, { end_col=13, hl_group = 'NonText', undo_restore=val})
  1938. screen:expect{grid=[[
  1939. ^for _,{1:item in} ipairs(items) do |
  1940. local text, hl_id_cell, count = unpack(item) |
  1941. if hl_id_cell ~= nil then |
  1942. hl_id = hl_id_cell |
  1943. |
  1944. ]]}
  1945. api.nvim_buf_set_text(0, 0, 4, 0, 8, {''})
  1946. screen:expect{grid=[[
  1947. ^for {1:em in} ipairs(items) do |
  1948. local text, hl_id_cell, count = unpack(item) |
  1949. if hl_id_cell ~= nil then |
  1950. hl_id = hl_id_cell |
  1951. |
  1952. ]]}
  1953. end
  1954. it("highlights do reapply to restored text after delete", function()
  1955. with_undo_restore(true) -- also default behavior
  1956. command('silent undo')
  1957. screen:expect{grid=[[
  1958. ^for _,{1:item in} ipairs(items) do |
  1959. local text, hl_id_cell, count = unpack(item) |
  1960. if hl_id_cell ~= nil then |
  1961. hl_id = hl_id_cell |
  1962. |
  1963. ]]}
  1964. end)
  1965. it("highlights don't reapply to restored text after delete with undo_restore=false", function()
  1966. with_undo_restore(false)
  1967. command('silent undo')
  1968. screen:expect{grid=[[
  1969. ^for _,it{1:em in} ipairs(items) do |
  1970. local text, hl_id_cell, count = unpack(item) |
  1971. if hl_id_cell ~= nil then |
  1972. hl_id = hl_id_cell |
  1973. |
  1974. ]]}
  1975. eq({ { 1, 0, 8, { end_col = 13, end_right_gravity = false, end_row = 0,
  1976. hl_eol = false, hl_group = "NonText", undo_restore = false,
  1977. ns_id = 1, priority = 4096, right_gravity = true } } },
  1978. api.nvim_buf_get_extmarks(0, ns, {0,0}, {0, -1}, {details=true}))
  1979. end)
  1980. it('virtual text works with rightleft', function()
  1981. screen:try_resize(50, 3)
  1982. insert('abcdefghijklmn')
  1983. feed('0')
  1984. command('set rightleft')
  1985. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'EOL', 'Underlined'}}})
  1986. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'right_align', 'Underlined'}}, virt_text_pos = 'right_align' })
  1987. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'win_col', 'Underlined'}}, virt_text_win_col = 20 })
  1988. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
  1989. screen:expect{grid=[[
  1990. {28:ngila_thgir} {28:loc_niw} {28:LOE} nml{28:deyalrevo}b^a|
  1991. {1: ~}|
  1992. |
  1993. ]]}
  1994. insert(('#'):rep(32))
  1995. feed('0')
  1996. screen:expect{grid=[[
  1997. {28:ngila_tdeyalrevo}ba#####{28:loc_niw}###################^#|
  1998. {1: ~}|
  1999. |
  2000. ]]}
  2001. insert(('#'):rep(16))
  2002. feed('0')
  2003. screen:expect{grid=[[
  2004. {28:ngila_thgir}############{28:loc_niw}###################^#|
  2005. {28:LOE} nml{28:deyalrevo}|
  2006. |
  2007. ]]}
  2008. insert('###')
  2009. feed('0')
  2010. screen:expect{grid=[[
  2011. #################################################^#|
  2012. {28:ngila_thgir} {28:loc_niw} {28:LOE} nml{28:deyalrevo}ba#|
  2013. |
  2014. ]]}
  2015. command('set number')
  2016. screen:expect{grid=[[
  2017. #############################################^#{2: 1 }|
  2018. {28:ngila_thgir} {28:loc_niw} nml{28:deyalrevo}ba#####{2: }|
  2019. |
  2020. ]]}
  2021. command('set cpoptions+=n')
  2022. screen:expect{grid=[[
  2023. #############################################^#{2: 1 }|
  2024. {28:ngila_thgir} {28:loc_niw} nml{28:deyalrevo}ba#####|
  2025. |
  2026. ]]}
  2027. end)
  2028. it('virtual text overwrites double-width char properly', function()
  2029. screen:try_resize(50, 3)
  2030. insert('abcdefghij口klmnopqrstu口vwx口yz')
  2031. feed('0')
  2032. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'!!!!!', 'Underlined'}}, virt_text_win_col = 11 })
  2033. screen:expect{grid=[[
  2034. ^abcdefghij {28:!!!!!}opqrstu口vwx口yz |
  2035. {1:~ }|
  2036. |
  2037. ]]}
  2038. feed('8x')
  2039. screen:expect{grid=[[
  2040. ^ij口klmnopq{28:!!!!!} vwx口yz |
  2041. {1:~ }|
  2042. |
  2043. ]]}
  2044. feed('3l5x')
  2045. screen:expect{grid=[[
  2046. ij口^pqrstu {28:!!!!!} yz |
  2047. {1:~ }|
  2048. |
  2049. ]]}
  2050. feed('5x')
  2051. screen:expect{grid=[[
  2052. ij口^u口vwx {28:!!!!!} |
  2053. {1:~ }|
  2054. |
  2055. ]]}
  2056. end)
  2057. it('virtual text blending space does not overwrite double-width char', function()
  2058. screen:try_resize(50, 3)
  2059. insert('abcdefghij口klmnopqrstu口vwx口yz')
  2060. feed('0')
  2061. command('hi Blendy guibg=Red blend=30')
  2062. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{' ! ! ', 'Blendy'}}, virt_text_win_col = 8, hl_mode = 'blend' })
  2063. screen:expect{grid=[[
  2064. ^abcdefgh{10:i}{7:!}{10:口}{7:!}{10:l}mnopqrstu口vwx口yz |
  2065. {1:~ }|
  2066. |
  2067. ]]}
  2068. feed('x')
  2069. screen:expect{grid=[[
  2070. ^bcdefghi{10:j}{7:!}{10: k}{7:!}{10:m}nopqrstu口vwx口yz |
  2071. {1:~ }|
  2072. |
  2073. ]]}
  2074. feed('x')
  2075. screen:expect{grid=[[
  2076. ^cdefghij{10: }{7:!}{10:kl}{7:!}{10:n}opqrstu口vwx口yz |
  2077. {1:~ }|
  2078. |
  2079. ]]}
  2080. feed('x')
  2081. screen:expect{grid=[[
  2082. ^defghij口{7:!}{10:lm}{7:!}{10:o}pqrstu口vwx口yz |
  2083. {1:~ }|
  2084. |
  2085. ]]}
  2086. feed('7x')
  2087. screen:expect{grid=[[
  2088. ^口klmnop{10:q}{7:!}{10:st}{7:!}{10:口}vwx口yz |
  2089. {1:~ }|
  2090. |
  2091. ]]}
  2092. end)
  2093. it('virtual text works with double-width char and rightleft', function()
  2094. screen:try_resize(50, 3)
  2095. insert('abcdefghij口klmnopqrstu口vwx口yz')
  2096. feed('0')
  2097. command('set rightleft')
  2098. screen:expect{grid=[[
  2099. zy口xwv口utsrqponmlk口jihgfedcb^a|
  2100. {1: ~}|
  2101. |
  2102. ]]}
  2103. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
  2104. api.nvim_buf_set_extmark(0, ns, 0, 14, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' })
  2105. api.nvim_buf_set_extmark(0, ns, 0, 20, { virt_text = {{'\t', 'Underlined'}}, virt_text_pos = 'overlay' })
  2106. api.nvim_buf_set_extmark(0, ns, 0, 29, { virt_text = {{'古', 'Underlined'}}, virt_text_pos = 'overlay' })
  2107. screen:expect{grid=[[
  2108. zy {28:古}wv {28: }qpon{28:古}k {28:deyalrevo}b^a|
  2109. {1: ~}|
  2110. |
  2111. ]]}
  2112. end)
  2113. it('virtual text is drawn correctly after delete and undo #27368', function()
  2114. insert('aaa\nbbb\nccc\nddd\neee')
  2115. command('vsplit')
  2116. api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = {{'EOL'}} })
  2117. feed('3gg')
  2118. screen:expect{grid=[[
  2119. aaa │aaa |
  2120. bbb │bbb |
  2121. ^ccc EOL │ccc EOL |
  2122. ddd │ddd |
  2123. eee │eee |
  2124. {1:~ }│{1:~ }|*8
  2125. {41:[No Name] [+] }{40:[No Name] [+] }|
  2126. |
  2127. ]]}
  2128. feed('dd')
  2129. screen:expect{grid=[[
  2130. aaa │aaa |
  2131. bbb │bbb |
  2132. ^ddd EOL │ddd EOL |
  2133. eee │eee |
  2134. {1:~ }│{1:~ }|*9
  2135. {41:[No Name] [+] }{40:[No Name] [+] }|
  2136. |
  2137. ]]}
  2138. command('silent undo')
  2139. screen:expect{grid=[[
  2140. aaa │aaa |
  2141. bbb │bbb |
  2142. ^ccc EOL │ccc EOL |
  2143. ddd │ddd |
  2144. eee │eee |
  2145. {1:~ }│{1:~ }|*8
  2146. {41:[No Name] [+] }{40:[No Name] [+] }|
  2147. |
  2148. ]]}
  2149. end)
  2150. it('virtual text does not crash with blend, conceal and wrap #27836', function()
  2151. screen:try_resize(50, 3)
  2152. insert(('a'):rep(45) .. '|hidden|' .. ('b'):rep(45))
  2153. command('syntax match test /|hidden|/ conceal')
  2154. command('set conceallevel=2 concealcursor=n')
  2155. api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{'FOO'}}, virt_text_pos='right_align', hl_mode='blend'})
  2156. screen:expect{grid=[[
  2157. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa FOO|
  2158. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b |
  2159. |
  2160. ]]}
  2161. end)
  2162. it('works with both hl_group and sign_hl_group', function()
  2163. screen:try_resize(50, 3)
  2164. screen:add_extra_attr_ids({
  2165. [100] = { background = Screen.colors.WebGray, foreground = Screen.colors.Blue, bold = true },
  2166. })
  2167. insert('abcdefghijklmn')
  2168. api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S', sign_hl_group='NonText', hl_group='Error', end_col=14})
  2169. screen:expect([[
  2170. {100:S }{9:abcdefghijklm^n} |
  2171. {1:~ }|
  2172. |
  2173. ]])
  2174. end)
  2175. it('virt_text_repeat_linebreak repeats virtual text on wrapped lines', function()
  2176. screen:try_resize(40, 5)
  2177. api.nvim_set_option_value('breakindent', true, {})
  2178. insert(example_text)
  2179. api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_pos = 'overlay', virt_text_repeat_linebreak = true })
  2180. api.nvim_buf_set_extmark(0, ns, 1, 3, { virt_text = {{'│', 'NonText'}}, virt_text_pos = 'overlay', virt_text_repeat_linebreak = true })
  2181. command('norm gg')
  2182. screen:expect{grid=[[
  2183. ^for _,item in ipairs(items) do |
  2184. {1:│} {1:│}local text, hl_id_cell, count = unpa|
  2185. {1:│} {1:│}ck(item) |
  2186. if hl_id_cell ~= nil then |
  2187. |
  2188. ]]}
  2189. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  2190. api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_repeat_linebreak = true, virt_text_win_col = 0 })
  2191. api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_repeat_linebreak = true, virt_text_win_col = 2 })
  2192. screen:expect{grid=[[
  2193. ^for _,item in ipairs(items) do |
  2194. {1:│} {1:│} local text, hl_id_cell, count = unpa|
  2195. {1:│} {1:│} ck(item) |
  2196. if hl_id_cell ~= nil then |
  2197. |
  2198. ]]}
  2199. end)
  2200. it('supports URLs', function()
  2201. insert(example_text)
  2202. local url1 = 'https://example.com'
  2203. local url2 = 'http://127.0.0.1'
  2204. screen:add_extra_attr_ids {
  2205. u = { url = url1 },
  2206. uh = { url = url2, background = Screen.colors.Yellow },
  2207. }
  2208. api.nvim_buf_set_extmark(0, ns, 1, 4, {
  2209. end_col = 14,
  2210. url = url1,
  2211. })
  2212. api.nvim_buf_set_extmark(0, ns, 2, 4, {
  2213. end_col = 17,
  2214. hl_group = 'Search',
  2215. url = url2,
  2216. })
  2217. screen:expect([[
  2218. for _,item in ipairs(items) do |
  2219. {u:local text}, hl_id_cell, count = unpack(item) |
  2220. {uh:if hl_id_cell} ~= nil then |
  2221. hl_id = hl_id_cell |
  2222. end |
  2223. for _ = 1, (count or 1) do |
  2224. local cell = line[colpos] |
  2225. cell.text = text |
  2226. cell.hl_id = hl_id |
  2227. colpos = colpos+1 |
  2228. end |
  2229. en^d |
  2230. {1:~ }|
  2231. {1:~ }|
  2232. |
  2233. ]])
  2234. end)
  2235. it('can replace marks in place with different decorations #27211', function()
  2236. local mark = api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{"foo", "ErrorMsg"}}}, })
  2237. screen:expect{grid=[[
  2238. ^ |
  2239. {4:foo} |
  2240. {1:~ }|*12
  2241. |
  2242. ]]}
  2243. api.nvim_buf_set_extmark(0, ns, 0, 0, {
  2244. id = mark,
  2245. virt_text = { { "testing", "NonText" } },
  2246. virt_text_pos = "inline",
  2247. })
  2248. screen:expect{grid=[[
  2249. {1:^testing} |
  2250. {1:~ }|*13
  2251. |
  2252. ]]}
  2253. api.nvim_buf_del_extmark(0, ns, mark)
  2254. screen:expect{grid=[[
  2255. ^ |
  2256. {1:~ }|*13
  2257. |
  2258. ]]}
  2259. n.assert_alive()
  2260. end)
  2261. it('priority ordering of overlay or win_col virtual text at same position', function()
  2262. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'A'}}, virt_text_pos = 'overlay', priority = 100 })
  2263. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'A'}}, virt_text_win_col = 30, priority = 100 })
  2264. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB'}}, virt_text_pos = 'overlay', priority = 90 })
  2265. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB'}}, virt_text_win_col = 30, priority = 90 })
  2266. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CCC'}}, virt_text_pos = 'overlay', priority = 80 })
  2267. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CCC'}}, virt_text_win_col = 30, priority = 80 })
  2268. screen:expect([[
  2269. ^ABC ABC |
  2270. {1:~ }|*13
  2271. |
  2272. ]])
  2273. end)
  2274. it('priority ordering of inline and non-inline virtual text at same char', function()
  2275. insert(('?'):rep(40) .. ('!'):rep(30))
  2276. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'A'}}, virt_text_pos = 'overlay', priority = 10 })
  2277. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'a'}}, virt_text_win_col = 15, priority = 10 })
  2278. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'BBBB'}}, virt_text_pos = 'inline', priority = 15 })
  2279. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'C'}}, virt_text_pos = 'overlay', priority = 20 })
  2280. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'c'}}, virt_text_win_col = 17, priority = 20 })
  2281. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'DDDD'}}, virt_text_pos = 'inline', priority = 25 })
  2282. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'E'}}, virt_text_pos = 'overlay', priority = 30 })
  2283. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'e'}}, virt_text_win_col = 19, priority = 30 })
  2284. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'FFFF'}}, virt_text_pos = 'inline', priority = 35 })
  2285. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'G'}}, virt_text_pos = 'overlay', priority = 40 })
  2286. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'g'}}, virt_text_win_col = 21, priority = 40 })
  2287. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'HHHH'}}, virt_text_pos = 'inline', priority = 45 })
  2288. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'I'}}, virt_text_pos = 'overlay', priority = 50 })
  2289. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'i'}}, virt_text_win_col = 23, priority = 50 })
  2290. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'JJJJ'}}, virt_text_pos = 'inline', priority = 55 })
  2291. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'K'}}, virt_text_pos = 'overlay', priority = 60 })
  2292. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'k'}}, virt_text_win_col = 25, priority = 60 })
  2293. screen:expect([[
  2294. ???????????????a?c?e????????????????????ABBBCDDDEF|
  2295. FFGHHHIJJJK!!!!!!!!!!g!i!k!!!!!!!!!!!!!^! |
  2296. {1:~ }|*12
  2297. |
  2298. ]])
  2299. feed('02x$')
  2300. screen:expect([[
  2301. ???????????????a?c?e??????????????????ABBBCDDDEFFF|
  2302. GHHHIJJJK!!!!!!!!!!!!g!i!k!!!!!!!!!!!^! |
  2303. {1:~ }|*12
  2304. |
  2305. ]])
  2306. feed('02x$')
  2307. screen:expect([[
  2308. ???????????????a?c?e?g??????????????ABBBCDDDEFFFGH|
  2309. HHIJJJK!!!!!!!!!!!!!!!!i!k!!!!!!!!!^! |
  2310. {1:~ }|*12
  2311. |
  2312. ]])
  2313. feed('02x$')
  2314. screen:expect([[
  2315. ???????????????a?c?e?g????????????ABBBCDDDEFFFGHHH|
  2316. IJJJK!!!!!!!!!!!!!!!!!!i!k!!!!!!!^! |
  2317. {1:~ }|*12
  2318. |
  2319. ]])
  2320. command('set nowrap')
  2321. feed('0')
  2322. screen:expect([[
  2323. ^???????????????a?c?e?g?i?k????????ABBBCDDDEFFFGHHH|
  2324. {1:~ }|*13
  2325. |
  2326. ]])
  2327. feed('2x')
  2328. screen:expect([[
  2329. ^???????????????a?c?e?g?i?k??????ABBBCDDDEFFFGHHHIJ|
  2330. {1:~ }|*13
  2331. |
  2332. ]])
  2333. feed('2x')
  2334. screen:expect([[
  2335. ^???????????????a?c?e?g?i?k????ABBBCDDDEFFFGHHHIJJJ|
  2336. {1:~ }|*13
  2337. |
  2338. ]])
  2339. feed('2x')
  2340. screen:expect([[
  2341. ^???????????????a?c?e?g?i?k??ABBBCDDDEFFFGHHHIJJJK!|
  2342. {1:~ }|*13
  2343. |
  2344. ]])
  2345. end)
  2346. end)
  2347. describe('decorations: inline virtual text', function()
  2348. local screen, ns
  2349. before_each( function()
  2350. clear()
  2351. screen = Screen.new(50, 3)
  2352. screen:set_default_attr_ids {
  2353. [1] = {bold=true, foreground=Screen.colors.Blue};
  2354. [2] = {foreground = Screen.colors.Brown};
  2355. [3] = {bold = true, foreground = Screen.colors.SeaGreen};
  2356. [4] = {background = Screen.colors.Red1, foreground = Screen.colors.Gray100};
  2357. [5] = {background = Screen.colors.Red1, bold = true};
  2358. [6] = {foreground = Screen.colors.DarkCyan};
  2359. [7] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Black};
  2360. [8] = {bold = true};
  2361. [9] = {background = Screen.colors.Plum1};
  2362. [10] = {foreground = Screen.colors.SlateBlue};
  2363. [11] = {blend = 30, background = Screen.colors.Red1};
  2364. [12] = {background = Screen.colors.Yellow};
  2365. [13] = {reverse = true};
  2366. [14] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightMagenta};
  2367. [15] = {bold = true, reverse = true};
  2368. [16] = {foreground = Screen.colors.Red};
  2369. [17] = {background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue};
  2370. [18] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Red};
  2371. [19] = {background = Screen.colors.Yellow, foreground = Screen.colors.SlateBlue};
  2372. [20] = {background = Screen.colors.LightGrey, foreground = Screen.colors.SlateBlue};
  2373. [21] = {reverse = true, foreground = Screen.colors.SlateBlue}
  2374. }
  2375. ns = api.nvim_create_namespace 'test'
  2376. end)
  2377. it('works', function()
  2378. screen:try_resize(50, 10)
  2379. insert(example_text)
  2380. feed 'gg'
  2381. screen:expect{grid=[[
  2382. ^for _,item in ipairs(items) do |
  2383. local text, hl_id_cell, count = unpack(item) |
  2384. if hl_id_cell ~= nil then |
  2385. hl_id = hl_id_cell |
  2386. end |
  2387. for _ = 1, (count or 1) do |
  2388. local cell = line[colpos] |
  2389. cell.text = text |
  2390. cell.hl_id = hl_id |
  2391. |
  2392. ]]}
  2393. api.nvim_buf_set_extmark(0, ns, 1, 14, {virt_text={{': ', 'Special'}, {'string', 'Type'}}, virt_text_pos='inline'})
  2394. screen:expect{grid=[[
  2395. ^for _,item in ipairs(items) do |
  2396. local text{10:: }{3:string}, hl_id_cell, count = unpack|
  2397. (item) |
  2398. if hl_id_cell ~= nil then |
  2399. hl_id = hl_id_cell |
  2400. end |
  2401. for _ = 1, (count or 1) do |
  2402. local cell = line[colpos] |
  2403. cell.text = text |
  2404. |
  2405. ]]}
  2406. screen:try_resize(55, 10)
  2407. screen:expect{grid=[[
  2408. ^for _,item in ipairs(items) do |
  2409. local text{10:: }{3:string}, hl_id_cell, count = unpack(item|
  2410. ) |
  2411. if hl_id_cell ~= nil then |
  2412. hl_id = hl_id_cell |
  2413. end |
  2414. for _ = 1, (count or 1) do |
  2415. local cell = line[colpos] |
  2416. cell.text = text |
  2417. |
  2418. ]]}
  2419. screen:try_resize(56, 10)
  2420. screen:expect{grid=[[
  2421. ^for _,item in ipairs(items) do |
  2422. local text{10:: }{3:string}, hl_id_cell, count = unpack(item)|
  2423. if hl_id_cell ~= nil then |
  2424. hl_id = hl_id_cell |
  2425. end |
  2426. for _ = 1, (count or 1) do |
  2427. local cell = line[colpos] |
  2428. cell.text = text |
  2429. cell.hl_id = hl_id |
  2430. |
  2431. ]]}
  2432. end)
  2433. it('works with 0-width chunk', function()
  2434. screen:try_resize(50, 10)
  2435. insert(example_text)
  2436. feed 'gg'
  2437. screen:expect{grid=[[
  2438. ^for _,item in ipairs(items) do |
  2439. local text, hl_id_cell, count = unpack(item) |
  2440. if hl_id_cell ~= nil then |
  2441. hl_id = hl_id_cell |
  2442. end |
  2443. for _ = 1, (count or 1) do |
  2444. local cell = line[colpos] |
  2445. cell.text = text |
  2446. cell.hl_id = hl_id |
  2447. |
  2448. ]]}
  2449. api.nvim_buf_set_extmark(0, ns, 0, 5, {virt_text={{''}, {''}}, virt_text_pos='inline'})
  2450. api.nvim_buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {': ', 'Special'}}, virt_text_pos='inline'})
  2451. api.nvim_buf_set_extmark(0, ns, 1, 48, {virt_text={{''}, {''}}, virt_text_pos='inline'})
  2452. screen:expect{grid=[[
  2453. ^for _,item in ipairs(items) do |
  2454. local text{10:: }, hl_id_cell, count = unpack(item)|
  2455. if hl_id_cell ~= nil then |
  2456. hl_id = hl_id_cell |
  2457. end |
  2458. for _ = 1, (count or 1) do |
  2459. local cell = line[colpos] |
  2460. cell.text = text |
  2461. cell.hl_id = hl_id |
  2462. |
  2463. ]]}
  2464. api.nvim_buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {'string', 'Type'}}, virt_text_pos='inline'})
  2465. feed('V')
  2466. screen:expect{grid=[[
  2467. ^f{7:or _,item in ipairs(items) do} |
  2468. local text{10:: }{3:string}, hl_id_cell, count = unpack|
  2469. (item) |
  2470. if hl_id_cell ~= nil then |
  2471. hl_id = hl_id_cell |
  2472. end |
  2473. for _ = 1, (count or 1) do |
  2474. local cell = line[colpos] |
  2475. cell.text = text |
  2476. {8:-- VISUAL LINE --} |
  2477. ]]}
  2478. feed('<Esc>jf,')
  2479. screen:expect{grid=[[
  2480. for _,item in ipairs(items) do |
  2481. local text{10:: }{3:string}^, hl_id_cell, count = unpack|
  2482. (item) |
  2483. if hl_id_cell ~= nil then |
  2484. hl_id = hl_id_cell |
  2485. end |
  2486. for _ = 1, (count or 1) do |
  2487. local cell = line[colpos] |
  2488. cell.text = text |
  2489. |
  2490. ]]}
  2491. end)
  2492. it('Normal mode "gM" command works properly', function()
  2493. command([[call setline(1, '123456789')]])
  2494. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
  2495. api.nvim_buf_set_extmark(0, ns, 0, 7, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
  2496. feed('gM')
  2497. screen:expect{grid=[[
  2498. 12{10:bbb}34^567{10:bbb}89 |
  2499. {1:~ }|
  2500. |
  2501. ]]}
  2502. end)
  2503. local function test_normal_gj_gk()
  2504. screen:try_resize(60, 6)
  2505. command([[call setline(1, repeat([repeat('a', 55)], 2))]])
  2506. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
  2507. api.nvim_buf_set_extmark(0, ns, 1, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
  2508. screen:expect{grid=[[
  2509. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2510. aaaaa |
  2511. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2512. aaaaa |
  2513. {1:~ }|
  2514. |
  2515. ]]}
  2516. feed('gj')
  2517. screen:expect{grid=[[
  2518. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2519. ^aaaaa |
  2520. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2521. aaaaa |
  2522. {1:~ }|
  2523. |
  2524. ]]}
  2525. feed('gj')
  2526. screen:expect{grid=[[
  2527. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2528. aaaaa |
  2529. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2530. aaaaa |
  2531. {1:~ }|
  2532. |
  2533. ]]}
  2534. feed('gj')
  2535. screen:expect{grid=[[
  2536. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2537. aaaaa |
  2538. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2539. ^aaaaa |
  2540. {1:~ }|
  2541. |
  2542. ]]}
  2543. feed('gk')
  2544. screen:expect{grid=[[
  2545. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2546. aaaaa |
  2547. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2548. aaaaa |
  2549. {1:~ }|
  2550. |
  2551. ]]}
  2552. feed('gk')
  2553. screen:expect{grid=[[
  2554. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2555. ^aaaaa |
  2556. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2557. aaaaa |
  2558. {1:~ }|
  2559. |
  2560. ]]}
  2561. feed('gk')
  2562. screen:expect{grid=[[
  2563. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2564. aaaaa |
  2565. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
  2566. aaaaa |
  2567. {1:~ }|
  2568. |
  2569. ]]}
  2570. end
  2571. describe('Normal mode "gj" "gk" commands work properly', function()
  2572. it('with virtualedit=', function()
  2573. test_normal_gj_gk()
  2574. end)
  2575. it('with virtualedit=all', function()
  2576. command('set virtualedit=all')
  2577. test_normal_gj_gk()
  2578. end)
  2579. end)
  2580. it('cursor positions are correct with multiple inline virtual text', function()
  2581. insert('12345678')
  2582. api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
  2583. api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
  2584. feed '^'
  2585. feed '4l'
  2586. screen:expect{grid=[[
  2587. 1234{10: virtual text virtual text }^5678 |
  2588. {1:~ }|
  2589. |
  2590. ]]}
  2591. end)
  2592. it('adjusts cursor location correctly when inserting around inline virtual text', function()
  2593. insert('12345678')
  2594. feed '$'
  2595. api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
  2596. screen:expect{grid=[[
  2597. 1234{10: virtual text }567^8 |
  2598. {1:~ }|
  2599. |
  2600. ]]}
  2601. end)
  2602. it('has correct highlighting with multi-byte characters', function()
  2603. insert('12345678')
  2604. api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { 'múlti-byté chñröcters 修补', 'Special' } }, virt_text_pos = 'inline' })
  2605. screen:expect{grid=[[
  2606. 1234{10:múlti-byté chñröcters 修补}567^8 |
  2607. {1:~ }|
  2608. |
  2609. ]]}
  2610. end)
  2611. it('has correct cursor position when inserting around virtual text', function()
  2612. insert('12345678')
  2613. api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  2614. feed '^'
  2615. feed '3l'
  2616. feed 'a'
  2617. screen:expect{grid=[[
  2618. 1234{10:^virtual text}5678 |
  2619. {1:~ }|
  2620. {8:-- INSERT --} |
  2621. ]]}
  2622. feed '<ESC>'
  2623. screen:expect{grid=[[
  2624. 123^4{10:virtual text}5678 |
  2625. {1:~ }|
  2626. |
  2627. ]]}
  2628. feed '^'
  2629. feed '4l'
  2630. feed 'i'
  2631. screen:expect{grid=[[
  2632. 1234{10:^virtual text}5678 |
  2633. {1:~ }|
  2634. {8:-- INSERT --} |
  2635. ]]}
  2636. end)
  2637. it('has correct cursor position with virtual text on an empty line', function()
  2638. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  2639. screen:expect{grid=[[
  2640. {10:^virtual text} |
  2641. {1:~ }|
  2642. |
  2643. ]]}
  2644. end)
  2645. it('text is drawn correctly with a wrapping virtual text', function()
  2646. screen:try_resize(60, 8)
  2647. exec([[
  2648. call setline(1, ['', 'aaa', '', 'bbbbbb'])
  2649. normal gg0
  2650. ]])
  2651. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('X', 60), 'Special' } }, virt_text_pos = 'inline' })
  2652. api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { string.rep('X', 61), 'Special' } }, virt_text_pos = 'inline' })
  2653. feed('$')
  2654. screen:expect{grid=[[
  2655. {10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2656. aaa |
  2657. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2658. {10:X} |
  2659. bbbbbb |
  2660. {1:~ }|*2
  2661. |
  2662. ]]}
  2663. feed('j')
  2664. screen:expect{grid=[[
  2665. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2666. aa^a |
  2667. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2668. {10:X} |
  2669. bbbbbb |
  2670. {1:~ }|*2
  2671. |
  2672. ]]}
  2673. feed('j')
  2674. screen:expect{grid=[[
  2675. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2676. aaa |
  2677. {10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2678. {10:X} |
  2679. bbbbbb |
  2680. {1:~ }|*2
  2681. |
  2682. ]]}
  2683. feed('j')
  2684. screen:expect{grid=[[
  2685. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2686. aaa |
  2687. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2688. {10:X} |
  2689. bbbbb^b |
  2690. {1:~ }|*2
  2691. |
  2692. ]]}
  2693. feed('0<C-V>2l2k')
  2694. screen:expect{grid=[[
  2695. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2696. {7:aa}^a |
  2697. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2698. {10:X} |
  2699. {7:bbb}bbb |
  2700. {1:~ }|*2
  2701. {8:-- VISUAL BLOCK --} |
  2702. ]]}
  2703. feed([[<Esc>/aaa\n\%V<CR>]])
  2704. screen:expect{grid=[[
  2705. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2706. {12:^aaa } |
  2707. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2708. {10:X} |
  2709. bbbbbb |
  2710. {1:~ }|*2
  2711. {16:search hit BOTTOM, continuing at TOP} |
  2712. ]]}
  2713. feed('3ggic')
  2714. screen:expect{grid=[[
  2715. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2716. {12:aaa } |
  2717. c{10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2718. {10:XX} |
  2719. bbbbbb |
  2720. {1:~ }|*2
  2721. {8:-- INSERT --} |
  2722. ]]}
  2723. feed([[<Esc>/aaa\nc\%V<CR>]])
  2724. screen:expect{grid=[[
  2725. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2726. {12:^aaa } |
  2727. {12:c}{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  2728. {10:XX} |
  2729. bbbbbb |
  2730. {1:~ }|*2
  2731. {16:search hit BOTTOM, continuing at TOP} |
  2732. ]]}
  2733. end)
  2734. it('cursor position is correct with virtual text attached to hard TABs', function()
  2735. command('set noexpandtab')
  2736. feed('i')
  2737. feed('<TAB>')
  2738. feed('<TAB>')
  2739. feed('test')
  2740. feed('<ESC>')
  2741. api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  2742. feed('0')
  2743. screen:expect{grid=[[
  2744. ^ {10:virtual text} test |
  2745. {1:~ }|
  2746. |
  2747. ]]}
  2748. feed('l')
  2749. screen:expect{grid=[[
  2750. {10:virtual text} ^ test |
  2751. {1:~ }|
  2752. |
  2753. ]]}
  2754. feed('l')
  2755. screen:expect{grid=[[
  2756. {10:virtual text} ^test |
  2757. {1:~ }|
  2758. |
  2759. ]]}
  2760. feed('l')
  2761. screen:expect{grid=[[
  2762. {10:virtual text} t^est |
  2763. {1:~ }|
  2764. |
  2765. ]]}
  2766. feed('l')
  2767. screen:expect{grid=[[
  2768. {10:virtual text} te^st |
  2769. {1:~ }|
  2770. |
  2771. ]]}
  2772. end)
  2773. it('cursor position is correct with virtual text on an empty line', function()
  2774. command('set linebreak')
  2775. insert('one twoword')
  2776. feed('0')
  2777. api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { ': virtual text', 'Special' } }, virt_text_pos = 'inline' })
  2778. screen:expect{grid=[[
  2779. ^one{10:: virtual text} twoword |
  2780. {1:~ }|
  2781. |
  2782. ]]}
  2783. end)
  2784. it('search highlight is correct', function()
  2785. insert('foo foo foo bar\nfoo foo foo bar')
  2786. feed('gg0')
  2787. api.nvim_buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
  2788. api.nvim_buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2789. api.nvim_buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2790. api.nvim_buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  2791. screen:expect{grid=[[
  2792. ^foo foo f{10:AAABBB}oo bar |
  2793. foo foo f{10:CCCDDD}oo bar |
  2794. |
  2795. ]]}
  2796. feed('/foo')
  2797. screen:expect{grid=[[
  2798. {12:foo} {13:foo} {12:f}{10:AAA}{19:BBB}{12:oo} bar |
  2799. {12:foo} {12:foo} {12:f}{19:CCC}{10:DDD}{12:oo} bar |
  2800. /foo^ |
  2801. ]]}
  2802. api.nvim_buf_set_extmark(0, ns, 0, 13, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2803. feed('<C-G>')
  2804. screen:expect{grid=[[
  2805. {12:foo} {12:foo} {13:f}{10:AAA}{21:BBB}{13:oo} b{10:EEE}ar |
  2806. {12:foo} {12:foo} {12:f}{19:CCC}{10:DDD}{12:oo} bar |
  2807. /foo^ |
  2808. ]]}
  2809. end)
  2810. it('Visual select highlight is correct', function()
  2811. insert('foo foo foo bar\nfoo foo foo bar')
  2812. feed('gg0')
  2813. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
  2814. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2815. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2816. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  2817. feed('8l')
  2818. screen:expect{grid=[[
  2819. foo foo {10:AAABBB}^foo bar |
  2820. foo foo {10:CCCDDD}foo bar |
  2821. |
  2822. ]]}
  2823. feed('<C-V>')
  2824. feed('2hj')
  2825. screen:expect{grid=[[
  2826. foo fo{7:o }{10:AAA}{20:BBB}{7:f}oo bar |
  2827. foo fo^o{7: }{20:CCC}{10:DDD}{7:f}oo bar |
  2828. {8:-- VISUAL BLOCK --} |
  2829. ]]}
  2830. api.nvim_buf_set_extmark(0, ns, 0, 10, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2831. screen:expect{grid=[[
  2832. foo fo{7:o }{10:AAA}{20:BBB}{7:f}o{10:EEE}o bar |
  2833. foo fo^o{7: }{20:CCC}{10:DDD}{7:f}oo bar |
  2834. {8:-- VISUAL BLOCK --} |
  2835. ]]}
  2836. end)
  2837. it('inside highlight range of another extmark', function()
  2838. insert('foo foo foo bar\nfoo foo foo bar')
  2839. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
  2840. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2841. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2842. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  2843. api.nvim_buf_set_extmark(0, ns, 0, 4, { end_col = 11, hl_group = 'Search' })
  2844. api.nvim_buf_set_extmark(0, ns, 1, 4, { end_col = 11, hl_group = 'Search' })
  2845. screen:expect{grid=[[
  2846. foo {12:foo }{10:AAA}{19:BBB}{12:foo} bar |
  2847. foo {12:foo }{19:CCC}{10:DDD}{12:foo} ba^r |
  2848. |
  2849. ]]}
  2850. end)
  2851. it('inside highlight range of syntax', function()
  2852. insert('foo foo foo bar\nfoo foo foo bar')
  2853. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
  2854. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2855. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  2856. api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  2857. command([[syntax match Search 'foo \zsfoo foo\ze bar']])
  2858. screen:expect{grid=[[
  2859. foo {12:foo }{10:AAA}{19:BBB}{12:foo} bar |
  2860. foo {12:foo }{19:CCC}{10:DDD}{12:foo} ba^r |
  2861. |
  2862. ]]}
  2863. end)
  2864. it('cursor position is correct when inserting around a virtual text with left gravity', function()
  2865. screen:try_resize(27, 4)
  2866. insert(('a'):rep(15))
  2867. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { ('>'):rep(43), 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
  2868. command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
  2869. feed('08l')
  2870. screen:expect{grid=[[
  2871. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
  2872. {1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
  2873. {1:+}^aaaaaaa |
  2874. |
  2875. ]]}
  2876. feed('i')
  2877. screen:expect{grid=[[
  2878. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
  2879. {1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
  2880. {1:+}^aaaaaaa |
  2881. {8:-- INSERT --} |
  2882. ]]}
  2883. feed([[<C-\><C-O>]])
  2884. screen:expect{grid=[[
  2885. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
  2886. {1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
  2887. {1:+}^aaaaaaa |
  2888. {8:-- (insert) --} |
  2889. ]]}
  2890. feed('D')
  2891. screen:expect{grid=[[
  2892. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
  2893. {1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
  2894. {1:^~ }|
  2895. {8:-- INSERT --} |
  2896. ]]}
  2897. command('setlocal list listchars=eol:$')
  2898. screen:expect{grid=[[
  2899. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>}|
  2900. {1:+}{10:>>>>>>>>>>>>>>>>>>>>>>>>}|
  2901. {1:+^$} |
  2902. {8:-- INSERT --} |
  2903. ]]}
  2904. feed('<C-U>')
  2905. screen:expect{grid=[[
  2906. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2907. {1:+}{10:>>>>>>>>>>>>>>>>}{1:^$} |
  2908. {1:~ }|
  2909. {8:-- INSERT --} |
  2910. ]]}
  2911. feed('a')
  2912. screen:expect{grid=[[
  2913. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2914. {1:+}{10:>>>>>>>>>>>>>>>>}a{1:^$} |
  2915. {1:~ }|
  2916. {8:-- INSERT --} |
  2917. ]]}
  2918. feed('<Esc>')
  2919. screen:expect{grid=[[
  2920. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2921. {1:+}{10:>>>>>>>>>>>>>>>>}^a{1:$} |
  2922. {1:~ }|
  2923. |
  2924. ]]}
  2925. feed('x')
  2926. screen:expect{grid=[[
  2927. {10:^>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2928. {1:+}{10:>>>>>>>>>>>>>>>>}{1:$} |
  2929. {1:~ }|
  2930. |
  2931. ]]}
  2932. end)
  2933. it('cursor position is correct when inserting around virtual texts with both left and right gravity', function()
  2934. screen:try_resize(30, 4)
  2935. command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
  2936. insert(('a'):rep(15))
  2937. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('>'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = false })
  2938. api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('<'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = true })
  2939. feed('08l')
  2940. screen:expect{grid=[[
  2941. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2942. {1:+}{10:>>>>>>>>>><<<<<<<<<<<<<<<<<}|
  2943. {1:+}{10:<<<<<<<<<<<<<<<}^aaaaaaa |
  2944. |
  2945. ]]}
  2946. feed('i')
  2947. screen:expect{grid=[[
  2948. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2949. {1:+}{10:>>>>>>>>>>^<<<<<<<<<<<<<<<<<}|
  2950. {1:+}{10:<<<<<<<<<<<<<<<}aaaaaaa |
  2951. {8:-- INSERT --} |
  2952. ]]}
  2953. feed('a')
  2954. screen:expect{grid=[[
  2955. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2956. {1:+}{10:>>>>>>>>>>}a{10:^<<<<<<<<<<<<<<<<}|
  2957. {1:+}{10:<<<<<<<<<<<<<<<<}aaaaaaa |
  2958. {8:-- INSERT --} |
  2959. ]]}
  2960. feed([[<C-\><C-O>]])
  2961. screen:expect{grid=[[
  2962. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2963. {1:+}{10:>>>>>>>>>>}a{10:<<<<<<<<<<<<<<<<}|
  2964. {1:+}{10:<<<<<<<<<<<<<<<<}^aaaaaaa |
  2965. {8:-- (insert) --} |
  2966. ]]}
  2967. feed('D')
  2968. screen:expect{grid=[[
  2969. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2970. {1:+}{10:>>>>>>>>>>}a{10:^<<<<<<<<<<<<<<<<}|
  2971. {1:+}{10:<<<<<<<<<<<<<<<<} |
  2972. {8:-- INSERT --} |
  2973. ]]}
  2974. feed('<BS>')
  2975. screen:expect{grid=[[
  2976. aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
  2977. {1:+}{10:>>>>>>>>>>^<<<<<<<<<<<<<<<<<}|
  2978. {1:+}{10:<<<<<<<<<<<<<<<} |
  2979. {8:-- INSERT --} |
  2980. ]]}
  2981. feed('<C-U>')
  2982. screen:expect{grid=[[
  2983. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2984. {1:+}{10:>>^<<<<<<<<<<<<<<<<<<<<<<<<<}|
  2985. {1:+}{10:<<<<<<<} |
  2986. {8:-- INSERT --} |
  2987. ]]}
  2988. feed('a')
  2989. screen:expect{grid=[[
  2990. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2991. {1:+}{10:>>}a{10:^<<<<<<<<<<<<<<<<<<<<<<<<}|
  2992. {1:+}{10:<<<<<<<<} |
  2993. {8:-- INSERT --} |
  2994. ]]}
  2995. feed('<Esc>')
  2996. screen:expect{grid=[[
  2997. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  2998. {1:+}{10:>>}^a{10:<<<<<<<<<<<<<<<<<<<<<<<<}|
  2999. {1:+}{10:<<<<<<<<} |
  3000. |
  3001. ]]}
  3002. feed('x')
  3003. screen:expect{grid=[[
  3004. {10:^>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  3005. {1:+}{10:>><<<<<<<<<<<<<<<<<<<<<<<<<}|
  3006. {1:+}{10:<<<<<<<} |
  3007. |
  3008. ]]}
  3009. feed('i')
  3010. screen:expect{grid=[[
  3011. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  3012. {1:+}{10:>>^<<<<<<<<<<<<<<<<<<<<<<<<<}|
  3013. {1:+}{10:<<<<<<<} |
  3014. {8:-- INSERT --} |
  3015. ]]}
  3016. screen:try_resize(32, 4)
  3017. screen:expect{grid=[[
  3018. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  3019. {1:+}{10:^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}|
  3020. {1:+}{10:<<<} |
  3021. {8:-- INSERT --} |
  3022. ]]}
  3023. command('setlocal nobreakindent')
  3024. screen:expect{grid=[[
  3025. {10:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}|
  3026. {1:+}{10:^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}|
  3027. {1:+}{10:<} |
  3028. {8:-- INSERT --} |
  3029. ]]}
  3030. end)
  3031. it('draws correctly with no wrap multiple virtual text, where one is hidden', function()
  3032. insert('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz')
  3033. command("set nowrap")
  3034. api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  3035. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  3036. feed('$')
  3037. screen:expect{grid=[[
  3038. opqrstuvwxyzabcdefghijklmnopqrstuvwx{10:virtual text}y^z|
  3039. {1:~ }|
  3040. |
  3041. ]]}
  3042. end)
  3043. it('draws correctly with no wrap and a long virtual text', function()
  3044. insert('abcdefghi')
  3045. command("set nowrap")
  3046. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
  3047. feed('$')
  3048. screen:expect{grid=[[
  3049. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}cdefgh^i|
  3050. {1:~ }|
  3051. |
  3052. ]]}
  3053. end)
  3054. it('tabs are the correct length with no wrap following virtual text', function()
  3055. command('set nowrap')
  3056. feed('itest<TAB>a<ESC>')
  3057. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
  3058. feed('gg$')
  3059. screen:expect{grid=[[
  3060. {10:aaaaaaaaaaaaaaaaaaaaaaaaa}test ^a |
  3061. {1:~ }|
  3062. |
  3063. ]]}
  3064. end)
  3065. it('highlighting does not extend with no wrap and a long virtual text', function()
  3066. insert('abcdef')
  3067. command("set nowrap")
  3068. api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { string.rep('X', 50), 'Special' } }, virt_text_pos = 'inline' })
  3069. feed('$')
  3070. screen:expect{grid=[[
  3071. {10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}de^f|
  3072. {1:~ }|
  3073. |
  3074. ]]}
  3075. end)
  3076. it('hidden virtual text does not interfere with Visual highlight', function()
  3077. insert('abcdef')
  3078. command('set nowrap')
  3079. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'XXX', 'Special' } }, virt_text_pos = 'inline' })
  3080. feed('V2zl')
  3081. screen:expect{grid=[[
  3082. {10:X}{7:abcde}^f |
  3083. {1:~ }|
  3084. {8:-- VISUAL LINE --} |
  3085. ]]}
  3086. feed('zl')
  3087. screen:expect{grid=[[
  3088. {7:abcde}^f |
  3089. {1:~ }|
  3090. {8:-- VISUAL LINE --} |
  3091. ]]}
  3092. feed('zl')
  3093. screen:expect{grid=[[
  3094. {7:bcde}^f |
  3095. {1:~ }|
  3096. {8:-- VISUAL LINE --} |
  3097. ]]}
  3098. end)
  3099. it('highlighting is correct when virtual text wraps with number', function()
  3100. screen:try_resize(50, 5)
  3101. insert([[
  3102. test
  3103. test]])
  3104. command('set number')
  3105. api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
  3106. feed('gg0')
  3107. screen:expect{grid=[[
  3108. {2: 1 }^t{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  3109. {2: }{10:XXXXXXXXXX}est |
  3110. {2: 2 }test |
  3111. {1:~ }|
  3112. |
  3113. ]]}
  3114. end)
  3115. it('highlighting is correct when virtual text is proceeded with a match', function()
  3116. insert([[test]])
  3117. api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
  3118. feed('gg0')
  3119. command('match ErrorMsg /e/')
  3120. screen:expect{grid=[[
  3121. ^t{4:e}{10:virtual text}st |
  3122. {1:~ }|
  3123. |
  3124. ]]}
  3125. command('match ErrorMsg /s/')
  3126. screen:expect{grid=[[
  3127. ^te{10:virtual text}{4:s}t |
  3128. {1:~ }|
  3129. |
  3130. ]]}
  3131. end)
  3132. it('smoothscroll works correctly when virtual text wraps', function()
  3133. insert('foobar')
  3134. api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
  3135. command('setlocal smoothscroll')
  3136. screen:expect{grid=[[
  3137. foo{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
  3138. {10:XXXXXXXX}ba^r |
  3139. |
  3140. ]]}
  3141. feed('<C-E>')
  3142. screen:expect{grid=[[
  3143. {1:<<<}{10:XXXXX}ba^r |
  3144. {1:~ }|
  3145. |
  3146. ]]}
  3147. end)
  3148. it('in diff mode is highlighted correct', function()
  3149. screen:try_resize(50, 10)
  3150. insert([[
  3151. 9000
  3152. 0009
  3153. 0009
  3154. 9000
  3155. 0009
  3156. ]])
  3157. insert('aaa\tbbb')
  3158. command("set diff")
  3159. api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
  3160. api.nvim_buf_set_extmark(0, ns, 5, 0, { virt_text = { { '!', 'Special' } }, virt_text_pos = 'inline' })
  3161. api.nvim_buf_set_extmark(0, ns, 5, 3, { virt_text = { { '' } }, virt_text_pos = 'inline' })
  3162. command("vnew")
  3163. insert([[
  3164. 000
  3165. 000
  3166. 000
  3167. 000
  3168. 000
  3169. ]])
  3170. insert('aaabbb')
  3171. command("set diff")
  3172. feed('gg0')
  3173. screen:expect{grid=[[
  3174. {9:^000 }│{5:9}{14:test}{9:000 }|
  3175. {9:000 }│{9:000}{5:9}{9: }|*2
  3176. {9:000 }│{5:9}{9:000 }|
  3177. {9:000 }│{9:000}{5:9}{9: }|
  3178. {9:aaabbb }│{14:!}{9:aaa}{5: }{9:bbb }|
  3179. {1:~ }│{1:~ }|*2
  3180. {15:[No Name] [+] }{13:[No Name] [+] }|
  3181. |
  3182. ]]}
  3183. command('wincmd w | set nowrap')
  3184. feed('zl')
  3185. screen:expect{grid=[[
  3186. {9:000 }│{14:test}{9:000 }|
  3187. {9:000 }│{9:00}{5:9}{9: }|*2
  3188. {9:000 }│{9:000 }|
  3189. {9:000 }│{9:00}{5:9}{9: }|
  3190. {9:aaabbb }│{9:aaa}{5: }{9:bb^b }|
  3191. {1:~ }│{1:~ }|*2
  3192. {13:[No Name] [+] }{15:[No Name] [+] }|
  3193. |
  3194. ]]}
  3195. end)
  3196. it('correctly draws when there are multiple overlapping virtual texts on the same line with nowrap', function()
  3197. command('set nowrap')
  3198. insert('a')
  3199. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
  3200. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('b', 55), 'Special' } }, virt_text_pos = 'inline' })
  3201. feed('$')
  3202. screen:expect{grid=[[
  3203. {10:bbbbbbbbbbbbbbbbbbbbbbbbb}^a |
  3204. {1:~ }|
  3205. |
  3206. ]]}
  3207. end)
  3208. it('correctly draws when overflowing virtual text is followed by TAB with no wrap', function()
  3209. command('set nowrap')
  3210. feed('i<TAB>test<ESC>')
  3211. api.nvim_buf_set_extmark( 0, ns, 0, 0, { virt_text = { { string.rep('a', 60), 'Special' } }, virt_text_pos = 'inline' })
  3212. feed('0')
  3213. screen:expect({grid=[[
  3214. {10:aaaaaaaaaaaaaaaaaaaaaa} ^ test |
  3215. {1:~ }|
  3216. |
  3217. ]]})
  3218. end)
  3219. it('does not crash at column 0 when folded in a wide window', function()
  3220. screen:try_resize(82, 5)
  3221. command('hi! CursorLine guibg=NONE guifg=Red gui=NONE')
  3222. command('set cursorline')
  3223. insert([[
  3224. aaaaa
  3225. bbbbb
  3226. ccccc]])
  3227. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'foo'}}, virt_text_pos = 'inline' })
  3228. api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = {{'bar'}}, virt_text_pos = 'inline' })
  3229. screen:expect{grid=[[
  3230. fooaaaaa |
  3231. bbbbb |
  3232. bar |
  3233. {16:cccc^c }|
  3234. |
  3235. ]]}
  3236. command('1,2fold')
  3237. screen:expect{grid=[[
  3238. {17:+-- 2 lines: aaaaa·······························································}|
  3239. bar |
  3240. {16:cccc^c }|
  3241. {1:~ }|
  3242. |
  3243. ]]}
  3244. feed('2k')
  3245. screen:expect{grid=[[
  3246. {18:^+-- 2 lines: aaaaa·······························································}|
  3247. bar |
  3248. ccccc |
  3249. {1:~ }|
  3250. |
  3251. ]]}
  3252. command('3,4fold')
  3253. screen:expect{grid=[[
  3254. {18:^+-- 2 lines: aaaaa·······························································}|
  3255. {17:+-- 2 lines: ccccc·······························································}|
  3256. {1:~ }|*2
  3257. |
  3258. ]]}
  3259. feed('j')
  3260. screen:expect{grid=[[
  3261. {17:+-- 2 lines: aaaaa·······························································}|
  3262. {18:^+-- 2 lines: ccccc·······························································}|
  3263. {1:~ }|*2
  3264. |
  3265. ]]}
  3266. end)
  3267. it('does not crash at right edge of wide window #23848', function()
  3268. screen:try_resize(82, 5)
  3269. api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{('a'):rep(82)}, {'b'}}, virt_text_pos = 'inline'})
  3270. screen:expect{grid=[[
  3271. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3272. b |
  3273. {1:~ }|*2
  3274. |
  3275. ]]}
  3276. command('set nowrap')
  3277. screen:expect{grid=[[
  3278. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3279. {1:~ }|*3
  3280. |
  3281. ]]}
  3282. feed('82i0<Esc>0')
  3283. screen:expect{grid=[[
  3284. ^0000000000000000000000000000000000000000000000000000000000000000000000000000000000|
  3285. {1:~ }|*3
  3286. |
  3287. ]]}
  3288. command('set wrap')
  3289. screen:expect{grid=[[
  3290. ^0000000000000000000000000000000000000000000000000000000000000000000000000000000000|
  3291. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3292. b |
  3293. {1:~ }|
  3294. |
  3295. ]]}
  3296. end)
  3297. it('lcs-extends is drawn with inline virtual text at end of screen line', function()
  3298. exec([[
  3299. setlocal nowrap list listchars=extends:!
  3300. call setline(1, repeat('a', 51))
  3301. ]])
  3302. api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
  3303. feed('20l')
  3304. screen:expect{grid=[[
  3305. aaaaaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:!}|
  3306. {1:~ }|
  3307. |
  3308. ]]}
  3309. feed('zl')
  3310. screen:expect{grid=[[
  3311. aaaaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:!}|
  3312. {1:~ }|
  3313. |
  3314. ]]}
  3315. feed('zl')
  3316. screen:expect{grid=[[
  3317. aaaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:b}{1:!}|
  3318. {1:~ }|
  3319. |
  3320. ]]}
  3321. feed('zl')
  3322. screen:expect{grid=[[
  3323. aaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bb}{1:!}|
  3324. {1:~ }|
  3325. |
  3326. ]]}
  3327. feed('zl')
  3328. screen:expect{grid=[[
  3329. aaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbb}a|
  3330. {1:~ }|
  3331. |
  3332. ]]}
  3333. end)
  3334. it('lcs-extends is drawn with only inline virtual text offscreen', function()
  3335. command('set nowrap')
  3336. command('set list')
  3337. command('set listchars+=extends:c')
  3338. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline' })
  3339. insert(string.rep('a', 50))
  3340. feed('gg0')
  3341. screen:expect{grid=[[
  3342. ^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:c}|
  3343. {1:~ }|
  3344. |
  3345. ]]}
  3346. end)
  3347. it('blockwise Visual highlight with double-width virtual text (replace)', function()
  3348. screen:try_resize(60, 6)
  3349. insert('123456789\n123456789\n123456789\n123456789')
  3350. api.nvim_buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-口-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  3351. api.nvim_buf_set_extmark(0, ns, 2, 2, { virt_text = { { '口', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
  3352. feed('gg0')
  3353. screen:expect{grid=[[
  3354. ^123456789 |
  3355. 1{10:-口-}23456789 |
  3356. 12{10:口}3456789 |
  3357. 123456789 |
  3358. {1:~ }|
  3359. |
  3360. ]]}
  3361. feed('<C-V>3jl')
  3362. screen:expect{grid=[[
  3363. {7:12}3456789 |
  3364. {7:1}{10:-口-}23456789 |
  3365. {7:12}{10:口}3456789 |
  3366. {7:1}^23456789 |
  3367. {1:~ }|
  3368. {8:-- VISUAL BLOCK --} |
  3369. ]]}
  3370. feed('l')
  3371. screen:expect{grid=[[
  3372. {7:123}456789 |
  3373. {7:1}{10:-口-}23456789 |
  3374. {7:12}{10:口}3456789 |
  3375. {7:12}^3456789 |
  3376. {1:~ }|
  3377. {8:-- VISUAL BLOCK --} |
  3378. ]]}
  3379. feed('4l')
  3380. screen:expect{grid=[[
  3381. {7:1234567}89 |
  3382. {7:1}{10:-口-}{7:23}456789 |
  3383. {7:12}{10:口}{7:345}6789 |
  3384. {7:123456}^789 |
  3385. {1:~ }|
  3386. {8:-- VISUAL BLOCK --} |
  3387. ]]}
  3388. feed('Ol')
  3389. screen:expect{grid=[[
  3390. 1{7:234567}89 |
  3391. 1{10:-口-}{7:23}456789 |
  3392. 1{7:2}{10:口}{7:345}6789 |
  3393. 1^2{7:34567}89 |
  3394. {1:~ }|
  3395. {8:-- VISUAL BLOCK --} |
  3396. ]]}
  3397. feed('l')
  3398. screen:expect{grid=[[
  3399. 12{7:34567}89 |
  3400. 1{10:-口-}{7:23}456789 |
  3401. 12{10:口}{7:345}6789 |
  3402. 12^3{7:4567}89 |
  3403. {1:~ }|
  3404. {8:-- VISUAL BLOCK --} |
  3405. ]]}
  3406. feed('l')
  3407. screen:expect{grid=[[
  3408. 123{7:4567}89 |
  3409. 1{10:-口-}{7:23}456789 |
  3410. 12{10:口}{7:345}6789 |
  3411. 123^4{7:567}89 |
  3412. {1:~ }|
  3413. {8:-- VISUAL BLOCK --} |
  3414. ]]}
  3415. end)
  3416. it('blockwise Visual highlight with double-width virtual text (combine)', function()
  3417. screen:try_resize(60, 6)
  3418. insert('123456789\n123456789\n123456789\n123456789')
  3419. api.nvim_buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-口-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  3420. api.nvim_buf_set_extmark(0, ns, 2, 2, { virt_text = { { '口', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
  3421. feed('gg0')
  3422. screen:expect{grid=[[
  3423. ^123456789 |
  3424. 1{10:-口-}23456789 |
  3425. 12{10:口}3456789 |
  3426. 123456789 |
  3427. {1:~ }|
  3428. |
  3429. ]]}
  3430. feed('<C-V>3jl')
  3431. screen:expect{grid=[[
  3432. {7:12}3456789 |
  3433. {7:1}{20:-}{10:口-}23456789 |
  3434. {7:12}{10:口}3456789 |
  3435. {7:1}^23456789 |
  3436. {1:~ }|
  3437. {8:-- VISUAL BLOCK --} |
  3438. ]]}
  3439. feed('l')
  3440. screen:expect{grid=[[
  3441. {7:123}456789 |
  3442. {7:1}{20:-口}{10:-}23456789 |
  3443. {7:12}{20:口}3456789 |
  3444. {7:12}^3456789 |
  3445. {1:~ }|
  3446. {8:-- VISUAL BLOCK --} |
  3447. ]]}
  3448. feed('4l')
  3449. screen:expect{grid=[[
  3450. {7:1234567}89 |
  3451. {7:1}{20:-口-}{7:23}456789 |
  3452. {7:12}{20:口}{7:345}6789 |
  3453. {7:123456}^789 |
  3454. {1:~ }|
  3455. {8:-- VISUAL BLOCK --} |
  3456. ]]}
  3457. feed('Ol')
  3458. screen:expect{grid=[[
  3459. 1{7:234567}89 |
  3460. 1{20:-口-}{7:23}456789 |
  3461. 1{7:2}{20:口}{7:345}6789 |
  3462. 1^2{7:34567}89 |
  3463. {1:~ }|
  3464. {8:-- VISUAL BLOCK --} |
  3465. ]]}
  3466. feed('l')
  3467. screen:expect{grid=[[
  3468. 12{7:34567}89 |
  3469. 1{10:-}{20:口-}{7:23}456789 |
  3470. 12{20:口}{7:345}6789 |
  3471. 12^3{7:4567}89 |
  3472. {1:~ }|
  3473. {8:-- VISUAL BLOCK --} |
  3474. ]]}
  3475. feed('l')
  3476. screen:expect{grid=[[
  3477. 123{7:4567}89 |
  3478. 1{10:-}{20:口-}{7:23}456789 |
  3479. 12{20:口}{7:345}6789 |
  3480. 123^4{7:567}89 |
  3481. {1:~ }|
  3482. {8:-- VISUAL BLOCK --} |
  3483. ]]}
  3484. end)
  3485. local function test_virt_inline_showbreak_smoothscroll()
  3486. screen:try_resize(30, 6)
  3487. exec([[
  3488. highlight! link LineNr Normal
  3489. setlocal number showbreak=+ breakindent breakindentopt=shift:2
  3490. setlocal scrolloff=0 smoothscroll
  3491. call setline(1, repeat('a', 28))
  3492. normal! $
  3493. ]])
  3494. api.nvim_buf_set_extmark(0, ns, 0, 27, { virt_text = { { ('123'):rep(23) } }, virt_text_pos = 'inline' })
  3495. feed(':<CR>') -- Have a screen line that doesn't start with spaces
  3496. screen:expect{grid=[[
  3497. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3498. {1:+}a1231231231231231231231|
  3499. {1:+}23123123123123123123123|
  3500. {1:+}12312312312312312312312|
  3501. {1:+}3^a |
  3502. : |
  3503. ]]}
  3504. feed('<C-E>')
  3505. screen:expect{grid=[[
  3506. {1:+}a1231231231231231231231|
  3507. {1:+}23123123123123123123123|
  3508. {1:+}12312312312312312312312|
  3509. {1:+}3^a |
  3510. {1:~ }|
  3511. : |
  3512. ]]}
  3513. feed('<C-E>')
  3514. screen:expect{grid=[[
  3515. {1:+}23123123123123123123123|
  3516. {1:+}12312312312312312312312|
  3517. {1:+}3^a |
  3518. {1:~ }|*2
  3519. : |
  3520. ]]}
  3521. feed('<C-E>')
  3522. screen:expect{grid=[[
  3523. {1:+}12312312312312312312312|
  3524. {1:+}3^a |
  3525. {1:~ }|*3
  3526. : |
  3527. ]]}
  3528. feed('<C-E>')
  3529. screen:expect{grid=[[
  3530. {1:+}3^a |
  3531. {1:~ }|*4
  3532. : |
  3533. ]]}
  3534. feed('zbi')
  3535. screen:expect{grid=[[
  3536. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3537. {1:+}a^1231231231231231231231|
  3538. {1:+}23123123123123123123123|
  3539. {1:+}12312312312312312312312|
  3540. {1:+}3a |
  3541. {8:-- INSERT --} |
  3542. ]]}
  3543. feed('<BS>')
  3544. screen:expect{grid=[[
  3545. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3546. {1:+}^12312312312312312312312|
  3547. {1:+}31231231231231231231231|
  3548. {1:+}23123123123123123123123|
  3549. {1:+}a |
  3550. {8:-- INSERT --} |
  3551. ]]}
  3552. feed('<Esc>l')
  3553. feed(':<CR>') -- Have a screen line that doesn't start with spaces
  3554. screen:expect{grid=[[
  3555. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3556. {1:+}12312312312312312312312|
  3557. {1:+}31231231231231231231231|
  3558. {1:+}23123123123123123123123|
  3559. {1:+}^a |
  3560. : |
  3561. ]]}
  3562. feed('<C-E>')
  3563. screen:expect{grid=[[
  3564. {1:+}12312312312312312312312|
  3565. {1:+}31231231231231231231231|
  3566. {1:+}23123123123123123123123|
  3567. {1:+}^a |
  3568. {1:~ }|
  3569. : |
  3570. ]]}
  3571. feed('<C-E>')
  3572. screen:expect{grid=[[
  3573. {1:+}31231231231231231231231|
  3574. {1:+}23123123123123123123123|
  3575. {1:+}^a |
  3576. {1:~ }|*2
  3577. : |
  3578. ]]}
  3579. feed('<C-E>')
  3580. screen:expect{grid=[[
  3581. {1:+}23123123123123123123123|
  3582. {1:+}^a |
  3583. {1:~ }|*3
  3584. : |
  3585. ]]}
  3586. feed('<C-E>')
  3587. screen:expect{grid=[[
  3588. {1:+}^a |
  3589. {1:~ }|*4
  3590. : |
  3591. ]]}
  3592. feed('023x$')
  3593. screen:expect{grid=[[
  3594. 1 aaa12312312312312312312312|
  3595. {1:+}31231231231231231231231|
  3596. {1:+}23123123123123123123123|
  3597. {1:+}^a |
  3598. {1:~ }|
  3599. : |
  3600. ]]}
  3601. feed('<C-E>')
  3602. screen:expect{grid=[[
  3603. {1:+}31231231231231231231231|
  3604. {1:+}23123123123123123123123|
  3605. {1:+}^a |
  3606. {1:~ }|*2
  3607. : |
  3608. ]]}
  3609. feed('<C-E>')
  3610. screen:expect{grid=[[
  3611. {1:+}23123123123123123123123|
  3612. {1:+}^a |
  3613. {1:~ }|*3
  3614. : |
  3615. ]]}
  3616. feed('<C-E>')
  3617. screen:expect{grid=[[
  3618. {1:+}^a |
  3619. {1:~ }|*4
  3620. : |
  3621. ]]}
  3622. feed('zbi')
  3623. screen:expect{grid=[[
  3624. 1 aaa^12312312312312312312312|
  3625. {1:+}31231231231231231231231|
  3626. {1:+}23123123123123123123123|
  3627. {1:+}a |
  3628. {1:~ }|
  3629. {8:-- INSERT --} |
  3630. ]]}
  3631. feed('<C-U>')
  3632. screen:expect{grid=[[
  3633. 1 ^12312312312312312312312312|
  3634. {1:+}31231231231231231231231|
  3635. {1:+}23123123123123123123a |
  3636. {1:~ }|*2
  3637. {8:-- INSERT --} |
  3638. ]]}
  3639. feed('<Esc>')
  3640. screen:expect{grid=[[
  3641. 1 12312312312312312312312312|
  3642. {1:+}31231231231231231231231|
  3643. {1:+}23123123123123123123^a |
  3644. {1:~ }|*2
  3645. |
  3646. ]]}
  3647. feed('<C-E>')
  3648. screen:expect{grid=[[
  3649. {1:+}31231231231231231231231|
  3650. {1:+}23123123123123123123^a |
  3651. {1:~ }|*3
  3652. |
  3653. ]]}
  3654. feed('<C-E>')
  3655. screen:expect{grid=[[
  3656. {1:+}23123123123123123123^a |
  3657. {1:~ }|*4
  3658. |
  3659. ]]}
  3660. feed('zbx')
  3661. screen:expect{grid=[[
  3662. 1 ^12312312312312312312312312|
  3663. {1:+}31231231231231231231231|
  3664. {1:+}23123123123123123123 |
  3665. {1:~ }|*2
  3666. |
  3667. ]]}
  3668. feed('26ia<Esc>a')
  3669. screen:expect{grid=[[
  3670. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3671. {1:+}^12312312312312312312312|
  3672. {1:+}31231231231231231231231|
  3673. {1:+}23123123123123123123123|
  3674. {1:~ }|
  3675. {8:-- INSERT --} |
  3676. ]]}
  3677. feed([[<C-\><C-O>:setlocal breakindentopt=<CR>]])
  3678. screen:expect{grid=[[
  3679. 1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
  3680. {1:+}^1231231231231231231231231|
  3681. {1:+}2312312312312312312312312|
  3682. {1:+}3123123123123123123 |
  3683. {1:~ }|
  3684. {8:-- INSERT --} |
  3685. ]]}
  3686. end
  3687. describe('with showbreak, smoothscroll', function()
  3688. it('and cpoptions-=n', function()
  3689. test_virt_inline_showbreak_smoothscroll()
  3690. end)
  3691. it('and cpoptions+=n', function()
  3692. command('set cpoptions+=n')
  3693. -- because of 'breakindent' the screen states are the same
  3694. test_virt_inline_showbreak_smoothscroll()
  3695. end)
  3696. end)
  3697. it('before TABs with smoothscroll', function()
  3698. screen:try_resize(30, 6)
  3699. exec([[
  3700. setlocal list listchars=tab:<-> scrolloff=0 smoothscroll
  3701. call setline(1, repeat("\t", 4) .. 'a')
  3702. normal! $
  3703. ]])
  3704. api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { ('12'):rep(32) } }, virt_text_pos = 'inline' })
  3705. screen:expect{grid=[[
  3706. {1:<------><------><------>}121212|
  3707. 121212121212121212121212121212|
  3708. 1212121212121212121212121212{1:<-}|
  3709. {1:----->}^a |
  3710. {1:~ }|
  3711. |
  3712. ]]}
  3713. feed('<C-E>')
  3714. screen:expect{grid=[[
  3715. {1:<<<}212121212121212121212121212|
  3716. 1212121212121212121212121212{1:<-}|
  3717. {1:----->}^a |
  3718. {1:~ }|*2
  3719. |
  3720. ]]}
  3721. feed('<C-E>')
  3722. screen:expect{grid=[[
  3723. {1:<<<}2121212121212121212121212{1:<-}|
  3724. {1:----->}^a |
  3725. {1:~ }|*3
  3726. |
  3727. ]]}
  3728. feed('<C-E>')
  3729. screen:expect{grid=[[
  3730. {1:<<<-->}^a |
  3731. {1:~ }|*4
  3732. |
  3733. ]]}
  3734. feed('zbh')
  3735. screen:expect{grid=[[
  3736. {1:<------><------><------>}121212|
  3737. 121212121212121212121212121212|
  3738. 1212121212121212121212121212{1:^<-}|
  3739. {1:----->}a |
  3740. {1:~ }|
  3741. |
  3742. ]]}
  3743. feed('i')
  3744. screen:expect{grid=[[
  3745. {1:<------><------><------>}^121212|
  3746. 121212121212121212121212121212|
  3747. 1212121212121212121212121212{1:<-}|
  3748. {1:----->}a |
  3749. {1:~ }|
  3750. {8:-- INSERT --} |
  3751. ]]}
  3752. feed('<C-O>:setlocal nolist<CR>')
  3753. screen:expect{grid=[[
  3754. ^121212|
  3755. 121212121212121212121212121212|
  3756. 1212121212121212121212121212 |
  3757. a |
  3758. {1:~ }|
  3759. {8:-- INSERT --} |
  3760. ]]}
  3761. feed('<Esc>l')
  3762. screen:expect{grid=[[
  3763. 121212|
  3764. 121212121212121212121212121212|
  3765. 1212121212121212121212121212 |
  3766. ^ a |
  3767. {1:~ }|
  3768. |
  3769. ]]}
  3770. feed('<C-E>')
  3771. screen:expect{grid=[[
  3772. {1:<<<}212121212121212121212121212|
  3773. 1212121212121212121212121212 |
  3774. ^ a |
  3775. {1:~ }|*2
  3776. |
  3777. ]]}
  3778. feed('<C-E>')
  3779. screen:expect{grid=[[
  3780. {1:<<<}2121212121212121212121212 |
  3781. ^ a |
  3782. {1:~ }|*3
  3783. |
  3784. ]]}
  3785. feed('<C-E>')
  3786. screen:expect{grid=[[
  3787. {1:<<<} ^ a |
  3788. {1:~ }|*4
  3789. |
  3790. ]]}
  3791. end)
  3792. it('before a space with linebreak', function()
  3793. screen:try_resize(50, 6)
  3794. exec([[
  3795. setlocal linebreak showbreak=+ breakindent breakindentopt=shift:2
  3796. call setline(1, repeat('a', 50) .. ' ' .. repeat('c', 45))
  3797. normal! $
  3798. ]])
  3799. api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('b'):rep(10) } }, virt_text_pos = 'inline' })
  3800. screen:expect{grid=[[
  3801. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3802. {1:+}bbbbbbbbbb |
  3803. {1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
  3804. {1:~ }|*2
  3805. |
  3806. ]]}
  3807. feed('05x$')
  3808. screen:expect{grid=[[
  3809. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb|
  3810. {1:+}bbbbb |
  3811. {1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
  3812. {1:~ }|*2
  3813. |
  3814. ]]}
  3815. end)
  3816. it('before double-width char that wraps', function()
  3817. exec([[
  3818. call setline(1, repeat('a', 40) .. '口' .. '12345')
  3819. normal! $
  3820. ]])
  3821. api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(9) } }, virt_text_pos = 'inline' })
  3822. screen:expect([[
  3823. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}|
  3824. 口1234^5 |
  3825. |
  3826. ]])
  3827. feed('g0')
  3828. screen:expect([[
  3829. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}|
  3830. ^口12345 |
  3831. |
  3832. ]])
  3833. command('set showbreak=+++')
  3834. screen:expect([[
  3835. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}|
  3836. {1:+++}^口12345 |
  3837. |
  3838. ]])
  3839. end)
  3840. it('cursor position is correct if end_row or end_col is specified', function()
  3841. screen:try_resize(50, 8)
  3842. api.nvim_buf_set_lines(0, 0, -1, false, { ('a'):rep(48), ('b'):rep(48), ('c'):rep(48), ('d'):rep(48) })
  3843. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 2, virt_text_pos = 'inline', virt_text = {{'I1', 'NonText'}}})
  3844. api.nvim_buf_set_extmark(0, ns, 3, 0, {end_col = 2, virt_text_pos = 'inline', virt_text = {{'I2', 'NonText'}}})
  3845. feed('$')
  3846. screen:expect([[
  3847. {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a|
  3848. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
  3849. cccccccccccccccccccccccccccccccccccccccccccccccc |
  3850. {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd|
  3851. {1:~ }|*3
  3852. |
  3853. ]])
  3854. feed('j')
  3855. screen:expect([[
  3856. {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3857. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b |
  3858. cccccccccccccccccccccccccccccccccccccccccccccccc |
  3859. {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd|
  3860. {1:~ }|*3
  3861. |
  3862. ]])
  3863. feed('j')
  3864. screen:expect([[
  3865. {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3866. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
  3867. ccccccccccccccccccccccccccccccccccccccccccccccc^c |
  3868. {1:I2}dddddddddddddddddddddddddddddddddddddddddddddddd|
  3869. {1:~ }|*3
  3870. |
  3871. ]])
  3872. feed('j')
  3873. screen:expect([[
  3874. {1:I1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3875. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
  3876. cccccccccccccccccccccccccccccccccccccccccccccccc |
  3877. {1:I2}ddddddddddddddddddddddddddddddddddddddddddddddd^d|
  3878. {1:~ }|*3
  3879. |
  3880. ]])
  3881. end)
  3882. it('cursor position is correct with invalidated inline virt text', function()
  3883. screen:try_resize(50, 8)
  3884. api.nvim_buf_set_lines(0, 0, -1, false, { ('a'):rep(48), ('b'):rep(48) })
  3885. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text_pos = 'inline', virt_text = {{'INLINE', 'NonText'}}, invalidate = true })
  3886. screen:expect([[
  3887. {1:INLINE}^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
  3888. aaaa |
  3889. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
  3890. {1:~ }|*4
  3891. |
  3892. ]])
  3893. feed('dd$')
  3894. screen:expect([[
  3895. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb^b |
  3896. {1:~ }|*6
  3897. |
  3898. ]])
  3899. end)
  3900. end)
  3901. describe('decorations: virtual lines', function()
  3902. local screen, ns
  3903. before_each(function()
  3904. clear()
  3905. screen = Screen.new(50, 12)
  3906. screen:add_extra_attr_ids {
  3907. [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow },
  3908. }
  3909. ns = api.nvim_create_namespace 'test'
  3910. end)
  3911. local example_text2 = [[
  3912. if (h->n_buckets < new_n_buckets) { // expand
  3913. khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t));
  3914. h->keys = new_keys;
  3915. if (kh_is_map && val_size) {
  3916. char *new_vals = krealloc( h->vals_buf, new_n_buckets * val_size);
  3917. h->vals_buf = new_vals;
  3918. }
  3919. }]]
  3920. it('works with one line', function()
  3921. insert(example_text2)
  3922. feed '2gg'
  3923. screen:expect{grid=[[
  3924. if (h->n_buckets < new_n_buckets) { // expand |
  3925. ^khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  3926. h->keys, new_n_buckets * sizeof(khkey_t)); |
  3927. h->keys = new_keys; |
  3928. if (kh_is_map && val_size) { |
  3929. char *new_vals = krealloc( h->vals_buf, new_n_|
  3930. buckets * val_size); |
  3931. h->vals_buf = new_vals; |
  3932. } |
  3933. } |
  3934. {1:~ }|
  3935. |
  3936. ]]}
  3937. api.nvim_buf_set_extmark(0, ns, 1, 33, {
  3938. virt_lines={ {{">> ", "NonText"}, {"krealloc", "Identifier"}, {": change the size of an allocation"}}};
  3939. virt_lines_above=true;
  3940. })
  3941. screen:expect{grid=[[
  3942. if (h->n_buckets < new_n_buckets) { // expand |
  3943. {1:>> }{25:krealloc}: change the size of an allocation |
  3944. ^khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  3945. h->keys, new_n_buckets * sizeof(khkey_t)); |
  3946. h->keys = new_keys; |
  3947. if (kh_is_map && val_size) { |
  3948. char *new_vals = krealloc( h->vals_buf, new_n_|
  3949. buckets * val_size); |
  3950. h->vals_buf = new_vals; |
  3951. } |
  3952. } |
  3953. |
  3954. ]]}
  3955. feed '/krealloc<cr>'
  3956. screen:expect{grid=[[
  3957. if (h->n_buckets < new_n_buckets) { // expand |
  3958. {1:>> }{25:krealloc}: change the size of an allocation |
  3959. khkey_t *new_keys = (khkey_t *){10:^krealloc}((void *)|
  3960. h->keys, new_n_buckets * sizeof(khkey_t)); |
  3961. h->keys = new_keys; |
  3962. if (kh_is_map && val_size) { |
  3963. char *new_vals = {10:krealloc}( h->vals_buf, new_n_|
  3964. buckets * val_size); |
  3965. h->vals_buf = new_vals; |
  3966. } |
  3967. } |
  3968. /krealloc |
  3969. ]]}
  3970. -- virtual line remains anchored to the extmark
  3971. feed 'i<cr>'
  3972. screen:expect{grid=[[
  3973. if (h->n_buckets < new_n_buckets) { // expand |
  3974. khkey_t *new_keys = (khkey_t *) |
  3975. {1:>> }{25:krealloc}: change the size of an allocation |
  3976. {10:^krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
  3977. hkey_t)); |
  3978. h->keys = new_keys; |
  3979. if (kh_is_map && val_size) { |
  3980. char *new_vals = {10:krealloc}( h->vals_buf, new_n_|
  3981. buckets * val_size); |
  3982. h->vals_buf = new_vals; |
  3983. } |
  3984. {5:-- INSERT --} |
  3985. ]]}
  3986. feed '<esc>3+'
  3987. screen:expect{grid=[[
  3988. if (h->n_buckets < new_n_buckets) { // expand |
  3989. khkey_t *new_keys = (khkey_t *) |
  3990. {1:>> }{25:krealloc}: change the size of an allocation |
  3991. {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
  3992. hkey_t)); |
  3993. h->keys = new_keys; |
  3994. if (kh_is_map && val_size) { |
  3995. ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_|
  3996. buckets * val_size); |
  3997. h->vals_buf = new_vals; |
  3998. } |
  3999. |
  4000. ]]}
  4001. api.nvim_buf_set_extmark(0, ns, 5, 0, {
  4002. virt_lines = { {{"^^ REVIEW:", "Todo"}, {" new_vals variable seems unnecessary?", "Comment"}} };
  4003. })
  4004. screen:expect{grid=[[
  4005. if (h->n_buckets < new_n_buckets) { // expand |
  4006. khkey_t *new_keys = (khkey_t *) |
  4007. {1:>> }{25:krealloc}: change the size of an allocation |
  4008. {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
  4009. hkey_t)); |
  4010. h->keys = new_keys; |
  4011. if (kh_is_map && val_size) { |
  4012. ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_|
  4013. buckets * val_size); |
  4014. {100:^^ REVIEW:}{18: new_vals variable seems unnecessary?} |
  4015. h->vals_buf = new_vals; |
  4016. |
  4017. ]]}
  4018. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  4019. screen:expect{grid=[[
  4020. if (h->n_buckets < new_n_buckets) { // expand |
  4021. khkey_t *new_keys = (khkey_t *) |
  4022. {10:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
  4023. hkey_t)); |
  4024. h->keys = new_keys; |
  4025. if (kh_is_map && val_size) { |
  4026. ^char *new_vals = {10:krealloc}( h->vals_buf, new_n_|
  4027. buckets * val_size); |
  4028. h->vals_buf = new_vals; |
  4029. } |
  4030. } |
  4031. |
  4032. ]]}
  4033. end)
  4034. it('works with text at the beginning of the buffer', function()
  4035. insert(example_text2)
  4036. feed 'gg'
  4037. screen:expect{grid=[[
  4038. ^if (h->n_buckets < new_n_buckets) { // expand |
  4039. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4040. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4041. h->keys = new_keys; |
  4042. if (kh_is_map && val_size) { |
  4043. char *new_vals = krealloc( h->vals_buf, new_n_|
  4044. buckets * val_size); |
  4045. h->vals_buf = new_vals; |
  4046. } |
  4047. } |
  4048. {1:~ }|
  4049. |
  4050. ]]}
  4051. api.nvim_buf_set_extmark(0, ns, 0, 0, {
  4052. virt_lines={
  4053. {{"refactor(khash): ", "Special"}, {"take size of values as parameter"}};
  4054. {{"Author: Dev Devsson, "}, {"Tue Aug 31 10:13:37 2021", "Comment"}};
  4055. };
  4056. virt_lines_above=true;
  4057. right_gravity=false;
  4058. })
  4059. -- placing virt_text on topline does not automatically cause a scroll
  4060. screen:expect{grid=[[
  4061. ^if (h->n_buckets < new_n_buckets) { // expand |
  4062. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4063. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4064. h->keys = new_keys; |
  4065. if (kh_is_map && val_size) { |
  4066. char *new_vals = krealloc( h->vals_buf, new_n_|
  4067. buckets * val_size); |
  4068. h->vals_buf = new_vals; |
  4069. } |
  4070. } |
  4071. {1:~ }|
  4072. |
  4073. ]], unchanged=true}
  4074. feed '<c-b>'
  4075. screen:expect{grid=[[
  4076. {16:refactor(khash): }take size of values as parameter |
  4077. Author: Dev Devsson, {18:Tue Aug 31 10:13:37 2021} |
  4078. if (h->n_buckets < new_n_buckets) { // expand |
  4079. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4080. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4081. h->keys = new_keys; |
  4082. if (kh_is_map && val_size) { |
  4083. char *new_vals = krealloc( h->vals_buf, new_n_|
  4084. buckets * val_size); |
  4085. h->vals_buf = new_vals; |
  4086. ^} |
  4087. |
  4088. ]]}
  4089. end)
  4090. it('works with text at the end of the buffer', function()
  4091. insert(example_text2)
  4092. feed 'G'
  4093. screen:expect{grid=[[
  4094. if (h->n_buckets < new_n_buckets) { // expand |
  4095. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4096. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4097. h->keys = new_keys; |
  4098. if (kh_is_map && val_size) { |
  4099. char *new_vals = krealloc( h->vals_buf, new_n_|
  4100. buckets * val_size); |
  4101. h->vals_buf = new_vals; |
  4102. } |
  4103. ^} |
  4104. {1:~ }|
  4105. |
  4106. ]]}
  4107. local id = api.nvim_buf_set_extmark(0, ns, 7, 0, {
  4108. virt_lines={{{"Grugg"}}};
  4109. right_gravity=false;
  4110. })
  4111. screen:expect{grid=[[
  4112. if (h->n_buckets < new_n_buckets) { // expand |
  4113. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4114. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4115. h->keys = new_keys; |
  4116. if (kh_is_map && val_size) { |
  4117. char *new_vals = krealloc( h->vals_buf, new_n_|
  4118. buckets * val_size); |
  4119. h->vals_buf = new_vals; |
  4120. } |
  4121. ^} |
  4122. Grugg |
  4123. |
  4124. ]]}
  4125. screen:try_resize(50, 11)
  4126. feed('gg')
  4127. screen:expect{grid=[[
  4128. ^if (h->n_buckets < new_n_buckets) { // expand |
  4129. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4130. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4131. h->keys = new_keys; |
  4132. if (kh_is_map && val_size) { |
  4133. char *new_vals = krealloc( h->vals_buf, new_n_|
  4134. buckets * val_size); |
  4135. h->vals_buf = new_vals; |
  4136. } |
  4137. } |
  4138. |
  4139. ]]}
  4140. feed('G<C-E>')
  4141. screen:expect{grid=[[
  4142. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4143. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4144. h->keys = new_keys; |
  4145. if (kh_is_map && val_size) { |
  4146. char *new_vals = krealloc( h->vals_buf, new_n_|
  4147. buckets * val_size); |
  4148. h->vals_buf = new_vals; |
  4149. } |
  4150. ^} |
  4151. Grugg |
  4152. |
  4153. ]]}
  4154. feed('gg')
  4155. screen:expect{grid=[[
  4156. ^if (h->n_buckets < new_n_buckets) { // expand |
  4157. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4158. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4159. h->keys = new_keys; |
  4160. if (kh_is_map && val_size) { |
  4161. char *new_vals = krealloc( h->vals_buf, new_n_|
  4162. buckets * val_size); |
  4163. h->vals_buf = new_vals; |
  4164. } |
  4165. } |
  4166. |
  4167. ]]}
  4168. screen:try_resize(50, 12)
  4169. feed('G')
  4170. screen:expect{grid=[[
  4171. if (h->n_buckets < new_n_buckets) { // expand |
  4172. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4173. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4174. h->keys = new_keys; |
  4175. if (kh_is_map && val_size) { |
  4176. char *new_vals = krealloc( h->vals_buf, new_n_|
  4177. buckets * val_size); |
  4178. h->vals_buf = new_vals; |
  4179. } |
  4180. ^} |
  4181. Grugg |
  4182. |
  4183. ]]}
  4184. api.nvim_buf_del_extmark(0, ns, id)
  4185. screen:expect{grid=[[
  4186. if (h->n_buckets < new_n_buckets) { // expand |
  4187. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4188. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4189. h->keys = new_keys; |
  4190. if (kh_is_map && val_size) { |
  4191. char *new_vals = krealloc( h->vals_buf, new_n_|
  4192. buckets * val_size); |
  4193. h->vals_buf = new_vals; |
  4194. } |
  4195. ^} |
  4196. {1:~ }|
  4197. |
  4198. ]]}
  4199. end)
  4200. it('works beyond end of the buffer with virt_lines_above', function()
  4201. insert(example_text2)
  4202. feed 'G'
  4203. screen:expect{grid=[[
  4204. if (h->n_buckets < new_n_buckets) { // expand |
  4205. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4206. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4207. h->keys = new_keys; |
  4208. if (kh_is_map && val_size) { |
  4209. char *new_vals = krealloc( h->vals_buf, new_n_|
  4210. buckets * val_size); |
  4211. h->vals_buf = new_vals; |
  4212. } |
  4213. ^} |
  4214. {1:~ }|
  4215. |
  4216. ]]}
  4217. local id = api.nvim_buf_set_extmark(0, ns, 8, 0, {
  4218. virt_lines={{{"Grugg"}}};
  4219. virt_lines_above = true,
  4220. })
  4221. screen:expect{grid=[[
  4222. if (h->n_buckets < new_n_buckets) { // expand |
  4223. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4224. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4225. h->keys = new_keys; |
  4226. if (kh_is_map && val_size) { |
  4227. char *new_vals = krealloc( h->vals_buf, new_n_|
  4228. buckets * val_size); |
  4229. h->vals_buf = new_vals; |
  4230. } |
  4231. ^} |
  4232. Grugg |
  4233. |
  4234. ]]}
  4235. feed('dd')
  4236. screen:expect{grid=[[
  4237. if (h->n_buckets < new_n_buckets) { // expand |
  4238. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4239. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4240. h->keys = new_keys; |
  4241. if (kh_is_map && val_size) { |
  4242. char *new_vals = krealloc( h->vals_buf, new_n_|
  4243. buckets * val_size); |
  4244. h->vals_buf = new_vals; |
  4245. ^} |
  4246. Grugg |
  4247. {1:~ }|
  4248. |
  4249. ]]}
  4250. feed('dk')
  4251. screen:expect{grid=[[
  4252. if (h->n_buckets < new_n_buckets) { // expand |
  4253. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4254. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4255. h->keys = new_keys; |
  4256. if (kh_is_map && val_size) { |
  4257. ^char *new_vals = krealloc( h->vals_buf, new_n_|
  4258. buckets * val_size); |
  4259. Grugg |
  4260. {1:~ }|*3
  4261. |
  4262. ]]}
  4263. feed('dgg')
  4264. screen:expect{grid=[[
  4265. ^ |
  4266. Grugg |
  4267. {1:~ }|*9
  4268. --No lines in buffer-- |
  4269. ]]}
  4270. api.nvim_buf_del_extmark(0, ns, id)
  4271. screen:expect{grid=[[
  4272. ^ |
  4273. {1:~ }|*10
  4274. --No lines in buffer-- |
  4275. ]]}
  4276. end)
  4277. it('does not cause syntax ml_get error at the end of a buffer #17816', function()
  4278. command([[syntax region foo keepend start='^foo' end='^$']])
  4279. command('syntax sync minlines=100')
  4280. insert('foo')
  4281. api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'bar', 'Comment'}}}})
  4282. screen:expect([[
  4283. fo^o |
  4284. {18:bar} |
  4285. {1:~ }|*9
  4286. |
  4287. ]])
  4288. end)
  4289. it('works with a block scrolling up', function()
  4290. screen:try_resize(30, 7)
  4291. insert("aa\nbb\ncc\ndd\nee\nff\ngg\nhh")
  4292. feed 'gg'
  4293. api.nvim_buf_set_extmark(0, ns, 6, 0, {
  4294. virt_lines={
  4295. {{"they see me"}};
  4296. {{"scrolling", "Special"}};
  4297. {{"they"}};
  4298. {{"hatin'", "Special"}};
  4299. };
  4300. })
  4301. screen:expect{grid=[[
  4302. ^aa |
  4303. bb |
  4304. cc |
  4305. dd |
  4306. ee |
  4307. ff |
  4308. |
  4309. ]]}
  4310. feed '<c-e>'
  4311. screen:expect{grid=[[
  4312. ^bb |
  4313. cc |
  4314. dd |
  4315. ee |
  4316. ff |
  4317. gg |
  4318. |
  4319. ]]}
  4320. feed '<c-e>'
  4321. screen:expect{grid=[[
  4322. ^cc |
  4323. dd |
  4324. ee |
  4325. ff |
  4326. gg |
  4327. they see me |
  4328. |
  4329. ]]}
  4330. feed '<c-e>'
  4331. screen:expect{grid=[[
  4332. ^dd |
  4333. ee |
  4334. ff |
  4335. gg |
  4336. they see me |
  4337. {16:scrolling} |
  4338. |
  4339. ]]}
  4340. feed '<c-e>'
  4341. screen:expect{grid=[[
  4342. ^ee |
  4343. ff |
  4344. gg |
  4345. they see me |
  4346. {16:scrolling} |
  4347. they |
  4348. |
  4349. ]]}
  4350. feed '<c-e>'
  4351. screen:expect{grid=[[
  4352. ^ff |
  4353. gg |
  4354. they see me |
  4355. {16:scrolling} |
  4356. they |
  4357. {16:hatin'} |
  4358. |
  4359. ]]}
  4360. feed '<c-e>'
  4361. screen:expect{grid=[[
  4362. ^gg |
  4363. they see me |
  4364. {16:scrolling} |
  4365. they |
  4366. {16:hatin'} |
  4367. hh |
  4368. |
  4369. ]]}
  4370. feed '<c-e>'
  4371. screen:expect{grid=[[
  4372. they see me |
  4373. {16:scrolling} |
  4374. they |
  4375. {16:hatin'} |
  4376. ^hh |
  4377. {1:~ }|
  4378. |
  4379. ]]}
  4380. feed '<c-e>'
  4381. screen:expect{grid=[[
  4382. {16:scrolling} |
  4383. they |
  4384. {16:hatin'} |
  4385. ^hh |
  4386. {1:~ }|*2
  4387. |
  4388. ]]}
  4389. feed '<c-e>'
  4390. screen:expect{grid=[[
  4391. they |
  4392. {16:hatin'} |
  4393. ^hh |
  4394. {1:~ }|*3
  4395. |
  4396. ]]}
  4397. feed '<c-e>'
  4398. screen:expect{grid=[[
  4399. {16:hatin'} |
  4400. ^hh |
  4401. {1:~ }|*4
  4402. |
  4403. ]]}
  4404. feed '<c-e>'
  4405. screen:expect{grid=[[
  4406. ^hh |
  4407. {1:~ }|*5
  4408. |
  4409. ]]}
  4410. end)
  4411. it('works with sign and numbercolumns', function()
  4412. insert(example_text2)
  4413. feed 'gg'
  4414. command 'set number signcolumn=yes'
  4415. screen:expect{grid=[[
  4416. {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
  4417. {7: }{8: }d |
  4418. {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
  4419. {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
  4420. {7: }{8: }t)); |
  4421. {7: }{8: 3 } h->keys = new_keys; |
  4422. {7: }{8: 4 } if (kh_is_map && val_size) { |
  4423. {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, |
  4424. {7: }{8: }new_n_buckets * val_size); |
  4425. {7: }{8: 6 } h->vals_buf = new_vals; |
  4426. {7: }{8: 7 } } |
  4427. |
  4428. ]]}
  4429. local markid = api.nvim_buf_set_extmark(0, ns, 2, 0, {
  4430. virt_lines={
  4431. {{"Some special", "Special"}};
  4432. {{"remark about codes", "Comment"}};
  4433. };
  4434. })
  4435. screen:expect{grid=[[
  4436. {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
  4437. {7: }{8: }d |
  4438. {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
  4439. {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
  4440. {7: }{8: }t)); |
  4441. {7: }{8: 3 } h->keys = new_keys; |
  4442. {7: }{8: }{16:Some special} |
  4443. {7: }{8: }{18:remark about codes} |
  4444. {7: }{8: 4 } if (kh_is_map && val_size) { |
  4445. {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, |
  4446. {7: }{8: }new_n_buckets * val_size); |
  4447. |
  4448. ]]}
  4449. api.nvim_buf_set_extmark(0, ns, 2, 0, {
  4450. virt_lines={
  4451. {{"Some special", "Special"}};
  4452. {{"remark about codes", "Comment"}};
  4453. };
  4454. virt_lines_leftcol=true;
  4455. id=markid;
  4456. })
  4457. screen:expect{grid=[[
  4458. {7: }{8: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
  4459. {7: }{8: }d |
  4460. {7: }{8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((v|
  4461. {7: }{8: }oid *)h->keys, new_n_buckets * sizeof(khkey_|
  4462. {7: }{8: }t)); |
  4463. {7: }{8: 3 } h->keys = new_keys; |
  4464. {16:Some special} |
  4465. {18:remark about codes} |
  4466. {7: }{8: 4 } if (kh_is_map && val_size) { |
  4467. {7: }{8: 5 } char *new_vals = krealloc( h->vals_buf, |
  4468. {7: }{8: }new_n_buckets * val_size); |
  4469. |
  4470. ]]}
  4471. end)
  4472. it('works with hard TABs', function()
  4473. insert(example_text2)
  4474. feed 'gg'
  4475. api.nvim_buf_set_extmark(0, ns, 1, 0, {
  4476. virt_lines={ {{">>", "NonText"}, {"\tvery\ttabby", "Identifier"}, {"text\twith\ttabs"}}};
  4477. })
  4478. screen:expect{grid=[[
  4479. ^if (h->n_buckets < new_n_buckets) { // expand |
  4480. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4481. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4482. {1:>>}{25: very tabby}text with tabs |
  4483. h->keys = new_keys; |
  4484. if (kh_is_map && val_size) { |
  4485. char *new_vals = krealloc( h->vals_buf, new_n_|
  4486. buckets * val_size); |
  4487. h->vals_buf = new_vals; |
  4488. } |
  4489. } |
  4490. |
  4491. ]]}
  4492. command 'set tabstop=4'
  4493. screen:expect{grid=[[
  4494. ^if (h->n_buckets < new_n_buckets) { // expand |
  4495. khkey_t *new_keys = (khkey_t *)krealloc((void *)|
  4496. h->keys, new_n_buckets * sizeof(khkey_t)); |
  4497. {1:>>}{25: very tabby}text with tabs |
  4498. h->keys = new_keys; |
  4499. if (kh_is_map && val_size) { |
  4500. char *new_vals = krealloc( h->vals_buf, new_n_|
  4501. buckets * val_size); |
  4502. h->vals_buf = new_vals; |
  4503. } |
  4504. } |
  4505. |
  4506. ]]}
  4507. command 'set number'
  4508. screen:expect{grid=[[
  4509. {8: 1 }^if (h->n_buckets < new_n_buckets) { // expand |
  4510. {8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi|
  4511. {8: }d *)h->keys, new_n_buckets * sizeof(khkey_t));|
  4512. {8: }{1:>>}{25: very tabby}text with tabs |
  4513. {8: 3 } h->keys = new_keys; |
  4514. {8: 4 } if (kh_is_map && val_size) { |
  4515. {8: 5 } char *new_vals = krealloc( h->vals_buf, ne|
  4516. {8: }w_n_buckets * val_size); |
  4517. {8: 6 } h->vals_buf = new_vals; |
  4518. {8: 7 } } |
  4519. {8: 8 }} |
  4520. |
  4521. ]]}
  4522. command 'set tabstop&'
  4523. screen:expect{grid=[[
  4524. {8: 1 }^if (h->n_buckets < new_n_buckets) { // expand |
  4525. {8: 2 } khkey_t *new_keys = (khkey_t *)krealloc((voi|
  4526. {8: }d *)h->keys, new_n_buckets * sizeof(khkey_t));|
  4527. {8: }{1:>>}{25: very tabby}text with tabs |
  4528. {8: 3 } h->keys = new_keys; |
  4529. {8: 4 } if (kh_is_map && val_size) { |
  4530. {8: 5 } char *new_vals = krealloc( h->vals_buf, ne|
  4531. {8: }w_n_buckets * val_size); |
  4532. {8: 6 } h->vals_buf = new_vals; |
  4533. {8: 7 } } |
  4534. {8: 8 }} |
  4535. |
  4536. ]]}
  4537. end)
  4538. it('does not show twice if end_row or end_col is specified #18622', function()
  4539. screen:try_resize(50, 8)
  4540. insert([[
  4541. aaa
  4542. bbb
  4543. ccc
  4544. ddd]])
  4545. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 2, virt_lines = {{{'VIRT LINE 1', 'NonText'}}}})
  4546. api.nvim_buf_set_extmark(0, ns, 3, 0, {end_col = 2, virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
  4547. screen:expect{grid=[[
  4548. aaa |
  4549. {1:VIRT LINE 1} |
  4550. bbb |
  4551. ccc |
  4552. dd^d |
  4553. {1:VIRT LINE 2} |
  4554. {1:~ }|
  4555. |
  4556. ]]}
  4557. end)
  4558. it('works with rightleft', function()
  4559. screen:try_resize(50, 8)
  4560. insert([[
  4561. aaa
  4562. bbb
  4563. ccc
  4564. ddd]])
  4565. command('set number rightleft')
  4566. api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'VIRT LINE 1', 'NonText'}}}, virt_lines_leftcol = true})
  4567. api.nvim_buf_set_extmark(0, ns, 3, 0, {virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
  4568. screen:expect{grid=[[
  4569. aaa{8: 1 }|
  4570. {1:1 ENIL TRIV}|
  4571. bbb{8: 2 }|
  4572. ccc{8: 3 }|
  4573. ^ddd{8: 4 }|
  4574. {1:2 ENIL TRIV}{8: }|
  4575. {1: ~}|
  4576. |
  4577. ]]}
  4578. end)
  4579. it('works when using dd or yyp #23915 #23916', function()
  4580. insert([[
  4581. line1
  4582. line2
  4583. line3
  4584. line4
  4585. line5]])
  4586. api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines={{{"foo"}}, {{"bar"}}, {{"baz"}}}})
  4587. screen:expect{grid=[[
  4588. line1 |
  4589. foo |
  4590. bar |
  4591. baz |
  4592. line2 |
  4593. line3 |
  4594. line4 |
  4595. line^5 |
  4596. {1:~ }|*3
  4597. |
  4598. ]]}
  4599. feed('gg')
  4600. feed('yyp')
  4601. screen:expect{grid=[[
  4602. line1 |
  4603. foo |
  4604. bar |
  4605. baz |
  4606. ^line1 |
  4607. line2 |
  4608. line3 |
  4609. line4 |
  4610. line5 |
  4611. {1:~ }|*2
  4612. |
  4613. ]]}
  4614. feed('dd')
  4615. screen:expect{grid=[[
  4616. line1 |
  4617. foo |
  4618. bar |
  4619. baz |
  4620. ^line2 |
  4621. line3 |
  4622. line4 |
  4623. line5 |
  4624. {1:~ }|*3
  4625. |
  4626. ]]}
  4627. feed('kdd')
  4628. screen:expect([[
  4629. ^line2 |
  4630. foo |
  4631. bar |
  4632. baz |
  4633. line3 |
  4634. line4 |
  4635. line5 |
  4636. {1:~ }|*4
  4637. |
  4638. ]])
  4639. end)
  4640. it('does not break cursor position with concealcursor #27887', function()
  4641. command('vsplit')
  4642. insert('\n')
  4643. api.nvim_set_option_value('conceallevel', 2, {})
  4644. api.nvim_set_option_value('concealcursor', 'niv', {})
  4645. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'VIRT1'}}, {{'VIRT2'}}} })
  4646. screen:expect([[
  4647. │ |
  4648. VIRT1 │VIRT1 |
  4649. VIRT2 │VIRT2 |
  4650. ^ │ |
  4651. {1:~ }│{1:~ }|*6
  4652. {3:[No Name] [+] }{2:[No Name] [+] }|
  4653. |
  4654. ]])
  4655. end)
  4656. it('works with full page scrolling #28290', function()
  4657. screen:try_resize(20, 8)
  4658. command('call setline(1, range(20))')
  4659. api.nvim_buf_set_extmark(0, ns, 10, 0, { virt_lines = {{{'VIRT1'}}, {{'VIRT2'}}} })
  4660. screen:expect([[
  4661. ^0 |
  4662. 1 |
  4663. 2 |
  4664. 3 |
  4665. 4 |
  4666. 5 |
  4667. 6 |
  4668. |
  4669. ]])
  4670. feed('<C-F>')
  4671. screen:expect([[
  4672. ^5 |
  4673. 6 |
  4674. 7 |
  4675. 8 |
  4676. 9 |
  4677. 10 |
  4678. VIRT1 |
  4679. |
  4680. ]])
  4681. feed('<C-F>')
  4682. screen:expect([[
  4683. ^10 |
  4684. VIRT1 |
  4685. VIRT2 |
  4686. 11 |
  4687. 12 |
  4688. 13 |
  4689. 14 |
  4690. |
  4691. ]])
  4692. feed('<C-F>')
  4693. screen:expect([[
  4694. ^13 |
  4695. 14 |
  4696. 15 |
  4697. 16 |
  4698. 17 |
  4699. 18 |
  4700. 19 |
  4701. |
  4702. ]])
  4703. feed('<C-B>')
  4704. screen:expect([[
  4705. 10 |
  4706. VIRT1 |
  4707. VIRT2 |
  4708. 11 |
  4709. 12 |
  4710. 13 |
  4711. ^14 |
  4712. |
  4713. ]])
  4714. feed('<C-B>')
  4715. screen:expect([[
  4716. 5 |
  4717. 6 |
  4718. 7 |
  4719. 8 |
  4720. 9 |
  4721. ^10 |
  4722. VIRT1 |
  4723. |
  4724. ]])
  4725. feed('<C-B>')
  4726. screen:expect([[
  4727. 0 |
  4728. 1 |
  4729. 2 |
  4730. 3 |
  4731. 4 |
  4732. 5 |
  4733. ^6 |
  4734. |
  4735. ]])
  4736. end)
  4737. it('not drawn when invalid', function()
  4738. api.nvim_buf_set_lines(0, 0, -1, false, { 'foo', 'bar' })
  4739. api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'VIRT1'}}}, invalidate = true })
  4740. screen:expect({
  4741. grid = [[
  4742. ^foo |
  4743. VIRT1 |
  4744. bar |
  4745. {1:~ }|*8
  4746. |
  4747. ]]
  4748. })
  4749. feed('dd')
  4750. screen:expect({
  4751. grid = [[
  4752. ^bar |
  4753. {1:~ }|*10
  4754. |
  4755. ]]
  4756. })
  4757. end)
  4758. end)
  4759. describe('decorations: signs', function()
  4760. local screen, ns
  4761. before_each(function()
  4762. clear()
  4763. screen = Screen.new(50, 10)
  4764. screen:add_extra_attr_ids {
  4765. [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow },
  4766. }
  4767. ns = api.nvim_create_namespace 'test'
  4768. api.nvim_set_option_value('signcolumn', 'auto:9', {})
  4769. end)
  4770. local example_test3 = [[
  4771. l1
  4772. l2
  4773. l3
  4774. l4
  4775. l5
  4776. ]]
  4777. it('can add a single sign (no end row)', function()
  4778. insert(example_test3)
  4779. feed 'gg'
  4780. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S'})
  4781. screen:expect([[
  4782. {7: }^l1 |
  4783. {7:S }l2 |
  4784. {7: }l3 |
  4785. {7: }l4 |
  4786. {7: }l5 |
  4787. {7: } |
  4788. {1:~ }|*3
  4789. |
  4790. ]])
  4791. end)
  4792. it('can add a single sign (with end row)', function()
  4793. insert(example_test3)
  4794. feed 'gg'
  4795. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1})
  4796. screen:expect([[
  4797. {7: }^l1 |
  4798. {7:S }l2 |
  4799. {7: }l3 |
  4800. {7: }l4 |
  4801. {7: }l5 |
  4802. {7: } |
  4803. {1:~ }|*3
  4804. |
  4805. ]])
  4806. end)
  4807. it('can add a single sign and text highlight', function()
  4808. insert(example_test3)
  4809. feed 'gg'
  4810. api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text='S', hl_group='Todo', end_col=1})
  4811. screen:expect([[
  4812. {7: }^l1 |
  4813. {7:S }{100:l}2 |
  4814. {7: }l3 |
  4815. {7: }l4 |
  4816. {7: }l5 |
  4817. {7: } |
  4818. {1:~ }|*3
  4819. |
  4820. ]])
  4821. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  4822. end)
  4823. it('can add multiple signs (single extmark)', function()
  4824. insert(example_test3)
  4825. feed 'gg'
  4826. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2})
  4827. screen:expect([[
  4828. {7: }^l1 |
  4829. {7:S }l2 |
  4830. {7:S }l3 |
  4831. {7: }l4 |
  4832. {7: }l5 |
  4833. {7: } |
  4834. {1:~ }|*3
  4835. |
  4836. ]])
  4837. end)
  4838. it('can add multiple signs (multiple extmarks)', function()
  4839. insert(example_test3)
  4840. feed'gg'
  4841. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S1'})
  4842. api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S2', end_row = 4})
  4843. screen:expect([[
  4844. {7: }^l1 |
  4845. {7:S1}l2 |
  4846. {7: }l3 |
  4847. {7:S2}l4 |
  4848. {7:S2}l5 |
  4849. {7: } |
  4850. {1:~ }|*3
  4851. |
  4852. ]])
  4853. end)
  4854. it('can add multiple signs (multiple extmarks) 2', function()
  4855. insert(example_test3)
  4856. feed 'gg'
  4857. api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S1'})
  4858. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row = 3})
  4859. screen:expect([[
  4860. {7: }^l1 |
  4861. {7:S2 }l2 |
  4862. {7:S2 }l3 |
  4863. {7:S2S1}l4 |
  4864. {7: }l5 |
  4865. {7: } |
  4866. {1:~ }|*3
  4867. |
  4868. ]])
  4869. end)
  4870. it('can add multiple signs (multiple extmarks) 3', function()
  4871. insert(example_test3)
  4872. feed 'gg'
  4873. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S1', end_row=2})
  4874. api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S2', end_row=3})
  4875. screen:expect([[
  4876. {7: }^l1 |
  4877. {7:S1 }l2 |
  4878. {7:S2S1}l3 |
  4879. {7:S2 }l4 |
  4880. {7: }l5 |
  4881. {7: } |
  4882. {1:~ }|*3
  4883. |
  4884. ]])
  4885. end)
  4886. it('can add multiple signs (multiple extmarks) 4', function()
  4887. insert(example_test3)
  4888. feed 'gg'
  4889. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=0})
  4890. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row=1})
  4891. screen:expect([[
  4892. {7:S1}^l1 |
  4893. {7:S2}l2 |
  4894. {7: }l3 |
  4895. {7: }l4 |
  4896. {7: }l5 |
  4897. {7: } |
  4898. {1:~ }|*3
  4899. |
  4900. ]])
  4901. end)
  4902. it('works with old signs', function()
  4903. insert(example_test3)
  4904. feed 'gg'
  4905. n.command('sign define Oldsign text=x')
  4906. n.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]])
  4907. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
  4908. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
  4909. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
  4910. api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
  4911. screen:expect([[
  4912. {7:S4S1}^l1 |
  4913. {7:S2x }l2 |
  4914. {7:S5 }l3 |
  4915. {7: }l4 |
  4916. {7: }l5 |
  4917. {7: } |
  4918. {1:~ }|*3
  4919. |
  4920. ]])
  4921. end)
  4922. it('works with old signs (with range)', function()
  4923. insert(example_test3)
  4924. feed 'gg'
  4925. n.command('sign define Oldsign text=x')
  4926. n.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]])
  4927. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
  4928. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
  4929. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S3', end_row = 4})
  4930. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
  4931. api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
  4932. screen:expect([[
  4933. {7:S4S3S1}^l1 |
  4934. {7:S3S2x }l2 |
  4935. {7:S5S3 }l3 |
  4936. {7:S3 }l4 |
  4937. {7:S3 }l5 |
  4938. {7: } |
  4939. {1:~ }|*3
  4940. |
  4941. ]])
  4942. end)
  4943. it('can add a ranged sign (with start out of view)', function()
  4944. insert(example_test3)
  4945. command 'set signcolumn=yes:2'
  4946. feed 'gg'
  4947. feed '2<C-e>'
  4948. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='X', end_row=3})
  4949. screen:expect([[
  4950. {7:X }^l3 |
  4951. {7:X }l4 |
  4952. {7: }l5 |
  4953. {7: } |
  4954. {1:~ }|*5
  4955. |
  4956. ]])
  4957. end)
  4958. it('can add lots of signs', function()
  4959. screen:try_resize(40, 10)
  4960. command 'normal 10oa b c d e f g h'
  4961. for i = 1, 10 do
  4962. api.nvim_buf_set_extmark(0, ns, i, 0, { end_col = 1, hl_group='Todo' })
  4963. api.nvim_buf_set_extmark(0, ns, i, 2, { end_col = 3, hl_group='Todo' })
  4964. api.nvim_buf_set_extmark(0, ns, i, 4, { end_col = 5, hl_group='Todo' })
  4965. api.nvim_buf_set_extmark(0, ns, i, 6, { end_col = 7, hl_group='Todo' })
  4966. api.nvim_buf_set_extmark(0, ns, i, 8, { end_col = 9, hl_group='Todo' })
  4967. api.nvim_buf_set_extmark(0, ns, i, 10, { end_col = 11, hl_group='Todo' })
  4968. api.nvim_buf_set_extmark(0, ns, i, 12, { end_col = 13, hl_group='Todo' })
  4969. api.nvim_buf_set_extmark(0, ns, i, 14, { end_col = 15, hl_group='Todo' })
  4970. api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='W' })
  4971. api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='X' })
  4972. api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='Y' })
  4973. api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='Z' })
  4974. end
  4975. screen:expect([[
  4976. {7:Z Y X W }{100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:h} |*8
  4977. {7:Z Y X W }{100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:^h} |
  4978. |
  4979. ]])
  4980. end)
  4981. it('works with priority #19716', function()
  4982. screen:try_resize(20, 3)
  4983. insert(example_test3)
  4984. feed 'gg'
  4985. command('sign define Oldsign text=O3')
  4986. command([[exe 'sign place 42 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  4987. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4', priority=100})
  4988. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S2', priority=5})
  4989. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
  4990. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
  4991. screen:expect([[
  4992. {7:S5S4O3S2S1}^l1 |
  4993. {7: }l2 |
  4994. |
  4995. ]])
  4996. -- Check truncation works too
  4997. api.nvim_set_option_value('signcolumn', 'auto', {})
  4998. screen:expect([[
  4999. {7:S5}^l1 |
  5000. {7: }l2 |
  5001. |
  5002. ]])
  5003. end)
  5004. it('does not overflow with many old signs #23852', function()
  5005. screen:try_resize(20, 3)
  5006. command('set signcolumn:auto:9')
  5007. command('sign define Oldsign text=O3')
  5008. command([[exe 'sign place 01 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5009. command([[exe 'sign place 02 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5010. command([[exe 'sign place 03 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5011. command([[exe 'sign place 04 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5012. command([[exe 'sign place 05 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5013. command([[exe 'sign place 06 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5014. command([[exe 'sign place 07 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5015. command([[exe 'sign place 08 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5016. command([[exe 'sign place 09 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
  5017. screen:expect([[
  5018. {7:O3O3O3O3O3O3O3O3O3}^ |
  5019. {1:~ }|
  5020. |
  5021. ]])
  5022. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
  5023. screen:expect_unchanged()
  5024. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
  5025. screen:expect([[
  5026. {7:S5O3O3O3O3O3O3O3O3}^ |
  5027. {1:~ }|
  5028. |
  5029. ]])
  5030. assert_alive()
  5031. end)
  5032. it('does not set signcolumn for signs without text', function()
  5033. screen:try_resize(20, 3)
  5034. api.nvim_set_option_value('signcolumn', 'auto', {})
  5035. insert(example_test3)
  5036. feed 'gg'
  5037. api.nvim_buf_set_extmark(0, ns, 0, -1, {number_hl_group='Error'})
  5038. screen:expect{grid=[[
  5039. ^l1 |
  5040. l2 |
  5041. |
  5042. ]]}
  5043. end)
  5044. it('correct width when removing multiple signs from sentinel line', function()
  5045. screen:try_resize(20, 4)
  5046. insert(example_test3)
  5047. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=3})
  5048. api.nvim_buf_set_extmark(0, ns, 1, -1, {invalidate = true, sign_text='S2'})
  5049. api.nvim_buf_set_extmark(0, ns, 1, -1, {invalidate = true, sign_text='S3'})
  5050. feed('2Gdd')
  5051. screen:expect([[
  5052. {7:S1}l1 |
  5053. {7:S1}^l3 |
  5054. {7:S1}l4 |
  5055. |
  5056. ]])
  5057. end)
  5058. it('correct width with multiple overlapping signs', function()
  5059. screen:try_resize(20, 4)
  5060. insert(example_test3)
  5061. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
  5062. api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S2', end_row=2})
  5063. api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S3', end_row=2})
  5064. feed('gg')
  5065. local s1 = [[
  5066. {7:S2S1}^l1 |
  5067. {7:S3S2}l2 |
  5068. {7:S3S2}l3 |
  5069. |
  5070. ]]
  5071. screen:expect(s1)
  5072. -- Correct width when :move'ing a line with signs
  5073. command('move2')
  5074. screen:expect([[
  5075. {7:S3 }l2 |
  5076. {7:S3S2S1}^l1 |
  5077. {7: }l3 |
  5078. |
  5079. ]])
  5080. command('silent undo')
  5081. screen:expect{grid=s1}
  5082. command('d')
  5083. screen:expect([[
  5084. {7:S3S2S1}^l2 |
  5085. {7:S3S2 }l3 |
  5086. {7: }l4 |
  5087. |
  5088. ]])
  5089. command('d')
  5090. screen:expect([[
  5091. {7:S3S2S1}^l3 |
  5092. {7: }l4 |
  5093. {7: }l5 |
  5094. |
  5095. ]])
  5096. end)
  5097. it('correct width when adding and removing multiple signs', function()
  5098. screen:try_resize(20, 4)
  5099. insert(example_test3)
  5100. feed('gg')
  5101. command([[
  5102. let ns = nvim_create_namespace('')
  5103. call nvim_buf_set_extmark(0, ns, 0, 0, {'sign_text':'S1', 'end_row':3})
  5104. let s1 = nvim_buf_set_extmark(0, ns, 2, 0, {'sign_text':'S2', 'end_row':4})
  5105. let s2 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
  5106. let s3 = nvim_buf_set_extmark(0, ns, 6, 0, {'sign_text':'S3'})
  5107. let s4 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
  5108. let s5 = nvim_buf_set_extmark(0, ns, 6, 0, {'sign_text':'S3'})
  5109. redraw!
  5110. call nvim_buf_del_extmark(0, ns, s2)
  5111. call nvim_buf_del_extmark(0, ns, s3)
  5112. call nvim_buf_del_extmark(0, ns, s4)
  5113. call nvim_buf_del_extmark(0, ns, s5)
  5114. redraw!
  5115. call nvim_buf_del_extmark(0, ns, s1)
  5116. ]])
  5117. screen:expect([[
  5118. {7:S1}^l1 |
  5119. {7:S1}l2 |
  5120. {7:S1}l3 |
  5121. |
  5122. ]])
  5123. end)
  5124. it('correct width when deleting lines', function()
  5125. screen:try_resize(20, 4)
  5126. insert(example_test3)
  5127. feed('gg')
  5128. command([[
  5129. let ns = nvim_create_namespace('')
  5130. call nvim_buf_set_extmark(0, ns, 4, 0, {'sign_text':'S1'})
  5131. call nvim_buf_set_extmark(0, ns, 4, 0, {'sign_text':'S2'})
  5132. let s3 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
  5133. call nvim_buf_del_extmark(0, ns, s3)
  5134. norm 4Gdd
  5135. ]])
  5136. screen:expect([[
  5137. {7: }l3 |
  5138. {7:S2S1}l5 |
  5139. {7: }^ |
  5140. |
  5141. ]])
  5142. end)
  5143. it('correct width when splitting lines with signs on different columns', function()
  5144. screen:try_resize(20, 4)
  5145. insert(example_test3)
  5146. feed('gg')
  5147. api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S1'})
  5148. api.nvim_buf_set_extmark(0, ns, 0, 1, {sign_text='S2'})
  5149. feed('a<cr><esc>')
  5150. screen:expect([[
  5151. {7:S1}l |
  5152. {7:S2}^1 |
  5153. {7: }l2 |
  5154. |
  5155. ]])
  5156. end)
  5157. it('correct width after wiping a buffer', function()
  5158. screen:try_resize(20, 4)
  5159. insert(example_test3)
  5160. feed('gg')
  5161. local buf = api.nvim_get_current_buf()
  5162. api.nvim_buf_set_extmark(buf, ns, 0, 0, { sign_text = 'h' })
  5163. screen:expect([[
  5164. {7:h }^l1 |
  5165. {7: }l2 |
  5166. {7: }l3 |
  5167. |
  5168. ]])
  5169. api.nvim_win_set_buf(0, api.nvim_create_buf(false, true))
  5170. api.nvim_buf_delete(buf, {unload=true, force=true})
  5171. api.nvim_buf_set_lines(buf, 0, -1, false, {''})
  5172. api.nvim_win_set_buf(0, buf)
  5173. screen:expect{grid=[[
  5174. ^ |
  5175. {1:~ }|*2
  5176. |
  5177. ]]}
  5178. end)
  5179. it('correct width with moved marks before undo savepos', function()
  5180. screen:try_resize(20, 4)
  5181. insert(example_test3)
  5182. feed('gg')
  5183. exec_lua([[
  5184. local ns = vim.api.nvim_create_namespace('')
  5185. vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { sign_text = 'S1' })
  5186. vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { sign_text = 'S2' })
  5187. local s3 = vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { sign_text = 'S3' })
  5188. local s4 = vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { sign_text = 'S4' })
  5189. vim.schedule(function()
  5190. vim.cmd('silent d3')
  5191. vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { id = s3, sign_text = 'S3' })
  5192. vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { id = s4, sign_text = 'S4' })
  5193. vim.cmd('silent undo')
  5194. vim.api.nvim_buf_del_extmark(0, ns, s3)
  5195. end)
  5196. ]])
  5197. screen:expect([[
  5198. {7:S1}^l1 |
  5199. {7:S2}l2 |
  5200. {7:S4}l3 |
  5201. |
  5202. ]])
  5203. end)
  5204. it('no crash with sign after many marks #27137', function()
  5205. screen:try_resize(20, 4)
  5206. insert('a')
  5207. for _ = 0, 104 do
  5208. api.nvim_buf_set_extmark(0, ns, 0, 0, {hl_group = 'Error', end_col = 1})
  5209. end
  5210. api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text = 'S1'})
  5211. screen:expect([[
  5212. {7:S1}{9:^a} |
  5213. {1:~ }|*2
  5214. |
  5215. ]])
  5216. end)
  5217. it('correct sort order with multiple namespaces and same id', function()
  5218. local ns2 = api.nvim_create_namespace('')
  5219. api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text = 'S1', id = 1})
  5220. api.nvim_buf_set_extmark(0, ns2, 0, 0, {sign_text = 'S2', id = 1})
  5221. screen:expect([[
  5222. {7:S2S1}^ |
  5223. {1:~ }|*8
  5224. |
  5225. ]])
  5226. end)
  5227. it('correct number of signs after deleting text (#27046)', function()
  5228. command('call setline(1, ["foo"]->repeat(31))')
  5229. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 0, sign_text = 'S1'})
  5230. api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 0, end_col = 3, hl_group = 'Error'})
  5231. api.nvim_buf_set_extmark(0, ns, 9, 0, {end_row = 9, sign_text = 'S2'})
  5232. api.nvim_buf_set_extmark(0, ns, 9, 0, {end_row = 9, end_col = 3, hl_group = 'Error'})
  5233. api.nvim_buf_set_extmark(0, ns, 19, 0, {end_row = 19, sign_text = 'S3'})
  5234. api.nvim_buf_set_extmark(0, ns, 19, 0, {end_row = 19, end_col = 3, hl_group = 'Error'})
  5235. api.nvim_buf_set_extmark(0, ns, 29, 0, {end_row = 29, sign_text = 'S4'})
  5236. api.nvim_buf_set_extmark(0, ns, 29, 0, {end_row = 29, end_col = 3, hl_group = 'Error'})
  5237. api.nvim_buf_set_extmark(0, ns, 30, 0, {end_row = 30, sign_text = 'S5'})
  5238. api.nvim_buf_set_extmark(0, ns, 30, 0, {end_row = 30, end_col = 3, hl_group = 'Error'})
  5239. command('0d29')
  5240. screen:expect([[
  5241. {7:S4S3S2S1}{9:^foo} |
  5242. {7:S5 }{9:foo} |
  5243. {1:~ }|*7
  5244. 29 fewer lines |
  5245. ]])
  5246. api.nvim_buf_clear_namespace(0, ns, 0, -1)
  5247. end)
  5248. it([[correct numberwidth with 'signcolumn' set to "number" #28984]], function()
  5249. command('set number numberwidth=1 signcolumn=number')
  5250. api.nvim_buf_set_extmark(0, ns, 0, 0, { sign_text = 'S1' })
  5251. screen:expect([[
  5252. {7:S1 }^ |
  5253. {1:~ }|*8
  5254. |
  5255. ]])
  5256. api.nvim_buf_del_extmark(0, ns, 1)
  5257. screen:expect([[
  5258. {8:1 }^ |
  5259. {1:~ }|*8
  5260. |
  5261. ]])
  5262. end)
  5263. it('supports emoji as signs', function()
  5264. insert(example_test3)
  5265. feed 'gg'
  5266. api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text='🧑‍🌾'})
  5267. -- VS16 can change width of character
  5268. api.nvim_buf_set_extmark(0, ns, 2, 0, {sign_text='❤️'})
  5269. api.nvim_buf_set_extmark(0, ns, 3, 0, {sign_text='❤'})
  5270. api.nvim_buf_set_extmark(0, ns, 4, 0, {sign_text='❤x'})
  5271. screen:expect([[
  5272. {7: }^l1 |
  5273. {7:🧑‍🌾}l2 |
  5274. {7:❤️}l3 |
  5275. {7:❤ }l4 |
  5276. {7:❤x}l5 |
  5277. {7: } |
  5278. {1:~ }|*3
  5279. |
  5280. ]])
  5281. eq("Invalid 'sign_text'", pcall_err(api.nvim_buf_set_extmark, 0, ns, 5, 0, {sign_text='❤️x'}))
  5282. end)
  5283. it('auto signcolumn hides with invalidated sign', function()
  5284. api.nvim_set_option_value('signcolumn', 'auto', {})
  5285. api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S1', invalidate=true})
  5286. feed('ia<cr>b<esc>dd')
  5287. screen:expect({
  5288. grid = [[
  5289. ^a |
  5290. {1:~ }|*8
  5291. |
  5292. ]]
  5293. })
  5294. end)
  5295. end)
  5296. describe('decorations: virt_text', function()
  5297. local screen
  5298. before_each(function()
  5299. clear()
  5300. screen = Screen.new(50, 10)
  5301. end)
  5302. it('avoids regression in #17638', function()
  5303. exec_lua[[
  5304. vim.wo.number = true
  5305. vim.wo.relativenumber = true
  5306. ]]
  5307. command 'normal 4ohello'
  5308. command 'normal aVIRTUAL'
  5309. local ns = api.nvim_create_namespace('test')
  5310. api.nvim_buf_set_extmark(0, ns, 2, 0, {
  5311. virt_text = {{"hello", "String"}},
  5312. virt_text_win_col = 20,
  5313. })
  5314. screen:expect{grid=[[
  5315. {8: 4 } |
  5316. {8: 3 }hello |
  5317. {8: 2 }hello {26:hello} |
  5318. {8: 1 }hello |
  5319. {8:5 }helloVIRTUA^L |
  5320. {1:~ }|*4
  5321. |
  5322. ]]}
  5323. -- Trigger a screen update
  5324. feed('k')
  5325. screen:expect{grid=[[
  5326. {8: 3 } |
  5327. {8: 2 }hello |
  5328. {8: 1 }hello {26:hello} |
  5329. {8:4 }hell^o |
  5330. {8: 1 }helloVIRTUAL |
  5331. {1:~ }|*4
  5332. |
  5333. ]]}
  5334. end)
  5335. it('redraws correctly when re-using extmark ids', function()
  5336. command 'normal 5ohello'
  5337. screen:expect{grid=[[
  5338. |
  5339. hello |*4
  5340. hell^o |
  5341. {1:~ }|*3
  5342. |
  5343. ]]}
  5344. local ns = api.nvim_create_namespace('ns')
  5345. for row = 1, 5 do
  5346. api.nvim_buf_set_extmark(0, ns, row, 0, { id = 1, virt_text = {{'world', 'Normal'}} })
  5347. end
  5348. screen:expect{grid=[[
  5349. |
  5350. hello |*4
  5351. hell^o world |
  5352. {1:~ }|*3
  5353. |
  5354. ]]}
  5355. end)
  5356. end)
  5357. describe('decorations: window scoped', function()
  5358. local screen, ns, win_other
  5359. local url = 'https://example.com'
  5360. before_each(function()
  5361. clear()
  5362. screen = Screen.new(20, 10)
  5363. screen:add_extra_attr_ids {
  5364. [100] = { special = Screen.colors.Red, undercurl = true },
  5365. [101] = { url = 'https://example.com' },
  5366. }
  5367. ns = api.nvim_create_namespace 'test'
  5368. insert('12345')
  5369. win_other = api.nvim_open_win(0, false, {
  5370. col=0,row=0,width=20,height=10,
  5371. relative = 'win',style = 'minimal',
  5372. hide = true
  5373. })
  5374. end)
  5375. local noextmarks = {
  5376. grid = [[
  5377. 1234^5 |
  5378. {1:~ }|*8
  5379. |
  5380. ]],
  5381. }
  5382. local function set_extmark(line, col, opts)
  5383. return api.nvim_buf_set_extmark(0, ns, line, col, opts)
  5384. end
  5385. it('hl_group', function()
  5386. set_extmark(0, 0, {
  5387. hl_group = 'Comment',
  5388. end_col = 3,
  5389. })
  5390. api.nvim__ns_set(ns, { wins = { 0 } })
  5391. screen:expect {
  5392. grid = [[
  5393. {18:123}4^5 |
  5394. {1:~ }|*8
  5395. |
  5396. ]],
  5397. }
  5398. command 'split'
  5399. command 'only'
  5400. screen:expect(noextmarks)
  5401. end)
  5402. it('virt_text', function()
  5403. set_extmark(0, 0, {
  5404. virt_text = { { 'a', 'Comment' } },
  5405. virt_text_pos = 'eol',
  5406. })
  5407. set_extmark(0, 5, {
  5408. virt_text = { { 'b', 'Comment' } },
  5409. virt_text_pos = 'inline',
  5410. })
  5411. set_extmark(0, 1, {
  5412. virt_text = { { 'c', 'Comment' } },
  5413. virt_text_pos = 'overlay',
  5414. })
  5415. set_extmark(0, 1, {
  5416. virt_text = { { 'd', 'Comment' } },
  5417. virt_text_pos = 'right_align',
  5418. })
  5419. api.nvim__ns_set(ns, { wins = { 0 } })
  5420. screen:expect {
  5421. grid = [[
  5422. 1{18:c}34^5{18:b} {18:a} {18:d}|
  5423. {1:~ }|*8
  5424. |
  5425. ]],
  5426. }
  5427. command 'split'
  5428. command 'only'
  5429. screen:expect(noextmarks)
  5430. api.nvim__ns_set(ns, { wins = {} })
  5431. screen:expect {
  5432. grid = [[
  5433. 1{18:c}34^5{18:b} {18:a} {18:d}|
  5434. {1:~ }|*8
  5435. |
  5436. ]],
  5437. }
  5438. end)
  5439. it('virt_lines', function()
  5440. set_extmark(0, 0, {
  5441. virt_lines = { { { 'a', 'Comment' } } },
  5442. })
  5443. api.nvim__ns_set(ns, { wins = { 0 } })
  5444. screen:expect {
  5445. grid = [[
  5446. 1234^5 |
  5447. {18:a} |
  5448. {1:~ }|*7
  5449. |
  5450. ]],
  5451. }
  5452. command 'split'
  5453. command 'only'
  5454. screen:expect(noextmarks)
  5455. end)
  5456. it('redraws correctly with inline virt_text and wrapping', function()
  5457. set_extmark(0, 2, {
  5458. virt_text = { { ('b'):rep(18), 'Comment' } },
  5459. virt_text_pos = 'inline',
  5460. })
  5461. api.nvim__ns_set(ns, { wins = { 0 } })
  5462. screen:expect {
  5463. grid = [[
  5464. 12{18:bbbbbbbbbbbbbbbbbb}|
  5465. 34^5 |
  5466. {1:~ }|*7
  5467. |
  5468. ]],
  5469. }
  5470. api.nvim__ns_set(ns, { wins = { win_other } })
  5471. screen:expect(noextmarks)
  5472. end)
  5473. pending('sign_text', function()
  5474. -- TODO(altermo): The window signcolumn width is calculated wrongly (when `signcolumn=auto`)
  5475. -- This happens in function `win_redraw_signcols` on line containing `buf_meta_total(buf, kMTMetaSignText) > 0`
  5476. set_extmark(0, 0, {
  5477. sign_text = 'a',
  5478. sign_hl_group = 'Comment',
  5479. })
  5480. api.nvim__ns_set(ns, { wins = { 0 } })
  5481. screen:expect {
  5482. grid = [[
  5483. a 1234^5 |
  5484. {2:~ }|*8
  5485. |
  5486. ]],
  5487. }
  5488. command 'split'
  5489. command 'only'
  5490. screen:expect(noextmarks)
  5491. end)
  5492. it('statuscolumn hl group', function()
  5493. set_extmark(0, 0, {
  5494. number_hl_group = 'comment',
  5495. })
  5496. set_extmark(0, 0, {
  5497. line_hl_group = 'comment',
  5498. })
  5499. command 'set number'
  5500. api.nvim__ns_set(ns, { wins = { win_other } })
  5501. screen:expect {
  5502. grid = [[
  5503. {8: 1 }1234^5 |
  5504. {1:~ }|*8
  5505. |
  5506. ]],
  5507. }
  5508. api.nvim__ns_set(ns, { wins = { 0 } })
  5509. screen:expect {
  5510. grid = [[
  5511. {18: 1 1234^5 }|
  5512. {1:~ }|*8
  5513. |
  5514. ]],
  5515. }
  5516. command 'split'
  5517. command 'only'
  5518. screen:expect {
  5519. grid = [[
  5520. {8: 1 }1234^5 |
  5521. {1:~ }|*8
  5522. |
  5523. ]],
  5524. }
  5525. end)
  5526. it('spell', function()
  5527. api.nvim_buf_set_lines(0, 0, -1, true, { 'aa' })
  5528. set_extmark(0, 0, {
  5529. spell = true,
  5530. end_col = 2,
  5531. })
  5532. command 'set spelloptions=noplainbuffer'
  5533. command 'set spell'
  5534. command 'syntax off'
  5535. screen:expect({ unchanged = true })
  5536. api.nvim__ns_set(ns, { wins = { win_other } })
  5537. screen:expect {
  5538. grid = [[
  5539. a^a |
  5540. {1:~ }|*8
  5541. |
  5542. ]],
  5543. }
  5544. api.nvim__ns_set(ns, { wins = { 0 } })
  5545. screen:expect {
  5546. grid = [[
  5547. {100:a^a} |
  5548. {1:~ }|*8
  5549. |
  5550. ]],
  5551. }
  5552. command 'split'
  5553. command 'only'
  5554. screen:expect {
  5555. grid = [[
  5556. a^a |
  5557. {1:~ }|*8
  5558. |
  5559. ]],
  5560. }
  5561. end)
  5562. it('url', function()
  5563. set_extmark(0, 0, {
  5564. end_col = 3,
  5565. url = url,
  5566. })
  5567. api.nvim__ns_set(ns, { wins = { 0 } })
  5568. screen:expect {
  5569. grid = [[
  5570. {101:123}4^5 |
  5571. {1:~ }|*8
  5572. |
  5573. ]],
  5574. }
  5575. command 'split'
  5576. command 'only'
  5577. screen:expect(noextmarks)
  5578. end)
  5579. it('change namespace scope', function()
  5580. set_extmark(0, 0, {
  5581. hl_group = 'Comment',
  5582. end_col = 3,
  5583. })
  5584. api.nvim__ns_set(ns, { wins = { 0 } })
  5585. eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
  5586. screen:expect {
  5587. grid = [[
  5588. {18:123}4^5 |
  5589. {1:~ }|*8
  5590. |
  5591. ]],
  5592. }
  5593. command 'split'
  5594. command 'only'
  5595. screen:expect(noextmarks)
  5596. api.nvim__ns_set(ns, { wins = { 0 } })
  5597. eq({ wins={ api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
  5598. screen:expect {
  5599. grid = [[
  5600. {18:123}4^5 |
  5601. {1:~ }|*8
  5602. |
  5603. ]],
  5604. }
  5605. local win_new = api.nvim_open_win(0, false, {
  5606. col=0,row=0,width=20,height=10,
  5607. relative = 'win',style = 'minimal',
  5608. hide = true
  5609. })
  5610. api.nvim__ns_set(ns, { wins = { win_new } })
  5611. eq({ wins={ win_new } }, api.nvim__ns_get(ns))
  5612. screen:expect(noextmarks)
  5613. end)
  5614. it('namespace get works', function()
  5615. eq({ wins = {} }, api.nvim__ns_get(ns))
  5616. api.nvim__ns_set(ns, { wins = { 0 } })
  5617. eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
  5618. api.nvim__ns_set(ns, { wins = {} })
  5619. eq({ wins = {} }, api.nvim__ns_get(ns))
  5620. end)
  5621. it('remove window from namespace scope when deleted', function ()
  5622. api.nvim__ns_set(ns, { wins = { 0 } })
  5623. eq({ wins = { api.nvim_get_current_win() } }, api.nvim__ns_get(ns))
  5624. command 'split'
  5625. command 'only'
  5626. eq({ wins = {} }, api.nvim__ns_get(ns))
  5627. end)
  5628. end)