TextFormatterTests.cs 169 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470
  1. using NStack;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Terminal.Gui;
  6. using Xunit;
  7. using Xunit.Abstractions;
  8. // Alias Console to MockConsole so we don't accidentally use Console
  9. using Console = Terminal.Gui.FakeConsole;
  10. namespace Terminal.Gui.TextTests {
  11. public class TextFormatterTests {
  12. readonly ITestOutputHelper output;
  13. public TextFormatterTests (ITestOutputHelper output)
  14. {
  15. this.output = output;
  16. }
  17. [Fact]
  18. public void Basic_Usage ()
  19. {
  20. var testText = ustring.Make ("test");
  21. var expectedSize = new Size ();
  22. var testBounds = new Rect (0, 0, 100, 1);
  23. var tf = new TextFormatter ();
  24. tf.Text = testText;
  25. expectedSize = new Size (testText.Length, 1);
  26. Assert.Equal (testText, tf.Text);
  27. Assert.Equal (TextAlignment.Left, tf.Alignment);
  28. Assert.Equal (expectedSize, tf.Size);
  29. tf.Draw (testBounds, new Attribute (), new Attribute ());
  30. Assert.Equal (expectedSize, tf.Size);
  31. Assert.NotEmpty (tf.Lines);
  32. tf.Alignment = TextAlignment.Right;
  33. expectedSize = new Size (testText.Length, 1);
  34. Assert.Equal (testText, tf.Text);
  35. Assert.Equal (TextAlignment.Right, tf.Alignment);
  36. Assert.Equal (expectedSize, tf.Size);
  37. tf.Draw (testBounds, new Attribute (), new Attribute ());
  38. Assert.Equal (expectedSize, tf.Size);
  39. Assert.NotEmpty (tf.Lines);
  40. tf.Alignment = TextAlignment.Right;
  41. expectedSize = new Size (testText.Length * 2, 1);
  42. tf.Size = expectedSize;
  43. Assert.Equal (testText, tf.Text);
  44. Assert.Equal (TextAlignment.Right, tf.Alignment);
  45. Assert.Equal (expectedSize, tf.Size);
  46. tf.Draw (testBounds, new Attribute (), new Attribute ());
  47. Assert.Equal (expectedSize, tf.Size);
  48. Assert.NotEmpty (tf.Lines);
  49. tf.Alignment = TextAlignment.Centered;
  50. expectedSize = new Size (testText.Length * 2, 1);
  51. tf.Size = expectedSize;
  52. Assert.Equal (testText, tf.Text);
  53. Assert.Equal (TextAlignment.Centered, tf.Alignment);
  54. Assert.Equal (expectedSize, tf.Size);
  55. tf.Draw (testBounds, new Attribute (), new Attribute ());
  56. Assert.Equal (expectedSize, tf.Size);
  57. Assert.NotEmpty (tf.Lines);
  58. }
  59. [Fact]
  60. public void TestSize_TextChange ()
  61. {
  62. var tf = new TextFormatter () { Text = "你" };
  63. Assert.Equal (2, tf.Size.Width);
  64. tf.Text = "你你";
  65. Assert.Equal (4, tf.Size.Width);
  66. }
  67. [Fact]
  68. public void NeedsFormat_Sets ()
  69. {
  70. var testText = ustring.Make ("test");
  71. var testBounds = new Rect (0, 0, 100, 1);
  72. var tf = new TextFormatter ();
  73. tf.Text = "test";
  74. Assert.True (tf.NeedsFormat); // get_Lines causes a Format
  75. Assert.NotEmpty (tf.Lines);
  76. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  77. Assert.Equal (testText, tf.Text);
  78. tf.Draw (testBounds, new Attribute (), new Attribute ());
  79. Assert.False (tf.NeedsFormat);
  80. tf.Size = new Size (1, 1);
  81. Assert.True (tf.NeedsFormat);
  82. Assert.NotEmpty (tf.Lines);
  83. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  84. tf.Alignment = TextAlignment.Centered;
  85. Assert.True (tf.NeedsFormat);
  86. Assert.NotEmpty (tf.Lines);
  87. Assert.False (tf.NeedsFormat); // get_Lines causes a Format
  88. }
  89. [Fact]
  90. public void FindHotKey_Invalid_ReturnsFalse ()
  91. {
  92. var text = ustring.Empty;
  93. Rune hotKeySpecifier = '_';
  94. bool supportFirstUpperCase = false;
  95. int hotPos = 0;
  96. Key hotKey = Key.Unknown;
  97. bool result = false;
  98. text = null;
  99. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  100. Assert.False (result);
  101. Assert.Equal (-1, hotPos);
  102. Assert.Equal (Key.Unknown, hotKey);
  103. text = "";
  104. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  105. Assert.False (result);
  106. Assert.Equal (-1, hotPos);
  107. Assert.Equal (Key.Unknown, hotKey);
  108. text = "no hotkey";
  109. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  110. Assert.False (result);
  111. Assert.Equal (-1, hotPos);
  112. Assert.Equal (Key.Unknown, hotKey);
  113. text = "No hotkey, Upper Case";
  114. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  115. Assert.False (result);
  116. Assert.Equal (-1, hotPos);
  117. Assert.Equal (Key.Unknown, hotKey);
  118. text = "Non-english: Сохранить";
  119. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  120. Assert.False (result);
  121. Assert.Equal (-1, hotPos);
  122. Assert.Equal (Key.Unknown, hotKey);
  123. }
  124. [Fact]
  125. public void FindHotKey_AlphaUpperCase_Succeeds ()
  126. {
  127. var text = ustring.Empty;
  128. Rune hotKeySpecifier = '_';
  129. bool supportFirstUpperCase = false;
  130. int hotPos = 0;
  131. Key hotKey = Key.Unknown;
  132. bool result = false;
  133. text = "_K Before";
  134. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  135. Assert.True (result);
  136. Assert.Equal (0, hotPos);
  137. Assert.Equal ((Key)'K', hotKey);
  138. text = "a_K Second";
  139. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  140. Assert.True (result);
  141. Assert.Equal (1, hotPos);
  142. Assert.Equal ((Key)'K', hotKey);
  143. text = "Last _K";
  144. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  145. Assert.True (result);
  146. Assert.Equal (5, hotPos);
  147. Assert.Equal ((Key)'K', hotKey);
  148. text = "After K_";
  149. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  150. Assert.False (result);
  151. Assert.Equal (-1, hotPos);
  152. Assert.Equal (Key.Unknown, hotKey);
  153. text = "Multiple _K and _R";
  154. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  155. Assert.True (result);
  156. Assert.Equal (9, hotPos);
  157. Assert.Equal ((Key)'K', hotKey);
  158. // Cryllic K (К)
  159. text = "Non-english: _Кдать";
  160. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  161. Assert.True (result);
  162. Assert.Equal (13, hotPos);
  163. Assert.Equal ((Key)'К', hotKey);
  164. // Turn on FirstUpperCase and verify same results
  165. supportFirstUpperCase = true;
  166. text = "_K Before";
  167. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  168. Assert.True (result);
  169. Assert.Equal (0, hotPos);
  170. Assert.Equal ((Key)'K', hotKey);
  171. text = "a_K Second";
  172. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  173. Assert.True (result);
  174. Assert.Equal (1, hotPos);
  175. Assert.Equal ((Key)'K', hotKey);
  176. text = "Last _K";
  177. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  178. Assert.True (result);
  179. Assert.Equal (5, hotPos);
  180. Assert.Equal ((Key)'K', hotKey);
  181. text = "After K_";
  182. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  183. Assert.False (result);
  184. Assert.Equal (-1, hotPos);
  185. Assert.Equal (Key.Unknown, hotKey);
  186. text = "Multiple _K and _R";
  187. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  188. Assert.True (result);
  189. Assert.Equal (9, hotPos);
  190. Assert.Equal ((Key)'K', hotKey);
  191. // Cryllic K (К)
  192. text = "Non-english: _Кдать";
  193. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  194. Assert.True (result);
  195. Assert.Equal (13, hotPos);
  196. Assert.Equal ((Key)'К', hotKey);
  197. }
  198. [Fact]
  199. public void FindHotKey_AlphaLowerCase_Succeeds ()
  200. {
  201. var text = ustring.Empty;
  202. Rune hotKeySpecifier = '_';
  203. bool supportFirstUpperCase = false;
  204. int hotPos = 0;
  205. Key hotKey = Key.Unknown;
  206. bool result = false;
  207. // lower case should return uppercase Hotkey
  208. text = "_k Before";
  209. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  210. Assert.True (result);
  211. Assert.Equal (0, hotPos);
  212. Assert.Equal ((Key)'K', hotKey);
  213. text = "a_k Second";
  214. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  215. Assert.True (result);
  216. Assert.Equal (1, hotPos);
  217. Assert.Equal ((Key)'K', hotKey);
  218. text = "Last _k";
  219. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  220. Assert.True (result);
  221. Assert.Equal (5, hotPos);
  222. Assert.Equal ((Key)'K', hotKey);
  223. text = "After k_";
  224. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  225. Assert.False (result);
  226. Assert.Equal (-1, hotPos);
  227. Assert.Equal (Key.Unknown, hotKey);
  228. text = "Multiple _k and _R";
  229. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  230. Assert.True (result);
  231. Assert.Equal (9, hotPos);
  232. Assert.Equal ((Key)'K', hotKey);
  233. // Lower case Cryllic K (к)
  234. text = "Non-english: _кдать";
  235. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  236. Assert.True (result);
  237. Assert.Equal (13, hotPos);
  238. Assert.Equal ((Key)'К', hotKey);
  239. // Turn on FirstUpperCase and verify same results
  240. supportFirstUpperCase = true;
  241. text = "_k Before";
  242. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  243. Assert.True (result);
  244. Assert.Equal (0, hotPos);
  245. Assert.Equal ((Key)'K', hotKey);
  246. text = "a_k Second";
  247. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  248. Assert.True (result);
  249. Assert.Equal (1, hotPos);
  250. Assert.Equal ((Key)'K', hotKey);
  251. text = "Last _k";
  252. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  253. Assert.True (result);
  254. Assert.Equal (5, hotPos);
  255. Assert.Equal ((Key)'K', hotKey);
  256. text = "After k_";
  257. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  258. Assert.False (result);
  259. Assert.Equal (-1, hotPos);
  260. Assert.Equal (Key.Unknown, hotKey);
  261. text = "Multiple _k and _R";
  262. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  263. Assert.True (result);
  264. Assert.Equal (9, hotPos);
  265. Assert.Equal ((Key)'K', hotKey);
  266. // Lower case Cryllic K (к)
  267. text = "Non-english: _кдать";
  268. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  269. Assert.True (result);
  270. Assert.Equal (13, hotPos);
  271. Assert.Equal ((Key)'К', hotKey);
  272. }
  273. [Fact]
  274. public void FindHotKey_Numeric_Succeeds ()
  275. {
  276. var text = ustring.Empty;
  277. Rune hotKeySpecifier = '_';
  278. bool supportFirstUpperCase = false;
  279. int hotPos = 0;
  280. Key hotKey = Key.Unknown;
  281. bool result = false;
  282. // Digits
  283. text = "_1 Before";
  284. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  285. Assert.True (result);
  286. Assert.Equal (0, hotPos);
  287. Assert.Equal ((Key)'1', hotKey);
  288. text = "a_1 Second";
  289. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  290. Assert.True (result);
  291. Assert.Equal (1, hotPos);
  292. Assert.Equal ((Key)'1', hotKey);
  293. text = "Last _1";
  294. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  295. Assert.True (result);
  296. Assert.Equal (5, hotPos);
  297. Assert.Equal ((Key)'1', hotKey);
  298. text = "After 1_";
  299. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  300. Assert.False (result);
  301. Assert.Equal (-1, hotPos);
  302. Assert.Equal (Key.Unknown, hotKey);
  303. text = "Multiple _1 and _2";
  304. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  305. Assert.True (result);
  306. Assert.Equal (9, hotPos);
  307. Assert.Equal ((Key)'1', hotKey);
  308. // Turn on FirstUpperCase and verify same results
  309. supportFirstUpperCase = true;
  310. text = "_1 Before";
  311. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  312. Assert.True (result);
  313. Assert.Equal (0, hotPos);
  314. Assert.Equal ((Key)'1', hotKey);
  315. text = "a_1 Second";
  316. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  317. Assert.True (result);
  318. Assert.Equal (1, hotPos);
  319. Assert.Equal ((Key)'1', hotKey);
  320. text = "Last _1";
  321. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  322. Assert.True (result);
  323. Assert.Equal (5, hotPos);
  324. Assert.Equal ((Key)'1', hotKey);
  325. text = "After 1_";
  326. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  327. Assert.False (result);
  328. Assert.Equal (-1, hotPos);
  329. Assert.Equal (Key.Unknown, hotKey);
  330. text = "Multiple _1 and _2";
  331. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  332. Assert.True (result);
  333. Assert.Equal (9, hotPos);
  334. Assert.Equal ((Key)'1', hotKey);
  335. }
  336. [Fact]
  337. public void FindHotKey_Legacy_FirstUpperCase_Succeeds ()
  338. {
  339. bool supportFirstUpperCase = true;
  340. var text = ustring.Empty;
  341. var hotKeySpecifier = (Rune)0;
  342. int hotPos = 0;
  343. Key hotKey = Key.Unknown;
  344. bool result = false;
  345. text = "K Before";
  346. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  347. Assert.True (result);
  348. Assert.Equal (0, hotPos);
  349. Assert.Equal ((Key)'K', hotKey);
  350. text = "aK Second";
  351. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  352. Assert.True (result);
  353. Assert.Equal (1, hotPos);
  354. Assert.Equal ((Key)'K', hotKey);
  355. text = "last K";
  356. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  357. Assert.True (result);
  358. Assert.Equal (5, hotPos);
  359. Assert.Equal ((Key)'K', hotKey);
  360. text = "multiple K and R";
  361. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  362. Assert.True (result);
  363. Assert.Equal (9, hotPos);
  364. Assert.Equal ((Key)'K', hotKey);
  365. // Cryllic K (К)
  366. text = "non-english: Кдать";
  367. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  368. Assert.True (result);
  369. Assert.Equal (13, hotPos);
  370. Assert.Equal ((Key)'К', hotKey);
  371. }
  372. [Fact]
  373. public void FindHotKey_Legacy_FirstUpperCase_NotFound_Returns_False ()
  374. {
  375. bool supportFirstUpperCase = true;
  376. var text = ustring.Empty;
  377. var hotKeySpecifier = (Rune)0;
  378. int hotPos = 0;
  379. Key hotKey = Key.Unknown;
  380. bool result = false;
  381. text = "k before";
  382. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  383. Assert.False (result);
  384. Assert.Equal (-1, hotPos);
  385. Assert.Equal (Key.Unknown, hotKey);
  386. text = "ak second";
  387. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  388. Assert.False (result);
  389. Assert.Equal (-1, hotPos);
  390. Assert.Equal (Key.Unknown, hotKey);
  391. text = "last k";
  392. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  393. Assert.False (result);
  394. Assert.Equal (-1, hotPos);
  395. Assert.Equal (Key.Unknown, hotKey);
  396. text = "multiple k and r";
  397. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  398. Assert.False (result);
  399. Assert.Equal (-1, hotPos);
  400. Assert.Equal (Key.Unknown, hotKey);
  401. text = "12345";
  402. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  403. Assert.False (result);
  404. Assert.Equal (-1, hotPos);
  405. Assert.Equal (Key.Unknown, hotKey);
  406. // punctuation
  407. text = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";
  408. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  409. Assert.False (result);
  410. Assert.Equal (-1, hotPos);
  411. Assert.Equal (Key.Unknown, hotKey);
  412. // ~IsLetterOrDigit + Unicode
  413. text = " ~  s  gui.cs   master ↑10";
  414. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  415. Assert.False (result);
  416. Assert.Equal (-1, hotPos);
  417. Assert.Equal (Key.Unknown, hotKey);
  418. // Lower case Cryllic K (к)
  419. text = "non-english: кдать";
  420. result = TextFormatter.FindHotKey (text, hotKeySpecifier, supportFirstUpperCase, out hotPos, out hotKey);
  421. Assert.False (result);
  422. Assert.Equal (-1, hotPos);
  423. Assert.Equal (Key.Unknown, hotKey);
  424. }
  425. static ustring testHotKeyAtStart = "_K Before";
  426. static ustring testHotKeyAtSecondPos = "a_K Second";
  427. static ustring testHotKeyAtLastPos = "Last _K";
  428. static ustring testHotKeyAfterLastChar = "After K_";
  429. static ustring testMultiHotKeys = "Multiple _K and _R";
  430. static ustring testNonEnglish = "Non-english: _Кдать";
  431. [Fact]
  432. public void RemoveHotKeySpecifier_InValid_ReturnsOriginal ()
  433. {
  434. Rune hotKeySpecifier = '_';
  435. Assert.Null (TextFormatter.RemoveHotKeySpecifier (null, 0, hotKeySpecifier));
  436. Assert.Equal ("", TextFormatter.RemoveHotKeySpecifier ("", 0, hotKeySpecifier));
  437. Assert.Equal ("", TextFormatter.RemoveHotKeySpecifier ("", -1, hotKeySpecifier));
  438. Assert.Equal ("", TextFormatter.RemoveHotKeySpecifier ("", 100, hotKeySpecifier));
  439. Assert.Equal ("a", TextFormatter.RemoveHotKeySpecifier ("a", -1, hotKeySpecifier));
  440. Assert.Equal ("a", TextFormatter.RemoveHotKeySpecifier ("a", 100, hotKeySpecifier));
  441. }
  442. [Fact]
  443. public void RemoveHotKeySpecifier_Valid_ReturnsStripped ()
  444. {
  445. Rune hotKeySpecifier = '_';
  446. Assert.Equal ("K Before", TextFormatter.RemoveHotKeySpecifier ("_K Before", 0, hotKeySpecifier));
  447. Assert.Equal ("aK Second", TextFormatter.RemoveHotKeySpecifier ("a_K Second", 1, hotKeySpecifier));
  448. Assert.Equal ("Last K", TextFormatter.RemoveHotKeySpecifier ("Last _K", 5, hotKeySpecifier));
  449. Assert.Equal ("After K", TextFormatter.RemoveHotKeySpecifier ("After K_", 7, hotKeySpecifier));
  450. Assert.Equal ("Multiple K and _R", TextFormatter.RemoveHotKeySpecifier ("Multiple _K and _R", 9, hotKeySpecifier));
  451. Assert.Equal ("Non-english: Кдать", TextFormatter.RemoveHotKeySpecifier ("Non-english: _Кдать", 13, hotKeySpecifier));
  452. }
  453. [Fact]
  454. public void RemoveHotKeySpecifier_Valid_Legacy_ReturnsOriginal ()
  455. {
  456. Rune hotKeySpecifier = '_';
  457. Assert.Equal ("all lower case", TextFormatter.RemoveHotKeySpecifier ("all lower case", 0, hotKeySpecifier));
  458. Assert.Equal ("K Before", TextFormatter.RemoveHotKeySpecifier ("K Before", 0, hotKeySpecifier));
  459. Assert.Equal ("aK Second", TextFormatter.RemoveHotKeySpecifier ("aK Second", 1, hotKeySpecifier));
  460. Assert.Equal ("Last K", TextFormatter.RemoveHotKeySpecifier ("Last K", 5, hotKeySpecifier));
  461. Assert.Equal ("After K", TextFormatter.RemoveHotKeySpecifier ("After K", 7, hotKeySpecifier));
  462. Assert.Equal ("Multiple K and R", TextFormatter.RemoveHotKeySpecifier ("Multiple K and R", 9, hotKeySpecifier));
  463. Assert.Equal ("Non-english: Кдать", TextFormatter.RemoveHotKeySpecifier ("Non-english: Кдать", 13, hotKeySpecifier));
  464. }
  465. [Fact]
  466. public void CalcRect_Invalid_Returns_Empty ()
  467. {
  468. Assert.Equal (Rect.Empty, TextFormatter.CalcRect (0, 0, null));
  469. Assert.Equal (Rect.Empty, TextFormatter.CalcRect (0, 0, ""));
  470. Assert.Equal (new Rect (new Point (1, 2), Size.Empty), TextFormatter.CalcRect (1, 2, ""));
  471. Assert.Equal (new Rect (new Point (-1, -2), Size.Empty), TextFormatter.CalcRect (-1, -2, ""));
  472. }
  473. [Fact]
  474. public void CalcRect_SingleLine_Returns_1High ()
  475. {
  476. var text = ustring.Empty;
  477. text = "test";
  478. Assert.Equal (new Rect (0, 0, text.RuneCount, 1), TextFormatter.CalcRect (0, 0, text));
  479. Assert.Equal (new Rect (0, 0, text.ConsoleWidth, 1), TextFormatter.CalcRect (0, 0, text));
  480. text = " ~  s  gui.cs   master ↑10";
  481. Assert.Equal (new Rect (0, 0, text.RuneCount, 1), TextFormatter.CalcRect (0, 0, text));
  482. Assert.Equal (new Rect (0, 0, text.ConsoleWidth, 1), TextFormatter.CalcRect (0, 0, text));
  483. }
  484. [Fact]
  485. public void CalcRect_MultiLine_Returns_nHigh ()
  486. {
  487. var text = ustring.Empty;
  488. var lines = 0;
  489. text = "line1\nline2";
  490. lines = 2;
  491. Assert.Equal (new Rect (0, 0, 5, lines), TextFormatter.CalcRect (0, 0, text));
  492. text = "\nline2";
  493. lines = 2;
  494. Assert.Equal (new Rect (0, 0, 5, lines), TextFormatter.CalcRect (0, 0, text));
  495. text = "\n\n";
  496. lines = 3;
  497. Assert.Equal (new Rect (0, 0, 0, lines), TextFormatter.CalcRect (0, 0, text));
  498. text = "\n\n\n";
  499. lines = 4;
  500. Assert.Equal (new Rect (0, 0, 0, lines), TextFormatter.CalcRect (0, 0, text));
  501. text = "line1\nline2\nline3long!";
  502. lines = 3;
  503. Assert.Equal (new Rect (0, 0, 10, lines), TextFormatter.CalcRect (0, 0, text));
  504. text = "line1\nline2\n\n";
  505. lines = 4;
  506. Assert.Equal (new Rect (0, 0, 5, lines), TextFormatter.CalcRect (0, 0, text));
  507. text = "line1\r\nline2";
  508. lines = 2;
  509. Assert.Equal (new Rect (0, 0, 5, lines), TextFormatter.CalcRect (0, 0, text));
  510. text = " ~  s  gui.cs   master ↑10\n";
  511. lines = 2;
  512. Assert.Equal (new Rect (0, 0, text.RuneCount - 1, lines), TextFormatter.CalcRect (0, 0, text));
  513. Assert.Equal (new Rect (0, 0, text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 0)), lines), TextFormatter.CalcRect (0, 0, text));
  514. text = "\n ~  s  gui.cs   master ↑10";
  515. lines = 2;
  516. Assert.Equal (new Rect (0, 0, text.RuneCount - 1, lines), TextFormatter.CalcRect (0, 0, text));
  517. Assert.Equal (new Rect (0, 0, text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 0)), lines), TextFormatter.CalcRect (0, 0, text));
  518. text = " ~  s  gui.cs   master\n↑10";
  519. lines = 2;
  520. Assert.Equal (new Rect (0, 0, ustring.Make (" ~  s  gui.cs   master\n").RuneCount - 1, lines), TextFormatter.CalcRect (0, 0, text));
  521. Assert.Equal (new Rect (0, 0, ustring.Make (" ~  s  gui.cs   master\n").ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 0)), lines), TextFormatter.CalcRect (0, 0, text));
  522. }
  523. [Fact]
  524. public void ClipAndJustify_Invalid_Returns_Original ()
  525. {
  526. var text = ustring.Empty;
  527. Assert.Equal (text, TextFormatter.ClipAndJustify (text, 0, TextAlignment.Left));
  528. text = null;
  529. Assert.Equal (text, TextFormatter.ClipAndJustify (text, 0, TextAlignment.Left));
  530. text = "test";
  531. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.ClipAndJustify (text, -1, TextAlignment.Left));
  532. }
  533. [Fact]
  534. public void ClipAndJustify_Valid_Left ()
  535. {
  536. var align = TextAlignment.Left;
  537. var text = ustring.Empty;
  538. var justifiedText = ustring.Empty;
  539. int maxWidth = 0;
  540. int expectedClippedWidth = 0;
  541. text = "test";
  542. maxWidth = 0;
  543. Assert.Equal (ustring.Empty, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  544. text = "test";
  545. maxWidth = 2;
  546. Assert.Equal (text.ToRunes () [0..maxWidth], justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  547. text = "test";
  548. maxWidth = int.MaxValue;
  549. Assert.Equal (text, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  550. Assert.True (justifiedText.RuneCount <= maxWidth);
  551. Assert.True (justifiedText.ConsoleWidth <= maxWidth);
  552. text = "A sentence has words.";
  553. // should fit
  554. maxWidth = text.RuneCount + 1;
  555. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  556. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  557. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  558. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  559. Assert.True (expectedClippedWidth <= maxWidth);
  560. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  561. // Should fit.
  562. maxWidth = text.RuneCount + 0;
  563. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  564. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  565. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  566. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  567. Assert.True (expectedClippedWidth <= maxWidth);
  568. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  569. // Should fit.
  570. maxWidth = int.MaxValue;
  571. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  572. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  573. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  574. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  575. Assert.True (expectedClippedWidth <= maxWidth);
  576. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  577. // Should not fit
  578. maxWidth = text.RuneCount - 1;
  579. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  580. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  581. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  582. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  583. Assert.True (expectedClippedWidth <= maxWidth);
  584. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  585. // Should not fit
  586. maxWidth = 10;
  587. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  588. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  589. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  590. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  591. Assert.True (expectedClippedWidth <= maxWidth);
  592. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  593. text = "A\tsentence\thas\twords.";
  594. maxWidth = int.MaxValue;
  595. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  596. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  597. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  598. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  599. Assert.True (expectedClippedWidth <= maxWidth);
  600. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  601. text = "A\tsentence\thas\twords.";
  602. maxWidth = 10;
  603. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  604. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  605. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  606. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  607. Assert.True (expectedClippedWidth <= maxWidth);
  608. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  609. text = "line1\nline2\nline3long!";
  610. maxWidth = int.MaxValue;
  611. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  612. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  613. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  614. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  615. Assert.True (expectedClippedWidth <= maxWidth);
  616. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  617. text = "line1\nline2\nline3long!";
  618. maxWidth = 10;
  619. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  620. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  621. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  622. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  623. Assert.True (expectedClippedWidth <= maxWidth);
  624. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  625. // Unicode
  626. text = " ~  s  gui.cs   master ↑10";
  627. maxWidth = 10;
  628. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  629. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  630. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  631. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  632. Assert.True (expectedClippedWidth <= maxWidth);
  633. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  634. // should fit
  635. text = "Ð ÑÐ";
  636. maxWidth = text.RuneCount + 1;
  637. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  638. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  639. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  640. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  641. Assert.True (expectedClippedWidth <= maxWidth);
  642. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  643. // Should fit.
  644. maxWidth = text.RuneCount + 0;
  645. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  646. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  647. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  648. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  649. Assert.True (expectedClippedWidth <= maxWidth);
  650. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  651. // Should not fit
  652. maxWidth = text.RuneCount - 1;
  653. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  654. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  655. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  656. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  657. Assert.True (expectedClippedWidth <= maxWidth);
  658. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  659. }
  660. [Fact]
  661. public void ClipAndJustify_Valid_Right ()
  662. {
  663. var align = TextAlignment.Right;
  664. var text = ustring.Empty;
  665. var justifiedText = ustring.Empty;
  666. int maxWidth = 0;
  667. int expectedClippedWidth = 0;
  668. text = "test";
  669. maxWidth = 0;
  670. Assert.Equal (ustring.Empty, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  671. text = "test";
  672. maxWidth = 2;
  673. Assert.Equal (text.ToRunes () [0..maxWidth], justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  674. text = "test";
  675. maxWidth = int.MaxValue;
  676. Assert.Equal (text, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  677. Assert.True (justifiedText.RuneCount <= maxWidth);
  678. Assert.True (justifiedText.ConsoleWidth <= maxWidth);
  679. text = "A sentence has words.";
  680. // should fit
  681. maxWidth = text.RuneCount + 1;
  682. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  683. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  684. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  685. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  686. Assert.True (expectedClippedWidth <= maxWidth);
  687. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  688. // Should fit.
  689. maxWidth = text.RuneCount + 0;
  690. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  691. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  692. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  693. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  694. Assert.True (expectedClippedWidth <= maxWidth);
  695. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  696. // Should fit.
  697. maxWidth = int.MaxValue;
  698. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  699. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  700. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  701. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  702. Assert.True (expectedClippedWidth <= maxWidth);
  703. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  704. // Should not fit
  705. maxWidth = text.RuneCount - 1;
  706. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  707. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  708. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  709. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  710. Assert.True (expectedClippedWidth <= maxWidth);
  711. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  712. // Should not fit
  713. maxWidth = 10;
  714. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  715. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  716. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  717. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  718. Assert.True (expectedClippedWidth <= maxWidth);
  719. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  720. text = "A\tsentence\thas\twords.";
  721. maxWidth = int.MaxValue;
  722. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  723. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  724. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  725. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  726. Assert.True (expectedClippedWidth <= maxWidth);
  727. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  728. text = "A\tsentence\thas\twords.";
  729. maxWidth = 10;
  730. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  731. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  732. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  733. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  734. Assert.True (expectedClippedWidth <= maxWidth);
  735. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  736. text = "line1\nline2\nline3long!";
  737. maxWidth = int.MaxValue;
  738. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  739. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  740. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  741. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  742. Assert.True (expectedClippedWidth <= maxWidth);
  743. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  744. text = "line1\nline2\nline3long!";
  745. maxWidth = 10;
  746. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  747. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  748. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  749. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  750. Assert.True (expectedClippedWidth <= maxWidth);
  751. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  752. // Unicode
  753. text = " ~  s  gui.cs   master ↑10";
  754. maxWidth = 10;
  755. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  756. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  757. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  758. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  759. Assert.True (expectedClippedWidth <= maxWidth);
  760. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  761. // should fit
  762. text = "Ð ÑÐ";
  763. maxWidth = text.RuneCount + 1;
  764. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  765. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  766. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  767. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  768. Assert.True (expectedClippedWidth <= maxWidth);
  769. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  770. // Should fit.
  771. maxWidth = text.RuneCount + 0;
  772. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  773. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  774. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  775. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  776. Assert.True (expectedClippedWidth <= maxWidth);
  777. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  778. // Should not fit
  779. maxWidth = text.RuneCount - 1;
  780. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  781. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  782. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  783. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  784. Assert.True (expectedClippedWidth <= maxWidth);
  785. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  786. }
  787. [Fact]
  788. public void ClipAndJustify_Valid_Centered ()
  789. {
  790. var align = TextAlignment.Centered;
  791. var text = ustring.Empty;
  792. var justifiedText = ustring.Empty;
  793. int maxWidth = 0;
  794. int expectedClippedWidth = 0;
  795. text = "test";
  796. maxWidth = 0;
  797. Assert.Equal (ustring.Empty, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  798. text = "test";
  799. maxWidth = 2;
  800. Assert.Equal (text.ToRunes () [0..maxWidth], justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  801. text = "test";
  802. maxWidth = int.MaxValue;
  803. Assert.Equal (text, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  804. Assert.True (justifiedText.RuneCount <= maxWidth);
  805. Assert.True (justifiedText.ConsoleWidth <= maxWidth);
  806. text = "A sentence has words.";
  807. // should fit
  808. maxWidth = text.RuneCount + 1;
  809. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  810. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  811. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  812. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  813. Assert.True (expectedClippedWidth <= maxWidth);
  814. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  815. // Should fit.
  816. maxWidth = text.RuneCount + 0;
  817. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  818. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  819. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  820. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  821. Assert.True (expectedClippedWidth <= maxWidth);
  822. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  823. // Should fit.
  824. maxWidth = int.MaxValue;
  825. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  826. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  827. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  828. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  829. Assert.True (expectedClippedWidth <= maxWidth);
  830. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  831. // Should not fit
  832. maxWidth = text.RuneCount - 1;
  833. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  834. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  835. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  836. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  837. Assert.True (expectedClippedWidth <= maxWidth);
  838. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  839. // Should not fit
  840. maxWidth = 10;
  841. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  842. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  843. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  844. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  845. Assert.True (expectedClippedWidth <= maxWidth);
  846. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  847. text = "A\tsentence\thas\twords.";
  848. maxWidth = int.MaxValue;
  849. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  850. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  851. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  852. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  853. Assert.True (expectedClippedWidth <= maxWidth);
  854. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  855. text = "A\tsentence\thas\twords.";
  856. maxWidth = 10;
  857. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  858. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  859. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  860. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  861. Assert.True (expectedClippedWidth <= maxWidth);
  862. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  863. text = "line1\nline2\nline3long!";
  864. maxWidth = int.MaxValue;
  865. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  866. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  867. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  868. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  869. Assert.True (expectedClippedWidth <= maxWidth);
  870. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  871. text = "line1\nline2\nline3long!";
  872. maxWidth = 10;
  873. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  874. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  875. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  876. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  877. Assert.True (expectedClippedWidth <= maxWidth);
  878. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  879. // Unicode
  880. text = " ~  s  gui.cs   master ↑10";
  881. maxWidth = 10;
  882. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  883. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  884. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  885. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  886. Assert.True (expectedClippedWidth <= maxWidth);
  887. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  888. // should fit
  889. text = "Ð ÑÐ";
  890. maxWidth = text.RuneCount + 1;
  891. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  892. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  893. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  894. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  895. Assert.True (expectedClippedWidth <= maxWidth);
  896. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  897. // Should fit.
  898. maxWidth = text.RuneCount + 0;
  899. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  900. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  901. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  902. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  903. Assert.True (expectedClippedWidth <= maxWidth);
  904. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  905. // Should not fit
  906. maxWidth = text.RuneCount - 1;
  907. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  908. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  909. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  910. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  911. Assert.True (expectedClippedWidth <= maxWidth);
  912. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  913. }
  914. [Fact]
  915. public void ClipAndJustify_Valid_Justified ()
  916. {
  917. var align = TextAlignment.Justified;
  918. var text = ustring.Empty;
  919. var justifiedText = ustring.Empty;
  920. int maxWidth = 0;
  921. int expectedClippedWidth = 0;
  922. text = "test";
  923. maxWidth = 0;
  924. Assert.Equal (ustring.Empty, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  925. text = "test";
  926. maxWidth = 2;
  927. Assert.Equal (text.ToRunes () [0..maxWidth], justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  928. text = "test";
  929. maxWidth = int.MaxValue;
  930. Assert.Equal (text, justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align));
  931. Assert.True (justifiedText.RuneCount <= maxWidth);
  932. text = "A sentence has words.";
  933. // should fit
  934. maxWidth = text.RuneCount + 1;
  935. expectedClippedWidth = Math.Max (text.RuneCount, maxWidth);
  936. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  937. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  938. Assert.True (expectedClippedWidth <= maxWidth);
  939. Assert.Throws<ArgumentOutOfRangeException> (() => ustring.Make (text.ToRunes () [0..expectedClippedWidth]));
  940. // Should fit.
  941. maxWidth = text.RuneCount + 0;
  942. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  943. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  944. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  945. Assert.True (expectedClippedWidth <= maxWidth);
  946. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  947. // Should fit.
  948. maxWidth = 500;
  949. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  950. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  951. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  952. Assert.True (expectedClippedWidth <= maxWidth);
  953. //Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  954. // Should not fit
  955. maxWidth = text.RuneCount - 1;
  956. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  957. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  958. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  959. Assert.True (expectedClippedWidth <= maxWidth);
  960. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  961. // Should not fit
  962. maxWidth = 10;
  963. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  964. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  965. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  966. Assert.True (expectedClippedWidth <= maxWidth);
  967. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  968. text = "A\tsentence\thas\twords.";
  969. maxWidth = int.MaxValue;
  970. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  971. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  972. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  973. Assert.True (expectedClippedWidth <= maxWidth);
  974. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  975. text = "A\tsentence\thas\twords.";
  976. maxWidth = 10;
  977. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  978. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  979. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  980. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  981. Assert.True (expectedClippedWidth <= maxWidth);
  982. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  983. text = "line1\nline2\nline3long!";
  984. maxWidth = int.MaxValue;
  985. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  986. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  987. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  988. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  989. Assert.True (expectedClippedWidth <= maxWidth);
  990. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  991. text = "line1\nline2\nline3long!";
  992. maxWidth = 10;
  993. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  994. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  995. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  996. Assert.Equal (expectedClippedWidth, justifiedText.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)));
  997. Assert.True (expectedClippedWidth <= maxWidth);
  998. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  999. // Unicode
  1000. text = " ~  s  gui.cs   master ↑10";
  1001. maxWidth = 10;
  1002. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1003. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  1004. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  1005. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  1006. Assert.True (expectedClippedWidth <= maxWidth);
  1007. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  1008. // should fit
  1009. text = "Ð ÑÐ";
  1010. maxWidth = text.RuneCount + 1;
  1011. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1012. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  1013. //Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  1014. Assert.True (expectedClippedWidth <= maxWidth);
  1015. //Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  1016. // Should fit.
  1017. maxWidth = text.RuneCount + 0;
  1018. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1019. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  1020. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  1021. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  1022. Assert.True (expectedClippedWidth <= maxWidth);
  1023. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  1024. // Should not fit
  1025. maxWidth = text.RuneCount - 1;
  1026. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1027. justifiedText = TextFormatter.ClipAndJustify (text, maxWidth, align);
  1028. Assert.Equal (expectedClippedWidth, justifiedText.RuneCount);
  1029. Assert.Equal (expectedClippedWidth, justifiedText.ConsoleWidth);
  1030. Assert.True (expectedClippedWidth <= maxWidth);
  1031. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), justifiedText);
  1032. // see Justify_ tests below
  1033. }
  1034. [Fact]
  1035. public void Justify_Invalid ()
  1036. {
  1037. var text = ustring.Empty;
  1038. Assert.Equal (text, TextFormatter.Justify (text, 0));
  1039. text = null;
  1040. Assert.Equal (text, TextFormatter.Justify (text, 0));
  1041. text = "test";
  1042. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.Justify (text, -1));
  1043. }
  1044. [Fact]
  1045. public void Justify_SingleWord ()
  1046. {
  1047. var text = ustring.Empty;
  1048. var justifiedText = ustring.Empty;
  1049. int width = 0;
  1050. char fillChar = '+';
  1051. // Even # of chars
  1052. text = "word";
  1053. justifiedText = text;
  1054. width = text.RuneCount;
  1055. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1056. width = text.RuneCount + 1;
  1057. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1058. width = text.RuneCount + 2;
  1059. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1060. width = text.RuneCount + 10;
  1061. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1062. width = text.RuneCount + 11;
  1063. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1064. // Odd # of chars
  1065. text = "word.";
  1066. justifiedText = text;
  1067. width = text.RuneCount;
  1068. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1069. width = text.RuneCount + 1;
  1070. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1071. width = text.RuneCount + 2;
  1072. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1073. width = text.RuneCount + 10;
  1074. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1075. width = text.RuneCount + 11;
  1076. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1077. // Unicode (even #)
  1078. text = "пÑивеÑ";
  1079. justifiedText = text;
  1080. width = text.RuneCount;
  1081. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1082. width = text.RuneCount + 1;
  1083. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1084. width = text.RuneCount + 2;
  1085. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1086. width = text.RuneCount + 10;
  1087. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1088. width = text.RuneCount + 11;
  1089. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1090. // Unicode (odd # of chars)
  1091. text = "пÑивеÑ.";
  1092. justifiedText = text;
  1093. width = text.RuneCount;
  1094. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1095. width = text.RuneCount + 1;
  1096. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1097. width = text.RuneCount + 2;
  1098. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1099. width = text.RuneCount + 10;
  1100. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1101. width = text.RuneCount + 11;
  1102. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, width, fillChar).ToString ());
  1103. }
  1104. [Fact]
  1105. public void Justify_Sentence ()
  1106. {
  1107. var text = ustring.Empty;
  1108. var justifiedText = ustring.Empty;
  1109. int forceToWidth = 0;
  1110. char fillChar = '+';
  1111. // Even # of spaces
  1112. // 0123456789
  1113. text = "012 456 89";
  1114. forceToWidth = text.RuneCount;
  1115. justifiedText = text.Replace (" ", "+");
  1116. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1117. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1118. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1119. justifiedText = "012++456+89";
  1120. forceToWidth = text.RuneCount + 1;
  1121. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1122. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1123. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1124. justifiedText = text.Replace (" ", "++");
  1125. forceToWidth = text.RuneCount + 2;
  1126. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1127. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1128. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1129. justifiedText = "012+++456++89";
  1130. forceToWidth = text.RuneCount + 3;
  1131. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1132. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1133. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1134. justifiedText = text.Replace (" ", "+++");
  1135. forceToWidth = text.RuneCount + 4;
  1136. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1137. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1138. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1139. justifiedText = "012++++456+++89";
  1140. forceToWidth = text.RuneCount + 5;
  1141. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1142. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1143. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1144. justifiedText = text.Replace (" ", "++++");
  1145. forceToWidth = text.RuneCount + 6;
  1146. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1147. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1148. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1149. justifiedText = text.Replace (" ", "+++++++++++");
  1150. forceToWidth = text.RuneCount + 20;
  1151. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1152. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1153. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1154. justifiedText = "012+++++++++++++456++++++++++++89";
  1155. forceToWidth = text.RuneCount + 23;
  1156. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1157. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1158. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1159. // Odd # of spaces
  1160. // 0123456789
  1161. text = "012 456 89 end";
  1162. forceToWidth = text.RuneCount;
  1163. justifiedText = text.Replace (" ", "+");
  1164. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1165. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1166. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1167. justifiedText = "012++456+89+end";
  1168. forceToWidth = text.RuneCount + 1;
  1169. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1170. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1171. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1172. justifiedText = "012++456++89+end";
  1173. forceToWidth = text.RuneCount + 2;
  1174. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1175. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1176. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1177. justifiedText = text.Replace (" ", "++");
  1178. forceToWidth = text.RuneCount + 3;
  1179. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1180. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1181. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1182. justifiedText = "012+++456++89++end";
  1183. forceToWidth = text.RuneCount + 4;
  1184. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1185. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1186. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1187. justifiedText = "012+++456+++89++end";
  1188. forceToWidth = text.RuneCount + 5;
  1189. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1190. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1191. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1192. justifiedText = text.Replace (" ", "+++");
  1193. forceToWidth = text.RuneCount + 6;
  1194. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1195. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1196. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1197. justifiedText = "012++++++++456++++++++89+++++++end";
  1198. forceToWidth = text.RuneCount + 20;
  1199. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1200. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1201. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1202. justifiedText = "012+++++++++456+++++++++89++++++++end";
  1203. forceToWidth = text.RuneCount + 23;
  1204. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1205. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1206. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1207. // Unicode
  1208. // Even # of chars
  1209. // 0123456789
  1210. text = "пÑРвРÑ";
  1211. forceToWidth = text.RuneCount;
  1212. justifiedText = text.Replace (" ", "+");
  1213. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1214. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1215. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1216. justifiedText = "пÑÐ++вÐ+Ñ";
  1217. forceToWidth = text.RuneCount + 1;
  1218. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1219. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1220. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1221. justifiedText = text.Replace (" ", "++");
  1222. forceToWidth = text.RuneCount + 2;
  1223. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1224. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1225. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1226. justifiedText = "пÑÐ+++вÐ++Ñ";
  1227. forceToWidth = text.RuneCount + 3;
  1228. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1229. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1230. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1231. justifiedText = text.Replace (" ", "+++");
  1232. forceToWidth = text.RuneCount + 4;
  1233. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1234. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1235. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1236. justifiedText = "пÑÐ++++вÐ+++Ñ";
  1237. forceToWidth = text.RuneCount + 5;
  1238. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1239. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1240. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1241. justifiedText = text.Replace (" ", "++++");
  1242. forceToWidth = text.RuneCount + 6;
  1243. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1244. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1245. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1246. justifiedText = text.Replace (" ", "+++++++++++");
  1247. forceToWidth = text.RuneCount + 20;
  1248. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1249. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1250. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1251. justifiedText = "пÑÐ+++++++++++++вÐ++++++++++++Ñ";
  1252. forceToWidth = text.RuneCount + 23;
  1253. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1254. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1255. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1256. // Unicode
  1257. // Odd # of chars
  1258. // 0123456789
  1259. text = "Ð ÑРвРÑ";
  1260. forceToWidth = text.RuneCount;
  1261. justifiedText = text.Replace (" ", "+");
  1262. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1263. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1264. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1265. justifiedText = "Ð++ÑÐ+вÐ+Ñ";
  1266. forceToWidth = text.RuneCount + 1;
  1267. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1268. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1269. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1270. justifiedText = "Ð++ÑÐ++вÐ+Ñ";
  1271. forceToWidth = text.RuneCount + 2;
  1272. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1273. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1274. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1275. justifiedText = text.Replace (" ", "++");
  1276. forceToWidth = text.RuneCount + 3;
  1277. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1278. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1279. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1280. justifiedText = "Ð+++ÑÐ++вÐ++Ñ";
  1281. forceToWidth = text.RuneCount + 4;
  1282. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1283. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1284. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1285. justifiedText = "Ð+++ÑÐ+++вÐ++Ñ";
  1286. forceToWidth = text.RuneCount + 5;
  1287. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1288. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1289. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1290. justifiedText = text.Replace (" ", "+++");
  1291. forceToWidth = text.RuneCount + 6;
  1292. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1293. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1294. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1295. justifiedText = "Ð++++++++ÑÐ++++++++вÐ+++++++Ñ";
  1296. forceToWidth = text.RuneCount + 20;
  1297. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1298. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1299. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1300. justifiedText = "Ð+++++++++ÑÐ+++++++++вÐ++++++++Ñ";
  1301. forceToWidth = text.RuneCount + 23;
  1302. Assert.Equal (justifiedText.ToString (), TextFormatter.Justify (text, forceToWidth, fillChar).ToString ());
  1303. Assert.True (Math.Abs (forceToWidth - justifiedText.RuneCount) < text.Count (" "));
  1304. Assert.True (Math.Abs (forceToWidth - justifiedText.ConsoleWidth) < text.Count (" "));
  1305. }
  1306. [Fact]
  1307. public void WordWrap_Invalid ()
  1308. {
  1309. var text = ustring.Empty;
  1310. int width = 0;
  1311. Assert.Empty (TextFormatter.WordWrap (null, width));
  1312. Assert.Empty (TextFormatter.WordWrap (text, width));
  1313. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.WordWrap (text, -1));
  1314. }
  1315. [Fact]
  1316. public void WordWrap_SingleWordLine ()
  1317. {
  1318. var text = ustring.Empty;
  1319. int width = 0;
  1320. List<ustring> wrappedLines;
  1321. text = "Constantinople";
  1322. width = text.RuneCount;
  1323. wrappedLines = TextFormatter.WordWrap (text, width);
  1324. Assert.True (wrappedLines.Count == 1);
  1325. width = text.RuneCount - 1;
  1326. wrappedLines = TextFormatter.WordWrap (text, width);
  1327. Assert.Equal (2, wrappedLines.Count);
  1328. Assert.Equal (text [0, text.RuneCount - 1].ToString (), wrappedLines [0].ToString ());
  1329. Assert.Equal ("e", wrappedLines [1].ToString ());
  1330. width = text.RuneCount - 2;
  1331. wrappedLines = TextFormatter.WordWrap (text, width);
  1332. Assert.Equal (2, wrappedLines.Count);
  1333. Assert.Equal (text [0, text.RuneCount - 2].ToString (), wrappedLines [0].ToString ());
  1334. width = text.RuneCount - 5;
  1335. wrappedLines = TextFormatter.WordWrap (text, width);
  1336. Assert.Equal (2, wrappedLines.Count);
  1337. width = (int)Math.Ceiling ((double)(text.RuneCount / 2F));
  1338. wrappedLines = TextFormatter.WordWrap (text, width);
  1339. Assert.Equal (2, wrappedLines.Count);
  1340. Assert.Equal ("Constan", wrappedLines [0].ToString ());
  1341. Assert.Equal ("tinople", wrappedLines [1].ToString ());
  1342. width = (int)Math.Ceiling ((double)(text.RuneCount / 3F));
  1343. wrappedLines = TextFormatter.WordWrap (text, width);
  1344. Assert.Equal (3, wrappedLines.Count);
  1345. Assert.Equal ("Const", wrappedLines [0].ToString ());
  1346. Assert.Equal ("antin", wrappedLines [1].ToString ());
  1347. Assert.Equal ("ople", wrappedLines [2].ToString ());
  1348. width = (int)Math.Ceiling ((double)(text.RuneCount / 4F));
  1349. wrappedLines = TextFormatter.WordWrap (text, width);
  1350. Assert.Equal (4, wrappedLines.Count);
  1351. width = (int)Math.Ceiling ((double)text.RuneCount / text.RuneCount);
  1352. wrappedLines = TextFormatter.WordWrap (text, width);
  1353. Assert.Equal (text.RuneCount, wrappedLines.Count);
  1354. Assert.Equal (text.ConsoleWidth, wrappedLines.Count);
  1355. Assert.Equal ("C", wrappedLines [0].ToString ());
  1356. Assert.Equal ("o", wrappedLines [1].ToString ());
  1357. Assert.Equal ("n", wrappedLines [2].ToString ());
  1358. Assert.Equal ("s", wrappedLines [3].ToString ());
  1359. Assert.Equal ("t", wrappedLines [4].ToString ());
  1360. Assert.Equal ("a", wrappedLines [5].ToString ());
  1361. Assert.Equal ("n", wrappedLines [6].ToString ());
  1362. Assert.Equal ("t", wrappedLines [7].ToString ());
  1363. Assert.Equal ("i", wrappedLines [8].ToString ());
  1364. Assert.Equal ("n", wrappedLines [9].ToString ());
  1365. Assert.Equal ("o", wrappedLines [10].ToString ());
  1366. Assert.Equal ("p", wrappedLines [11].ToString ());
  1367. Assert.Equal ("l", wrappedLines [12].ToString ());
  1368. Assert.Equal ("e", wrappedLines [13].ToString ());
  1369. }
  1370. [Fact]
  1371. public void WordWrap_Unicode_SingleWordLine ()
  1372. {
  1373. var text = ustring.Empty;
  1374. int width = 0;
  1375. List<ustring> wrappedLines;
  1376. text = "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ";
  1377. width = text.RuneCount;
  1378. wrappedLines = TextFormatter.WordWrap (text, width);
  1379. Assert.True (wrappedLines.Count == 1);
  1380. width = text.RuneCount - 1;
  1381. wrappedLines = TextFormatter.WordWrap (text, width);
  1382. Assert.Equal (2, wrappedLines.Count);
  1383. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 1)]).ToString (), wrappedLines [0].ToString ());
  1384. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)) - 1)]).ToString (), wrappedLines [0].ToString ());
  1385. Assert.Equal ("ำ", wrappedLines [1].ToString ());
  1386. width = text.RuneCount - 2;
  1387. wrappedLines = TextFormatter.WordWrap (text, width);
  1388. Assert.Equal (2, wrappedLines.Count);
  1389. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 2)]).ToString (), wrappedLines [0].ToString ());
  1390. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)) - 2)]).ToString (), wrappedLines [0].ToString ());
  1391. width = text.RuneCount - 5;
  1392. wrappedLines = TextFormatter.WordWrap (text, width);
  1393. Assert.Equal (2, wrappedLines.Count);
  1394. width = (int)Math.Ceiling ((double)(text.RuneCount / 2F));
  1395. wrappedLines = TextFormatter.WordWrap (text, width);
  1396. Assert.Equal (2, wrappedLines.Count);
  1397. Assert.Equal ("กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบ", wrappedLines [0].ToString ());
  1398. Assert.Equal ("ปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำ", wrappedLines [1].ToString ());
  1399. width = (int)Math.Ceiling ((double)(text.RuneCount / 3F));
  1400. wrappedLines = TextFormatter.WordWrap (text, width);
  1401. Assert.Equal (3, wrappedLines.Count);
  1402. Assert.Equal ("กขฃคฅฆงจฉชซฌญฎฏฐฑ", wrappedLines [0].ToString ());
  1403. Assert.Equal ("ฒณดตถทธนบปผฝพฟภมย", wrappedLines [1].ToString ());
  1404. Assert.Equal ("รฤลฦวศษสหฬอฮฯะัาำ", wrappedLines [2].ToString ());
  1405. width = (int)Math.Ceiling ((double)(text.RuneCount / 4F));
  1406. wrappedLines = TextFormatter.WordWrap (text, width);
  1407. Assert.Equal (4, wrappedLines.Count);
  1408. width = (int)Math.Ceiling ((double)text.RuneCount / text.RuneCount);
  1409. wrappedLines = TextFormatter.WordWrap (text, width);
  1410. Assert.Equal (text.RuneCount, wrappedLines.Count);
  1411. Assert.Equal (text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)), wrappedLines.Count);
  1412. Assert.Equal ("ก", wrappedLines [0].ToString ());
  1413. Assert.Equal ("ข", wrappedLines [1].ToString ());
  1414. Assert.Equal ("ฃ", wrappedLines [2].ToString ());
  1415. Assert.Equal ("ำ", wrappedLines [^1].ToString ());
  1416. }
  1417. [Fact]
  1418. public void WordWrap_Unicode_LineWithNonBreakingSpace ()
  1419. {
  1420. var text = ustring.Empty;
  1421. int width = 0;
  1422. List<ustring> wrappedLines;
  1423. text = "This\u00A0is\u00A0a\u00A0sentence.";
  1424. width = text.RuneCount;
  1425. wrappedLines = TextFormatter.WordWrap (text, width);
  1426. Assert.True (wrappedLines.Count == 1);
  1427. width = text.RuneCount - 1;
  1428. wrappedLines = TextFormatter.WordWrap (text, width);
  1429. Assert.Equal (2, wrappedLines.Count);
  1430. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 1)]).ToString (), wrappedLines [0].ToString ());
  1431. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)) - 1)]).ToString (), wrappedLines [0].ToString ());
  1432. Assert.Equal (".", wrappedLines [1].ToString ());
  1433. width = text.RuneCount - 2;
  1434. wrappedLines = TextFormatter.WordWrap (text, width);
  1435. Assert.Equal (2, wrappedLines.Count);
  1436. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 2)]).ToString (), wrappedLines [0].ToString ());
  1437. Assert.Equal (ustring.Make (text.ToRunes () [0..(text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)) - 2)]).ToString (), wrappedLines [0].ToString ());
  1438. width = text.RuneCount - 5;
  1439. wrappedLines = TextFormatter.WordWrap (text, width);
  1440. Assert.Equal (2, wrappedLines.Count);
  1441. width = (int)Math.Ceiling ((double)(text.RuneCount / 2F));
  1442. wrappedLines = TextFormatter.WordWrap (text, width);
  1443. Assert.Equal (2, wrappedLines.Count);
  1444. Assert.Equal ("This\u00A0is\u00A0a\u00A0", wrappedLines [0].ToString ());
  1445. Assert.Equal ("sentence.", wrappedLines [1].ToString ());
  1446. width = (int)Math.Ceiling ((double)(text.RuneCount / 3F));
  1447. wrappedLines = TextFormatter.WordWrap (text, width);
  1448. Assert.Equal (3, wrappedLines.Count);
  1449. Assert.Equal ("This\u00A0is", wrappedLines [0].ToString ());
  1450. Assert.Equal ("\u00a0a\u00a0sent", wrappedLines [1].ToString ());
  1451. Assert.Equal ("ence.", wrappedLines [2].ToString ());
  1452. width = (int)Math.Ceiling ((double)(text.RuneCount / 4F));
  1453. wrappedLines = TextFormatter.WordWrap (text, width);
  1454. Assert.Equal (4, wrappedLines.Count);
  1455. width = (int)Math.Ceiling ((double)text.RuneCount / text.RuneCount);
  1456. wrappedLines = TextFormatter.WordWrap (text, width);
  1457. Assert.Equal (text.RuneCount, wrappedLines.Count);
  1458. Assert.Equal (text.ToRuneList ().Sum (r => Math.Max (Rune.ColumnWidth (r), 1)), wrappedLines.Count);
  1459. Assert.Equal ("T", wrappedLines [0].ToString ());
  1460. Assert.Equal ("h", wrappedLines [1].ToString ());
  1461. Assert.Equal ("i", wrappedLines [2].ToString ());
  1462. Assert.Equal (".", wrappedLines [^1].ToString ());
  1463. }
  1464. [Fact]
  1465. public void WordWrap_Unicode_2LinesWithNonBreakingSpace ()
  1466. {
  1467. var text = ustring.Empty;
  1468. int width = 0;
  1469. List<ustring> wrappedLines;
  1470. text = "This\u00A0is\n\u00A0a\u00A0sentence.";
  1471. width = text.RuneCount;
  1472. wrappedLines = TextFormatter.WordWrap (text, width);
  1473. Assert.True (wrappedLines.Count == 1);
  1474. width = text.RuneCount - 1;
  1475. wrappedLines = TextFormatter.WordWrap (text, width);
  1476. #pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
  1477. Assert.Equal (1, wrappedLines.Count);
  1478. #pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
  1479. Assert.Equal ("This\u00A0is\u00A0a\u00A0sentence.", wrappedLines [0].ToString ());
  1480. text = "\u00A0\u00A0\u00A0\u00A0\u00A0test\u00A0sentence.";
  1481. width = text.RuneCount;
  1482. wrappedLines = TextFormatter.WordWrap (text, width);
  1483. Assert.True (wrappedLines.Count == 1);
  1484. }
  1485. [Fact]
  1486. public void WordWrap_NoNewLines ()
  1487. {
  1488. var text = ustring.Empty;
  1489. int maxWidth = 0;
  1490. int expectedClippedWidth = 0;
  1491. List<ustring> wrappedLines;
  1492. text = "A sentence has words.";
  1493. maxWidth = text.RuneCount;
  1494. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1495. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1496. Assert.True (wrappedLines.Count == 1);
  1497. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1498. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1499. Assert.Equal ("A sentence has words.", wrappedLines [0].ToString ());
  1500. maxWidth = text.RuneCount - 1;
  1501. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1502. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1503. Assert.Equal (2, wrappedLines.Count);
  1504. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1505. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1506. Assert.Equal ("A sentence has", wrappedLines [0].ToString ());
  1507. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1508. maxWidth = text.RuneCount - "words.".Length;
  1509. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1510. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1511. Assert.Equal (2, wrappedLines.Count);
  1512. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1513. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1514. Assert.Equal ("A sentence has", wrappedLines [0].ToString ());
  1515. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1516. maxWidth = text.RuneCount - " words.".Length;
  1517. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1518. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1519. Assert.Equal (2, wrappedLines.Count);
  1520. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1521. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1522. Assert.Equal ("A sentence has", wrappedLines [0].ToString ());
  1523. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1524. maxWidth = text.RuneCount - "s words.".Length;
  1525. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1526. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1527. Assert.Equal (2, wrappedLines.Count);
  1528. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1529. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1530. Assert.Equal ("A sentence", wrappedLines [0].ToString ());
  1531. Assert.Equal ("has words.", wrappedLines [1].ToString ());
  1532. // Unicode
  1533. text = "A Unicode sentence (пÑивеÑ) has words.";
  1534. maxWidth = text.RuneCount;
  1535. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1536. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1537. Assert.True (wrappedLines.Count == 1);
  1538. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1539. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1540. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.", wrappedLines [0].ToString ());
  1541. maxWidth = text.RuneCount - 1;
  1542. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1543. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1544. Assert.Equal (2, wrappedLines.Count);
  1545. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1546. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1547. Assert.Equal ("A Unicode sentence (пÑивеÑ) has", wrappedLines [0].ToString ());
  1548. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1549. maxWidth = text.RuneCount - "words.".Length;
  1550. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1551. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1552. Assert.Equal (2, wrappedLines.Count);
  1553. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1554. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1555. Assert.Equal ("A Unicode sentence (пÑивеÑ) has", wrappedLines [0].ToString ());
  1556. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1557. maxWidth = text.RuneCount - " words.".Length;
  1558. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1559. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1560. Assert.Equal (2, wrappedLines.Count);
  1561. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1562. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1563. Assert.Equal ("A Unicode sentence (пÑивеÑ) has", wrappedLines [0].ToString ());
  1564. Assert.Equal ("words.", wrappedLines [1].ToString ());
  1565. maxWidth = text.RuneCount - "s words.".Length;
  1566. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1567. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1568. Assert.Equal (2, wrappedLines.Count);
  1569. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1570. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1571. Assert.Equal ("A Unicode sentence (пÑивеÑ)", wrappedLines [0].ToString ());
  1572. Assert.Equal ("has words.", wrappedLines [1].ToString ());
  1573. maxWidth = text.RuneCount - "веÑ) has words.".Length;
  1574. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1575. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1576. Assert.Equal (2, wrappedLines.Count);
  1577. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1578. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1579. Assert.Equal ("A Unicode sentence", wrappedLines [0].ToString ());
  1580. Assert.Equal ("(пÑивеÑ) has words.", wrappedLines [1].ToString ());
  1581. }
  1582. /// <summary>
  1583. /// WordWrap strips CRLF
  1584. /// </summary>
  1585. [Fact]
  1586. public void WordWrap_WithNewLines ()
  1587. {
  1588. var text = ustring.Empty;
  1589. int maxWidth = 0;
  1590. int expectedClippedWidth = 0;
  1591. List<ustring> wrappedLines;
  1592. text = "A sentence has words.\nA paragraph has lines.";
  1593. maxWidth = text.RuneCount;
  1594. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1595. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1596. #pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
  1597. Assert.Equal (1, wrappedLines.Count);
  1598. #pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
  1599. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1600. Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ());
  1601. maxWidth = text.RuneCount - 1;
  1602. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1603. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1604. #pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
  1605. Assert.Equal (1, wrappedLines.Count);
  1606. #pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
  1607. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1608. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1609. Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ());
  1610. maxWidth = text.RuneCount - "words.".Length;
  1611. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1612. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1613. Assert.Equal (2, wrappedLines.Count);
  1614. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1615. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1616. Assert.Equal ("A sentence has words.A paragraph has", wrappedLines [0].ToString ());
  1617. Assert.Equal ("lines.", wrappedLines [1].ToString ());
  1618. // Unicode
  1619. text = "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии.";
  1620. maxWidth = text.RuneCount;
  1621. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1622. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1623. Assert.True (wrappedLines.Count == 1);
  1624. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1625. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1626. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии.", wrappedLines [0].ToString ());
  1627. maxWidth = text.RuneCount - 1;
  1628. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1629. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1630. Assert.Equal (2, wrappedLines.Count);
  1631. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1632. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1633. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ());
  1634. Assert.Equal ("Линии.", wrappedLines [1].ToString ());
  1635. maxWidth = text.RuneCount - "words.".Length;
  1636. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1637. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1638. Assert.Equal (2, wrappedLines.Count);
  1639. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1640. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1641. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ());
  1642. Assert.Equal ("Линии.", wrappedLines [1].ToString ());
  1643. maxWidth = text.RuneCount - "s words.".Length;
  1644. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1645. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1646. Assert.Equal (2, wrappedLines.Count);
  1647. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1648. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1649. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт", wrappedLines [0].ToString ());
  1650. Assert.Equal ("has Линии.", wrappedLines [1].ToString ());
  1651. maxWidth = text.RuneCount - "веÑ) has words.".Length;
  1652. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  1653. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1654. Assert.Equal (2, wrappedLines.Count);
  1655. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1656. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1657. Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode", wrappedLines [0].ToString ());
  1658. Assert.Equal ("Пункт has Линии.", wrappedLines [1].ToString ());
  1659. }
  1660. [Fact]
  1661. public void WordWrap_Narrow ()
  1662. {
  1663. var text = ustring.Empty;
  1664. int maxWidth = 1;
  1665. int expectedClippedWidth = 1;
  1666. List<ustring> wrappedLines;
  1667. text = "A sentence has words.";
  1668. maxWidth = 3;
  1669. expectedClippedWidth = 3;
  1670. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1671. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1672. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1673. Assert.Equal ("A", wrappedLines [0].ToString ());
  1674. Assert.Equal ("sen", wrappedLines [1].ToString ());
  1675. Assert.Equal ("ten", wrappedLines [2].ToString ());
  1676. Assert.Equal ("ce", wrappedLines [3].ToString ());
  1677. Assert.Equal ("has", wrappedLines [4].ToString ());
  1678. Assert.Equal ("wor", wrappedLines [5].ToString ());
  1679. Assert.Equal ("ds.", wrappedLines [6].ToString ());
  1680. maxWidth = 2;
  1681. expectedClippedWidth = 2;
  1682. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1683. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1684. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1685. Assert.Equal ("A", wrappedLines [0].ToString ());
  1686. Assert.Equal ("se", wrappedLines [1].ToString ());
  1687. Assert.Equal ("nt", wrappedLines [2].ToString ());
  1688. Assert.Equal ("en", wrappedLines [3].ToString ());
  1689. Assert.Equal ("s.", wrappedLines [^1].ToString ());
  1690. maxWidth = 1;
  1691. expectedClippedWidth = 1;
  1692. wrappedLines = TextFormatter.WordWrap (text, maxWidth);
  1693. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1694. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1695. Assert.Equal ("A", wrappedLines [0].ToString ());
  1696. Assert.Equal ("s", wrappedLines [1].ToString ());
  1697. Assert.Equal ("e", wrappedLines [2].ToString ());
  1698. Assert.Equal ("n", wrappedLines [3].ToString ());
  1699. Assert.Equal (".", wrappedLines [^1].ToString ());
  1700. }
  1701. [Fact]
  1702. public void WordWrap_preserveTrailingSpaces ()
  1703. {
  1704. var text = ustring.Empty;
  1705. int maxWidth = 1;
  1706. int expectedClippedWidth = 1;
  1707. List<ustring> wrappedLines;
  1708. text = "A sentence has words.";
  1709. maxWidth = 14;
  1710. expectedClippedWidth = 14;
  1711. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1712. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1713. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1714. Assert.Equal ("A sentence ", wrappedLines [0].ToString ());
  1715. Assert.Equal ("has words.", wrappedLines [1].ToString ());
  1716. Assert.True (wrappedLines.Count == 2);
  1717. maxWidth = 8;
  1718. expectedClippedWidth = 8;
  1719. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1720. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1721. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1722. Assert.Equal ("A ", wrappedLines [0].ToString ());
  1723. Assert.Equal ("sentence", wrappedLines [1].ToString ());
  1724. Assert.Equal (" has ", wrappedLines [2].ToString ());
  1725. Assert.Equal ("words.", wrappedLines [^1].ToString ());
  1726. Assert.True (wrappedLines.Count == 4);
  1727. maxWidth = 6;
  1728. expectedClippedWidth = 6;
  1729. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1730. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1731. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1732. Assert.Equal ("A ", wrappedLines [0].ToString ());
  1733. Assert.Equal ("senten", wrappedLines [1].ToString ());
  1734. Assert.Equal ("ce ", wrappedLines [2].ToString ());
  1735. Assert.Equal ("has ", wrappedLines [3].ToString ());
  1736. Assert.Equal ("words.", wrappedLines [^1].ToString ());
  1737. Assert.True (wrappedLines.Count == 5);
  1738. maxWidth = 3;
  1739. expectedClippedWidth = 3;
  1740. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1741. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1742. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1743. Assert.Equal ("A ", wrappedLines [0].ToString ());
  1744. Assert.Equal ("sen", wrappedLines [1].ToString ());
  1745. Assert.Equal ("ten", wrappedLines [2].ToString ());
  1746. Assert.Equal ("ce ", wrappedLines [3].ToString ());
  1747. Assert.Equal ("has", wrappedLines [4].ToString ());
  1748. Assert.Equal (" ", wrappedLines [5].ToString ());
  1749. Assert.Equal ("wor", wrappedLines [6].ToString ());
  1750. Assert.Equal ("ds.", wrappedLines [^1].ToString ());
  1751. Assert.True (wrappedLines.Count == 8);
  1752. maxWidth = 2;
  1753. expectedClippedWidth = 2;
  1754. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1755. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1756. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1757. Assert.Equal ("A ", wrappedLines [0].ToString ());
  1758. Assert.Equal ("se", wrappedLines [1].ToString ());
  1759. Assert.Equal ("nt", wrappedLines [2].ToString ());
  1760. Assert.Equal ("en", wrappedLines [3].ToString ());
  1761. Assert.Equal ("ce", wrappedLines [4].ToString ());
  1762. Assert.Equal (" ", wrappedLines [5].ToString ());
  1763. Assert.Equal ("ha", wrappedLines [6].ToString ());
  1764. Assert.Equal ("s ", wrappedLines [7].ToString ());
  1765. Assert.Equal ("wo", wrappedLines [8].ToString ());
  1766. Assert.Equal ("rd", wrappedLines [9].ToString ());
  1767. Assert.Equal ("s.", wrappedLines [^1].ToString ());
  1768. Assert.True (wrappedLines.Count == 11);
  1769. maxWidth = 1;
  1770. expectedClippedWidth = 1;
  1771. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1772. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1773. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1774. Assert.Equal ("A", wrappedLines [0].ToString ());
  1775. Assert.Equal (" ", wrappedLines [1].ToString ());
  1776. Assert.Equal ("s", wrappedLines [2].ToString ());
  1777. Assert.Equal ("e", wrappedLines [3].ToString ());
  1778. Assert.Equal ("n", wrappedLines [4].ToString ());
  1779. Assert.Equal ("t", wrappedLines [5].ToString ());
  1780. Assert.Equal ("e", wrappedLines [6].ToString ());
  1781. Assert.Equal ("n", wrappedLines [7].ToString ());
  1782. Assert.Equal ("c", wrappedLines [8].ToString ());
  1783. Assert.Equal ("e", wrappedLines [9].ToString ());
  1784. Assert.Equal (" ", wrappedLines [10].ToString ());
  1785. Assert.Equal (".", wrappedLines [^1].ToString ());
  1786. Assert.True (wrappedLines.Count == text.Length);
  1787. }
  1788. [Fact]
  1789. public void WordWrap_preserveTrailingSpaces_Wide_Runes ()
  1790. {
  1791. var text = ustring.Empty;
  1792. int maxWidth = 1;
  1793. int expectedClippedWidth = 1;
  1794. List<ustring> wrappedLines;
  1795. text = "文に は言葉 があり ます。";
  1796. maxWidth = 14;
  1797. expectedClippedWidth = 14;
  1798. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1799. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1800. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1801. Assert.Equal ("文に は言葉 ", wrappedLines [0].ToString ());
  1802. Assert.Equal ("があり ます。", wrappedLines [1].ToString ());
  1803. Assert.True (wrappedLines.Count == 2);
  1804. maxWidth = 3;
  1805. expectedClippedWidth = 3;
  1806. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1807. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1808. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1809. Assert.Equal ("文", wrappedLines [0].ToString ());
  1810. Assert.Equal ("に ", wrappedLines [1].ToString ());
  1811. Assert.Equal ("は", wrappedLines [2].ToString ());
  1812. Assert.Equal ("言", wrappedLines [3].ToString ());
  1813. Assert.Equal ("葉 ", wrappedLines [4].ToString ());
  1814. Assert.Equal ("が", wrappedLines [5].ToString ());
  1815. Assert.Equal ("あ", wrappedLines [6].ToString ());
  1816. Assert.Equal ("り ", wrappedLines [7].ToString ());
  1817. Assert.Equal ("ま", wrappedLines [8].ToString ());
  1818. Assert.Equal ("す", wrappedLines [9].ToString ());
  1819. Assert.Equal ("。", wrappedLines [^1].ToString ());
  1820. Assert.True (wrappedLines.Count == 11);
  1821. maxWidth = 2;
  1822. expectedClippedWidth = 2;
  1823. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1824. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1825. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.ConsoleWidth));
  1826. Assert.Equal ("文", wrappedLines [0].ToString ());
  1827. Assert.Equal ("に", wrappedLines [1].ToString ());
  1828. Assert.Equal (" ", wrappedLines [2].ToString ());
  1829. Assert.Equal ("は", wrappedLines [3].ToString ());
  1830. Assert.Equal ("言", wrappedLines [4].ToString ());
  1831. Assert.Equal ("葉", wrappedLines [5].ToString ());
  1832. Assert.Equal (" ", wrappedLines [6].ToString ());
  1833. Assert.Equal ("が", wrappedLines [7].ToString ());
  1834. Assert.Equal ("あ", wrappedLines [8].ToString ());
  1835. Assert.Equal ("り", wrappedLines [9].ToString ());
  1836. Assert.Equal (" ", wrappedLines [10].ToString ());
  1837. Assert.Equal ("ま", wrappedLines [11].ToString ());
  1838. Assert.Equal ("す", wrappedLines [12].ToString ());
  1839. Assert.Equal ("。", wrappedLines [^1].ToString ());
  1840. Assert.True (wrappedLines.Count == 14);
  1841. maxWidth = 1;
  1842. expectedClippedWidth = 0;
  1843. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true);
  1844. Assert.Empty (wrappedLines);
  1845. Assert.False (wrappedLines.Count == text.Length);
  1846. Assert.False (wrappedLines.Count == text.RuneCount);
  1847. Assert.False (wrappedLines.Count == text.ConsoleWidth);
  1848. Assert.Equal (25, text.ConsoleWidth);
  1849. Assert.Equal (25, TextFormatter.GetTextWidth (text));
  1850. }
  1851. [Fact, AutoInitShutdown]
  1852. public void WordWrap_preserveTrailingSpaces_Horizontal_With_Simple_Runes ()
  1853. {
  1854. var text = "A sentence has words.";
  1855. var width = 3;
  1856. var height = 8;
  1857. var wrappedLines = TextFormatter.WordWrap (text, width, true);
  1858. var breakLines = "";
  1859. foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}";
  1860. var label = new Label (breakLines) { Width = Dim.Fill (), Height = Dim.Fill () };
  1861. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  1862. frame.Add (label);
  1863. Application.Top.Add (frame);
  1864. Application.Begin (Application.Top);
  1865. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, height + 2);
  1866. Assert.True (label.AutoSize);
  1867. Assert.Equal (new Rect (0, 0, width, height + 1), label.Frame);
  1868. Assert.Equal (new Rect (0, 0, width + 2, height + 2), frame.Frame);
  1869. var expected = @"
  1870. ┌───┐
  1871. │A │
  1872. │sen│
  1873. │ten│
  1874. │ce │
  1875. │has│
  1876. │ │
  1877. │wor│
  1878. │ds.│
  1879. └───┘
  1880. ";
  1881. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1882. Assert.Equal (new Rect (0, 0, width + 2, height + 2), pos);
  1883. }
  1884. [Fact, AutoInitShutdown]
  1885. public void WordWrap_preserveTrailingSpaces_Vertical_With_Simple_Runes ()
  1886. {
  1887. var text = "A sentence has words.";
  1888. var width = 8;
  1889. var height = 3;
  1890. var wrappedLines = TextFormatter.WordWrap (text, height, true);
  1891. var breakLines = "";
  1892. for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}";
  1893. var label = new Label (breakLines) {
  1894. TextDirection = TextDirection.TopBottom_LeftRight,
  1895. Width = Dim.Fill (),
  1896. Height = Dim.Fill ()
  1897. };
  1898. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  1899. frame.Add (label);
  1900. Application.Top.Add (frame);
  1901. Application.Begin (Application.Top);
  1902. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, height + 2);
  1903. Assert.True (label.AutoSize);
  1904. Assert.Equal (new Rect (0, 0, width, height), label.Frame);
  1905. Assert.Equal (new Rect (0, 0, width + 2, height + 2), frame.Frame);
  1906. var expected = @"
  1907. ┌────────┐
  1908. │Astch wd│
  1909. │ eeea os│
  1910. │ nn s r.│
  1911. └────────┘
  1912. ";
  1913. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1914. Assert.Equal (new Rect (0, 0, width + 2, height + 2), pos);
  1915. }
  1916. [Fact, AutoInitShutdown]
  1917. public void WordWrap_preserveTrailingSpaces_Horizontal_With_Wide_Runes ()
  1918. {
  1919. var text = "文に は言葉 があり ます。";
  1920. var width = 6;
  1921. var height = 8;
  1922. var wrappedLines = TextFormatter.WordWrap (text, width, true);
  1923. var breakLines = "";
  1924. foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}";
  1925. var label = new Label (breakLines) { Width = Dim.Fill (), Height = Dim.Fill () };
  1926. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  1927. frame.Add (label);
  1928. Application.Top.Add (frame);
  1929. Application.Begin (Application.Top);
  1930. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, height + 2);
  1931. Assert.True (label.AutoSize);
  1932. Assert.Equal (new Rect (0, 0, width, height), label.Frame);
  1933. Assert.Equal (new Size (width, height), label.TextFormatter.Size);
  1934. Assert.Equal (new Rect (0, 0, width + 2, height + 2), frame.Frame);
  1935. var expected = @"
  1936. ┌──────┐
  1937. │文に │
  1938. │は言葉│
  1939. │ があ │
  1940. │り ま │
  1941. │す。 │
  1942. │ │
  1943. │ │
  1944. │ │
  1945. └──────┘
  1946. ";
  1947. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1948. Assert.Equal (new Rect (0, 0, width + 2, height + 2), pos);
  1949. }
  1950. [Fact, AutoInitShutdown]
  1951. public void WordWrap_preserveTrailingSpaces_Vertical_With_Wide_Runes ()
  1952. {
  1953. var text = "文に は言葉 があり ます。";
  1954. var width = 8;
  1955. var height = 4;
  1956. var wrappedLines = TextFormatter.WordWrap (text, width, true);
  1957. var breakLines = "";
  1958. for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}";
  1959. var label = new Label (breakLines) {
  1960. TextDirection = TextDirection.TopBottom_LeftRight,
  1961. Width = Dim.Fill (),
  1962. Height = Dim.Fill ()
  1963. };
  1964. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  1965. frame.Add (label);
  1966. Application.Top.Add (frame);
  1967. Application.Begin (Application.Top);
  1968. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, height + 2);
  1969. Assert.True (label.AutoSize);
  1970. Assert.Equal (new Rect (0, 0, width, height), label.Frame);
  1971. Assert.Equal (new Rect (0, 0, width + 2, height + 2), frame.Frame);
  1972. var expected = @"
  1973. ┌────────┐
  1974. │文言あす│
  1975. │に葉り。│
  1976. │ │
  1977. │はがま │
  1978. └────────┘
  1979. ";
  1980. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  1981. Assert.Equal (new Rect (0, 0, width + 2, height + 2), pos);
  1982. }
  1983. [Fact]
  1984. public void WordWrap_preserveTrailingSpaces_With_Tab ()
  1985. {
  1986. var text = ustring.Empty;
  1987. int maxWidth = 1;
  1988. int expectedClippedWidth = 1;
  1989. List<ustring> wrappedLines;
  1990. text = "A sentence\t\t\t has words.";
  1991. var tabWidth = 4;
  1992. maxWidth = 14;
  1993. expectedClippedWidth = 11;
  1994. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true, tabWidth);
  1995. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  1996. Assert.Equal ("A sentence\t", wrappedLines [0].ToString ());
  1997. Assert.Equal ("\t\t has ", wrappedLines [1].ToString ());
  1998. Assert.Equal ("words.", wrappedLines [2].ToString ());
  1999. Assert.True (wrappedLines.Count == 3);
  2000. maxWidth = 8;
  2001. expectedClippedWidth = 8;
  2002. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true, tabWidth);
  2003. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  2004. Assert.Equal ("A ", wrappedLines [0].ToString ());
  2005. Assert.Equal ("sentence", wrappedLines [1].ToString ());
  2006. Assert.Equal ("\t\t", wrappedLines [2].ToString ());
  2007. Assert.Equal ("\t ", wrappedLines [3].ToString ());
  2008. Assert.Equal ("has ", wrappedLines [4].ToString ());
  2009. Assert.Equal ("words.", wrappedLines [^1].ToString ());
  2010. Assert.True (wrappedLines.Count == 6);
  2011. maxWidth = 3;
  2012. expectedClippedWidth = 3;
  2013. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true, tabWidth);
  2014. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  2015. Assert.Equal ("A ", wrappedLines [0].ToString ());
  2016. Assert.Equal ("sen", wrappedLines [1].ToString ());
  2017. Assert.Equal ("ten", wrappedLines [2].ToString ());
  2018. Assert.Equal ("ce", wrappedLines [3].ToString ());
  2019. Assert.Equal ("\t", wrappedLines [4].ToString ());
  2020. Assert.Equal ("\t", wrappedLines [5].ToString ());
  2021. Assert.Equal ("\t", wrappedLines [6].ToString ());
  2022. Assert.Equal (" ", wrappedLines [7].ToString ());
  2023. Assert.Equal ("has", wrappedLines [8].ToString ());
  2024. Assert.Equal (" ", wrappedLines [9].ToString ());
  2025. Assert.Equal ("wor", wrappedLines [10].ToString ());
  2026. Assert.Equal ("ds.", wrappedLines [^1].ToString ());
  2027. Assert.True (wrappedLines.Count == 12);
  2028. maxWidth = 2;
  2029. expectedClippedWidth = 2;
  2030. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true, tabWidth);
  2031. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  2032. Assert.Equal ("A ", wrappedLines [0].ToString ());
  2033. Assert.Equal ("se", wrappedLines [1].ToString ());
  2034. Assert.Equal ("nt", wrappedLines [2].ToString ());
  2035. Assert.Equal ("en", wrappedLines [3].ToString ());
  2036. Assert.Equal ("ce", wrappedLines [4].ToString ());
  2037. Assert.Equal ("\t", wrappedLines [5].ToString ());
  2038. Assert.Equal ("\t", wrappedLines [6].ToString ());
  2039. Assert.Equal ("\t", wrappedLines [7].ToString ());
  2040. Assert.Equal (" ", wrappedLines [8].ToString ());
  2041. Assert.Equal ("ha", wrappedLines [9].ToString ());
  2042. Assert.Equal ("s ", wrappedLines [10].ToString ());
  2043. Assert.Equal ("wo", wrappedLines [11].ToString ());
  2044. Assert.Equal ("rd", wrappedLines [12].ToString ());
  2045. Assert.Equal ("s.", wrappedLines [^1].ToString ());
  2046. Assert.True (wrappedLines.Count == 14);
  2047. maxWidth = 1;
  2048. expectedClippedWidth = 1;
  2049. wrappedLines = TextFormatter.WordWrap (text, maxWidth, true, tabWidth);
  2050. Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
  2051. Assert.Equal ("A", wrappedLines [0].ToString ());
  2052. Assert.Equal (" ", wrappedLines [1].ToString ());
  2053. Assert.Equal ("s", wrappedLines [2].ToString ());
  2054. Assert.Equal ("e", wrappedLines [3].ToString ());
  2055. Assert.Equal ("n", wrappedLines [4].ToString ());
  2056. Assert.Equal ("t", wrappedLines [5].ToString ());
  2057. Assert.Equal ("e", wrappedLines [6].ToString ());
  2058. Assert.Equal ("n", wrappedLines [7].ToString ());
  2059. Assert.Equal ("c", wrappedLines [8].ToString ());
  2060. Assert.Equal ("e", wrappedLines [9].ToString ());
  2061. Assert.Equal ("\t", wrappedLines [10].ToString ());
  2062. Assert.Equal ("\t", wrappedLines [11].ToString ());
  2063. Assert.Equal ("\t", wrappedLines [12].ToString ());
  2064. Assert.Equal (" ", wrappedLines [13].ToString ());
  2065. Assert.Equal (".", wrappedLines [^1].ToString ());
  2066. Assert.True (wrappedLines.Count == text.Length);
  2067. }
  2068. [Fact]
  2069. public void WordWrap_Unicode_Wide_Runes ()
  2070. {
  2071. ustring text = "これが最初の行です。 こんにちは世界。 これが2行目です。";
  2072. var width = text.RuneCount;
  2073. var wrappedLines = TextFormatter.WordWrap (text, width);
  2074. Assert.Equal (3, wrappedLines.Count);
  2075. Assert.Equal ("これが最初の行です。", wrappedLines [0].ToString ());
  2076. Assert.Equal ("こんにちは世界。", wrappedLines [1].ToString ());
  2077. Assert.Equal ("これが2行目です。", wrappedLines [^1].ToString ());
  2078. }
  2079. [Fact]
  2080. public void ReplaceHotKeyWithTag ()
  2081. {
  2082. var tf = new TextFormatter ();
  2083. ustring text = "test";
  2084. int hotPos = 0;
  2085. uint tag = 't';
  2086. Assert.Equal (ustring.Make (new Rune [] { tag, 'e', 's', 't' }), tf.ReplaceHotKeyWithTag (text, hotPos));
  2087. tag = 'e';
  2088. hotPos = 1;
  2089. Assert.Equal (ustring.Make (new Rune [] { 't', tag, 's', 't' }), tf.ReplaceHotKeyWithTag (text, hotPos));
  2090. var result = tf.ReplaceHotKeyWithTag (text, hotPos);
  2091. Assert.Equal ('e', result.ToRunes () [1]);
  2092. text = "Ok";
  2093. tag = 'O';
  2094. hotPos = 0;
  2095. Assert.Equal (ustring.Make (new Rune [] { tag, 'k' }), result = tf.ReplaceHotKeyWithTag (text, hotPos));
  2096. Assert.Equal ('O', result.ToRunes () [0]);
  2097. text = "[◦ Ok ◦]";
  2098. text = ustring.Make (new Rune [] { '[', '◦', ' ', 'O', 'k', ' ', '◦', ']' });
  2099. var runes = text.ToRuneList ();
  2100. Assert.Equal (text.RuneCount, runes.Count);
  2101. Assert.Equal (text, ustring.Make (runes));
  2102. tag = 'O';
  2103. hotPos = 3;
  2104. Assert.Equal (ustring.Make (new Rune [] { '[', '◦', ' ', tag, 'k', ' ', '◦', ']' }), result = tf.ReplaceHotKeyWithTag (text, hotPos));
  2105. Assert.Equal ('O', result.ToRunes () [3]);
  2106. text = "^k";
  2107. tag = '^';
  2108. hotPos = 0;
  2109. Assert.Equal (ustring.Make (new Rune [] { tag, 'k' }), result = tf.ReplaceHotKeyWithTag (text, hotPos));
  2110. Assert.Equal ('^', result.ToRunes () [0]);
  2111. }
  2112. [Fact]
  2113. public void Reformat_Invalid ()
  2114. {
  2115. var text = ustring.Empty;
  2116. var list = new List<ustring> ();
  2117. Assert.Throws<ArgumentOutOfRangeException> (() => TextFormatter.Format (text, -1, TextAlignment.Left, false));
  2118. list = TextFormatter.Format (text, 0, TextAlignment.Left, false);
  2119. Assert.NotEmpty (list);
  2120. Assert.True (list.Count == 1);
  2121. Assert.Equal (ustring.Empty, list [0]);
  2122. text = null;
  2123. list = TextFormatter.Format (text, 0, TextAlignment.Left, false);
  2124. Assert.NotEmpty (list);
  2125. Assert.True (list.Count == 1);
  2126. Assert.Equal (ustring.Empty, list [0]);
  2127. list = TextFormatter.Format (text, 0, TextAlignment.Left, true);
  2128. Assert.NotEmpty (list);
  2129. Assert.True (list.Count == 1);
  2130. Assert.Equal (ustring.Empty, list [0]);
  2131. }
  2132. [Fact]
  2133. public void Reformat_NoWordrap_SingleLine ()
  2134. {
  2135. var text = ustring.Empty;
  2136. var list = new List<ustring> ();
  2137. var maxWidth = 0;
  2138. var expectedClippedWidth = 0;
  2139. var wrap = false;
  2140. maxWidth = 0;
  2141. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2142. Assert.True (list.Count == 1);
  2143. maxWidth = 1;
  2144. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2145. Assert.True (list.Count == 1);
  2146. text = "A sentence has words.";
  2147. maxWidth = 0;
  2148. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2149. Assert.True (list.Count == 1);
  2150. Assert.Equal (ustring.Empty, list [0]);
  2151. maxWidth = 1;
  2152. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2153. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2154. Assert.True (list.Count == 1);
  2155. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2156. maxWidth = 5;
  2157. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2158. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2159. Assert.True (list.Count == 1);
  2160. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2161. maxWidth = text.RuneCount - 1;
  2162. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2163. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2164. Assert.True (list.Count == 1);
  2165. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2166. // no clip
  2167. maxWidth = text.RuneCount + 0;
  2168. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2169. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2170. Assert.True (list.Count == 1);
  2171. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2172. maxWidth = text.RuneCount + 1;
  2173. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2174. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2175. Assert.True (list.Count == 1);
  2176. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2177. }
  2178. [Fact]
  2179. public void Reformat_NoWordrap_NewLines ()
  2180. {
  2181. var text = ustring.Empty;
  2182. var list = new List<ustring> ();
  2183. var maxWidth = 0;
  2184. var expectedClippedWidth = 0;
  2185. var wrap = false;
  2186. text = "A sentence has words.\nLine 2.";
  2187. maxWidth = 0;
  2188. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2189. Assert.True (list.Count == 1);
  2190. Assert.Equal (ustring.Empty, list [0]);
  2191. maxWidth = 1;
  2192. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2193. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2194. Assert.True (list.Count == 1);
  2195. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2196. maxWidth = 5;
  2197. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2198. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2199. Assert.True (list.Count == 1);
  2200. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2201. maxWidth = text.RuneCount - 1;
  2202. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2203. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2204. Assert.True (list.Count == 1);
  2205. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\n", " "), list [0]);
  2206. // no clip
  2207. maxWidth = text.RuneCount + 0;
  2208. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2209. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2210. Assert.True (list.Count == 1);
  2211. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\n", " "), list [0]);
  2212. maxWidth = text.RuneCount + 1;
  2213. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2214. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2215. Assert.True (list.Count == 1);
  2216. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\n", " "), list [0]);
  2217. text = "A sentence has words.\r\nLine 2.";
  2218. maxWidth = 0;
  2219. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2220. Assert.True (list.Count == 1);
  2221. Assert.Equal (ustring.Empty, list [0]);
  2222. maxWidth = 1;
  2223. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2224. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2225. Assert.True (list.Count == 1);
  2226. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2227. maxWidth = 5;
  2228. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2229. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2230. Assert.True (list.Count == 1);
  2231. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2232. maxWidth = text.RuneCount - 1;
  2233. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth) + 1;
  2234. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2235. Assert.True (list.Count == 1);
  2236. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\r\n", " ").ToString (), list [0].ToString ());
  2237. // no clip
  2238. maxWidth = text.RuneCount + 0;
  2239. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2240. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2241. Assert.True (list.Count == 1);
  2242. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\r\n", " "), list [0]);
  2243. maxWidth = text.RuneCount + 1;
  2244. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2245. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2246. Assert.True (list.Count == 1);
  2247. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]).Replace ("\r\n", " "), list [0]);
  2248. }
  2249. [Fact]
  2250. public void Reformat_Wrap_Spaces_No_NewLines ()
  2251. {
  2252. var text = ustring.Empty;
  2253. var list = new List<ustring> ();
  2254. var maxWidth = 0;
  2255. var expectedClippedWidth = 0;
  2256. var wrap = true;
  2257. var preserveTrailingSpaces = true;
  2258. // Even # of spaces
  2259. // 0123456789
  2260. text = "012 456 89";
  2261. // See WordWrap BUGBUGs above.
  2262. maxWidth = 0;
  2263. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2264. Assert.True (list.Count == 1);
  2265. Assert.Equal (ustring.Empty, list [0]);
  2266. maxWidth = 1;
  2267. // remove 3 whitespace chars
  2268. expectedClippedWidth = text.RuneCount - text.Sum (r => r == ' ' ? 1 : 0);
  2269. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2270. Assert.Equal (expectedClippedWidth, list.Count);
  2271. Assert.Equal ("01245689", ustring.Join ("", list.ToArray ()));
  2272. maxWidth = 1;
  2273. // keep 3 whitespace chars
  2274. expectedClippedWidth = text.RuneCount;
  2275. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap, preserveTrailingSpaces);
  2276. Assert.Equal (expectedClippedWidth, list.Count);
  2277. Assert.Equal (text, ustring.Join ("", list.ToArray ()));
  2278. maxWidth = 5;
  2279. // remove 3 whitespace chars
  2280. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth - text.Sum (r => r == ' ' ? 1 : 0));
  2281. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2282. Assert.Equal (expectedClippedWidth, list.Count);
  2283. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2284. Assert.Equal ("01245689", ustring.Join ("", list.ToArray ()));
  2285. maxWidth = 5;
  2286. // keep 3 whitespace chars
  2287. expectedClippedWidth = Math.Min (text.RuneCount, (int)Math.Ceiling ((double)(text.RuneCount / 3F)));
  2288. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap, preserveTrailingSpaces);
  2289. Assert.Equal (expectedClippedWidth - (maxWidth - expectedClippedWidth), list.Count);
  2290. Assert.Equal (ustring.Make (text.ToRunes () [0..expectedClippedWidth]), list [0]);
  2291. Assert.Equal ("012 456 89", ustring.Join ("", list.ToArray ()));
  2292. maxWidth = text.RuneCount - 1;
  2293. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2294. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2295. Assert.True (list.Count == 2);
  2296. Assert.Equal ("012 456", list [0]);
  2297. Assert.Equal ("89", list [1]);
  2298. // no clip
  2299. maxWidth = text.RuneCount + 0;
  2300. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2301. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2302. Assert.True (list.Count == 1);
  2303. Assert.Equal ("012 456 89", list [0]);
  2304. maxWidth = text.RuneCount + 1;
  2305. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2306. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2307. Assert.True (list.Count == 1);
  2308. Assert.Equal ("012 456 89", list [0]);
  2309. // Odd # of spaces
  2310. // 0123456789
  2311. text = "012 456 89 end";
  2312. maxWidth = text.RuneCount - 1;
  2313. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2314. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2315. Assert.True (list.Count == 2);
  2316. Assert.Equal ("012 456 89", list [0]);
  2317. Assert.Equal ("end", list [1]);
  2318. // no clip
  2319. maxWidth = text.RuneCount + 0;
  2320. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2321. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2322. Assert.True (list.Count == 1);
  2323. Assert.Equal ("012 456 89 end", list [0]);
  2324. maxWidth = text.RuneCount + 1;
  2325. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2326. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2327. Assert.True (list.Count == 1);
  2328. Assert.Equal ("012 456 89 end", list [0]);
  2329. }
  2330. [Fact]
  2331. public void Reformat_Unicode_Wrap_Spaces_No_NewLines ()
  2332. {
  2333. var text = ustring.Empty;
  2334. var list = new List<ustring> ();
  2335. var maxWidth = 0;
  2336. var expectedClippedWidth = 0;
  2337. var wrap = true;
  2338. // Unicode
  2339. // Even # of chars
  2340. // 0123456789
  2341. text = "\u2660пÑРвРÑ";
  2342. maxWidth = text.RuneCount - 1;
  2343. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2344. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2345. Assert.True (list.Count == 2);
  2346. Assert.Equal ("\u2660пÑРвÐ", list [0]);
  2347. Assert.Equal ("Ñ", list [1]);
  2348. // no clip
  2349. maxWidth = text.RuneCount + 0;
  2350. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2351. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2352. Assert.True (list.Count == 1);
  2353. Assert.Equal ("\u2660пÑРвРÑ", list [0]);
  2354. maxWidth = text.RuneCount + 1;
  2355. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2356. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2357. Assert.True (list.Count == 1);
  2358. Assert.Equal ("\u2660пÑРвРÑ", list [0]);
  2359. // Unicode
  2360. // Odd # of chars
  2361. // 0123456789
  2362. text = "\u2660 ÑРвРÑ";
  2363. maxWidth = text.RuneCount - 1;
  2364. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2365. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2366. Assert.True (list.Count == 2);
  2367. Assert.Equal ("\u2660 ÑРвÐ", list [0]);
  2368. Assert.Equal ("Ñ", list [1]);
  2369. // no clip
  2370. maxWidth = text.RuneCount + 0;
  2371. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2372. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2373. Assert.True (list.Count == 1);
  2374. Assert.Equal ("\u2660 ÑРвРÑ", list [0]);
  2375. maxWidth = text.RuneCount + 1;
  2376. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2377. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2378. Assert.True (list.Count == 1);
  2379. Assert.Equal ("\u2660 ÑРвРÑ", list [0]);
  2380. }
  2381. [Fact]
  2382. public void Reformat_Unicode_Wrap_Spaces_NewLines ()
  2383. {
  2384. var text = ustring.Empty;
  2385. var list = new List<ustring> ();
  2386. var maxWidth = 0;
  2387. var expectedClippedWidth = 0;
  2388. var wrap = true;
  2389. // Unicode
  2390. text = "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464";
  2391. maxWidth = text.RuneCount - 1;
  2392. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2393. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2394. Assert.Equal (2, list.Count);
  2395. Assert.Equal ("\u2460\u2461\u2462", list [0]);
  2396. Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
  2397. // no clip
  2398. maxWidth = text.RuneCount + 0;
  2399. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2400. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2401. Assert.Equal (2, list.Count);
  2402. Assert.Equal ("\u2460\u2461\u2462", list [0]);
  2403. Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
  2404. maxWidth = text.RuneCount + 1;
  2405. expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
  2406. list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
  2407. Assert.Equal (2, list.Count);
  2408. Assert.Equal ("\u2460\u2461\u2462", list [0]);
  2409. Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
  2410. }
  2411. [Fact]
  2412. public void System_Rune_ColumnWidth ()
  2413. {
  2414. var c = new Rune ('a');
  2415. Assert.Equal (1, Rune.ColumnWidth (c));
  2416. Assert.Equal (1, ustring.Make (c).ConsoleWidth);
  2417. Assert.Equal (1, ustring.Make (c).Length);
  2418. c = new Rune ('b');
  2419. Assert.Equal (1, Rune.ColumnWidth (c));
  2420. Assert.Equal (1, ustring.Make (c).ConsoleWidth);
  2421. Assert.Equal (1, ustring.Make (c).Length);
  2422. c = new Rune (123);
  2423. Assert.Equal (1, Rune.ColumnWidth (c));
  2424. Assert.Equal (1, ustring.Make (c).ConsoleWidth);
  2425. Assert.Equal (1, ustring.Make (c).Length);
  2426. c = new Rune ('\u1150');
  2427. Assert.Equal (2, Rune.ColumnWidth (c)); // 0x1150 ᅐ Unicode Technical Report #11
  2428. Assert.Equal (2, ustring.Make (c).ConsoleWidth);
  2429. Assert.Equal (3, ustring.Make (c).Length);
  2430. c = new Rune ('\u1161');
  2431. Assert.Equal (0, Rune.ColumnWidth (c)); // 0x1161 ᅡ column width of 0
  2432. Assert.Equal (0, ustring.Make (c).ConsoleWidth);
  2433. Assert.Equal (3, ustring.Make (c).Length);
  2434. c = new Rune (31);
  2435. Assert.Equal (-1, Rune.ColumnWidth (c)); // non printable character
  2436. Assert.Equal (0, ustring.Make (c).ConsoleWidth);// ConsoleWidth only returns zero or greater than zero
  2437. Assert.Equal (1, ustring.Make (c).Length);
  2438. c = new Rune (127);
  2439. Assert.Equal (-1, Rune.ColumnWidth (c)); // non printable character
  2440. Assert.Equal (0, ustring.Make (c).ConsoleWidth);
  2441. Assert.Equal (1, ustring.Make (c).Length);
  2442. }
  2443. [Fact]
  2444. public void System_Text_Rune ()
  2445. {
  2446. var c = new System.Text.Rune ('a');
  2447. Assert.Equal (1, c.Utf8SequenceLength);
  2448. c = new System.Text.Rune ('b');
  2449. Assert.Equal (1, c.Utf8SequenceLength);
  2450. c = new System.Text.Rune (123);
  2451. Assert.Equal (1, c.Utf8SequenceLength);
  2452. c = new System.Text.Rune ('\u1150');
  2453. Assert.Equal (3, c.Utf8SequenceLength); // 0x1150 ᅐ Unicode Technical Report #11
  2454. c = new System.Text.Rune ('\u1161');
  2455. Assert.Equal (3, c.Utf8SequenceLength); // 0x1161 ᅡ column width of 0
  2456. c = new System.Text.Rune (31);
  2457. Assert.Equal (1, c.Utf8SequenceLength); // non printable character
  2458. c = new System.Text.Rune (127);
  2459. Assert.Equal (1, c.Utf8SequenceLength); // non printable character
  2460. }
  2461. [Fact]
  2462. public void Format_WordWrap_preserveTrailingSpaces ()
  2463. {
  2464. ustring text = " A sentence has words. \n This is the second Line - 2. ";
  2465. // With preserveTrailingSpaces = false by default.
  2466. var list1 = TextFormatter.Format (text, 4, TextAlignment.Left, true);
  2467. ustring wrappedText1 = ustring.Empty;
  2468. Assert.Equal (" A", list1 [0].ToString ());
  2469. Assert.Equal ("sent", list1 [1].ToString ());
  2470. Assert.Equal ("ence", list1 [2].ToString ());
  2471. Assert.Equal ("has", list1 [3].ToString ());
  2472. Assert.Equal ("word", list1 [4].ToString ());
  2473. Assert.Equal ("s. ", list1 [5].ToString ());
  2474. Assert.Equal (" Thi", list1 [6].ToString ());
  2475. Assert.Equal ("s is", list1 [7].ToString ());
  2476. Assert.Equal ("the", list1 [8].ToString ());
  2477. Assert.Equal ("seco", list1 [9].ToString ());
  2478. Assert.Equal ("nd", list1 [10].ToString ());
  2479. Assert.Equal ("Line", list1 [11].ToString ());
  2480. Assert.Equal ("- 2.", list1 [^1].ToString ());
  2481. foreach (var txt in list1) wrappedText1 += txt;
  2482. Assert.Equal (" Asentencehaswords. This isthesecondLine- 2.", wrappedText1);
  2483. // With preserveTrailingSpaces = true.
  2484. var list2 = TextFormatter.Format (text, 4, TextAlignment.Left, true, true);
  2485. ustring wrappedText2 = ustring.Empty;
  2486. Assert.Equal (" A ", list2 [0].ToString ());
  2487. Assert.Equal ("sent", list2 [1].ToString ());
  2488. Assert.Equal ("ence", list2 [2].ToString ());
  2489. Assert.Equal (" ", list2 [3].ToString ());
  2490. Assert.Equal ("has ", list2 [4].ToString ());
  2491. Assert.Equal ("word", list2 [5].ToString ());
  2492. Assert.Equal ("s. ", list2 [6].ToString ());
  2493. Assert.Equal (" ", list2 [7].ToString ());
  2494. Assert.Equal ("This", list2 [8].ToString ());
  2495. Assert.Equal (" is ", list2 [9].ToString ());
  2496. Assert.Equal ("the ", list2 [10].ToString ());
  2497. Assert.Equal ("seco", list2 [11].ToString ());
  2498. Assert.Equal ("nd ", list2 [12].ToString ());
  2499. Assert.Equal ("Line", list2 [13].ToString ());
  2500. Assert.Equal (" - ", list2 [14].ToString ());
  2501. Assert.Equal ("2. ", list2 [^1].ToString ());
  2502. foreach (var txt in list2) wrappedText2 += txt;
  2503. Assert.Equal (" A sentence has words. This is the second Line - 2. ", wrappedText2);
  2504. }
  2505. [Fact]
  2506. public void Format_Dont_Throw_ArgumentException_With_WordWrap_As_False_And_Keep_End_Spaces_As_True ()
  2507. {
  2508. var exception = Record.Exception (() => TextFormatter.Format ("Some text", 4, TextAlignment.Left, false, true));
  2509. Assert.Null (exception);
  2510. }
  2511. [Fact, AutoInitShutdown]
  2512. public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Horizontal ()
  2513. {
  2514. ustring text = "Hello world, how are you today? Pretty neat!";
  2515. Assert.Equal (44, text.RuneCount);
  2516. for (int i = 44; i < 80; i++) {
  2517. var fmtText = TextFormatter.Format (text, i, TextAlignment.Justified, false, true) [0];
  2518. Assert.Equal (i, fmtText.RuneCount);
  2519. var c = (char)fmtText [^1];
  2520. Assert.Equal ('!', c);
  2521. }
  2522. }
  2523. [Fact, AutoInitShutdown]
  2524. public void Format_Justified_Always_Returns_Text_Width_Equal_To_Passed_Width_Vertical ()
  2525. {
  2526. ustring text = "Hello world, how are you today? Pretty neat!";
  2527. Assert.Equal (44, text.RuneCount);
  2528. for (int i = 44; i < 80; i++) {
  2529. var fmtText = TextFormatter.Format (text, i, TextAlignment.Justified, false, true, 0, TextDirection.TopBottom_LeftRight) [0];
  2530. Assert.Equal (i, fmtText.RuneCount);
  2531. var c = (char)fmtText [^1];
  2532. Assert.Equal ('!', c);
  2533. }
  2534. }
  2535. [Fact]
  2536. public void Draw_Horizontal_Throws_IndexOutOfRangeException_With_Negative_Bounds ()
  2537. {
  2538. Application.Init (new FakeDriver ());
  2539. var top = Application.Top;
  2540. var view = new View ("view") { X = -2 };
  2541. top.Add (view);
  2542. Application.Iteration += () => {
  2543. Assert.Equal (-2, view.X);
  2544. Application.RequestStop ();
  2545. };
  2546. try {
  2547. Application.Run ();
  2548. } catch (IndexOutOfRangeException ex) {
  2549. // After the fix this exception will not be caught.
  2550. Assert.IsType<IndexOutOfRangeException> (ex);
  2551. }
  2552. // Shutdown must be called to safely clean up Application if Init has been called
  2553. Application.Shutdown ();
  2554. }
  2555. [Fact]
  2556. public void TestClipOrPad_ShortWord ()
  2557. {
  2558. // word is short but we want it to fill 6 so it should be padded
  2559. Assert.Equal ("fff ", TextFormatter.ClipOrPad ("fff", 6));
  2560. }
  2561. [Fact]
  2562. public void TestClipOrPad_LongWord ()
  2563. {
  2564. // word is long but we want it to fill 3 space only
  2565. Assert.Equal ("123", TextFormatter.ClipOrPad ("123456789", 3));
  2566. }
  2567. [Fact]
  2568. public void Draw_Vertical_Throws_IndexOutOfRangeException_With_Negative_Bounds ()
  2569. {
  2570. Application.Init (new FakeDriver ());
  2571. var top = Application.Top;
  2572. var view = new View ("view") {
  2573. Y = -2,
  2574. Height = 10,
  2575. TextDirection = TextDirection.TopBottom_LeftRight
  2576. };
  2577. top.Add (view);
  2578. Application.Iteration += () => {
  2579. Assert.Equal (-2, view.Y);
  2580. Application.RequestStop ();
  2581. };
  2582. try {
  2583. Application.Run ();
  2584. } catch (IndexOutOfRangeException ex) {
  2585. // After the fix this exception will not be caught.
  2586. Assert.IsType<IndexOutOfRangeException> (ex);
  2587. }
  2588. // Shutdown must be called to safely clean up Application if Init has been called
  2589. Application.Shutdown ();
  2590. }
  2591. [Fact]
  2592. public void Internal_Tests ()
  2593. {
  2594. var tf = new TextFormatter ();
  2595. Assert.Equal (Key.Null, tf.HotKey);
  2596. tf.HotKey = Key.CtrlMask | Key.Q;
  2597. Assert.Equal (Key.CtrlMask | Key.Q, tf.HotKey);
  2598. }
  2599. [Fact, AutoInitShutdown]
  2600. public void Draw_Horizontal_Simple_Runes ()
  2601. {
  2602. var label = new Label ("Demo Simple Rune");
  2603. Application.Top.Add (label);
  2604. Application.Begin (Application.Top);
  2605. Assert.True (label.AutoSize);
  2606. Assert.Equal (new Rect (0, 0, 16, 1), label.Frame);
  2607. var expected = @"
  2608. Demo Simple Rune
  2609. ";
  2610. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2611. Assert.Equal (new Rect (0, 0, 16, 1), pos);
  2612. }
  2613. [Fact, AutoInitShutdown]
  2614. public void Draw_Vertical_Simple_Runes ()
  2615. {
  2616. var label = new Label ("Demo Simple Rune") {
  2617. TextDirection = TextDirection.TopBottom_LeftRight
  2618. };
  2619. Application.Top.Add (label);
  2620. Application.Begin (Application.Top);
  2621. Assert.True (label.AutoSize);
  2622. Assert.Equal (new Rect (0, 0, 1, 16), label.Frame);
  2623. Assert.NotNull (label.Width);
  2624. Assert.NotNull (label.Height);
  2625. var expected = @"
  2626. D
  2627. e
  2628. m
  2629. o
  2630. S
  2631. i
  2632. m
  2633. p
  2634. l
  2635. e
  2636. R
  2637. u
  2638. n
  2639. e
  2640. ";
  2641. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2642. Assert.Equal (new Rect (0, 0, 1, 16), pos);
  2643. }
  2644. [Fact, AutoInitShutdown]
  2645. public void Draw_Horizontal_Wide_Runes ()
  2646. {
  2647. var label = new Label ("デモエムポンズ");
  2648. Application.Top.Add (label);
  2649. Application.Begin (Application.Top);
  2650. Assert.True (label.AutoSize);
  2651. Assert.Equal (new Rect (0, 0, 14, 1), label.Frame);
  2652. var expected = @"
  2653. デモエムポンズ
  2654. ";
  2655. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2656. Assert.Equal (new Rect (0, 0, 14, 1), pos);
  2657. }
  2658. [Fact, AutoInitShutdown]
  2659. public void Draw_Vertical_Wide_Runes ()
  2660. {
  2661. var label = new Label ("デモエムポンズ") {
  2662. TextDirection = TextDirection.TopBottom_LeftRight
  2663. };
  2664. Application.Top.Add (label);
  2665. Application.Begin (Application.Top);
  2666. Assert.True (label.AutoSize);
  2667. Assert.Equal (new Rect (0, 0, 2, 7), label.Frame);
  2668. var expected = @"
  2669. ";
  2670. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2671. Assert.Equal (new Rect (0, 0, 2, 7), pos);
  2672. }
  2673. [Fact, AutoInitShutdown]
  2674. public void Draw_Vertical_Wide_Runes_With_ForceValidatePosDim ()
  2675. {
  2676. var label = new Label ("デモエムポンズ") {
  2677. Width = Dim.Fill (),
  2678. Height = Dim.Percent (50f),
  2679. TextDirection = TextDirection.TopBottom_LeftRight,
  2680. ForceValidatePosDim = true
  2681. };
  2682. Application.Top.Add (label);
  2683. Application.Begin (Application.Top);
  2684. Assert.True (label.AutoSize);
  2685. Assert.Equal (new Rect (0, 0, 80, 12), label.Frame);
  2686. var expected = @"
  2687. ";
  2688. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2689. Assert.Equal (new Rect (0, 0, 2, 7), pos);
  2690. }
  2691. [Fact, AutoInitShutdown]
  2692. public void Draw_Horizontal_Simple_TextAlignments ()
  2693. {
  2694. var text = "Hello World";
  2695. var width = 20;
  2696. var lblLeft = new Label (text) { Width = width };
  2697. var lblCenter = new Label (text) { Y = 1, Width = width, TextAlignment = TextAlignment.Centered };
  2698. var lblRight = new Label (text) { Y = 2, Width = width, TextAlignment = TextAlignment.Right };
  2699. var lblJust = new Label (text) { Y = 3, Width = width, TextAlignment = TextAlignment.Justified };
  2700. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  2701. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  2702. Application.Top.Add (frame);
  2703. Application.Begin (Application.Top);
  2704. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6);
  2705. Assert.True (lblLeft.AutoSize);
  2706. Assert.True (lblCenter.AutoSize);
  2707. Assert.True (lblRight.AutoSize);
  2708. Assert.True (lblJust.AutoSize);
  2709. Assert.Equal (new Rect (0, 0, width, 1), lblLeft.Frame);
  2710. Assert.Equal (new Rect (0, 1, width, 1), lblCenter.Frame);
  2711. Assert.Equal (new Rect (0, 2, width, 1), lblRight.Frame);
  2712. Assert.Equal (new Rect (0, 3, width, 1), lblJust.Frame);
  2713. Assert.Equal (new Rect (0, 0, width + 2, 6), frame.Frame);
  2714. var expected = @"
  2715. ┌────────────────────┐
  2716. │Hello World │
  2717. │ Hello World │
  2718. │ Hello World│
  2719. │Hello World│
  2720. └────────────────────┘
  2721. ";
  2722. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2723. Assert.Equal (new Rect (0, 0, width + 2, 6), pos);
  2724. }
  2725. [Fact, AutoInitShutdown]
  2726. public void Draw_Vertical_Simple_TextAlignments ()
  2727. {
  2728. var text = "Hello World";
  2729. var height = 20;
  2730. var lblLeft = new Label (text, direction: TextDirection.TopBottom_LeftRight) { Height = height };
  2731. var lblCenter = new Label (text, direction: TextDirection.TopBottom_LeftRight) { X = 2, Height = height, VerticalTextAlignment = VerticalTextAlignment.Middle };
  2732. var lblRight = new Label (text, direction: TextDirection.TopBottom_LeftRight) { X = 4, Height = height, VerticalTextAlignment = VerticalTextAlignment.Bottom };
  2733. var lblJust = new Label (text, direction: TextDirection.TopBottom_LeftRight) { X = 6, Height = height, VerticalTextAlignment = VerticalTextAlignment.Justified };
  2734. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  2735. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  2736. Application.Top.Add (frame);
  2737. Application.Begin (Application.Top);
  2738. ((FakeDriver)Application.Driver).SetBufferSize (9, height + 2);
  2739. Assert.True (lblLeft.AutoSize);
  2740. Assert.True (lblCenter.AutoSize);
  2741. Assert.True (lblRight.AutoSize);
  2742. Assert.True (lblJust.AutoSize);
  2743. Assert.Equal (new Rect (0, 0, 1, height), lblLeft.Frame);
  2744. Assert.Equal (new Rect (2, 0, 1, height), lblCenter.Frame);
  2745. Assert.Equal (new Rect (4, 0, 1, height), lblRight.Frame);
  2746. Assert.Equal (new Rect (6, 0, 1, height), lblJust.Frame);
  2747. Assert.Equal (new Rect (0, 0, 9, height + 2), frame.Frame);
  2748. var expected = @"
  2749. ┌───────┐
  2750. │H H│
  2751. │e e│
  2752. │l l│
  2753. │l l│
  2754. │o H o│
  2755. │ e │
  2756. │W l │
  2757. │o l │
  2758. │r o │
  2759. │l H │
  2760. │d W e │
  2761. │ o l │
  2762. │ r l │
  2763. │ l o │
  2764. │ d │
  2765. │ W W│
  2766. │ o o│
  2767. │ r r│
  2768. │ l l│
  2769. │ d d│
  2770. └───────┘
  2771. ";
  2772. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2773. Assert.Equal (new Rect (0, 0, 9, height + 2), pos);
  2774. }
  2775. [Fact, AutoInitShutdown]
  2776. public void Draw_Horizontal_Wide_TextAlignments ()
  2777. {
  2778. var text = "こんにちは 世界";
  2779. var width = 25;
  2780. var lblLeft = new Label (text) { Width = width };
  2781. var lblCenter = new Label (text) { Y = 1, Width = width, TextAlignment = TextAlignment.Centered };
  2782. var lblRight = new Label (text) { Y = 2, Width = width, TextAlignment = TextAlignment.Right };
  2783. var lblJust = new Label (text) { Y = 3, Width = width, TextAlignment = TextAlignment.Justified };
  2784. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  2785. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  2786. Application.Top.Add (frame);
  2787. Application.Begin (Application.Top);
  2788. ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6);
  2789. Assert.True (lblLeft.AutoSize);
  2790. Assert.True (lblCenter.AutoSize);
  2791. Assert.True (lblRight.AutoSize);
  2792. Assert.True (lblJust.AutoSize);
  2793. Assert.Equal (new Rect (0, 0, width, 1), lblLeft.Frame);
  2794. Assert.Equal (new Rect (0, 1, width, 1), lblCenter.Frame);
  2795. Assert.Equal (new Rect (0, 2, width, 1), lblRight.Frame);
  2796. Assert.Equal (new Rect (0, 3, width, 1), lblJust.Frame);
  2797. Assert.Equal (new Rect (0, 0, width + 2, 6), frame.Frame);
  2798. var expected = @"
  2799. ┌─────────────────────────┐
  2800. │こんにちは 世界 │
  2801. │ こんにちは 世界 │
  2802. │ こんにちは 世界│
  2803. │こんにちは 世界│
  2804. └─────────────────────────┘
  2805. ";
  2806. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2807. Assert.Equal (new Rect (0, 0, width + 2, 6), pos);
  2808. }
  2809. [Fact, AutoInitShutdown]
  2810. public void Draw_Vertical_Wide_TextAlignments ()
  2811. {
  2812. var text = "こんにちは 世界";
  2813. var height = 23;
  2814. var lblLeft = new Label (text) { Width = 2, Height = height, TextDirection = TextDirection.TopBottom_LeftRight };
  2815. var lblCenter = new Label (text) { X = 3, Width = 2, Height = height, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Middle };
  2816. var lblRight = new Label (text) { X = 6, Width = 2, Height = height, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
  2817. var lblJust = new Label (text) { X = 9, Width = 2, Height = height, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Justified };
  2818. var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () };
  2819. frame.Add (lblLeft, lblCenter, lblRight, lblJust);
  2820. Application.Top.Add (frame);
  2821. Application.Begin (Application.Top);
  2822. ((FakeDriver)Application.Driver).SetBufferSize (13, height + 2);
  2823. // All AutoSize are false because the Frame.Height != TextFormatter.Size.Height
  2824. Assert.True (lblLeft.AutoSize);
  2825. Assert.True (lblCenter.AutoSize);
  2826. Assert.True (lblRight.AutoSize);
  2827. Assert.True (lblJust.AutoSize);
  2828. Assert.Equal (new Rect (0, 0, 2, height), lblLeft.Frame);
  2829. Assert.Equal (new Rect (3, 0, 2, height), lblCenter.Frame);
  2830. Assert.Equal (new Rect (6, 0, 2, height), lblRight.Frame);
  2831. Assert.Equal (new Rect (9, 0, 2, height), lblJust.Frame);
  2832. Assert.Equal (new Rect (0, 0, 13, height + 2), frame.Frame);
  2833. var expected = @"
  2834. ┌───────────┐
  2835. │こ こ│
  2836. │ん ん│
  2837. │に に│
  2838. │ち ち│
  2839. │は は│
  2840. │ │
  2841. │世 │
  2842. │界 こ │
  2843. │ ん │
  2844. │ に │
  2845. │ ち │
  2846. │ は │
  2847. │ │
  2848. │ 世 │
  2849. │ 界 │
  2850. │ こ │
  2851. │ ん │
  2852. │ に │
  2853. │ ち │
  2854. │ は │
  2855. │ │
  2856. │ 世 世│
  2857. │ 界 界│
  2858. └───────────┘
  2859. ";
  2860. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2861. Assert.Equal (new Rect (0, 0, 13, height + 2), pos);
  2862. }
  2863. [Fact, AutoInitShutdown]
  2864. public void Draw_Fill_Remaining ()
  2865. {
  2866. var view = new View ("This view needs to be cleared before rewritten.");
  2867. var tf1 = new TextFormatter ();
  2868. tf1.Text = "This TextFormatter (tf1) without fill will not be cleared on rewritten.";
  2869. var tf1Size = tf1.Size;
  2870. var tf2 = new TextFormatter ();
  2871. tf2.Text = "This TextFormatter (tf2) with fill will be cleared on rewritten.";
  2872. var tf2Size = tf2.Size;
  2873. Application.Top.Add (view);
  2874. Application.Begin (Application.Top);
  2875. tf1.Draw (new Rect (new Point (0, 1), tf1Size), view.GetNormalColor (), view.ColorScheme.HotNormal, default, false);
  2876. tf2.Draw (new Rect (new Point (0, 2), tf2Size), view.GetNormalColor (), view.ColorScheme.HotNormal);
  2877. TestHelpers.AssertDriverContentsWithFrameAre (@"
  2878. This view needs to be cleared before rewritten.
  2879. This TextFormatter (tf1) without fill will not be cleared on rewritten.
  2880. This TextFormatter (tf2) with fill will be cleared on rewritten.
  2881. ", output);
  2882. view.Text = "This view is rewritten.";
  2883. view.Redraw (view.Bounds);
  2884. tf1.Text = "This TextFormatter (tf1) is rewritten.";
  2885. tf1.Draw (new Rect (new Point (0, 1), tf1Size), view.GetNormalColor (), view.ColorScheme.HotNormal, default, false);
  2886. tf2.Text = "This TextFormatter (tf2) is rewritten.";
  2887. tf2.Draw (new Rect (new Point (0, 2), tf2Size), view.GetNormalColor (), view.ColorScheme.HotNormal);
  2888. TestHelpers.AssertDriverContentsWithFrameAre (@"
  2889. This view is rewritten.
  2890. This TextFormatter (tf1) is rewritten.will not be cleared on rewritten.
  2891. This TextFormatter (tf2) is rewritten.
  2892. ", output);
  2893. }
  2894. [Fact]
  2895. public void GetTextWidth_Simple_And_Wide_Runes ()
  2896. {
  2897. ustring text = "Hello World";
  2898. Assert.Equal (11, TextFormatter.GetTextWidth (text));
  2899. text = "こんにちは世界";
  2900. Assert.Equal (14, TextFormatter.GetTextWidth (text));
  2901. }
  2902. [Fact]
  2903. public void GetSumMaxCharWidth_Simple_And_Wide_Runes ()
  2904. {
  2905. ustring text = "Hello World";
  2906. Assert.Equal (11, TextFormatter.GetSumMaxCharWidth (text));
  2907. Assert.Equal (1, TextFormatter.GetSumMaxCharWidth (text, 6, 1));
  2908. text = "こんにちは 世界";
  2909. Assert.Equal (15, TextFormatter.GetSumMaxCharWidth (text));
  2910. Assert.Equal (2, TextFormatter.GetSumMaxCharWidth (text, 6, 1));
  2911. }
  2912. [Fact]
  2913. public void GetSumMaxCharWidth_List_Simple_And_Wide_Runes ()
  2914. {
  2915. var text = new List<ustring> () { "Hello", "World" };
  2916. Assert.Equal (2, TextFormatter.GetSumMaxCharWidth (text));
  2917. Assert.Equal (1, TextFormatter.GetSumMaxCharWidth (text, 1, 1));
  2918. text = new List<ustring> () { "こんにちは", "世界" };
  2919. Assert.Equal (4, TextFormatter.GetSumMaxCharWidth (text));
  2920. Assert.Equal (2, TextFormatter.GetSumMaxCharWidth (text, 1, 1));
  2921. }
  2922. [Fact]
  2923. public void GetMaxLengthForWidth_Simple_And_Wide_Runes ()
  2924. {
  2925. ustring text = "Hello World";
  2926. Assert.Equal (6, TextFormatter.GetMaxLengthForWidth (text, 6));
  2927. text = "こんにちは 世界";
  2928. Assert.Equal (3, TextFormatter.GetMaxLengthForWidth (text, 6));
  2929. }
  2930. [Fact]
  2931. public void GetMaxLengthForWidth_List_Simple_And_Wide_Runes ()
  2932. {
  2933. var runes = ustring.Make ("Hello World").ToRuneList ();
  2934. Assert.Equal (6, TextFormatter.GetMaxLengthForWidth (runes, 6));
  2935. runes = ustring.Make ("こんにちは 世界").ToRuneList ();
  2936. Assert.Equal (3, TextFormatter.GetMaxLengthForWidth (runes, 6));
  2937. runes = ustring.Make ("[ Say Hello 你 ]").ToRuneList ();
  2938. Assert.Equal (15, TextFormatter.GetMaxLengthForWidth (runes, 16));
  2939. }
  2940. [Fact]
  2941. public void Format_Truncate_Simple_And_Wide_Runes ()
  2942. {
  2943. var text = "Truncate";
  2944. var list = TextFormatter.Format (text, 3, false, false);
  2945. Assert.Equal ("Tru", list [^1].ToString ());
  2946. text = "デモエムポンズ";
  2947. list = TextFormatter.Format (text, 3, false, false);
  2948. Assert.Equal ("デ", list [^1].ToString ());
  2949. }
  2950. [Fact, AutoInitShutdown]
  2951. public void AutoSize_False_View_IsEmpty_False_Return_Null_Lines ()
  2952. {
  2953. var text = "Views";
  2954. var view = new View () {
  2955. Width = Dim.Fill () - text.Length,
  2956. Height = 1,
  2957. Text = text
  2958. };
  2959. var win = new Window ("Window") {
  2960. Width = Dim.Fill (),
  2961. Height = Dim.Fill ()
  2962. };
  2963. win.Add (view);
  2964. Application.Top.Add (win);
  2965. Application.Begin (Application.Top);
  2966. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  2967. Assert.Equal (5, text.Length);
  2968. Assert.False (view.AutoSize);
  2969. Assert.Equal (new Rect (0, 0, 3, 1), view.Frame);
  2970. Assert.Equal (new Size (3, 1), view.TextFormatter.Size);
  2971. Assert.Equal (new List<ustring> () { "Vie" }, view.TextFormatter.Lines);
  2972. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  2973. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  2974. var expected = @"
  2975. ┌ Wind ──┐
  2976. │Vie │
  2977. │ │
  2978. └────────┘
  2979. ";
  2980. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2981. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  2982. text = "0123456789";
  2983. Assert.Equal (10, text.Length);
  2984. view.Width = Dim.Fill () - text.Length;
  2985. Application.Refresh ();
  2986. Assert.Equal (new Rect (0, 0, 0, 1), view.Frame);
  2987. Assert.Equal (new Size (0, 1), view.TextFormatter.Size);
  2988. Assert.Equal (new List<ustring> () { ustring.Empty }, view.TextFormatter.Lines);
  2989. expected = @"
  2990. ┌ Wind ──┐
  2991. │ │
  2992. │ │
  2993. └────────┘
  2994. ";
  2995. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  2996. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  2997. }
  2998. [Fact, AutoInitShutdown]
  2999. public void AutoSize_False_View_IsEmpty_True_Minimum_Height ()
  3000. {
  3001. var text = "Views";
  3002. var view = new View () {
  3003. Width = Dim.Fill () - text.Length,
  3004. Text = text
  3005. };
  3006. var win = new Window ("Window") {
  3007. Width = Dim.Fill (),
  3008. Height = Dim.Fill ()
  3009. };
  3010. win.Add (view);
  3011. Application.Top.Add (win);
  3012. Application.Begin (Application.Top);
  3013. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3014. Assert.Equal (5, text.Length);
  3015. Assert.False (view.AutoSize);
  3016. Assert.Equal (new Rect (0, 0, 3, 1), view.Frame);
  3017. Assert.Equal (new Size (3, 1), view.TextFormatter.Size);
  3018. Assert.Single (view.TextFormatter.Lines);
  3019. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  3020. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  3021. var expected = @"
  3022. ┌ Wind ──┐
  3023. │Vie │
  3024. │ │
  3025. └────────┘
  3026. ";
  3027. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3028. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3029. text = "0123456789";
  3030. Assert.Equal (10, text.Length);
  3031. view.Width = Dim.Fill () - text.Length;
  3032. Application.Refresh ();
  3033. Assert.Equal (new Rect (0, 0, 0, 1), view.Frame);
  3034. Assert.Equal (new Size (0, 1), view.TextFormatter.Size);
  3035. var exception = Record.Exception (() => Assert.Equal (new List<ustring> () { ustring.Empty }, view.TextFormatter.Lines));
  3036. Assert.Null (exception);
  3037. expected = @"
  3038. ┌ Wind ──┐
  3039. │ │
  3040. │ │
  3041. └────────┘
  3042. ";
  3043. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3044. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3045. }
  3046. [Fact, AutoInitShutdown]
  3047. public void AutoSize_True_Label_IsEmpty_False_Never_Return_Null_Lines ()
  3048. {
  3049. var text = "Label";
  3050. var label = new Label () {
  3051. Width = Dim.Fill () - text.Length,
  3052. Height = 1,
  3053. Text = text
  3054. };
  3055. var win = new Window ("Window") {
  3056. Width = Dim.Fill (),
  3057. Height = Dim.Fill ()
  3058. };
  3059. win.Add (label);
  3060. Application.Top.Add (win);
  3061. Application.Begin (Application.Top);
  3062. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3063. Assert.Equal (5, text.Length);
  3064. Assert.True (label.AutoSize);
  3065. Assert.Equal (new Rect (0, 0, 5, 1), label.Frame);
  3066. Assert.Equal (new Size (5, 1), label.TextFormatter.Size);
  3067. Assert.Equal (new List<ustring> () { "Label" }, label.TextFormatter.Lines);
  3068. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  3069. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  3070. var expected = @"
  3071. ┌ Wind ──┐
  3072. │Label │
  3073. │ │
  3074. └────────┘
  3075. ";
  3076. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3077. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3078. text = "0123456789";
  3079. Assert.Equal (10, text.Length);
  3080. label.Width = Dim.Fill () - text.Length;
  3081. Application.Refresh ();
  3082. Assert.True (label.AutoSize);
  3083. Assert.Equal (new Rect (0, 0, 5, 1), label.Frame);
  3084. Assert.Equal (new Size (5, 1), label.TextFormatter.Size);
  3085. Assert.Single (label.TextFormatter.Lines);
  3086. expected = @"
  3087. ┌ Wind ──┐
  3088. │Label │
  3089. │ │
  3090. └────────┘
  3091. ";
  3092. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3093. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3094. }
  3095. [Fact, AutoInitShutdown]
  3096. public void AutoSize_False_Label_IsEmpty_True_Return_Null_Lines ()
  3097. {
  3098. var text = "Label";
  3099. var label = new Label () {
  3100. Width = Dim.Fill () - text.Length,
  3101. Height = 1,
  3102. Text = text,
  3103. AutoSize = false
  3104. };
  3105. var win = new Window ("Window") {
  3106. Width = Dim.Fill (),
  3107. Height = Dim.Fill ()
  3108. };
  3109. win.Add (label);
  3110. Application.Top.Add (win);
  3111. Application.Begin (Application.Top);
  3112. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3113. Assert.Equal (5, text.Length);
  3114. Assert.False (label.AutoSize);
  3115. Assert.Equal (new Rect (0, 0, 3, 1), label.Frame);
  3116. Assert.Equal (new Size (3, 1), label.TextFormatter.Size);
  3117. Assert.Equal (new List<ustring> () { "Lab" }, label.TextFormatter.Lines);
  3118. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  3119. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  3120. var expected = @"
  3121. ┌ Wind ──┐
  3122. │Lab │
  3123. │ │
  3124. └────────┘
  3125. ";
  3126. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3127. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3128. text = "0123456789";
  3129. Assert.Equal (10, text.Length);
  3130. label.Width = Dim.Fill () - text.Length;
  3131. Application.Refresh ();
  3132. Assert.False (label.AutoSize);
  3133. Assert.Equal (new Rect (0, 0, 0, 1), label.Frame);
  3134. Assert.Equal (new Size (0, 1), label.TextFormatter.Size);
  3135. Assert.Equal (new List<ustring> { ustring.Empty }, label.TextFormatter.Lines);
  3136. expected = @"
  3137. ┌ Wind ──┐
  3138. │ │
  3139. │ │
  3140. └────────┘
  3141. ";
  3142. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3143. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3144. }
  3145. [Fact, AutoInitShutdown]
  3146. public void AutoSize_True_Label_IsEmpty_False_Minimum_Height ()
  3147. {
  3148. var text = "Label";
  3149. var label = new Label () {
  3150. Width = Dim.Fill () - text.Length,
  3151. Text = text
  3152. };
  3153. var win = new Window ("Window") {
  3154. Width = Dim.Fill (),
  3155. Height = Dim.Fill ()
  3156. };
  3157. win.Add (label);
  3158. Application.Top.Add (win);
  3159. Application.Begin (Application.Top);
  3160. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3161. Assert.Equal (5, text.Length);
  3162. Assert.True (label.AutoSize);
  3163. Assert.Equal (new Rect (0, 0, 5, 1), label.Frame);
  3164. Assert.Equal (new Size (5, 1), label.TextFormatter.Size);
  3165. Assert.Equal (new List<ustring> () { "Label" }, label.TextFormatter.Lines);
  3166. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  3167. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  3168. var expected = @"
  3169. ┌ Wind ──┐
  3170. │Label │
  3171. │ │
  3172. └────────┘
  3173. ";
  3174. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3175. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3176. text = "0123456789";
  3177. Assert.Equal (10, text.Length);
  3178. label.Width = Dim.Fill () - text.Length;
  3179. Application.Refresh ();
  3180. Assert.Equal (new Rect (0, 0, 5, 1), label.Frame);
  3181. Assert.Equal (new Size (5, 1), label.TextFormatter.Size);
  3182. var exception = Record.Exception (() => Assert.Single (label.TextFormatter.Lines));
  3183. Assert.Null (exception);
  3184. expected = @"
  3185. ┌ Wind ──┐
  3186. │Label │
  3187. │ │
  3188. └────────┘
  3189. ";
  3190. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3191. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3192. }
  3193. [Fact, AutoInitShutdown]
  3194. public void AutoSize_False_Label_Height_Zero_Returns_Minimum_Height ()
  3195. {
  3196. var text = "Label";
  3197. var label = new Label () {
  3198. Width = Dim.Fill () - text.Length,
  3199. Text = text,
  3200. AutoSize = false
  3201. };
  3202. var win = new Window ("Window") {
  3203. Width = Dim.Fill (),
  3204. Height = Dim.Fill ()
  3205. };
  3206. win.Add (label);
  3207. Application.Top.Add (win);
  3208. Application.Begin (Application.Top);
  3209. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3210. Assert.Equal (5, text.Length);
  3211. Assert.False (label.AutoSize);
  3212. Assert.Equal (new Rect (0, 0, 3, 1), label.Frame);
  3213. Assert.Equal (new Size (3, 1), label.TextFormatter.Size);
  3214. Assert.Single (label.TextFormatter.Lines);
  3215. Assert.Equal (new Rect (0, 0, 10, 4), win.Frame);
  3216. Assert.Equal (new Rect (0, 0, 10, 4), Application.Top.Frame);
  3217. var expected = @"
  3218. ┌ Wind ──┐
  3219. │Lab │
  3220. │ │
  3221. └────────┘
  3222. ";
  3223. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3224. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3225. text = "0123456789";
  3226. Assert.Equal (10, text.Length);
  3227. label.Width = Dim.Fill () - text.Length;
  3228. Application.Refresh ();
  3229. Assert.Equal (new Rect (0, 0, 0, 1), label.Frame);
  3230. Assert.Equal (new Size (0, 1), label.TextFormatter.Size);
  3231. var exception = Record.Exception (() => Assert.Equal (new List<ustring> () { ustring.Empty }, label.TextFormatter.Lines));
  3232. Assert.Null (exception);
  3233. expected = @"
  3234. ┌ Wind ──┐
  3235. │ │
  3236. │ │
  3237. └────────┘
  3238. ";
  3239. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3240. Assert.Equal (new Rect (0, 0, 10, 4), pos);
  3241. }
  3242. [Fact, AutoInitShutdown]
  3243. public void AutoSize_True_View_IsEmpty_False_Minimum_Width ()
  3244. {
  3245. var text = "Views";
  3246. var view = new View () {
  3247. TextDirection = TextDirection.TopBottom_LeftRight,
  3248. Height = Dim.Fill () - text.Length,
  3249. Text = text,
  3250. AutoSize = true
  3251. };
  3252. var win = new Window ("Window") {
  3253. Width = Dim.Fill (),
  3254. Height = Dim.Fill ()
  3255. };
  3256. win.Add (view);
  3257. Application.Top.Add (win);
  3258. Application.Begin (Application.Top);
  3259. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  3260. Assert.Equal (5, text.Length);
  3261. Assert.True (view.AutoSize);
  3262. Assert.Equal (new Rect (0, 0, 1, 5), view.Frame);
  3263. Assert.Equal (new Size (1, 5), view.TextFormatter.Size);
  3264. Assert.Equal (new List<ustring> () { "Views" }, view.TextFormatter.Lines);
  3265. Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
  3266. Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
  3267. var expected = @"
  3268. ┌──┐
  3269. │V │
  3270. │i │
  3271. │e │
  3272. │w │
  3273. │s │
  3274. │ │
  3275. │ │
  3276. │ │
  3277. └──┘
  3278. ";
  3279. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3280. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3281. text = "0123456789";
  3282. Assert.Equal (10, text.Length);
  3283. view.Height = Dim.Fill () - text.Length;
  3284. Application.Refresh ();
  3285. Assert.Equal (new Rect (0, 0, 1, 5), view.Frame);
  3286. Assert.Equal (new Size (1, 5), view.TextFormatter.Size);
  3287. var exception = Record.Exception (() => Assert.Single (view.TextFormatter.Lines));
  3288. Assert.Null (exception);
  3289. expected = @"
  3290. ┌──┐
  3291. │V │
  3292. │i │
  3293. │e │
  3294. │w │
  3295. │s │
  3296. │ │
  3297. │ │
  3298. │ │
  3299. └──┘
  3300. ";
  3301. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3302. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3303. }
  3304. [Fact, AutoInitShutdown]
  3305. public void AutoSize_False_View_Width_Null_Returns_Host_Frame_Width ()
  3306. {
  3307. var text = "Views";
  3308. var view = new View () {
  3309. TextDirection = TextDirection.TopBottom_LeftRight,
  3310. Height = Dim.Fill () - text.Length,
  3311. Text = text
  3312. };
  3313. var win = new Window ("Window") {
  3314. Width = Dim.Fill (),
  3315. Height = Dim.Fill ()
  3316. };
  3317. win.Add (view);
  3318. Application.Top.Add (win);
  3319. Application.Begin (Application.Top);
  3320. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  3321. Assert.Equal (5, text.Length);
  3322. Assert.False (view.AutoSize);
  3323. Assert.Equal (new Rect (0, 0, 1, 3), view.Frame);
  3324. Assert.Equal (new Size (1, 3), view.TextFormatter.Size);
  3325. Assert.Single (view.TextFormatter.Lines);
  3326. Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
  3327. Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
  3328. var expected = @"
  3329. ┌──┐
  3330. │V │
  3331. │i │
  3332. │e │
  3333. │ │
  3334. │ │
  3335. │ │
  3336. │ │
  3337. │ │
  3338. └──┘
  3339. ";
  3340. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3341. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3342. text = "0123456789";
  3343. Assert.Equal (10, text.Length);
  3344. view.Height = Dim.Fill () - text.Length;
  3345. Application.Refresh ();
  3346. Assert.Equal (new Rect (0, 0, 1, 0), view.Frame);
  3347. Assert.Equal (new Size (1, 0), view.TextFormatter.Size);
  3348. var exception = Record.Exception (() => Assert.Equal (new List<ustring> () { ustring.Empty }, view.TextFormatter.Lines));
  3349. Assert.Null (exception);
  3350. expected = @"
  3351. ┌──┐
  3352. │ │
  3353. │ │
  3354. │ │
  3355. │ │
  3356. │ │
  3357. │ │
  3358. │ │
  3359. │ │
  3360. └──┘
  3361. ";
  3362. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3363. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3364. }
  3365. [Fact, AutoInitShutdown]
  3366. public void AutoSize_True_View_IsEmpty_False_Minimum_Width_Wide_Rune ()
  3367. {
  3368. var text = "界View";
  3369. var view = new View () {
  3370. TextDirection = TextDirection.TopBottom_LeftRight,
  3371. Height = Dim.Fill () - text.Length,
  3372. Text = text,
  3373. AutoSize = true
  3374. };
  3375. var win = new Window ("Window") {
  3376. Width = Dim.Fill (),
  3377. Height = Dim.Fill ()
  3378. };
  3379. win.Add (view);
  3380. Application.Top.Add (win);
  3381. Application.Begin (Application.Top);
  3382. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  3383. Assert.Equal (5, text.Length);
  3384. Assert.True (view.AutoSize);
  3385. Assert.Equal (new Rect (0, 0, 2, 5), view.Frame);
  3386. Assert.Equal (new Size (2, 5), view.TextFormatter.Size);
  3387. Assert.Equal (new List<ustring> () { "界View" }, view.TextFormatter.Lines);
  3388. Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
  3389. Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
  3390. var expected = @"
  3391. ┌──┐
  3392. │界│
  3393. │V │
  3394. │i │
  3395. │e │
  3396. │w │
  3397. │ │
  3398. │ │
  3399. │ │
  3400. └──┘
  3401. ";
  3402. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3403. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3404. text = "0123456789";
  3405. Assert.Equal (10, text.Length);
  3406. view.Height = Dim.Fill () - text.Length;
  3407. Application.Refresh ();
  3408. Assert.Equal (new Rect (0, 0, 2, 5), view.Frame);
  3409. Assert.Equal (new Size (2, 5), view.TextFormatter.Size);
  3410. var exception = Record.Exception (() => Assert.Equal (new List<ustring> () { "界View" }, view.TextFormatter.Lines));
  3411. Assert.Null (exception);
  3412. expected = @"
  3413. ┌──┐
  3414. │界│
  3415. │V │
  3416. │i │
  3417. │e │
  3418. │w │
  3419. │ │
  3420. │ │
  3421. │ │
  3422. └──┘
  3423. ";
  3424. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3425. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3426. }
  3427. [Fact, AutoInitShutdown]
  3428. public void AutoSize_False_View_Width_Zero_Returns_Minimum_Width_With_Wide_Rune ()
  3429. {
  3430. var text = "界View";
  3431. var view = new View () {
  3432. TextDirection = TextDirection.TopBottom_LeftRight,
  3433. Height = Dim.Fill () - text.Length,
  3434. Text = text
  3435. };
  3436. var win = new Window ("Window") {
  3437. Width = Dim.Fill (),
  3438. Height = Dim.Fill ()
  3439. };
  3440. win.Add (view);
  3441. Application.Top.Add (win);
  3442. Application.Begin (Application.Top);
  3443. ((FakeDriver)Application.Driver).SetBufferSize (4, 10);
  3444. Assert.Equal (5, text.Length);
  3445. Assert.False (view.AutoSize);
  3446. Assert.Equal (new Rect (0, 0, 2, 3), view.Frame);
  3447. Assert.Equal (new Size (2, 3), view.TextFormatter.Size);
  3448. Assert.Single (view.TextFormatter.Lines);
  3449. Assert.Equal (new Rect (0, 0, 4, 10), win.Frame);
  3450. Assert.Equal (new Rect (0, 0, 4, 10), Application.Top.Frame);
  3451. var expected = @"
  3452. ┌──┐
  3453. │界│
  3454. │V │
  3455. │i │
  3456. │ │
  3457. │ │
  3458. │ │
  3459. │ │
  3460. │ │
  3461. └──┘
  3462. ";
  3463. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3464. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3465. text = "0123456789";
  3466. Assert.Equal (10, text.Length);
  3467. view.Height = Dim.Fill () - text.Length;
  3468. Application.Refresh ();
  3469. Assert.Equal (new Rect (0, 0, 2, 0), view.Frame);
  3470. Assert.Equal (new Size (2, 0), view.TextFormatter.Size);
  3471. var exception = Record.Exception (() => Assert.Equal (new List<ustring> () { ustring.Empty }, view.TextFormatter.Lines));
  3472. Assert.Null (exception);
  3473. expected = @"
  3474. ┌──┐
  3475. │ │
  3476. │ │
  3477. │ │
  3478. │ │
  3479. │ │
  3480. │ │
  3481. │ │
  3482. │ │
  3483. └──┘
  3484. ";
  3485. pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3486. Assert.Equal (new Rect (0, 0, 4, 10), pos);
  3487. }
  3488. [Fact]
  3489. public void Format_With_PreserveTrailingSpaces_And_Without_PreserveTrailingSpaces ()
  3490. {
  3491. var text = $"Line1{Environment.NewLine}Line2{Environment.NewLine}Line3{Environment.NewLine}";
  3492. var width = 60;
  3493. var preserveTrailingSpaces = false;
  3494. var formated = TextFormatter.Format (text, width, false, true, preserveTrailingSpaces);
  3495. Assert.Equal ("Line1", formated [0]);
  3496. Assert.Equal ("Line2", formated [1]);
  3497. Assert.Equal ("Line3", formated [^1]);
  3498. preserveTrailingSpaces = true;
  3499. formated = TextFormatter.Format (text, width, false, true, preserveTrailingSpaces);
  3500. Assert.Equal ("Line1", formated [0]);
  3501. Assert.Equal ("Line2", formated [1]);
  3502. Assert.Equal ("Line3", formated [^1]);
  3503. }
  3504. [Fact]
  3505. public void SplitNewLine_Ending_Without_NewLine_Probably_CRLF ()
  3506. {
  3507. var text = $"First Line 界{Environment.NewLine}Second Line 界{Environment.NewLine}Third Line 界";
  3508. var splited = TextFormatter.SplitNewLine (text);
  3509. Assert.Equal ("First Line 界", splited [0]);
  3510. Assert.Equal ("Second Line 界", splited [1]);
  3511. Assert.Equal ("Third Line 界", splited [^1]);
  3512. }
  3513. [Fact]
  3514. public void SplitNewLine_Ending_With_NewLine_Probably_CRLF ()
  3515. {
  3516. var text = $"First Line 界{Environment.NewLine}Second Line 界{Environment.NewLine}Third Line 界{Environment.NewLine}";
  3517. var splited = TextFormatter.SplitNewLine (text);
  3518. Assert.Equal ("First Line 界", splited [0]);
  3519. Assert.Equal ("Second Line 界", splited [1]);
  3520. Assert.Equal ("Third Line 界", splited [2]);
  3521. Assert.Equal ("", splited [^1]);
  3522. }
  3523. [Fact]
  3524. public void SplitNewLine_Ending_Without_NewLine_Only_LF ()
  3525. {
  3526. var text = $"First Line 界\nSecond Line 界\nThird Line 界";
  3527. var splited = TextFormatter.SplitNewLine (text);
  3528. Assert.Equal ("First Line 界", splited [0]);
  3529. Assert.Equal ("Second Line 界", splited [1]);
  3530. Assert.Equal ("Third Line 界", splited [^1]);
  3531. }
  3532. [Fact]
  3533. public void SplitNewLine_Ending_With_NewLine_Only_LF ()
  3534. {
  3535. var text = $"First Line 界\nSecond Line 界\nThird Line 界\n";
  3536. var splited = TextFormatter.SplitNewLine (text);
  3537. Assert.Equal ("First Line 界", splited [0]);
  3538. Assert.Equal ("Second Line 界", splited [1]);
  3539. Assert.Equal ("Third Line 界", splited [2]);
  3540. Assert.Equal ("", splited [^1]);
  3541. }
  3542. [Fact]
  3543. public void MaxWidthLine_With_And_Without_Newlines ()
  3544. {
  3545. var text = "Single Line 界";
  3546. Assert.Equal (14, TextFormatter.MaxWidthLine (text));
  3547. text = $"First Line 界\nSecond Line 界\nThird Line 界\n";
  3548. Assert.Equal (14, TextFormatter.MaxWidthLine (text));
  3549. }
  3550. [Fact]
  3551. public void Ustring_Array_Is_Not_Equal_ToRunes_Array_And_String_Array ()
  3552. {
  3553. var text = "New Test 你";
  3554. ustring us = text;
  3555. string s = text;
  3556. Assert.Equal (10, us.RuneCount);
  3557. Assert.Equal (10, s.Length);
  3558. // The reason is ustring index is related to byte length and not rune length
  3559. Assert.Equal (12, us.Length);
  3560. Assert.NotEqual (20320, us [9]);
  3561. Assert.Equal (20320, s [9]);
  3562. Assert.Equal (228, us [9]);
  3563. Assert.Equal ("ä", ((Rune)us [9]).ToString ());
  3564. Assert.Equal ("你", s [9].ToString ());
  3565. // Rune array is equal to string array
  3566. var usToRunes = us.ToRunes ();
  3567. Assert.Equal (10, usToRunes.Length);
  3568. Assert.Equal (10, s.Length);
  3569. Assert.Equal (20320, (int)usToRunes [9]);
  3570. Assert.Equal (20320, s [9]);
  3571. Assert.Equal ("你", ((Rune)usToRunes [9]).ToString ());
  3572. Assert.Equal ("你", s [9].ToString ());
  3573. }
  3574. [Fact, AutoInitShutdown]
  3575. public void Non_Bmp_ConsoleWidth_ColumnWidth_Equal_Two ()
  3576. {
  3577. ustring us = "\U0001d539";
  3578. Rune r = 0x1d539;
  3579. Assert.Equal ("𝔹", us);
  3580. Assert.Equal ("𝔹", r.ToString ());
  3581. Assert.Equal (us, r.ToString ());
  3582. Assert.Equal (2, us.ConsoleWidth);
  3583. Assert.Equal (2, Rune.ColumnWidth (r));
  3584. var win = new Window (us);
  3585. var label = new Label (ustring.Make (r));
  3586. var tf = new TextField (us) { Y = 1, Width = 3 };
  3587. win.Add (label, tf);
  3588. var top = Application.Top;
  3589. top.Add (win);
  3590. Application.Begin (top);
  3591. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3592. var expected = @"
  3593. ┌ 𝔹 ────┐
  3594. │𝔹 │
  3595. │𝔹 │
  3596. └────────┘";
  3597. TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3598. TestHelpers.AssertDriverContentsAre (expected, output);
  3599. var expectedColors = new Attribute [] {
  3600. // 0
  3601. Colors.Base.Normal,
  3602. // 1
  3603. Colors.Base.Focus,
  3604. // 2
  3605. Colors.Base.HotNormal
  3606. };
  3607. TestHelpers.AssertDriverColorsAre (@"
  3608. 0222200000
  3609. 0000000000
  3610. 0111000000
  3611. 0000000000", expectedColors);
  3612. }
  3613. [Fact, AutoInitShutdown]
  3614. public void CJK_Compatibility_Ideographs_ConsoleWidth_ColumnWidth_Equal_Two ()
  3615. {
  3616. ustring us = "\U0000f900";
  3617. Rune r = 0xf900;
  3618. Assert.Equal ("豈", us);
  3619. Assert.Equal ("豈", r.ToString ());
  3620. Assert.Equal (us, r.ToString ());
  3621. Assert.Equal (2, us.ConsoleWidth);
  3622. Assert.Equal (2, Rune.ColumnWidth (r));
  3623. var win = new Window (us);
  3624. var label = new Label (ustring.Make (r));
  3625. var tf = new TextField (us) { Y = 1, Width = 3 };
  3626. win.Add (label, tf);
  3627. var top = Application.Top;
  3628. top.Add (win);
  3629. Application.Begin (top);
  3630. ((FakeDriver)Application.Driver).SetBufferSize (10, 4);
  3631. var expected = @"
  3632. ┌ 豈 ────┐
  3633. │豈 │
  3634. │豈 │
  3635. └────────┘";
  3636. TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
  3637. TestHelpers.AssertDriverContentsAre (expected, output);
  3638. var expectedColors = new Attribute [] {
  3639. // 0
  3640. Colors.Base.Normal,
  3641. // 1
  3642. Colors.Base.Focus,
  3643. // 2
  3644. Colors.Base.HotNormal
  3645. };
  3646. TestHelpers.AssertDriverColorsAre (@"
  3647. 0222200000
  3648. 0000000000
  3649. 0111000000
  3650. 0000000000", expectedColors);
  3651. }
  3652. [Fact, AutoInitShutdown]
  3653. public void Colors_On_TextAlignment_Right_And_Bottom ()
  3654. {
  3655. var labelRight = new Label ("Test") {
  3656. Width = 6,
  3657. Height = 1,
  3658. TextAlignment = TextAlignment.Right,
  3659. ColorScheme = Colors.Base
  3660. };
  3661. var labelBottom = new Label ("Test", TextDirection.TopBottom_LeftRight) {
  3662. Y = 1,
  3663. Width = 1,
  3664. Height = 6,
  3665. VerticalTextAlignment = VerticalTextAlignment.Bottom,
  3666. ColorScheme = Colors.Base
  3667. };
  3668. var top = Application.Top;
  3669. top.Add (labelRight, labelBottom);
  3670. Application.Begin (top);
  3671. ((FakeDriver)Application.Driver).SetBufferSize (7, 7);
  3672. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3673. Test
  3674. T
  3675. e
  3676. s
  3677. t ", output);
  3678. TestHelpers.AssertDriverColorsAre (@"
  3679. 000000
  3680. 0
  3681. 0
  3682. 0
  3683. 0
  3684. 0
  3685. 0", new Attribute [] { Colors.Base.Normal });
  3686. }
  3687. [Fact, AutoInitShutdown]
  3688. public void Draw_Negative_Bounds_Horizontal_Without_New_Lines ()
  3689. {
  3690. var subView = new View () { Id = "subView", Y = 1, Width = 7, Text = "subView" };
  3691. var view = new View () { Id = "view", Width = 20, Height = 2, Text = "01234567890123456789" };
  3692. view.Add (subView);
  3693. var content = new View () { Id = "content", Width = 20, Height = 20 };
  3694. content.Add (view);
  3695. var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 };
  3696. container.Add (content);
  3697. var top = Application.Top;
  3698. top.Add (container);
  3699. Application.Driver.Clip = container.Frame;
  3700. Application.Begin (top);
  3701. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3702. 01234
  3703. subVi", output);
  3704. content.X = -1;
  3705. Application.Refresh ();
  3706. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3707. 12345
  3708. ubVie", output);
  3709. content.Y = -1;
  3710. Application.Refresh ();
  3711. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3712. ubVie", output);
  3713. content.Y = -2;
  3714. Application.Refresh ();
  3715. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3716. content.X = -20;
  3717. content.Y = 0;
  3718. Application.Refresh ();
  3719. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3720. }
  3721. [Fact, AutoInitShutdown]
  3722. public void Draw_Negative_Bounds_Horizontal_With_New_Lines ()
  3723. {
  3724. var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "s\nu\nb\nV\ni\ne\nw" };
  3725. var view = new View () { Id = "view", Width = 2, Height = 20, Text = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9" };
  3726. view.Add (subView);
  3727. var content = new View () { Id = "content", Width = 20, Height = 20 };
  3728. content.Add (view);
  3729. var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 };
  3730. container.Add (content);
  3731. var top = Application.Top;
  3732. top.Add (container);
  3733. Application.Driver.Clip = container.Frame;
  3734. Application.Begin (top);
  3735. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3736. 0s
  3737. 1u
  3738. 2b
  3739. 3V
  3740. 4i", output);
  3741. content.X = -1;
  3742. Application.Refresh ();
  3743. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3744. s
  3745. u
  3746. b
  3747. V
  3748. i", output);
  3749. content.X = -2;
  3750. Application.Refresh ();
  3751. TestHelpers.AssertDriverContentsWithFrameAre (@"", output);
  3752. content.X = 0;
  3753. content.Y = -1;
  3754. Application.Refresh ();
  3755. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3756. 1u
  3757. 2b
  3758. 3V
  3759. 4i
  3760. 5e", output);
  3761. content.Y = -6;
  3762. Application.Refresh ();
  3763. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3764. 6w
  3765. 7
  3766. 8
  3767. 9
  3768. 0 ", output);
  3769. content.Y = -19;
  3770. Application.Refresh ();
  3771. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3772. 9", output);
  3773. content.Y = -20;
  3774. Application.Refresh ();
  3775. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3776. content.X = -2;
  3777. content.Y = 0;
  3778. Application.Refresh ();
  3779. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3780. }
  3781. [Fact, AutoInitShutdown]
  3782. public void Draw_Negative_Bounds_Vertical ()
  3783. {
  3784. var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "subView", TextDirection = TextDirection.TopBottom_LeftRight };
  3785. var view = new View () { Id = "view", Width = 2, Height = 20, Text = "01234567890123456789", TextDirection = TextDirection.TopBottom_LeftRight };
  3786. view.Add (subView);
  3787. var content = new View () { Id = "content", Width = 20, Height = 20 };
  3788. content.Add (view);
  3789. var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 };
  3790. container.Add (content);
  3791. var top = Application.Top;
  3792. top.Add (container);
  3793. Application.Driver.Clip = container.Frame;
  3794. Application.Begin (top);
  3795. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3796. 0s
  3797. 1u
  3798. 2b
  3799. 3V
  3800. 4i", output);
  3801. content.X = -1;
  3802. Application.Refresh ();
  3803. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3804. s
  3805. u
  3806. b
  3807. V
  3808. i", output);
  3809. content.X = -2;
  3810. Application.Refresh ();
  3811. TestHelpers.AssertDriverContentsWithFrameAre (@"", output);
  3812. content.X = 0;
  3813. content.Y = -1;
  3814. Application.Refresh ();
  3815. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3816. 1u
  3817. 2b
  3818. 3V
  3819. 4i
  3820. 5e", output);
  3821. content.Y = -6;
  3822. Application.Refresh ();
  3823. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3824. 6w
  3825. 7
  3826. 8
  3827. 9
  3828. 0 ", output);
  3829. content.Y = -19;
  3830. Application.Refresh ();
  3831. TestHelpers.AssertDriverContentsWithFrameAre (@"
  3832. 9", output);
  3833. content.Y = -20;
  3834. Application.Refresh ();
  3835. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3836. content.X = -2;
  3837. content.Y = 0;
  3838. Application.Refresh ();
  3839. TestHelpers.AssertDriverContentsWithFrameAre ("", output);
  3840. }
  3841. }
  3842. }