shada_spec.lua 115 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local t_shada = require('test.functional.shada.testutil')
  5. local clear = n.clear
  6. local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed =
  7. t.eq, n.api, n.eval, n.command, n.exc_exec, n.fn, n.feed
  8. local neq = t.neq
  9. local read_file = t.read_file
  10. local get_shada_rw = t_shada.get_shada_rw
  11. local function reset(shada_file)
  12. clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } }
  13. end
  14. local mpack_eq = function(expected, mpack_result)
  15. local mpack_keys = { 'type', 'timestamp', 'length', 'value' }
  16. local unpack = vim.mpack.Unpacker()
  17. local actual = {}
  18. local cur, val
  19. local i = 0
  20. local off = 1
  21. while off <= #mpack_result do
  22. val, off = unpack(mpack_result, off)
  23. if i % 4 == 0 then
  24. cur = {}
  25. actual[#actual + 1] = cur
  26. end
  27. local key = mpack_keys[(i % 4) + 1]
  28. if key ~= 'length' then
  29. if key == 'timestamp' and math.abs(val - os.time()) < 2 then
  30. val = 'current'
  31. end
  32. cur[key] = val
  33. end
  34. i = i + 1
  35. end
  36. eq(expected, actual)
  37. end
  38. local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada')
  39. local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
  40. describe('autoload/shada.vim', function()
  41. local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
  42. before_each(function()
  43. reset()
  44. nvim_command([[
  45. function ModifyVal(val)
  46. if type(a:val) == type([])
  47. if len(a:val) == 2 && type(a:val[0]) == type('') && a:val[0][0] is# '!' && has_key(v:msgpack_types, a:val[0][1:])
  48. return {'_TYPE': v:msgpack_types[ a:val[0][1:] ], '_VAL': a:val[1]}
  49. else
  50. return map(copy(a:val), 'ModifyVal(v:val)')
  51. endif
  52. elseif type(a:val) == type({})
  53. let keys = sort(keys(a:val))
  54. let ret = {'_TYPE': v:msgpack_types.map, '_VAL': []}
  55. for key in keys
  56. let k = {'_TYPE': v:msgpack_types.string, '_VAL': split(key, "\n", 1)}
  57. let v = ModifyVal(a:val[key])
  58. call add(ret._VAL, [k, v])
  59. unlet v
  60. endfor
  61. return ret
  62. elseif type(a:val) == type('')
  63. return {'_TYPE': v:msgpack_types.string, '_VAL': split(a:val, "\n", 1)}
  64. else
  65. return a:val
  66. endif
  67. endfunction
  68. ]])
  69. end)
  70. local sp = function(typ, val)
  71. return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val)
  72. end
  73. describe('function shada#mpack_to_sd', function()
  74. local mpack2sd = function(arg)
  75. return ('shada#mpack_to_sd(%s)'):format(arg)
  76. end
  77. it('works', function()
  78. eq({}, nvim_eval(mpack2sd('[]')))
  79. eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]')))
  80. eq({
  81. { type = 1, timestamp = 5, length = 1, data = 7 },
  82. { type = 1, timestamp = 10, length = 1, data = 5 },
  83. }, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]')))
  84. eq(
  85. 'zero-uint:Entry 1 has type element which is zero',
  86. exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]'))
  87. )
  88. eq(
  89. 'zero-uint:Entry 1 has type element which is zero',
  90. exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]'))))
  91. )
  92. eq(
  93. 'not-uint:Entry 1 has timestamp element which is not an unsigned integer',
  94. exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]'))
  95. )
  96. eq(
  97. 'not-uint:Entry 1 has length element which is not an unsigned integer',
  98. exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]'))
  99. )
  100. eq(
  101. 'not-uint:Entry 1 has type element which is not an unsigned integer',
  102. exc_exec('call ' .. mpack2sd('["", 1, -1, 7]'))
  103. )
  104. end)
  105. end)
  106. describe('function shada#sd_to_strings', function()
  107. local sd2strings_eq = function(expected, arg)
  108. if type(arg) == 'table' then
  109. eq(expected, fn['shada#sd_to_strings'](arg))
  110. else
  111. eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg)))
  112. end
  113. end
  114. it('works with empty input', function()
  115. sd2strings_eq({}, '[]')
  116. end)
  117. it('works with unknown items', function()
  118. sd2strings_eq({
  119. 'Unknown (0x64) with timestamp ' .. epoch .. ':',
  120. ' = 100',
  121. }, { { type = 100, timestamp = 0, length = 1, data = 100 } })
  122. sd2strings_eq(
  123. {
  124. 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':',
  125. ' = 100',
  126. },
  127. ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format(
  128. sp('integer', '[1, 1, 35, 6]')
  129. )
  130. )
  131. end)
  132. it('works with multiple unknown items', function()
  133. sd2strings_eq({
  134. 'Unknown (0x64) with timestamp ' .. epoch .. ':',
  135. ' = 100',
  136. 'Unknown (0x65) with timestamp ' .. epoch .. ':',
  137. ' = 500',
  138. }, {
  139. { type = 100, timestamp = 0, length = 1, data = 100 },
  140. { type = 101, timestamp = 0, length = 1, data = 500 },
  141. })
  142. end)
  143. it('works with header items', function()
  144. sd2strings_eq({
  145. 'Header with timestamp ' .. epoch .. ':',
  146. ' % Key______ Value',
  147. ' + generator "test"',
  148. }, { { type = 1, timestamp = 0, data = { generator = 'test' } } })
  149. sd2strings_eq({
  150. 'Header with timestamp ' .. epoch .. ':',
  151. ' % Key Description Value',
  152. ' + a 1',
  153. ' + b 2',
  154. ' + c column 3',
  155. ' + d 4',
  156. }, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } })
  157. sd2strings_eq({
  158. 'Header with timestamp ' .. epoch .. ':',
  159. ' % Key Value',
  160. ' + t "test"',
  161. }, { { type = 1, timestamp = 0, data = { t = 'test' } } })
  162. sd2strings_eq({
  163. 'Header with timestamp ' .. epoch .. ':',
  164. ' # Unexpected type: array instead of map',
  165. ' = [1, 2, 3]',
  166. }, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } })
  167. end)
  168. it('processes standard keys correctly, even in header', function()
  169. sd2strings_eq(
  170. {
  171. 'Header with timestamp ' .. epoch .. ':',
  172. ' % Key Description________ Value',
  173. ' + c column 0',
  174. ' + f file name "/tmp/foo"',
  175. ' + l line number 10',
  176. " + n name '@'",
  177. ' + rc contents ["abc", "def"]',
  178. ' + rt type CHARACTERWISE',
  179. ' + ru is_unnamed FALSE',
  180. ' + rw block width 10',
  181. ' + sb search backward TRUE',
  182. ' + sc smartcase value FALSE',
  183. ' + se place cursor at end TRUE',
  184. ' + sh v:hlsearch value TRUE',
  185. ' + sl has line offset FALSE',
  186. ' + sm magic value TRUE',
  187. ' + so offset value 10',
  188. ' + sp pattern "100"',
  189. ' + ss is :s pattern TRUE',
  190. ' + su is last used FALSE',
  191. },
  192. ([[ [{'type': 1, 'timestamp': 0, 'data': {
  193. 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  194. 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  195. 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  196. 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  197. 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  198. 'so': 10,
  199. 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  200. 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  201. 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  202. 'sp': '100',
  203. 'rt': 0,
  204. 'rw': 10,
  205. 'rc': ['abc', 'def'],
  206. 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  207. 'n': 0x40,
  208. 'l': 10,
  209. 'c': 0,
  210. 'f': '/tmp/foo',
  211. }}] ]]):gsub('\n', '')
  212. )
  213. sd2strings_eq(
  214. {
  215. 'Header with timestamp ' .. epoch .. ':',
  216. ' % Key Description____ Value',
  217. ' # Expected integer',
  218. ' + c column "abc"',
  219. ' # Expected no NUL bytes',
  220. ' + f file name "abc\\0def"',
  221. ' # Value is negative',
  222. ' + l line number -10',
  223. ' # Value is negative',
  224. ' + n name -64',
  225. ' # Expected array value',
  226. ' + rc contents "10"',
  227. ' # Unexpected enum value: expected one of '
  228. .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
  229. ' + rt type 10',
  230. ' # Expected boolean',
  231. ' + ru is_unnamed 10',
  232. ' # Expected boolean',
  233. ' + sc smartcase value NIL',
  234. ' # Expected boolean',
  235. ' + sm magic value "TRUE"',
  236. ' # Expected integer',
  237. ' + so offset value "TRUE"',
  238. ' + sp pattern "abc"',
  239. },
  240. ([[ [{'type': 1, 'timestamp': 0, 'data': {
  241. 'sm': 'TRUE',
  242. 'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
  243. 'so': 'TRUE',
  244. 'sp': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]},
  245. 'rt': 10,
  246. 'rc': '10',
  247. 'ru': 10,
  248. 'n': -0x40,
  249. 'l': -10,
  250. 'c': 'abc',
  251. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
  252. }}] ]]):gsub('\n', '')
  253. )
  254. sd2strings_eq(
  255. {
  256. 'Header with timestamp ' .. epoch .. ':',
  257. ' % Key Description Value',
  258. ' # Expected no NUL bytes',
  259. ' + f file name "abc\\0def"',
  260. ' + rc contents ["abc", "abc"]',
  261. ' # Expected integer',
  262. ' + rt type "ABC"',
  263. },
  264. ([[ [{'type': 1, 'timestamp': 0, 'data': {
  265. 'rt': 'ABC',
  266. 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}],
  267. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
  268. }}] ]]):gsub('\n', '')
  269. )
  270. sd2strings_eq(
  271. {
  272. 'Header with timestamp ' .. epoch .. ':',
  273. ' % Key Description Value',
  274. ' # Expected no NUL bytes',
  275. ' + rc contents ["abc", "a\\nd\\0"]',
  276. },
  277. ([[ [{'type': 1, 'timestamp': 0, 'data': {
  278. 'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["a", "d\n"]}],
  279. }}] ]]):gsub('\n', '')
  280. )
  281. end)
  282. it('works with search pattern items', function()
  283. sd2strings_eq({
  284. 'Search pattern with timestamp ' .. epoch .. ':',
  285. ' # Unexpected type: array instead of map',
  286. ' = [1, 2, 3]',
  287. }, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } })
  288. sd2strings_eq(
  289. {
  290. 'Search pattern with timestamp ' .. epoch .. ':',
  291. ' % Key Description________ Value',
  292. ' + sp pattern "abc"',
  293. ' + sh v:hlsearch value FALSE',
  294. ' + ss is :s pattern FALSE',
  295. ' + sb search backward FALSE',
  296. ' + sm magic value TRUE',
  297. ' + sc smartcase value FALSE',
  298. ' + sl has line offset FALSE',
  299. ' + se place cursor at end FALSE',
  300. ' + so offset value 0',
  301. ' + su is last used TRUE',
  302. },
  303. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  304. 'sp': 'abc',
  305. }}] ]]):gsub('\n', '')
  306. )
  307. sd2strings_eq(
  308. {
  309. 'Search pattern with timestamp ' .. epoch .. ':',
  310. ' % Key Description________ Value',
  311. ' + sp pattern "abc"',
  312. ' + sh v:hlsearch value FALSE',
  313. ' + ss is :s pattern FALSE',
  314. ' + sb search backward FALSE',
  315. ' + sm magic value TRUE',
  316. ' + sc smartcase value FALSE',
  317. ' + sl has line offset FALSE',
  318. ' + se place cursor at end FALSE',
  319. ' + so offset value 0',
  320. ' + su is last used TRUE',
  321. ' + sX NIL',
  322. ' + sY NIL',
  323. ' + sZ NIL',
  324. },
  325. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  326. 'sp': 'abc',
  327. 'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
  328. 'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
  329. 'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
  330. }}] ]]):gsub('\n', '')
  331. )
  332. sd2strings_eq(
  333. {
  334. 'Search pattern with timestamp ' .. epoch .. ':',
  335. ' % Key Description________ Value',
  336. ' + sp pattern "abc"',
  337. ' + sh v:hlsearch value FALSE',
  338. ' + ss is :s pattern FALSE',
  339. ' + sb search backward FALSE',
  340. ' + sm magic value TRUE',
  341. ' + sc smartcase value FALSE',
  342. ' + sl has line offset FALSE',
  343. ' + se place cursor at end FALSE',
  344. ' + so offset value 0',
  345. ' + su is last used TRUE',
  346. },
  347. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  348. 'sp': 'abc',
  349. 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  350. 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  351. 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  352. 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  353. 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  354. 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  355. 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  356. 'so': 0,
  357. 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  358. }}] ]]):gsub('\n', '')
  359. )
  360. sd2strings_eq(
  361. {
  362. 'Search pattern with timestamp ' .. epoch .. ':',
  363. ' % Key Description________ Value',
  364. ' # Required key missing: sp',
  365. ' + sh v:hlsearch value FALSE',
  366. ' + ss is :s pattern FALSE',
  367. ' + sb search backward FALSE',
  368. ' + sm magic value TRUE',
  369. ' + sc smartcase value FALSE',
  370. ' + sl has line offset FALSE',
  371. ' + se place cursor at end FALSE',
  372. ' + so offset value 0',
  373. ' + su is last used TRUE',
  374. },
  375. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  376. }}] ]]):gsub('\n', '')
  377. )
  378. sd2strings_eq(
  379. {
  380. 'Search pattern with timestamp ' .. epoch .. ':',
  381. ' % Key Description________ Value',
  382. ' + sp pattern ""',
  383. ' + sh v:hlsearch value TRUE',
  384. ' + ss is :s pattern TRUE',
  385. ' + sb search backward TRUE',
  386. ' + sm magic value FALSE',
  387. ' + sc smartcase value TRUE',
  388. ' + sl has line offset TRUE',
  389. ' + se place cursor at end TRUE',
  390. ' + so offset value -10',
  391. ' + su is last used FALSE',
  392. },
  393. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  394. 'sp': '',
  395. 'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  396. 'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  397. 'sb': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  398. 'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  399. 'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  400. 'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  401. 'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  402. 'so': -10,
  403. 'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  404. }}] ]]):gsub('\n', '')
  405. )
  406. sd2strings_eq(
  407. {
  408. 'Search pattern with timestamp ' .. epoch .. ':',
  409. ' % Key Description________ Value',
  410. ' # Expected binary string',
  411. ' + sp pattern 0',
  412. ' # Expected boolean',
  413. ' + sh v:hlsearch value 0',
  414. ' # Expected boolean',
  415. ' + ss is :s pattern 0',
  416. ' # Expected boolean',
  417. ' + sb search backward 0',
  418. ' # Expected boolean',
  419. ' + sm magic value 0',
  420. ' # Expected boolean',
  421. ' + sc smartcase value 0',
  422. ' # Expected boolean',
  423. ' + sl has line offset 0',
  424. ' # Expected boolean',
  425. ' + se place cursor at end 0',
  426. ' # Expected integer',
  427. ' + so offset value ""',
  428. ' # Expected boolean',
  429. ' + su is last used 0',
  430. },
  431. ([[ [{'type': 2, 'timestamp': 0, 'data': {
  432. 'sp': 0,
  433. 'sh': 0,
  434. 'ss': 0,
  435. 'sb': 0,
  436. 'sm': 0,
  437. 'sc': 0,
  438. 'sl': 0,
  439. 'se': 0,
  440. 'so': '',
  441. 'su': 0,
  442. }}] ]]):gsub('\n', '')
  443. )
  444. end)
  445. it('works with replacement string items', function()
  446. sd2strings_eq({
  447. 'Replacement string with timestamp ' .. epoch .. ':',
  448. ' # Unexpected type: map instead of array',
  449. ' = {"a": [10]}',
  450. }, { { type = 3, timestamp = 0, data = { a = { 10 } } } })
  451. sd2strings_eq(
  452. {
  453. 'Replacement string with timestamp ' .. epoch .. ':',
  454. ' @ Description__________ Value',
  455. ' # Expected more elements in list',
  456. },
  457. ([[ [{'type': 3, 'timestamp': 0, 'data': [
  458. ]}] ]]):gsub('\n', '')
  459. )
  460. sd2strings_eq(
  461. {
  462. 'Replacement string with timestamp ' .. epoch .. ':',
  463. ' @ Description__________ Value',
  464. ' # Expected binary string',
  465. ' - :s replacement string 0',
  466. },
  467. ([[ [{'type': 3, 'timestamp': 0, 'data': [
  468. 0,
  469. ]}] ]]):gsub('\n', '')
  470. )
  471. sd2strings_eq(
  472. {
  473. 'Replacement string with timestamp ' .. epoch .. ':',
  474. ' @ Description__________ Value',
  475. ' # Expected no NUL bytes',
  476. ' - :s replacement string "abc\\0def"',
  477. },
  478. ([[ [{'type': 3, 'timestamp': 0, 'data': [
  479. {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
  480. ]}] ]]):gsub('\n', '')
  481. )
  482. sd2strings_eq(
  483. {
  484. 'Replacement string with timestamp ' .. epoch .. ':',
  485. ' @ Description__________ Value',
  486. ' - :s replacement string "abc\\ndef"',
  487. },
  488. ([[ [{'type': 3, 'timestamp': 0, 'data': [
  489. {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
  490. ]}] ]]):gsub('\n', '')
  491. )
  492. sd2strings_eq(
  493. {
  494. 'Replacement string with timestamp ' .. epoch .. ':',
  495. ' @ Description__________ Value',
  496. ' - :s replacement string "abc\\ndef"',
  497. ' - 0',
  498. },
  499. ([[ [{'type': 3, 'timestamp': 0, 'data': [
  500. {'_TYPE': v:msgpack_types.string, '_VAL': ["abc", "def"]},
  501. 0,
  502. ]}] ]]):gsub('\n', '')
  503. )
  504. end)
  505. it('works with history entry items', function()
  506. sd2strings_eq({
  507. 'History entry with timestamp ' .. epoch .. ':',
  508. ' # Unexpected type: map instead of array',
  509. ' = {"a": [10]}',
  510. }, { { type = 4, timestamp = 0, data = { a = { 10 } } } })
  511. sd2strings_eq(
  512. {
  513. 'History entry with timestamp ' .. epoch .. ':',
  514. ' @ Description_ Value',
  515. ' # Expected more elements in list',
  516. },
  517. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  518. ]}] ]]):gsub('\n', '')
  519. )
  520. sd2strings_eq(
  521. {
  522. 'History entry with timestamp ' .. epoch .. ':',
  523. ' @ Description_ Value',
  524. ' # Expected integer',
  525. ' - history type ""',
  526. ' # Expected more elements in list',
  527. },
  528. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  529. '',
  530. ]}] ]]):gsub('\n', '')
  531. )
  532. sd2strings_eq(
  533. {
  534. 'History entry with timestamp ' .. epoch .. ':',
  535. ' @ Description_ Value',
  536. ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
  537. .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
  538. ' - history type 5',
  539. ' - contents ""',
  540. },
  541. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  542. 5,
  543. ''
  544. ]}] ]]):gsub('\n', '')
  545. )
  546. sd2strings_eq(
  547. {
  548. 'History entry with timestamp ' .. epoch .. ':',
  549. ' @ Description_ Value',
  550. ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
  551. .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
  552. ' - history type 5',
  553. ' - contents ""',
  554. ' - 32',
  555. },
  556. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  557. 5,
  558. '',
  559. 0x20
  560. ]}] ]]):gsub('\n', '')
  561. )
  562. sd2strings_eq(
  563. {
  564. 'History entry with timestamp ' .. epoch .. ':',
  565. ' @ Description_ Value',
  566. ' - history type CMD',
  567. ' - contents ""',
  568. ' - 32',
  569. },
  570. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  571. 0,
  572. '',
  573. 0x20
  574. ]}] ]]):gsub('\n', '')
  575. )
  576. sd2strings_eq(
  577. {
  578. 'History entry with timestamp ' .. epoch .. ':',
  579. ' @ Description_ Value',
  580. ' - history type SEARCH',
  581. ' - contents ""',
  582. " - separator ' '",
  583. },
  584. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  585. 1,
  586. '',
  587. 0x20
  588. ]}] ]]):gsub('\n', '')
  589. )
  590. sd2strings_eq(
  591. {
  592. 'History entry with timestamp ' .. epoch .. ':',
  593. ' @ Description_ Value',
  594. ' - history type SEARCH',
  595. ' - contents ""',
  596. ' # Expected more elements in list',
  597. },
  598. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  599. 1,
  600. '',
  601. ]}] ]]):gsub('\n', '')
  602. )
  603. sd2strings_eq(
  604. {
  605. 'History entry with timestamp ' .. epoch .. ':',
  606. ' @ Description_ Value',
  607. ' - history type EXPR',
  608. ' - contents ""',
  609. },
  610. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  611. 2,
  612. '',
  613. ]}] ]]):gsub('\n', '')
  614. )
  615. sd2strings_eq(
  616. {
  617. 'History entry with timestamp ' .. epoch .. ':',
  618. ' @ Description_ Value',
  619. ' - history type INPUT',
  620. ' - contents ""',
  621. },
  622. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  623. 3,
  624. '',
  625. ]}] ]]):gsub('\n', '')
  626. )
  627. sd2strings_eq(
  628. {
  629. 'History entry with timestamp ' .. epoch .. ':',
  630. ' @ Description_ Value',
  631. ' - history type DEBUG',
  632. ' - contents ""',
  633. },
  634. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  635. 4,
  636. '',
  637. ]}] ]]):gsub('\n', '')
  638. )
  639. sd2strings_eq(
  640. {
  641. 'History entry with timestamp ' .. epoch .. ':',
  642. ' @ Description_ Value',
  643. ' - history type DEBUG',
  644. ' # Expected binary string',
  645. ' - contents 10',
  646. },
  647. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  648. 4,
  649. 10,
  650. ]}] ]]):gsub('\n', '')
  651. )
  652. sd2strings_eq(
  653. {
  654. 'History entry with timestamp ' .. epoch .. ':',
  655. ' @ Description_ Value',
  656. ' - history type DEBUG',
  657. ' # Expected no NUL bytes',
  658. ' - contents "abc\\0def"',
  659. },
  660. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  661. 4,
  662. {'_TYPE': v:msgpack_types.string, '_VAL': ["abc\ndef"]},
  663. ]}] ]]):gsub('\n', '')
  664. )
  665. sd2strings_eq(
  666. {
  667. 'History entry with timestamp ' .. epoch .. ':',
  668. ' @ Description_ Value',
  669. ' - history type SEARCH',
  670. ' - contents "abc"',
  671. ' # Expected integer',
  672. ' - separator ""',
  673. },
  674. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  675. 1,
  676. 'abc',
  677. '',
  678. ]}] ]]):gsub('\n', '')
  679. )
  680. sd2strings_eq(
  681. {
  682. 'History entry with timestamp ' .. epoch .. ':',
  683. ' @ Description_ Value',
  684. ' - history type SEARCH',
  685. ' - contents "abc"',
  686. ' # Value is negative',
  687. ' - separator -1',
  688. },
  689. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  690. 1,
  691. 'abc',
  692. -1,
  693. ]}] ]]):gsub('\n', '')
  694. )
  695. -- Regression: NUL separator must be properly supported
  696. sd2strings_eq(
  697. {
  698. 'History entry with timestamp ' .. epoch .. ':',
  699. ' @ Description_ Value',
  700. ' - history type SEARCH',
  701. ' - contents ""',
  702. " - separator '\\0'",
  703. },
  704. ([[ [{'type': 4, 'timestamp': 0, 'data': [
  705. 1,
  706. '',
  707. 0x0
  708. ]}] ]]):gsub('\n', '')
  709. )
  710. end)
  711. it('works with register items', function()
  712. sd2strings_eq({
  713. 'Register with timestamp ' .. epoch .. ':',
  714. ' # Unexpected type: array instead of map',
  715. ' = [1, 2, 3]',
  716. }, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } })
  717. sd2strings_eq(
  718. {
  719. 'Register with timestamp ' .. epoch .. ':',
  720. ' % Key Description Value',
  721. ' # Required key missing: n',
  722. ' # Required key missing: rc',
  723. ' + rw block width 0',
  724. ' + rt type CHARACTERWISE',
  725. ' + ru is_unnamed FALSE',
  726. },
  727. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  728. }}] ]]):gsub('\n', '')
  729. )
  730. sd2strings_eq(
  731. {
  732. 'Register with timestamp ' .. epoch .. ':',
  733. ' % Key Description Value',
  734. " + n name ' '",
  735. ' # Required key missing: rc',
  736. ' + rw block width 0',
  737. ' + rt type CHARACTERWISE',
  738. ' + ru is_unnamed FALSE',
  739. },
  740. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  741. 'n': 0x20,
  742. }}] ]]):gsub('\n', '')
  743. )
  744. sd2strings_eq(
  745. {
  746. 'Register with timestamp ' .. epoch .. ':',
  747. ' % Key Description Value',
  748. " + n name ' '",
  749. ' + rc contents ["abc", "def"]',
  750. ' + rw block width 0',
  751. ' + rt type CHARACTERWISE',
  752. ' + ru is_unnamed FALSE',
  753. },
  754. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  755. 'n': 0x20,
  756. 'rc': ["abc", "def"],
  757. 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
  758. }}] ]]):gsub('\n', '')
  759. )
  760. sd2strings_eq(
  761. {
  762. 'Register with timestamp ' .. epoch .. ':',
  763. ' % Key Description Value',
  764. " + n name ' '",
  765. ' + rc contents @',
  766. ' | - "abcdefghijklmnopqrstuvwxyz"',
  767. ' | - "abcdefghijklmnopqrstuvwxyz"',
  768. ' + rw block width 0',
  769. ' + rt type CHARACTERWISE',
  770. ' + ru is_unnamed TRUE',
  771. },
  772. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  773. 'n': 0x20,
  774. 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
  775. 'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
  776. }}] ]]):gsub('\n', '')
  777. )
  778. sd2strings_eq(
  779. {
  780. 'Register with timestamp ' .. epoch .. ':',
  781. ' % Key Description Value',
  782. " + n name ' '",
  783. ' + rc contents @',
  784. ' | - "abcdefghijklmnopqrstuvwxyz"',
  785. ' | - "abcdefghijklmnopqrstuvwxyz"',
  786. ' + rw block width 0',
  787. ' + rt type CHARACTERWISE',
  788. ' + ru is_unnamed FALSE',
  789. },
  790. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  791. 'n': 0x20,
  792. 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
  793. 'rw': 0,
  794. 'rt': 0,
  795. }}] ]]):gsub('\n', '')
  796. )
  797. sd2strings_eq(
  798. {
  799. 'Register with timestamp ' .. epoch .. ':',
  800. ' % Key Description Value',
  801. " + n name ' '",
  802. ' + rc contents @',
  803. ' | - "abcdefghijklmnopqrstuvwxyz"',
  804. ' | - "abcdefghijklmnopqrstuvwxyz"',
  805. ' + rw block width 5',
  806. ' + rt type LINEWISE',
  807. ' + ru is_unnamed FALSE',
  808. },
  809. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  810. 'n': 0x20,
  811. 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
  812. 'rw': 5,
  813. 'rt': 1,
  814. }}] ]]):gsub('\n', '')
  815. )
  816. sd2strings_eq(
  817. {
  818. 'Register with timestamp ' .. epoch .. ':',
  819. ' % Key Description Value',
  820. " + n name ' '",
  821. ' + rc contents @',
  822. ' | - "abcdefghijklmnopqrstuvwxyz"',
  823. ' | - "abcdefghijklmnopqrstuvwxyz"',
  824. ' # Expected integer',
  825. ' + rw block width ""',
  826. ' + rt type BLOCKWISE',
  827. ' # Expected boolean',
  828. ' + ru is_unnamed ""',
  829. },
  830. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  831. 'n': 0x20,
  832. 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
  833. 'rw': "",
  834. 'rt': 2,
  835. 'ru': ""
  836. }}] ]]):gsub('\n', '')
  837. )
  838. sd2strings_eq(
  839. {
  840. 'Register with timestamp ' .. epoch .. ':',
  841. ' % Key Description Value',
  842. " + n name ' '",
  843. ' # Expected array value',
  844. ' + rc contents 0',
  845. ' # Value is negative',
  846. ' + rw block width -1',
  847. ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
  848. .. '1 (LINEWISE), 2 (BLOCKWISE)',
  849. ' + rt type 10',
  850. ' # Expected boolean',
  851. ' + ru is_unnamed ["abc", "def"]',
  852. },
  853. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  854. 'n': 0x20,
  855. 'rc': 0,
  856. 'rw': -1,
  857. 'rt': 10,
  858. 'ru': ['abc', 'def'],
  859. }}] ]]):gsub('\n', '')
  860. )
  861. sd2strings_eq(
  862. {
  863. 'Register with timestamp ' .. epoch .. ':',
  864. ' % Key Description Value',
  865. " + n name ' '",
  866. ' + rc contents @',
  867. ' | - "abcdefghijklmnopqrstuvwxyz"',
  868. ' | - "abcdefghijklmnopqrstuvwxyz"',
  869. ' + rw block width 5',
  870. ' + rt type LINEWISE',
  871. ' # Expected boolean',
  872. ' + ru is_unnamed 0',
  873. },
  874. ([[ [{'type': 5, 'timestamp': 0, 'data': {
  875. 'n': 0x20,
  876. 'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
  877. 'rw': 5,
  878. 'rt': 1,
  879. 'ru': 0,
  880. }}] ]]):gsub('\n', '')
  881. )
  882. end)
  883. it('works with variable items', function()
  884. sd2strings_eq({
  885. 'Variable with timestamp ' .. epoch .. ':',
  886. ' # Unexpected type: map instead of array',
  887. ' = {"a": [10]}',
  888. }, { { type = 6, timestamp = 0, data = { a = { 10 } } } })
  889. sd2strings_eq(
  890. {
  891. 'Variable with timestamp ' .. epoch .. ':',
  892. ' @ Description Value',
  893. ' # Expected more elements in list',
  894. },
  895. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  896. ]}] ]]):gsub('\n', '')
  897. )
  898. sd2strings_eq(
  899. {
  900. 'Variable with timestamp ' .. epoch .. ':',
  901. ' @ Description Value',
  902. ' # Expected binary string',
  903. ' - name 1',
  904. ' # Expected more elements in list',
  905. },
  906. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  907. 1
  908. ]}] ]]):gsub('\n', '')
  909. )
  910. sd2strings_eq(
  911. {
  912. 'Variable with timestamp ' .. epoch .. ':',
  913. ' @ Description Value',
  914. ' # Expected no NUL bytes',
  915. ' - name "\\0"',
  916. ' # Expected more elements in list',
  917. },
  918. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  919. {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
  920. ]}] ]]):gsub('\n', '')
  921. )
  922. sd2strings_eq(
  923. {
  924. 'Variable with timestamp ' .. epoch .. ':',
  925. ' @ Description Value',
  926. ' - name "foo"',
  927. ' # Expected more elements in list',
  928. },
  929. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  930. {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
  931. ]}] ]]):gsub('\n', '')
  932. )
  933. sd2strings_eq(
  934. {
  935. 'Variable with timestamp ' .. epoch .. ':',
  936. ' @ Description Value',
  937. ' - name "foo"',
  938. ' - value NIL',
  939. },
  940. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  941. {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
  942. {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
  943. ]}] ]]):gsub('\n', '')
  944. )
  945. sd2strings_eq(
  946. {
  947. 'Variable with timestamp ' .. epoch .. ':',
  948. ' @ Description Value',
  949. ' - name "foo"',
  950. ' - value NIL',
  951. ' - NIL',
  952. },
  953. ([[ [{'type': 6, 'timestamp': 0, 'data': [
  954. {'_TYPE': v:msgpack_types.string, '_VAL': ["foo"]},
  955. {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
  956. {'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
  957. ]}] ]]):gsub('\n', '')
  958. )
  959. end)
  960. it('works with global mark items', function()
  961. sd2strings_eq({
  962. 'Global mark with timestamp ' .. epoch .. ':',
  963. ' # Unexpected type: array instead of map',
  964. ' = [1, 2, 3]',
  965. }, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } })
  966. sd2strings_eq(
  967. {
  968. 'Global mark with timestamp ' .. epoch .. ':',
  969. ' % Key Description Value',
  970. ' # Required key missing: n',
  971. ' # Required key missing: f',
  972. ' + l line number 1',
  973. ' + c column 0',
  974. },
  975. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  976. }}] ]]):gsub('\n', '')
  977. )
  978. sd2strings_eq(
  979. {
  980. 'Global mark with timestamp ' .. epoch .. ':',
  981. ' % Key Description Value',
  982. ' # Expected integer',
  983. ' + n name "foo"',
  984. ' # Required key missing: f',
  985. ' + l line number 1',
  986. ' + c column 0',
  987. },
  988. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  989. 'n': 'foo',
  990. }}] ]]):gsub('\n', '')
  991. )
  992. sd2strings_eq(
  993. {
  994. 'Global mark with timestamp ' .. epoch .. ':',
  995. ' % Key Description Value',
  996. ' # Required key missing: n',
  997. ' + f file name "foo"',
  998. ' + l line number 1',
  999. ' + c column 0',
  1000. },
  1001. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1002. 'f': 'foo',
  1003. }}] ]]):gsub('\n', '')
  1004. )
  1005. sd2strings_eq(
  1006. {
  1007. 'Global mark with timestamp ' .. epoch .. ':',
  1008. ' % Key Description Value',
  1009. ' # Value is negative',
  1010. ' + n name -10',
  1011. ' # Expected no NUL bytes',
  1012. ' + f file name "\\0"',
  1013. ' + l line number 1',
  1014. ' + c column 0',
  1015. },
  1016. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1017. 'n': -10,
  1018. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
  1019. }}] ]]):gsub('\n', '')
  1020. )
  1021. sd2strings_eq(
  1022. {
  1023. 'Global mark with timestamp ' .. epoch .. ':',
  1024. ' % Key Description Value',
  1025. " + n name '\\20'",
  1026. ' + f file name "foo"',
  1027. ' # Value is negative',
  1028. ' + l line number -10',
  1029. ' # Value is negative',
  1030. ' + c column -10',
  1031. },
  1032. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1033. 'n': 20,
  1034. 'f': 'foo',
  1035. 'l': -10,
  1036. 'c': -10,
  1037. }}] ]]):gsub('\n', '')
  1038. )
  1039. sd2strings_eq(
  1040. {
  1041. 'Global mark with timestamp ' .. epoch .. ':',
  1042. ' % Key Description Value',
  1043. ' + n name 128',
  1044. ' + f file name "foo"',
  1045. ' + l line number 1',
  1046. ' + c column 0',
  1047. },
  1048. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1049. 'n': 128,
  1050. 'f': 'foo',
  1051. }}] ]]):gsub('\n', '')
  1052. )
  1053. sd2strings_eq(
  1054. {
  1055. 'Global mark with timestamp ' .. epoch .. ':',
  1056. ' % Key Description Value',
  1057. " + n name '\\20'",
  1058. ' + f file name "foo"',
  1059. ' # Expected integer',
  1060. ' + l line number "FOO"',
  1061. ' # Expected integer',
  1062. ' + c column "foo"',
  1063. ' + mX 10',
  1064. },
  1065. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1066. 'n': 20,
  1067. 'f': 'foo',
  1068. 'l': 'FOO',
  1069. 'c': 'foo',
  1070. 'mX': 10,
  1071. }}] ]]):gsub('\n', '')
  1072. )
  1073. sd2strings_eq(
  1074. {
  1075. 'Global mark with timestamp ' .. epoch .. ':',
  1076. ' % Key________ Description Value',
  1077. " + n name 'A'",
  1078. ' + f file name "foo"',
  1079. ' + l line number 2',
  1080. ' + c column 200',
  1081. ' + mX 10',
  1082. ' + mYYYYYYYYYY 10',
  1083. },
  1084. ([[ [{'type': 7, 'timestamp': 0, 'data': {
  1085. 'n': char2nr('A'),
  1086. 'f': 'foo',
  1087. 'l': 2,
  1088. 'c': 200,
  1089. 'mX': 10,
  1090. 'mYYYYYYYYYY': 10,
  1091. }}] ]]):gsub('\n', '')
  1092. )
  1093. end)
  1094. it('works with jump items', function()
  1095. sd2strings_eq({
  1096. 'Jump with timestamp ' .. epoch .. ':',
  1097. ' # Unexpected type: array instead of map',
  1098. ' = [1, 2, 3]',
  1099. }, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } })
  1100. sd2strings_eq(
  1101. {
  1102. 'Jump with timestamp ' .. epoch .. ':',
  1103. ' % Key Description Value',
  1104. ' # Required key missing: f',
  1105. ' + l line number 1',
  1106. ' + c column 0',
  1107. },
  1108. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1109. }}] ]]):gsub('\n', '')
  1110. )
  1111. sd2strings_eq(
  1112. {
  1113. 'Jump with timestamp ' .. epoch .. ':',
  1114. ' % Key Description Value',
  1115. ' # Required key missing: f',
  1116. ' + l line number 1',
  1117. ' + c column 0',
  1118. ' # Expected integer',
  1119. ' + n name "foo"',
  1120. },
  1121. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1122. 'n': 'foo',
  1123. }}] ]]):gsub('\n', '')
  1124. )
  1125. sd2strings_eq(
  1126. {
  1127. 'Jump with timestamp ' .. epoch .. ':',
  1128. ' % Key Description Value',
  1129. ' + f file name "foo"',
  1130. ' + l line number 1',
  1131. ' + c column 0',
  1132. },
  1133. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1134. 'f': 'foo',
  1135. }}] ]]):gsub('\n', '')
  1136. )
  1137. sd2strings_eq(
  1138. {
  1139. 'Jump with timestamp ' .. epoch .. ':',
  1140. ' % Key Description Value',
  1141. ' # Expected no NUL bytes',
  1142. ' + f file name "\\0"',
  1143. ' + l line number 1',
  1144. ' + c column 0',
  1145. ' # Value is negative',
  1146. ' + n name -10',
  1147. },
  1148. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1149. 'n': -10,
  1150. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
  1151. }}] ]]):gsub('\n', '')
  1152. )
  1153. sd2strings_eq(
  1154. {
  1155. 'Jump with timestamp ' .. epoch .. ':',
  1156. ' % Key Description Value',
  1157. ' + f file name "foo"',
  1158. ' # Value is negative',
  1159. ' + l line number -10',
  1160. ' # Value is negative',
  1161. ' + c column -10',
  1162. },
  1163. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1164. 'f': 'foo',
  1165. 'l': -10,
  1166. 'c': -10,
  1167. }}] ]]):gsub('\n', '')
  1168. )
  1169. sd2strings_eq(
  1170. {
  1171. 'Jump with timestamp ' .. epoch .. ':',
  1172. ' % Key Description Value',
  1173. ' + f file name "foo"',
  1174. ' # Expected integer',
  1175. ' + l line number "FOO"',
  1176. ' # Expected integer',
  1177. ' + c column "foo"',
  1178. ' + mX 10',
  1179. },
  1180. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1181. 'f': 'foo',
  1182. 'l': 'FOO',
  1183. 'c': 'foo',
  1184. 'mX': 10,
  1185. }}] ]]):gsub('\n', '')
  1186. )
  1187. sd2strings_eq(
  1188. {
  1189. 'Jump with timestamp ' .. epoch .. ':',
  1190. ' % Key________ Description Value',
  1191. ' + f file name "foo"',
  1192. ' + l line number 2',
  1193. ' + c column 200',
  1194. ' + mX 10',
  1195. ' + mYYYYYYYYYY 10',
  1196. " + n name ' '",
  1197. },
  1198. ([[ [{'type': 8, 'timestamp': 0, 'data': {
  1199. 'n': 0x20,
  1200. 'f': 'foo',
  1201. 'l': 2,
  1202. 'c': 200,
  1203. 'mX': 10,
  1204. 'mYYYYYYYYYY': 10,
  1205. }}] ]]):gsub('\n', '')
  1206. )
  1207. end)
  1208. it('works with buffer list items', function()
  1209. sd2strings_eq({
  1210. 'Buffer list with timestamp ' .. epoch .. ':',
  1211. ' # Unexpected type: map instead of array',
  1212. ' = {"a": [10]}',
  1213. }, { { type = 9, timestamp = 0, data = { a = { 10 } } } })
  1214. sd2strings_eq({
  1215. 'Buffer list with timestamp ' .. epoch .. ':',
  1216. ' # Expected array of maps',
  1217. ' = [[], []]',
  1218. }, { { type = 9, timestamp = 0, data = { {}, {} } } })
  1219. sd2strings_eq({
  1220. 'Buffer list with timestamp ' .. epoch .. ':',
  1221. ' # Expected array of maps',
  1222. ' = [{"a": 10}, []]',
  1223. }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } })
  1224. sd2strings_eq({
  1225. 'Buffer list with timestamp ' .. epoch .. ':',
  1226. ' % Key Description Value',
  1227. ' # Required key missing: f',
  1228. ' + l line number 1',
  1229. ' + c column 0',
  1230. ' + a 10',
  1231. }, { { type = 9, timestamp = 0, data = { { a = 10 } } } })
  1232. sd2strings_eq({
  1233. 'Buffer list with timestamp ' .. epoch .. ':',
  1234. ' % Key Description Value',
  1235. ' # Required key missing: f',
  1236. ' # Expected integer',
  1237. ' + l line number "10"',
  1238. ' # Expected integer',
  1239. ' + c column "10"',
  1240. ' + a 10',
  1241. }, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } })
  1242. sd2strings_eq({
  1243. 'Buffer list with timestamp ' .. epoch .. ':',
  1244. ' % Key Description Value',
  1245. ' # Required key missing: f',
  1246. ' + l line number 10',
  1247. ' + c column 10',
  1248. ' + a 10',
  1249. }, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } })
  1250. sd2strings_eq({
  1251. 'Buffer list with timestamp ' .. epoch .. ':',
  1252. ' % Key Description Value',
  1253. ' # Required key missing: f',
  1254. ' # Value is negative',
  1255. ' + l line number -10',
  1256. ' # Value is negative',
  1257. ' + c column -10',
  1258. }, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } })
  1259. sd2strings_eq({
  1260. 'Buffer list with timestamp ' .. epoch .. ':',
  1261. ' % Key Description Value',
  1262. ' + f file name "abc"',
  1263. ' + l line number 1',
  1264. ' + c column 0',
  1265. }, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } })
  1266. sd2strings_eq({
  1267. 'Buffer list with timestamp ' .. epoch .. ':',
  1268. ' % Key Description Value',
  1269. ' # Expected binary string',
  1270. ' + f file name 10',
  1271. ' + l line number 1',
  1272. ' + c column 0',
  1273. '',
  1274. ' % Key Description Value',
  1275. ' # Expected binary string',
  1276. ' + f file name 20',
  1277. ' + l line number 1',
  1278. ' + c column 0',
  1279. }, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } })
  1280. sd2strings_eq(
  1281. {
  1282. 'Buffer list with timestamp ' .. epoch .. ':',
  1283. ' % Key Description Value',
  1284. ' # Expected binary string',
  1285. ' + f file name 10',
  1286. ' + l line number 1',
  1287. ' + c column 0',
  1288. '',
  1289. ' % Key Description Value',
  1290. ' # Expected no NUL bytes',
  1291. ' + f file name "\\0"',
  1292. ' + l line number 1',
  1293. ' + c column 0',
  1294. },
  1295. ([[ [{'type': 9, 'timestamp': 0, 'data': [
  1296. {'f': 10},
  1297. {'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]}},
  1298. ]}] ]]):gsub('\n', '')
  1299. )
  1300. end)
  1301. it('works with local mark items', function()
  1302. sd2strings_eq({
  1303. 'Local mark with timestamp ' .. epoch .. ':',
  1304. ' # Unexpected type: array instead of map',
  1305. ' = [1, 2, 3]',
  1306. }, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } })
  1307. sd2strings_eq(
  1308. {
  1309. 'Local mark with timestamp ' .. epoch .. ':',
  1310. ' % Key Description Value',
  1311. ' # Required key missing: f',
  1312. " + n name '\"'",
  1313. ' + l line number 1',
  1314. ' + c column 0',
  1315. },
  1316. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1317. }}] ]]):gsub('\n', '')
  1318. )
  1319. sd2strings_eq(
  1320. {
  1321. 'Local mark with timestamp ' .. epoch .. ':',
  1322. ' % Key Description Value',
  1323. ' # Required key missing: f',
  1324. ' # Expected integer',
  1325. ' + n name "foo"',
  1326. ' + l line number 1',
  1327. ' + c column 0',
  1328. },
  1329. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1330. 'n': 'foo',
  1331. }}] ]]):gsub('\n', '')
  1332. )
  1333. sd2strings_eq(
  1334. {
  1335. 'Local mark with timestamp ' .. epoch .. ':',
  1336. ' % Key Description Value',
  1337. ' + f file name "foo"',
  1338. " + n name '\"'",
  1339. ' + l line number 1',
  1340. ' + c column 0',
  1341. },
  1342. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1343. 'f': 'foo',
  1344. }}] ]]):gsub('\n', '')
  1345. )
  1346. sd2strings_eq(
  1347. {
  1348. 'Local mark with timestamp ' .. epoch .. ':',
  1349. ' % Key Description Value',
  1350. ' # Expected no NUL bytes',
  1351. ' + f file name "\\0"',
  1352. ' # Value is negative',
  1353. ' + n name -10',
  1354. ' + l line number 1',
  1355. ' + c column 0',
  1356. },
  1357. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1358. 'n': -10,
  1359. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
  1360. }}] ]]):gsub('\n', '')
  1361. )
  1362. sd2strings_eq(
  1363. {
  1364. 'Local mark with timestamp ' .. epoch .. ':',
  1365. ' % Key Description Value',
  1366. ' + f file name "foo"',
  1367. " + n name '\\20'",
  1368. ' # Value is negative',
  1369. ' + l line number -10',
  1370. ' # Value is negative',
  1371. ' + c column -10',
  1372. },
  1373. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1374. 'n': 20,
  1375. 'f': 'foo',
  1376. 'l': -10,
  1377. 'c': -10,
  1378. }}] ]]):gsub('\n', '')
  1379. )
  1380. sd2strings_eq(
  1381. {
  1382. 'Local mark with timestamp ' .. epoch .. ':',
  1383. ' % Key Description Value',
  1384. ' + f file name "foo"',
  1385. " + n name '\\20'",
  1386. ' # Expected integer',
  1387. ' + l line number "FOO"',
  1388. ' # Expected integer',
  1389. ' + c column "foo"',
  1390. ' + mX 10',
  1391. },
  1392. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1393. 'n': 20,
  1394. 'f': 'foo',
  1395. 'l': 'FOO',
  1396. 'c': 'foo',
  1397. 'mX': 10,
  1398. }}] ]]):gsub('\n', '')
  1399. )
  1400. sd2strings_eq(
  1401. {
  1402. 'Local mark with timestamp ' .. epoch .. ':',
  1403. ' % Key________ Description Value',
  1404. ' + f file name "foo"',
  1405. " + n name 'a'",
  1406. ' + l line number 2',
  1407. ' + c column 200',
  1408. ' + mX 10',
  1409. ' + mYYYYYYYYYY 10',
  1410. },
  1411. ([[ [{'type': 10, 'timestamp': 0, 'data': {
  1412. 'n': char2nr('a'),
  1413. 'f': 'foo',
  1414. 'l': 2,
  1415. 'c': 200,
  1416. 'mX': 10,
  1417. 'mYYYYYYYYYY': 10,
  1418. }}] ]]):gsub('\n', '')
  1419. )
  1420. end)
  1421. it('works with change items', function()
  1422. sd2strings_eq({
  1423. 'Change with timestamp ' .. epoch .. ':',
  1424. ' # Unexpected type: array instead of map',
  1425. ' = [1, 2, 3]',
  1426. }, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } })
  1427. sd2strings_eq(
  1428. {
  1429. 'Change with timestamp ' .. epoch .. ':',
  1430. ' % Key Description Value',
  1431. ' # Required key missing: f',
  1432. ' + l line number 1',
  1433. ' + c column 0',
  1434. },
  1435. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1436. }}] ]]):gsub('\n', '')
  1437. )
  1438. sd2strings_eq(
  1439. {
  1440. 'Change with timestamp ' .. epoch .. ':',
  1441. ' % Key Description Value',
  1442. ' # Required key missing: f',
  1443. ' + l line number 1',
  1444. ' + c column 0',
  1445. ' # Expected integer',
  1446. ' + n name "foo"',
  1447. },
  1448. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1449. 'n': 'foo',
  1450. }}] ]]):gsub('\n', '')
  1451. )
  1452. sd2strings_eq(
  1453. {
  1454. 'Change with timestamp ' .. epoch .. ':',
  1455. ' % Key Description Value',
  1456. ' + f file name "foo"',
  1457. ' + l line number 1',
  1458. ' + c column 0',
  1459. },
  1460. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1461. 'f': 'foo',
  1462. }}] ]]):gsub('\n', '')
  1463. )
  1464. sd2strings_eq(
  1465. {
  1466. 'Change with timestamp ' .. epoch .. ':',
  1467. ' % Key Description Value',
  1468. ' # Expected no NUL bytes',
  1469. ' + f file name "\\0"',
  1470. ' + l line number 1',
  1471. ' + c column 0',
  1472. ' # Value is negative',
  1473. ' + n name -10',
  1474. },
  1475. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1476. 'n': -10,
  1477. 'f': {'_TYPE': v:msgpack_types.string, '_VAL': ["\n"]},
  1478. }}] ]]):gsub('\n', '')
  1479. )
  1480. sd2strings_eq(
  1481. {
  1482. 'Change with timestamp ' .. epoch .. ':',
  1483. ' % Key Description Value',
  1484. ' + f file name "foo"',
  1485. ' # Value is negative',
  1486. ' + l line number -10',
  1487. ' # Value is negative',
  1488. ' + c column -10',
  1489. },
  1490. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1491. 'f': 'foo',
  1492. 'l': -10,
  1493. 'c': -10,
  1494. }}] ]]):gsub('\n', '')
  1495. )
  1496. sd2strings_eq(
  1497. {
  1498. 'Change with timestamp ' .. epoch .. ':',
  1499. ' % Key Description Value',
  1500. ' + f file name "foo"',
  1501. ' # Expected integer',
  1502. ' + l line number "FOO"',
  1503. ' # Expected integer',
  1504. ' + c column "foo"',
  1505. ' + mX 10',
  1506. },
  1507. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1508. 'f': 'foo',
  1509. 'l': 'FOO',
  1510. 'c': 'foo',
  1511. 'mX': 10,
  1512. }}] ]]):gsub('\n', '')
  1513. )
  1514. sd2strings_eq(
  1515. {
  1516. 'Change with timestamp ' .. epoch .. ':',
  1517. ' % Key________ Description Value',
  1518. ' + f file name "foo"',
  1519. ' + l line number 2',
  1520. ' + c column 200',
  1521. ' + mX 10',
  1522. ' + mYYYYYYYYYY 10',
  1523. " + n name ' '",
  1524. },
  1525. ([[ [{'type': 11, 'timestamp': 0, 'data': {
  1526. 'n': 0x20,
  1527. 'f': 'foo',
  1528. 'l': 2,
  1529. 'c': 200,
  1530. 'mX': 10,
  1531. 'mYYYYYYYYYY': 10,
  1532. }}] ]]):gsub('\n', '')
  1533. )
  1534. end)
  1535. end)
  1536. describe('function shada#get_strings', function()
  1537. it('works', function()
  1538. eq({
  1539. 'Header with timestamp ' .. epoch .. ':',
  1540. ' % Key Value',
  1541. }, nvim_eval('shada#get_strings(msgpackdump([1, 0, 0, {}]))'))
  1542. end)
  1543. end)
  1544. describe('function shada#strings_to_sd', function()
  1545. local strings2sd_eq = function(expected, input)
  1546. api.nvim_set_var('__input', input)
  1547. nvim_command(
  1548. 'let g:__actual = map(shada#strings_to_sd(g:__input), '
  1549. .. '"filter(v:val, \\"v:key[0] isnot# \'_\' '
  1550. .. '&& v:key isnot# \'length\'\\")")'
  1551. )
  1552. -- print()
  1553. if type(expected) == 'table' then
  1554. api.nvim_set_var('__expected', expected)
  1555. nvim_command('let g:__expected = ModifyVal(g:__expected)')
  1556. expected = 'g:__expected'
  1557. -- print(nvim_eval('msgpack#string(g:__expected)'))
  1558. end
  1559. -- print(nvim_eval('msgpack#string(g:__actual)'))
  1560. eq(1, nvim_eval(('msgpack#equal(%s, g:__actual)'):format(expected)))
  1561. if type(expected) == 'table' then
  1562. nvim_command('unlet g:__expected')
  1563. end
  1564. nvim_command('unlet g:__input')
  1565. nvim_command('unlet g:__actual')
  1566. end
  1567. it('works with multiple items', function()
  1568. strings2sd_eq({
  1569. {
  1570. type = 11,
  1571. timestamp = 0,
  1572. data = {
  1573. f = 'foo',
  1574. l = 2,
  1575. c = 200,
  1576. mX = 10,
  1577. mYYYYYYYYYY = 10,
  1578. n = (' '):byte(),
  1579. },
  1580. },
  1581. {
  1582. type = 1,
  1583. timestamp = 0,
  1584. data = {
  1585. c = 'abc',
  1586. f = { '!string', { 'abc\ndef' } },
  1587. l = -10,
  1588. n = -64,
  1589. rc = '10',
  1590. rt = 10,
  1591. sc = { '!nil', 0 },
  1592. sm = 'TRUE',
  1593. so = 'TRUE',
  1594. sp = { '!string', { 'abc' } },
  1595. },
  1596. },
  1597. }, {
  1598. 'Change with timestamp ' .. epoch .. ':',
  1599. ' % Key________ Description Value',
  1600. ' + f file name "foo"',
  1601. ' + l line number 2',
  1602. ' + c column 200',
  1603. ' + mX 10',
  1604. ' + mYYYYYYYYYY 10',
  1605. " + n name ' '",
  1606. 'Header with timestamp ' .. epoch .. ':',
  1607. ' % Key Description____ Value',
  1608. ' # Expected integer',
  1609. ' + c column "abc"',
  1610. ' # Expected no NUL bytes',
  1611. ' + f file name "abc\\0def"',
  1612. ' # Value is negative',
  1613. ' + l line number -10',
  1614. ' # Value is negative',
  1615. ' + n name -64',
  1616. ' # Expected array value',
  1617. ' + rc contents "10"',
  1618. ' # Unexpected enum value: expected one of '
  1619. .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
  1620. ' + rt type 10',
  1621. ' # Expected boolean',
  1622. ' + sc smartcase value NIL',
  1623. ' # Expected boolean',
  1624. ' + sm magic value "TRUE"',
  1625. ' # Expected integer',
  1626. ' + so offset value "TRUE"',
  1627. ' # Expected binary string',
  1628. ' + sp pattern ="abc"',
  1629. })
  1630. end)
  1631. it('works with empty list', function()
  1632. strings2sd_eq({}, {})
  1633. end)
  1634. it('works with header items', function()
  1635. strings2sd_eq({ { type = 1, timestamp = 0, data = {
  1636. generator = 'test',
  1637. } } }, {
  1638. 'Header with timestamp ' .. epoch .. ':',
  1639. ' % Key______ Value',
  1640. ' + generator "test"',
  1641. })
  1642. strings2sd_eq(
  1643. { { type = 1, timestamp = 0, data = {
  1644. 1,
  1645. 2,
  1646. 3,
  1647. } } },
  1648. {
  1649. 'Header with timestamp ' .. epoch .. ':',
  1650. ' # Unexpected type: array instead of map',
  1651. ' = [1, 2, 3]',
  1652. }
  1653. )
  1654. strings2sd_eq({
  1655. {
  1656. type = 1,
  1657. timestamp = 0,
  1658. data = {
  1659. a = 1,
  1660. b = 2,
  1661. c = 3,
  1662. d = 4,
  1663. },
  1664. },
  1665. }, {
  1666. 'Header with timestamp ' .. epoch .. ':',
  1667. ' % Key Description Value',
  1668. ' + a 1',
  1669. ' + b 2',
  1670. ' + c column 3',
  1671. ' + d 4',
  1672. })
  1673. strings2sd_eq({
  1674. {
  1675. type = 1,
  1676. timestamp = 0,
  1677. data = {
  1678. c = 'abc',
  1679. f = { '!string', { 'abc\ndef' } },
  1680. l = -10,
  1681. n = -64,
  1682. rc = '10',
  1683. rt = 10,
  1684. sc = { '!nil', 0 },
  1685. sm = 'TRUE',
  1686. so = 'TRUE',
  1687. sp = { '!string', { 'abc' } },
  1688. },
  1689. },
  1690. }, {
  1691. 'Header with timestamp ' .. epoch .. ':',
  1692. ' % Key Description____ Value',
  1693. ' # Expected integer',
  1694. ' + c column "abc"',
  1695. ' # Expected no NUL bytes',
  1696. ' + f file name "abc\\0def"',
  1697. ' # Value is negative',
  1698. ' + l line number -10',
  1699. ' # Value is negative',
  1700. ' + n name -64',
  1701. ' # Expected array value',
  1702. ' + rc contents "10"',
  1703. ' # Unexpected enum value: expected one of '
  1704. .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
  1705. ' + rt type 10',
  1706. ' # Expected boolean',
  1707. ' + sc smartcase value NIL',
  1708. ' # Expected boolean',
  1709. ' + sm magic value "TRUE"',
  1710. ' # Expected integer',
  1711. ' + so offset value "TRUE"',
  1712. ' # Expected binary string',
  1713. ' + sp pattern ="abc"',
  1714. })
  1715. end)
  1716. it('works with search pattern items', function()
  1717. strings2sd_eq(
  1718. { { type = 2, timestamp = 0, data = {
  1719. 1,
  1720. 2,
  1721. 3,
  1722. } } },
  1723. {
  1724. 'Search pattern with timestamp ' .. epoch .. ':',
  1725. ' # Unexpected type: array instead of map',
  1726. ' = [1, 2, 3]',
  1727. }
  1728. )
  1729. strings2sd_eq({ { type = 2, timestamp = 0, data = {
  1730. sp = 'abc',
  1731. } } }, {
  1732. 'Search pattern with timestamp ' .. epoch .. ':',
  1733. ' % Key Description________ Value',
  1734. ' + sp pattern "abc"',
  1735. ' + sh v:hlsearch value FALSE',
  1736. ' + ss is :s pattern FALSE',
  1737. ' + sm magic value TRUE',
  1738. ' + sc smartcase value FALSE',
  1739. ' + sl has line offset FALSE',
  1740. ' + se place cursor at end FALSE',
  1741. ' + so offset value 0',
  1742. ' + su is last used TRUE',
  1743. })
  1744. strings2sd_eq({
  1745. {
  1746. type = 2,
  1747. timestamp = 0,
  1748. data = {
  1749. sp = 'abc',
  1750. sX = { '!nil', 0 },
  1751. sY = { '!nil', 0 },
  1752. sZ = { '!nil', 0 },
  1753. },
  1754. },
  1755. }, {
  1756. 'Search pattern with timestamp ' .. epoch .. ':',
  1757. ' % Key Description________ Value',
  1758. ' + sp pattern "abc"',
  1759. ' + sh v:hlsearch value FALSE',
  1760. ' + ss is :s pattern FALSE',
  1761. ' + sm magic value TRUE',
  1762. ' + sc smartcase value FALSE',
  1763. ' + sl has line offset FALSE',
  1764. ' + se place cursor at end FALSE',
  1765. ' + so offset value 0',
  1766. ' + su is last used TRUE',
  1767. ' + sX NIL',
  1768. ' + sY NIL',
  1769. ' + sZ NIL',
  1770. })
  1771. strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, {
  1772. 'Search pattern with timestamp ' .. epoch .. ':',
  1773. ' % Key Description________ Value',
  1774. ' # Required key missing: sp',
  1775. ' + sh v:hlsearch value FALSE',
  1776. ' + ss is :s pattern FALSE',
  1777. ' + sm magic value TRUE',
  1778. ' + sc smartcase value FALSE',
  1779. ' + sl has line offset FALSE',
  1780. ' + se place cursor at end FALSE',
  1781. ' + so offset value 0',
  1782. ' + su is last used TRUE',
  1783. })
  1784. strings2sd_eq({
  1785. {
  1786. type = 2,
  1787. timestamp = 0,
  1788. data = {
  1789. sp = '',
  1790. sh = { '!boolean', 1 },
  1791. ss = { '!boolean', 1 },
  1792. sc = { '!boolean', 1 },
  1793. sl = { '!boolean', 1 },
  1794. se = { '!boolean', 1 },
  1795. sm = { '!boolean', 0 },
  1796. su = { '!boolean', 0 },
  1797. so = -10,
  1798. },
  1799. },
  1800. }, {
  1801. 'Search pattern with timestamp ' .. epoch .. ':',
  1802. ' % Key Description________ Value',
  1803. ' + sp pattern ""',
  1804. ' + sh v:hlsearch value TRUE',
  1805. ' + ss is :s pattern TRUE',
  1806. ' + sm magic value FALSE',
  1807. ' + sc smartcase value TRUE',
  1808. ' + sl has line offset TRUE',
  1809. ' + se place cursor at end TRUE',
  1810. ' + so offset value -10',
  1811. ' + su is last used FALSE',
  1812. })
  1813. strings2sd_eq({
  1814. {
  1815. type = 2,
  1816. timestamp = 0,
  1817. data = {
  1818. sp = 0,
  1819. sh = 0,
  1820. ss = 0,
  1821. sc = 0,
  1822. sl = 0,
  1823. se = 0,
  1824. sm = 0,
  1825. su = 0,
  1826. so = '',
  1827. },
  1828. },
  1829. }, {
  1830. 'Search pattern with timestamp ' .. epoch .. ':',
  1831. ' % Key Description________ Value',
  1832. ' # Expected binary string',
  1833. ' + sp pattern 0',
  1834. ' # Expected boolean',
  1835. ' + sh v:hlsearch value 0',
  1836. ' # Expected boolean',
  1837. ' + ss is :s pattern 0',
  1838. ' # Expected boolean',
  1839. ' + sm magic value 0',
  1840. ' # Expected boolean',
  1841. ' + sc smartcase value 0',
  1842. ' # Expected boolean',
  1843. ' + sl has line offset 0',
  1844. ' # Expected boolean',
  1845. ' + se place cursor at end 0',
  1846. ' # Expected integer',
  1847. ' + so offset value ""',
  1848. ' # Expected boolean',
  1849. ' + su is last used 0',
  1850. })
  1851. end)
  1852. it('works with replacement string items', function()
  1853. strings2sd_eq({ { type = 3, timestamp = 0, data = {
  1854. a = { 10 },
  1855. } } }, {
  1856. 'Replacement string with timestamp ' .. epoch .. ':',
  1857. ' # Unexpected type: map instead of array',
  1858. ' = {"a": [10]}',
  1859. })
  1860. strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, {
  1861. 'Replacement string with timestamp ' .. epoch .. ':',
  1862. ' @ Description__________ Value',
  1863. ' # Expected more elements in list',
  1864. })
  1865. strings2sd_eq({ { type = 3, timestamp = 0, data = {
  1866. 0,
  1867. } } }, {
  1868. 'Replacement string with timestamp ' .. epoch .. ':',
  1869. ' @ Description__________ Value',
  1870. ' # Expected binary string',
  1871. ' - :s replacement string 0',
  1872. })
  1873. strings2sd_eq(
  1874. { { type = 3, timestamp = 0, data = {
  1875. 'abc\ndef',
  1876. 0,
  1877. } } },
  1878. {
  1879. 'Replacement string with timestamp ' .. epoch .. ':',
  1880. ' @ Description__________ Value',
  1881. ' - :s replacement string "abc\\ndef"',
  1882. ' - 0',
  1883. }
  1884. )
  1885. strings2sd_eq({ { type = 3, timestamp = 0, data = {
  1886. 'abc\ndef',
  1887. } } }, {
  1888. 'Replacement string with timestamp ' .. epoch .. ':',
  1889. ' @ Description__________ Value',
  1890. ' - :s replacement string "abc\\ndef"',
  1891. })
  1892. end)
  1893. it('works with history entry items', function()
  1894. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1895. a = { 10 },
  1896. } } }, {
  1897. 'History entry with timestamp ' .. epoch .. ':',
  1898. ' # Unexpected type: map instead of array',
  1899. ' = {"a": [10]}',
  1900. })
  1901. strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, {
  1902. 'History entry with timestamp ' .. epoch .. ':',
  1903. ' @ Description_ Value',
  1904. ' # Expected more elements in list',
  1905. })
  1906. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1907. '',
  1908. } } }, {
  1909. 'History entry with timestamp ' .. epoch .. ':',
  1910. ' @ Description_ Value',
  1911. ' # Expected integer',
  1912. ' - history type ""',
  1913. ' # Expected more elements in list',
  1914. })
  1915. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1916. 5,
  1917. '',
  1918. } } }, {
  1919. 'History entry with timestamp ' .. epoch .. ':',
  1920. ' @ Description_ Value',
  1921. ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
  1922. .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
  1923. ' - history type 5',
  1924. ' - contents ""',
  1925. })
  1926. strings2sd_eq(
  1927. { { type = 4, timestamp = 0, data = {
  1928. 5,
  1929. '',
  1930. 32,
  1931. } } },
  1932. {
  1933. 'History entry with timestamp ' .. epoch .. ':',
  1934. ' @ Description_ Value',
  1935. ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
  1936. .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
  1937. ' - history type 5',
  1938. ' - contents ""',
  1939. ' - 32',
  1940. }
  1941. )
  1942. strings2sd_eq(
  1943. { { type = 4, timestamp = 0, data = {
  1944. 0,
  1945. '',
  1946. 32,
  1947. } } },
  1948. {
  1949. 'History entry with timestamp ' .. epoch .. ':',
  1950. ' @ Description_ Value',
  1951. ' - history type CMD',
  1952. ' - contents ""',
  1953. ' - 32',
  1954. }
  1955. )
  1956. strings2sd_eq(
  1957. { { type = 4, timestamp = 0, data = {
  1958. 1,
  1959. '',
  1960. 32,
  1961. } } },
  1962. {
  1963. 'History entry with timestamp ' .. epoch .. ':',
  1964. ' @ Description_ Value',
  1965. ' - history type SEARCH',
  1966. ' - contents ""',
  1967. " - separator ' '",
  1968. }
  1969. )
  1970. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1971. 1,
  1972. '',
  1973. } } }, {
  1974. 'History entry with timestamp ' .. epoch .. ':',
  1975. ' @ Description_ Value',
  1976. ' - history type SEARCH',
  1977. ' - contents ""',
  1978. ' # Expected more elements in list',
  1979. })
  1980. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1981. 2,
  1982. '',
  1983. } } }, {
  1984. 'History entry with timestamp ' .. epoch .. ':',
  1985. ' @ Description_ Value',
  1986. ' - history type EXPR',
  1987. ' - contents ""',
  1988. })
  1989. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1990. 3,
  1991. '',
  1992. } } }, {
  1993. 'History entry with timestamp ' .. epoch .. ':',
  1994. ' @ Description_ Value',
  1995. ' - history type INPUT',
  1996. ' - contents ""',
  1997. })
  1998. strings2sd_eq({ { type = 4, timestamp = 0, data = {
  1999. 4,
  2000. '',
  2001. } } }, {
  2002. 'History entry with timestamp ' .. epoch .. ':',
  2003. ' @ Description_ Value',
  2004. ' - history type DEBUG',
  2005. ' - contents ""',
  2006. })
  2007. end)
  2008. it('works with register items', function()
  2009. strings2sd_eq(
  2010. { { type = 5, timestamp = 0, data = {
  2011. 1,
  2012. 2,
  2013. 3,
  2014. } } },
  2015. {
  2016. 'Register with timestamp ' .. epoch .. ':',
  2017. ' # Unexpected type: array instead of map',
  2018. ' = [1, 2, 3]',
  2019. }
  2020. )
  2021. strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, {
  2022. 'Register with timestamp ' .. epoch .. ':',
  2023. ' % Key Description Value',
  2024. ' # Required key missing: n',
  2025. ' # Required key missing: rc',
  2026. ' + rw block width 0',
  2027. ' + rt type CHARACTERWISE',
  2028. })
  2029. strings2sd_eq({ { type = 5, timestamp = 0, data = {
  2030. n = (' '):byte(),
  2031. } } }, {
  2032. 'Register with timestamp ' .. epoch .. ':',
  2033. ' % Key Description Value',
  2034. " + n name ' '",
  2035. ' # Required key missing: rc',
  2036. ' + rw block width 0',
  2037. ' + rt type CHARACTERWISE',
  2038. })
  2039. strings2sd_eq({
  2040. {
  2041. type = 5,
  2042. timestamp = 0,
  2043. data = {
  2044. n = (' '):byte(),
  2045. rc = { 'abc', 'def' },
  2046. },
  2047. },
  2048. }, {
  2049. 'Register with timestamp ' .. epoch .. ':',
  2050. ' % Key Description Value',
  2051. " + n name ' '",
  2052. ' + rc contents ["abc", "def"]',
  2053. ' + rw block width 0',
  2054. ' + rt type CHARACTERWISE',
  2055. })
  2056. strings2sd_eq({
  2057. {
  2058. type = 5,
  2059. timestamp = 0,
  2060. data = {
  2061. n = (' '):byte(),
  2062. rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
  2063. },
  2064. },
  2065. }, {
  2066. 'Register with timestamp ' .. epoch .. ':',
  2067. ' % Key Description Value',
  2068. " + n name ' '",
  2069. ' + rc contents @',
  2070. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2071. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2072. ' + rw block width 0',
  2073. ' + rt type CHARACTERWISE',
  2074. })
  2075. strings2sd_eq({
  2076. {
  2077. type = 5,
  2078. timestamp = 0,
  2079. data = {
  2080. n = (' '):byte(),
  2081. rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
  2082. rw = 5,
  2083. rt = 1,
  2084. },
  2085. },
  2086. }, {
  2087. 'Register with timestamp ' .. epoch .. ':',
  2088. ' % Key Description Value',
  2089. " + n name ' '",
  2090. ' + rc contents @',
  2091. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2092. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2093. ' + rw block width 5',
  2094. ' + rt type LINEWISE',
  2095. })
  2096. strings2sd_eq({
  2097. {
  2098. type = 5,
  2099. timestamp = 0,
  2100. data = {
  2101. n = (' '):byte(),
  2102. rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
  2103. rw = 5,
  2104. rt = 2,
  2105. },
  2106. },
  2107. }, {
  2108. 'Register with timestamp ' .. epoch .. ':',
  2109. ' % Key Description Value',
  2110. " + n name ' '",
  2111. ' + rc contents @',
  2112. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2113. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2114. ' + rw block width 5',
  2115. ' + rt type BLOCKWISE',
  2116. })
  2117. strings2sd_eq({
  2118. {
  2119. type = 5,
  2120. timestamp = 0,
  2121. data = {
  2122. n = (' '):byte(),
  2123. rc = 0,
  2124. rw = -1,
  2125. rt = 10,
  2126. },
  2127. },
  2128. }, {
  2129. 'Register with timestamp ' .. epoch .. ':',
  2130. ' % Key Description Value',
  2131. " + n name ' '",
  2132. ' # Expected array value',
  2133. ' + rc contents 0',
  2134. ' # Value is negative',
  2135. ' + rw block width -1',
  2136. ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
  2137. .. '1 (LINEWISE), 2 (BLOCKWISE)',
  2138. ' + rt type 10',
  2139. })
  2140. end)
  2141. it('works with variable items', function()
  2142. strings2sd_eq({ { type = 6, timestamp = 0, data = {
  2143. a = { 10 },
  2144. } } }, {
  2145. 'Variable with timestamp ' .. epoch .. ':',
  2146. ' # Unexpected type: map instead of array',
  2147. ' = {"a": [10]}',
  2148. })
  2149. strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, {
  2150. 'Variable with timestamp ' .. epoch .. ':',
  2151. ' @ Description Value',
  2152. ' # Expected more elements in list',
  2153. })
  2154. strings2sd_eq({ { type = 6, timestamp = 0, data = {
  2155. 'foo',
  2156. } } }, {
  2157. 'Variable with timestamp ' .. epoch .. ':',
  2158. ' @ Description Value',
  2159. ' - name "foo"',
  2160. ' # Expected more elements in list',
  2161. })
  2162. strings2sd_eq({
  2163. {
  2164. type = 6,
  2165. timestamp = 0,
  2166. data = {
  2167. 'foo',
  2168. { '!nil', 0 },
  2169. },
  2170. },
  2171. }, {
  2172. 'Variable with timestamp ' .. epoch .. ':',
  2173. ' @ Description Value',
  2174. ' - name "foo"',
  2175. ' - value NIL',
  2176. })
  2177. strings2sd_eq({
  2178. {
  2179. type = 6,
  2180. timestamp = 0,
  2181. data = {
  2182. 'foo',
  2183. { '!nil', 0 },
  2184. { '!nil', 0 },
  2185. },
  2186. },
  2187. }, {
  2188. 'Variable with timestamp ' .. epoch .. ':',
  2189. ' @ Description Value',
  2190. ' - name "foo"',
  2191. ' - value NIL',
  2192. ' - NIL',
  2193. })
  2194. end)
  2195. it('works with global mark items', function()
  2196. strings2sd_eq(
  2197. { { type = 7, timestamp = 0, data = {
  2198. 1,
  2199. 2,
  2200. 3,
  2201. } } },
  2202. {
  2203. 'Global mark with timestamp ' .. epoch .. ':',
  2204. ' # Unexpected type: array instead of map',
  2205. ' = [1, 2, 3]',
  2206. }
  2207. )
  2208. strings2sd_eq({
  2209. {
  2210. type = 7,
  2211. timestamp = 0,
  2212. data = {
  2213. n = ('A'):byte(),
  2214. f = 'foo',
  2215. l = 2,
  2216. c = 200,
  2217. mX = 10,
  2218. mYYYYYYYYYY = 10,
  2219. },
  2220. },
  2221. }, {
  2222. 'Global mark with timestamp ' .. epoch .. ':',
  2223. ' % Key________ Description Value',
  2224. " + n name 'A'",
  2225. ' + f file name "foo"',
  2226. ' + l line number 2',
  2227. ' + c column 200',
  2228. ' + mX 10',
  2229. ' + mYYYYYYYYYY 10',
  2230. })
  2231. end)
  2232. it('works with jump items', function()
  2233. strings2sd_eq(
  2234. { { type = 8, timestamp = 0, data = {
  2235. 1,
  2236. 2,
  2237. 3,
  2238. } } },
  2239. {
  2240. 'Jump with timestamp ' .. epoch .. ':',
  2241. ' # Unexpected type: array instead of map',
  2242. ' = [1, 2, 3]',
  2243. }
  2244. )
  2245. strings2sd_eq({
  2246. {
  2247. type = 8,
  2248. timestamp = 0,
  2249. data = {
  2250. n = ('A'):byte(),
  2251. f = 'foo',
  2252. l = 2,
  2253. c = 200,
  2254. mX = 10,
  2255. mYYYYYYYYYY = 10,
  2256. },
  2257. },
  2258. }, {
  2259. 'Jump with timestamp ' .. epoch .. ':',
  2260. ' % Key________ Description Value',
  2261. " + n name 'A'",
  2262. ' + f file name "foo"',
  2263. ' + l line number 2',
  2264. ' + c column 200',
  2265. ' + mX 10',
  2266. ' + mYYYYYYYYYY 10',
  2267. })
  2268. end)
  2269. it('works with buffer list items', function()
  2270. strings2sd_eq({ { type = 9, timestamp = 0, data = {
  2271. a = { 10 },
  2272. } } }, {
  2273. 'Buffer list with timestamp ' .. epoch .. ':',
  2274. ' # Unexpected type: map instead of array',
  2275. ' = {"a": [10]}',
  2276. })
  2277. strings2sd_eq(
  2278. { { type = 9, timestamp = 0, data = {
  2279. { a = 10 },
  2280. {},
  2281. } } },
  2282. {
  2283. 'Buffer list with timestamp ' .. epoch .. ':',
  2284. ' # Expected array of maps',
  2285. ' = [{"a": 10}, []]',
  2286. }
  2287. )
  2288. strings2sd_eq({ { type = 9, timestamp = 0, data = {
  2289. { a = 10 },
  2290. } } }, {
  2291. 'Buffer list with timestamp ' .. epoch .. ':',
  2292. ' % Key Description Value',
  2293. ' # Required key missing: f',
  2294. ' + l line number 1',
  2295. ' + c column 0',
  2296. ' + a 10',
  2297. })
  2298. strings2sd_eq({
  2299. {
  2300. type = 9,
  2301. timestamp = 0,
  2302. data = {
  2303. { l = '10', c = '10', a = 10 },
  2304. },
  2305. },
  2306. }, {
  2307. 'Buffer list with timestamp ' .. epoch .. ':',
  2308. ' % Key Description Value',
  2309. ' # Required key missing: f',
  2310. ' # Expected integer',
  2311. ' + l line number "10"',
  2312. ' # Expected integer',
  2313. ' + c column "10"',
  2314. ' + a 10',
  2315. })
  2316. strings2sd_eq(
  2317. { { type = 9, timestamp = 0, data = {
  2318. { l = 10, c = 10, a = 10 },
  2319. } } },
  2320. {
  2321. 'Buffer list with timestamp ' .. epoch .. ':',
  2322. ' % Key Description Value',
  2323. ' # Required key missing: f',
  2324. ' + l line number 10',
  2325. ' + c column 10',
  2326. ' + a 10',
  2327. }
  2328. )
  2329. strings2sd_eq(
  2330. { { type = 9, timestamp = 0, data = {
  2331. { l = -10, c = -10 },
  2332. } } },
  2333. {
  2334. 'Buffer list with timestamp ' .. epoch .. ':',
  2335. ' % Key Description Value',
  2336. ' # Required key missing: f',
  2337. ' # Value is negative',
  2338. ' + l line number -10',
  2339. ' # Value is negative',
  2340. ' + c column -10',
  2341. }
  2342. )
  2343. strings2sd_eq({ { type = 9, timestamp = 0, data = {
  2344. { f = 'abc' },
  2345. } } }, {
  2346. 'Buffer list with timestamp ' .. epoch .. ':',
  2347. ' % Key Description Value',
  2348. ' + f file name "abc"',
  2349. ' + l line number 1',
  2350. ' + c column 0',
  2351. })
  2352. strings2sd_eq({
  2353. {
  2354. type = 9,
  2355. timestamp = 0,
  2356. data = {
  2357. { f = 10 },
  2358. { f = 20 },
  2359. },
  2360. },
  2361. }, {
  2362. 'Buffer list with timestamp ' .. epoch .. ':',
  2363. ' % Key Description Value',
  2364. ' # Expected binary string',
  2365. " + f file name '\\10'",
  2366. ' + l line number 1',
  2367. ' + c column 0',
  2368. '',
  2369. ' % Key Description Value',
  2370. ' # Expected binary string',
  2371. " + f file name '\\20'",
  2372. ' + l line number 1',
  2373. ' + c column 0',
  2374. })
  2375. strings2sd_eq({
  2376. {
  2377. type = 9,
  2378. timestamp = 0,
  2379. data = {
  2380. { f = 10 },
  2381. { f = { '!string', { '\n' } } },
  2382. },
  2383. },
  2384. }, {
  2385. 'Buffer list with timestamp ' .. epoch .. ':',
  2386. ' % Key Description Value',
  2387. ' # Expected binary string',
  2388. " + f file name '\\10'",
  2389. ' + l line number 1',
  2390. ' + c column 0',
  2391. '',
  2392. ' % Key Description Value',
  2393. ' # Expected no NUL bytes',
  2394. ' + f file name "\\0"',
  2395. ' + l line number 1',
  2396. ' + c column 0',
  2397. })
  2398. end)
  2399. it('works with local mark items', function()
  2400. strings2sd_eq(
  2401. { { type = 10, timestamp = 0, data = {
  2402. 1,
  2403. 2,
  2404. 3,
  2405. } } },
  2406. {
  2407. 'Local mark with timestamp ' .. epoch .. ':',
  2408. ' # Unexpected type: array instead of map',
  2409. ' = [1, 2, 3]',
  2410. }
  2411. )
  2412. strings2sd_eq({
  2413. {
  2414. type = 10,
  2415. timestamp = 0,
  2416. data = {
  2417. n = ('A'):byte(),
  2418. f = 'foo',
  2419. l = 2,
  2420. c = 200,
  2421. mX = 10,
  2422. mYYYYYYYYYY = 10,
  2423. },
  2424. },
  2425. }, {
  2426. 'Local mark with timestamp ' .. epoch .. ':',
  2427. ' % Key________ Description Value',
  2428. " + n name 'A'",
  2429. ' + f file name "foo"',
  2430. ' + l line number 2',
  2431. ' + c column 200',
  2432. ' + mX 10',
  2433. ' + mYYYYYYYYYY 10',
  2434. })
  2435. end)
  2436. it('works with change items', function()
  2437. strings2sd_eq(
  2438. { { type = 11, timestamp = 0, data = {
  2439. 1,
  2440. 2,
  2441. 3,
  2442. } } },
  2443. {
  2444. 'Change with timestamp ' .. epoch .. ':',
  2445. ' # Unexpected type: array instead of map',
  2446. ' = [1, 2, 3]',
  2447. }
  2448. )
  2449. strings2sd_eq({
  2450. {
  2451. type = 11,
  2452. timestamp = 0,
  2453. data = {
  2454. n = ('A'):byte(),
  2455. f = 'foo',
  2456. l = 2,
  2457. c = 200,
  2458. mX = 10,
  2459. mYYYYYYYYYY = 10,
  2460. },
  2461. },
  2462. }, {
  2463. 'Change with timestamp ' .. epoch .. ':',
  2464. ' % Key________ Description Value',
  2465. " + n name 'A'",
  2466. ' + f file name "foo"',
  2467. ' + l line number 2',
  2468. ' + c column 200',
  2469. ' + mX 10',
  2470. ' + mYYYYYYYYYY 10',
  2471. })
  2472. end)
  2473. end)
  2474. describe('function shada#get_binstrings', function()
  2475. local getbstrings_eq = function(expected, input)
  2476. local result = fn['shada#get_binstrings'](input)
  2477. for i, s in ipairs(result) do
  2478. result[i] = s:gsub('\n', '\0')
  2479. end
  2480. local mpack_result = table.concat(result, '\n')
  2481. return mpack_eq(expected, mpack_result)
  2482. end
  2483. it('works', function()
  2484. local version = api.nvim_get_vvar('version')
  2485. getbstrings_eq({
  2486. {
  2487. timestamp = 'current',
  2488. type = 1,
  2489. value = {
  2490. generator = 'shada.vim',
  2491. version = version,
  2492. },
  2493. },
  2494. }, {})
  2495. getbstrings_eq({
  2496. {
  2497. timestamp = 'current',
  2498. type = 1,
  2499. value = {
  2500. generator = 'shada.vim',
  2501. version = version,
  2502. },
  2503. },
  2504. { timestamp = 0, type = 1, value = { generator = 'test' } },
  2505. }, {
  2506. 'Header with timestamp ' .. epoch .. ':',
  2507. ' % Key______ Value',
  2508. ' + generator "test"',
  2509. })
  2510. api.nvim_set_var('shada#add_own_header', 1)
  2511. getbstrings_eq({
  2512. {
  2513. timestamp = 'current',
  2514. type = 1,
  2515. value = {
  2516. generator = 'shada.vim',
  2517. version = version,
  2518. },
  2519. },
  2520. }, {})
  2521. getbstrings_eq({
  2522. {
  2523. timestamp = 'current',
  2524. type = 1,
  2525. value = {
  2526. generator = 'shada.vim',
  2527. version = version,
  2528. },
  2529. },
  2530. { timestamp = 0, type = 1, value = { generator = 'test' } },
  2531. }, {
  2532. 'Header with timestamp ' .. epoch .. ':',
  2533. ' % Key______ Value',
  2534. ' + generator "test"',
  2535. })
  2536. api.nvim_set_var('shada#add_own_header', 0)
  2537. getbstrings_eq({}, {})
  2538. getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, {
  2539. 'Header with timestamp ' .. epoch .. ':',
  2540. ' % Key______ Value',
  2541. ' + generator "test"',
  2542. })
  2543. api.nvim_set_var('shada#keep_old_header', 0)
  2544. getbstrings_eq({}, {
  2545. 'Header with timestamp ' .. epoch .. ':',
  2546. ' % Key______ Value',
  2547. ' + generator "test"',
  2548. })
  2549. getbstrings_eq({
  2550. { type = 3, timestamp = 0, value = { 'abc\ndef' } },
  2551. { type = 3, timestamp = 0, value = { 'abc\ndef' } },
  2552. { type = 3, timestamp = 0, value = { 'abc\ndef' } },
  2553. }, {
  2554. 'Replacement string with timestamp ' .. epoch .. ':',
  2555. ' @ Description__________ Value',
  2556. ' - :s replacement string "abc\\ndef"',
  2557. 'Replacement string with timestamp ' .. epoch .. ':',
  2558. ' @ Description__________ Value',
  2559. ' - :s replacement string "abc\\ndef"',
  2560. 'Replacement string with timestamp ' .. epoch .. ':',
  2561. ' @ Description__________ Value',
  2562. ' - :s replacement string "abc\\ndef"',
  2563. })
  2564. end)
  2565. end)
  2566. end)
  2567. describe('plugin/shada.vim', function()
  2568. local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
  2569. local eol = t.is_os('win') and '\r\n' or '\n'
  2570. before_each(function()
  2571. -- Note: reset() is called explicitly in each test.
  2572. os.remove(fname)
  2573. os.remove(fname .. '.tst')
  2574. os.remove(fname_tmp)
  2575. end)
  2576. teardown(function()
  2577. os.remove(fname)
  2578. os.remove(fname .. '.tst')
  2579. os.remove(fname_tmp)
  2580. end)
  2581. local shada_eq = function(expected, fname_)
  2582. local mpack_result = read_file(fname_)
  2583. mpack_eq(expected, mpack_result)
  2584. end
  2585. it('event BufReadCmd', function()
  2586. reset()
  2587. wshada('\004\000\009\147\000\196\002ab\196\001a')
  2588. wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
  2589. local bufread_commands =
  2590. api.nvim_get_autocmds({ group = 'ShaDaCommands', event = 'BufReadCmd' })
  2591. eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]])
  2592. -- Need to set nohidden so that the buffer containing 'fname' is not unloaded
  2593. -- after loading 'fname_tmp', otherwise the '++opt not supported' test below
  2594. -- won't work since the BufReadCmd autocmd won't be triggered.
  2595. nvim_command('set nohidden')
  2596. nvim_command('edit ' .. fname)
  2597. eq({
  2598. 'History entry with timestamp ' .. epoch .. ':',
  2599. ' @ Description_ Value',
  2600. ' - history type CMD',
  2601. ' - contents "ab"',
  2602. ' - "a"',
  2603. }, nvim_eval('getline(1, "$")'))
  2604. eq(false, api.nvim_get_option_value('modified', {}))
  2605. eq('shada', api.nvim_get_option_value('filetype', {}))
  2606. nvim_command('edit ' .. fname_tmp)
  2607. eq({
  2608. 'History entry with timestamp ' .. epoch .. ':',
  2609. ' @ Description_ Value',
  2610. ' - history type CMD',
  2611. ' - contents "ab"',
  2612. ' - "b"',
  2613. }, nvim_eval('getline(1, "$")'))
  2614. eq(false, api.nvim_get_option_value('modified', {}))
  2615. eq('shada', api.nvim_get_option_value('filetype', {}))
  2616. eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname))
  2617. neq({
  2618. 'History entry with timestamp ' .. epoch .. ':',
  2619. ' @ Description_ Value',
  2620. ' - history type CMD',
  2621. ' - contents "ab"',
  2622. ' - "a"',
  2623. }, nvim_eval('getline(1, "$")'))
  2624. neq(true, api.nvim_get_option_value('modified', {}))
  2625. end)
  2626. it('event FileReadCmd', function()
  2627. reset()
  2628. wshada('\004\000\009\147\000\196\002ab\196\001a')
  2629. wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
  2630. nvim_command('$read ' .. fname)
  2631. eq({
  2632. '',
  2633. 'History entry with timestamp ' .. epoch .. ':',
  2634. ' @ Description_ Value',
  2635. ' - history type CMD',
  2636. ' - contents "ab"',
  2637. ' - "a"',
  2638. }, nvim_eval('getline(1, "$")'))
  2639. eq(true, api.nvim_get_option_value('modified', {}))
  2640. neq('shada', api.nvim_get_option_value('filetype', {}))
  2641. nvim_command('1,$read ' .. fname_tmp)
  2642. eq({
  2643. '',
  2644. 'History entry with timestamp ' .. epoch .. ':',
  2645. ' @ Description_ Value',
  2646. ' - history type CMD',
  2647. ' - contents "ab"',
  2648. ' - "a"',
  2649. 'History entry with timestamp ' .. epoch .. ':',
  2650. ' @ Description_ Value',
  2651. ' - history type CMD',
  2652. ' - contents "ab"',
  2653. ' - "b"',
  2654. }, nvim_eval('getline(1, "$")'))
  2655. eq(true, api.nvim_get_option_value('modified', {}))
  2656. neq('shada', api.nvim_get_option_value('filetype', {}))
  2657. api.nvim_set_option_value('modified', false, {})
  2658. eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname))
  2659. eq({
  2660. '',
  2661. 'History entry with timestamp ' .. epoch .. ':',
  2662. ' @ Description_ Value',
  2663. ' - history type CMD',
  2664. ' - contents "ab"',
  2665. ' - "a"',
  2666. 'History entry with timestamp ' .. epoch .. ':',
  2667. ' @ Description_ Value',
  2668. ' - history type CMD',
  2669. ' - contents "ab"',
  2670. ' - "b"',
  2671. }, nvim_eval('getline(1, "$")'))
  2672. neq(true, api.nvim_get_option_value('modified', {}))
  2673. end)
  2674. it('event BufWriteCmd', function()
  2675. reset()
  2676. api.nvim_set_var('shada#add_own_header', 0)
  2677. api.nvim_buf_set_lines(0, 0, 1, true, {
  2678. 'Jump with timestamp ' .. epoch .. ':',
  2679. ' % Key________ Description Value',
  2680. " + n name 'A'",
  2681. ' + f file name ["foo"]',
  2682. ' + l line number 2',
  2683. ' + c column -200',
  2684. 'Jump with timestamp ' .. epoch .. ':',
  2685. ' % Key________ Description Value',
  2686. " + n name 'A'",
  2687. ' + f file name ["foo"]',
  2688. ' + l line number 2',
  2689. ' + c column -200',
  2690. })
  2691. nvim_command('w ' .. fname .. '.tst')
  2692. nvim_command('w ' .. fname)
  2693. nvim_command('w ' .. fname_tmp)
  2694. eq('++opt not supported', exc_exec('w! ++enc=latin1 ' .. fname))
  2695. eq(table.concat({
  2696. 'Jump with timestamp ' .. epoch .. ':',
  2697. ' % Key________ Description Value',
  2698. " + n name 'A'",
  2699. ' + f file name ["foo"]',
  2700. ' + l line number 2',
  2701. ' + c column -200',
  2702. 'Jump with timestamp ' .. epoch .. ':',
  2703. ' % Key________ Description Value',
  2704. " + n name 'A'",
  2705. ' + f file name ["foo"]',
  2706. ' + l line number 2',
  2707. ' + c column -200',
  2708. }, eol) .. eol, read_file(fname .. '.tst'))
  2709. shada_eq({
  2710. {
  2711. timestamp = 0,
  2712. type = 8,
  2713. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2714. },
  2715. {
  2716. timestamp = 0,
  2717. type = 8,
  2718. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2719. },
  2720. }, fname)
  2721. shada_eq({
  2722. {
  2723. timestamp = 0,
  2724. type = 8,
  2725. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2726. },
  2727. {
  2728. timestamp = 0,
  2729. type = 8,
  2730. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2731. },
  2732. }, fname_tmp)
  2733. end)
  2734. it('event FileWriteCmd', function()
  2735. reset()
  2736. api.nvim_set_var('shada#add_own_header', 0)
  2737. api.nvim_buf_set_lines(0, 0, 1, true, {
  2738. 'Jump with timestamp ' .. epoch .. ':',
  2739. ' % Key________ Description Value',
  2740. " + n name 'A'",
  2741. ' + f file name ["foo"]',
  2742. ' + l line number 2',
  2743. ' + c column -200',
  2744. 'Jump with timestamp ' .. epoch .. ':',
  2745. ' % Key________ Description Value',
  2746. " + n name 'A'",
  2747. ' + f file name ["foo"]',
  2748. ' + l line number 2',
  2749. ' + c column -200',
  2750. })
  2751. nvim_command('1,3w ' .. fname .. '.tst')
  2752. nvim_command('1,3w ' .. fname)
  2753. nvim_command('1,3w ' .. fname_tmp)
  2754. eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 ' .. fname))
  2755. eq(table.concat({
  2756. 'Jump with timestamp ' .. epoch .. ':',
  2757. ' % Key________ Description Value',
  2758. " + n name 'A'",
  2759. }, eol) .. eol, read_file(fname .. '.tst'))
  2760. shada_eq(
  2761. { {
  2762. timestamp = 0,
  2763. type = 8,
  2764. value = { n = ('A'):byte() },
  2765. } },
  2766. fname
  2767. )
  2768. shada_eq(
  2769. { {
  2770. timestamp = 0,
  2771. type = 8,
  2772. value = { n = ('A'):byte() },
  2773. } },
  2774. fname_tmp
  2775. )
  2776. end)
  2777. it('event FileAppendCmd', function()
  2778. reset()
  2779. api.nvim_set_var('shada#add_own_header', 0)
  2780. api.nvim_buf_set_lines(0, 0, 1, true, {
  2781. 'Jump with timestamp ' .. epoch .. ':',
  2782. ' % Key________ Description Value',
  2783. " + n name 'A'",
  2784. ' + f file name ["foo"]',
  2785. ' + l line number 2',
  2786. ' + c column -200',
  2787. 'Jump with timestamp ' .. epoch .. ':',
  2788. ' % Key________ Description Value',
  2789. " + n name 'A'",
  2790. ' + f file name ["foo"]',
  2791. ' + l line number 2',
  2792. ' + c column -200',
  2793. })
  2794. fn.writefile({ '' }, fname .. '.tst', 'b')
  2795. fn.writefile({ '' }, fname, 'b')
  2796. fn.writefile({ '' }, fname_tmp, 'b')
  2797. nvim_command('1,3w >> ' .. fname .. '.tst')
  2798. nvim_command('1,3w >> ' .. fname)
  2799. nvim_command('1,3w >> ' .. fname_tmp)
  2800. nvim_command('w >> ' .. fname .. '.tst')
  2801. nvim_command('w >> ' .. fname)
  2802. nvim_command('w >> ' .. fname_tmp)
  2803. eq('++opt not supported', exc_exec('1,3w! ++enc=latin1 >> ' .. fname))
  2804. eq(table.concat({
  2805. 'Jump with timestamp ' .. epoch .. ':',
  2806. ' % Key________ Description Value',
  2807. " + n name 'A'",
  2808. 'Jump with timestamp ' .. epoch .. ':',
  2809. ' % Key________ Description Value',
  2810. " + n name 'A'",
  2811. ' + f file name ["foo"]',
  2812. ' + l line number 2',
  2813. ' + c column -200',
  2814. 'Jump with timestamp ' .. epoch .. ':',
  2815. ' % Key________ Description Value',
  2816. " + n name 'A'",
  2817. ' + f file name ["foo"]',
  2818. ' + l line number 2',
  2819. ' + c column -200',
  2820. }, eol) .. eol, read_file(fname .. '.tst'))
  2821. shada_eq({
  2822. {
  2823. timestamp = 0,
  2824. type = 8,
  2825. value = { n = ('A'):byte() },
  2826. },
  2827. {
  2828. timestamp = 0,
  2829. type = 8,
  2830. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2831. },
  2832. {
  2833. timestamp = 0,
  2834. type = 8,
  2835. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2836. },
  2837. }, fname)
  2838. shada_eq({
  2839. {
  2840. timestamp = 0,
  2841. type = 8,
  2842. value = { n = ('A'):byte() },
  2843. },
  2844. {
  2845. timestamp = 0,
  2846. type = 8,
  2847. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2848. },
  2849. {
  2850. timestamp = 0,
  2851. type = 8,
  2852. value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
  2853. },
  2854. }, fname_tmp)
  2855. end)
  2856. it('event SourceCmd', function()
  2857. reset(fname)
  2858. finally(function()
  2859. nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit
  2860. end)
  2861. wshada('\004\000\006\146\000\196\002ab')
  2862. wshada_tmp('\004\001\006\146\000\196\002bc')
  2863. eq(0, exc_exec('source ' .. fname))
  2864. eq(0, exc_exec('source ' .. fname_tmp))
  2865. eq('bc', fn.histget(':', -1))
  2866. eq('ab', fn.histget(':', -2))
  2867. end)
  2868. end)
  2869. describe('ftplugin/shada.vim', function()
  2870. local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
  2871. before_each(reset)
  2872. it('sets indentexpr correctly', function()
  2873. nvim_command('filetype plugin indent on')
  2874. nvim_command('setlocal filetype=shada')
  2875. fn.setline(1, {
  2876. 'Jump with timestamp ' .. epoch .. ':',
  2877. '% Key________ Description Value',
  2878. "+ n name 'A'",
  2879. '+ f file name "foo"',
  2880. '+ l line number 2',
  2881. '+ c column 200',
  2882. '+ mX 10',
  2883. '+ mYYYYYYYYYY 10',
  2884. 'Register with timestamp ' .. epoch .. ':',
  2885. '% Key Description Value',
  2886. "+ n name ' '",
  2887. '+ rc contents @',
  2888. '| - "abcdefghijklmnopqrstuvwxyz"',
  2889. '| - "abcdefghijklmnopqrstuvwxyz"',
  2890. '+ rw block width 0',
  2891. '+ rt type CHARACTERWISE',
  2892. 'Replacement string with timestamp ' .. epoch .. ':',
  2893. ' @ Description__________ Value',
  2894. ' - :s replacement string "abc\\ndef"',
  2895. ' Buffer list with timestamp ' .. epoch .. ':',
  2896. ' # Expected array of maps',
  2897. '= [{"a": 10}, []]',
  2898. ' Buffer list with timestamp ' .. epoch .. ':',
  2899. ' % Key Description Value',
  2900. ' # Expected binary string',
  2901. '+ f file name 10',
  2902. ' + l line number 1',
  2903. ' + c column 0',
  2904. '',
  2905. ' % Key Description Value',
  2906. ' # Expected binary string',
  2907. ' + f file name 20',
  2908. '+ l line number 1',
  2909. ' + c column 0',
  2910. })
  2911. nvim_command('normal! gg=G')
  2912. eq({
  2913. 'Jump with timestamp ' .. epoch .. ':',
  2914. ' % Key________ Description Value',
  2915. " + n name 'A'",
  2916. ' + f file name "foo"',
  2917. ' + l line number 2',
  2918. ' + c column 200',
  2919. ' + mX 10',
  2920. ' + mYYYYYYYYYY 10',
  2921. 'Register with timestamp ' .. epoch .. ':',
  2922. ' % Key Description Value',
  2923. " + n name ' '",
  2924. ' + rc contents @',
  2925. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2926. ' | - "abcdefghijklmnopqrstuvwxyz"',
  2927. ' + rw block width 0',
  2928. ' + rt type CHARACTERWISE',
  2929. 'Replacement string with timestamp ' .. epoch .. ':',
  2930. ' @ Description__________ Value',
  2931. ' - :s replacement string "abc\\ndef"',
  2932. 'Buffer list with timestamp ' .. epoch .. ':',
  2933. ' # Expected array of maps',
  2934. ' = [{"a": 10}, []]',
  2935. 'Buffer list with timestamp ' .. epoch .. ':',
  2936. ' % Key Description Value',
  2937. ' # Expected binary string',
  2938. ' + f file name 10',
  2939. ' + l line number 1',
  2940. ' + c column 0',
  2941. '',
  2942. ' % Key Description Value',
  2943. ' # Expected binary string',
  2944. ' + f file name 20',
  2945. ' + l line number 1',
  2946. ' + c column 0',
  2947. }, fn.getline(1, fn.line('$')))
  2948. end)
  2949. it('sets options correctly', function()
  2950. nvim_command('filetype plugin indent on')
  2951. nvim_command('setlocal filetype=shada')
  2952. eq(true, api.nvim_get_option_value('expandtab', {}))
  2953. eq(2, api.nvim_get_option_value('tabstop', {}))
  2954. eq(2, api.nvim_get_option_value('softtabstop', {}))
  2955. eq(2, api.nvim_get_option_value('shiftwidth', {}))
  2956. end)
  2957. it('sets indentkeys correctly', function()
  2958. nvim_command('filetype plugin indent on')
  2959. nvim_command('setlocal filetype=shada')
  2960. fn.setline(1, ' Replacement with timestamp ' .. epoch)
  2961. nvim_feed('ggA:\027')
  2962. eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1])
  2963. nvim_feed('o-\027')
  2964. eq({ ' -' }, api.nvim_buf_get_lines(0, 1, 2, true))
  2965. nvim_feed('ggO+\027')
  2966. eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true))
  2967. nvim_feed('GO*\027')
  2968. eq({ ' *' }, api.nvim_buf_get_lines(0, 2, 3, true))
  2969. nvim_feed('ggO /\027')
  2970. eq({ ' /' }, api.nvim_buf_get_lines(0, 0, 1, true))
  2971. nvim_feed('ggOx\027')
  2972. eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true))
  2973. end)
  2974. end)
  2975. describe('syntax/shada.vim', function()
  2976. local epoch = os.date('!%Y-%m-%dT%H:%M:%S', 0)
  2977. before_each(reset)
  2978. it('works', function()
  2979. nvim_command('syntax on')
  2980. nvim_command('setlocal syntax=shada')
  2981. nvim_command('set laststatus&')
  2982. local screen = Screen.new(60, 37)
  2983. screen:set_default_attr_ids {
  2984. [1] = { bold = true, foreground = Screen.colors.Brown },
  2985. [2] = { foreground = tonumber('0x6a0dad') },
  2986. [3] = { foreground = Screen.colors.Fuchsia },
  2987. [4] = { foreground = Screen.colors.Blue1 },
  2988. [5] = { bold = true, foreground = Screen.colors.SeaGreen4 },
  2989. [6] = { foreground = Screen.colors.SlateBlue },
  2990. [7] = { bold = true, reverse = true },
  2991. [8] = { bold = true, foreground = Screen.colors.Blue },
  2992. }
  2993. api.nvim_buf_set_lines(0, 0, 1, true, {
  2994. 'Header with timestamp ' .. epoch .. ':',
  2995. ' % Key Value',
  2996. ' + t "test"',
  2997. 'Jump with timestamp ' .. epoch .. ':',
  2998. ' % Key________ Description Value',
  2999. " + n name 'A'",
  3000. ' + f file name ["foo"]',
  3001. ' + l line number 2',
  3002. ' + c column -200',
  3003. 'Register with timestamp ' .. epoch .. ':',
  3004. ' % Key Description Value',
  3005. ' + rc contents @',
  3006. ' | - {"abcdefghijklmnopqrstuvwxyz": 1.0}',
  3007. ' + rt type CHARACTERWISE',
  3008. ' + rt type LINEWISE',
  3009. ' + rt type BLOCKWISE',
  3010. 'Replacement string with timestamp ' .. epoch .. ':',
  3011. ' @ Description__________ Value',
  3012. ' - :s replacement string CMD',
  3013. ' - :s replacement string SEARCH',
  3014. ' - :s replacement string EXPR',
  3015. ' - :s replacement string INPUT',
  3016. ' - :s replacement string DEBUG',
  3017. 'Buffer list with timestamp ' .. epoch .. ':',
  3018. ' # Expected array of maps',
  3019. ' = [{"a": +(10)"ac\\0df\\ngi\\"tt\\.", TRUE: FALSE}, [NIL, +(-10)""]]',
  3020. 'Buffer list with timestamp ' .. epoch .. ':',
  3021. ' % Key Description Value',
  3022. '',
  3023. ' % Key Description Value',
  3024. 'Header with timestamp ' .. epoch .. ':',
  3025. ' % Key Description________ Value',
  3026. ' + se place cursor at end TRUE',
  3027. })
  3028. screen:expect {
  3029. grid = [=[
  3030. {1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3031. {2: % Key Value} |
  3032. {1: +} {3:t } {1:"}{3:test}{1:"} |
  3033. {1:Jump} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3034. {2: % Key________ Description Value} |
  3035. {1: +} {3:n } {4:name } {3:'A'} |
  3036. {1: +} {3:f } {4:file name } {1:["}{3:foo}{1:"]} |
  3037. {1: +} {3:l } {4:line number} {3:2} |
  3038. {1: +} {3:c } {4:column } {3:-200} |
  3039. {1:Register} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3040. {2: % Key Description Value} |
  3041. {1: +} {3:rc } {4:contents } {1:@} |
  3042. {1: | -} {1:{"}{3:abcdefghijklmnopqrstuvwxyz}{1:":} {3:1.0}{1:}} |
  3043. {1: +} {3:rt } {4:type } {1:CHARACTERWISE} |
  3044. {1: +} {3:rt } {4:type } {1:LINEWISE} |
  3045. {1: +} {3:rt } {4:type } {1:BLOCKWISE} |
  3046. {1:Replacement string} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3047. {2: @ Description__________ Value} |
  3048. {1: -} {4::s replacement string} {1:CMD} |
  3049. {1: -} {4::s replacement string} {1:SEARCH} |
  3050. {1: -} {4::s replacement string} {1:EXPR} |
  3051. {1: -} {4::s replacement string} {1:INPUT} |
  3052. {1: -} {4::s replacement string} {1:DEBUG} |
  3053. {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3054. {4: # Expected array of maps} |
  3055. = {1:[{"}{3:a}{1:":} {1:+(}{5:10}{1:)"}{3:ac}{6:\0}{3:df}{6:\n}{3:gi}{6:\"}{3:tt\.}{1:",} {1:TRUE:} {1:FALSE},} {1:[NIL,} {1:+(}{5:-1}|
  3056. {5:0}{1:)""]]} |
  3057. {1:Buffer list} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3058. {2: % Key Description Value} |
  3059. |
  3060. {2: % Key Description Value} |
  3061. {1:Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
  3062. {2: % Key Description________ Value} |
  3063. {1: +} {3:se } {4:place cursor at end} {1:TRUE} |
  3064. {8:~ }|
  3065. {7:[No Name] [+] }|
  3066. |
  3067. ]=],
  3068. }
  3069. nvim_command([[
  3070. function GetSyntax()
  3071. let lines = []
  3072. for l in range(1, line('$'))
  3073. let columns = []
  3074. let line = getline(l)
  3075. for c in range(1, col([l, '$']) - 1)
  3076. let synstack = map(synstack(l, c), 'synIDattr(v:val, "name")')
  3077. if !empty(columns) && columns[-1][0] ==# synstack
  3078. let columns[-1][1] .= line[c - 1]
  3079. else
  3080. call add(columns, [ synstack, line[c - 1] ])
  3081. endif
  3082. endfor
  3083. call add(lines, columns)
  3084. endfor
  3085. return lines
  3086. endfunction
  3087. ]])
  3088. local hname = function(s)
  3089. return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s }
  3090. end
  3091. local h = function(s)
  3092. return { { 'ShaDaEntryHeader' }, s }
  3093. end
  3094. local htsnum = function(s)
  3095. return {
  3096. { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' },
  3097. s,
  3098. }
  3099. end
  3100. local synhtssep = function(s)
  3101. return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s }
  3102. end
  3103. local synepoch = {
  3104. year = htsnum(os.date('%Y', 0)),
  3105. month = htsnum(os.date('%m', 0)),
  3106. day = htsnum(os.date('%d', 0)),
  3107. hour = htsnum(os.date('!%H', 0)),
  3108. minute = htsnum(os.date('%M', 0)),
  3109. second = htsnum(os.date('%S', 0)),
  3110. }
  3111. local msh = function(s)
  3112. return {
  3113. { 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' },
  3114. s,
  3115. }
  3116. end
  3117. local mlh = function(s)
  3118. return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s }
  3119. end
  3120. local ah = function(s)
  3121. return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s }
  3122. end
  3123. -- luacheck: ignore
  3124. local mses = function(s)
  3125. return {
  3126. {
  3127. 'ShaDaEntryMapShort',
  3128. 'ShaDaEntryMapShortEntryStart',
  3129. },
  3130. s,
  3131. }
  3132. end
  3133. local mles = function(s)
  3134. return {
  3135. { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' },
  3136. s,
  3137. }
  3138. end
  3139. local act = fn.GetSyntax()
  3140. local ms = function(syn)
  3141. return {
  3142. { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' },
  3143. ' + ',
  3144. }
  3145. end
  3146. local as = function()
  3147. return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, ' - ' }
  3148. end
  3149. local ad = function(s)
  3150. return {
  3151. { 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' },
  3152. s,
  3153. }
  3154. end
  3155. local mbas = function(syn)
  3156. return {
  3157. { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' },
  3158. ' | - ',
  3159. }
  3160. end
  3161. local msk = function(s)
  3162. return {
  3163. { 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' },
  3164. s,
  3165. }
  3166. end
  3167. local mlk = function(s)
  3168. return {
  3169. { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' },
  3170. s,
  3171. }
  3172. end
  3173. local mld = function(s)
  3174. return {
  3175. { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' },
  3176. s,
  3177. }
  3178. end
  3179. local c = function(s)
  3180. return { { 'ShaDaComment' }, s }
  3181. end
  3182. local exp = {
  3183. {
  3184. hname('Header'),
  3185. h(' with timestamp '),
  3186. synepoch.year,
  3187. synhtssep('-'),
  3188. synepoch.month,
  3189. synhtssep('-'),
  3190. synepoch.day,
  3191. synhtssep('T'),
  3192. synepoch.hour,
  3193. synhtssep(':'),
  3194. synepoch.minute,
  3195. synhtssep(':'),
  3196. synepoch.second,
  3197. h(':'),
  3198. },
  3199. {
  3200. msh(' % Key Value'),
  3201. },
  3202. {
  3203. ms('Short'),
  3204. msk('t '),
  3205. {
  3206. { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' },
  3207. '"',
  3208. },
  3209. { { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' },
  3210. { { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' },
  3211. },
  3212. {
  3213. hname('Jump'),
  3214. h(' with timestamp '),
  3215. synepoch.year,
  3216. synhtssep('-'),
  3217. synepoch.month,
  3218. synhtssep('-'),
  3219. synepoch.day,
  3220. synhtssep('T'),
  3221. synepoch.hour,
  3222. synhtssep(':'),
  3223. synepoch.minute,
  3224. synhtssep(':'),
  3225. synepoch.second,
  3226. h(':'),
  3227. },
  3228. {
  3229. mlh(' % Key________ Description Value'),
  3230. },
  3231. {
  3232. ms('Long'),
  3233. mlk('n '),
  3234. mld('name '),
  3235. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" },
  3236. },
  3237. {
  3238. ms('Long'),
  3239. mlk('f '),
  3240. mld('file name '),
  3241. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
  3242. {
  3243. {
  3244. 'ShaDaEntryMapLong',
  3245. 'ShaDaMsgpackArray',
  3246. 'ShaDaMsgpackBinaryString',
  3247. 'ShaDaMsgpackStringQuotes',
  3248. },
  3249. '"',
  3250. },
  3251. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' },
  3252. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
  3253. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' },
  3254. },
  3255. {
  3256. ms('Long'),
  3257. mlk('l '),
  3258. mld('line number '),
  3259. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' },
  3260. },
  3261. {
  3262. ms('Long'),
  3263. mlk('c '),
  3264. mld('column '),
  3265. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' },
  3266. },
  3267. {
  3268. hname('Register'),
  3269. h(' with timestamp '),
  3270. synepoch.year,
  3271. synhtssep('-'),
  3272. synepoch.month,
  3273. synhtssep('-'),
  3274. synepoch.day,
  3275. synhtssep('T'),
  3276. synepoch.hour,
  3277. synhtssep(':'),
  3278. synepoch.minute,
  3279. synhtssep(':'),
  3280. synepoch.second,
  3281. h(':'),
  3282. },
  3283. {
  3284. mlh(' % Key Description Value'),
  3285. },
  3286. {
  3287. ms('Long'),
  3288. mlk('rc '),
  3289. mld('contents '),
  3290. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' },
  3291. },
  3292. {
  3293. mbas('Long'),
  3294. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
  3295. {
  3296. {
  3297. 'ShaDaEntryMapLong',
  3298. 'ShaDaMsgpackMap',
  3299. 'ShaDaMsgpackBinaryString',
  3300. 'ShaDaMsgpackStringQuotes',
  3301. },
  3302. '"',
  3303. },
  3304. {
  3305. { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' },
  3306. 'abcdefghijklmnopqrstuvwxyz',
  3307. },
  3308. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
  3309. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
  3310. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' },
  3311. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' },
  3312. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' },
  3313. },
  3314. {
  3315. ms('Long'),
  3316. mlk('rt '),
  3317. mld('type '),
  3318. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' },
  3319. },
  3320. {
  3321. ms('Long'),
  3322. mlk('rt '),
  3323. mld('type '),
  3324. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' },
  3325. },
  3326. {
  3327. ms('Long'),
  3328. mlk('rt '),
  3329. mld('type '),
  3330. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' },
  3331. },
  3332. {
  3333. hname('Replacement string'),
  3334. h(' with timestamp '),
  3335. synepoch.year,
  3336. synhtssep('-'),
  3337. synepoch.month,
  3338. synhtssep('-'),
  3339. synepoch.day,
  3340. synhtssep('T'),
  3341. synepoch.hour,
  3342. synhtssep(':'),
  3343. synepoch.minute,
  3344. synhtssep(':'),
  3345. synepoch.second,
  3346. h(':'),
  3347. },
  3348. {
  3349. ah(' @ Description__________ Value'),
  3350. },
  3351. {
  3352. as(),
  3353. ad(':s replacement string '),
  3354. { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' },
  3355. },
  3356. {
  3357. as(),
  3358. ad(':s replacement string '),
  3359. { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' },
  3360. },
  3361. {
  3362. as(),
  3363. ad(':s replacement string '),
  3364. { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' },
  3365. },
  3366. {
  3367. as(),
  3368. ad(':s replacement string '),
  3369. { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' },
  3370. },
  3371. {
  3372. as(),
  3373. ad(':s replacement string '),
  3374. { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' },
  3375. },
  3376. {
  3377. hname('Buffer list'),
  3378. h(' with timestamp '),
  3379. synepoch.year,
  3380. synhtssep('-'),
  3381. synepoch.month,
  3382. synhtssep('-'),
  3383. synepoch.day,
  3384. synhtssep('T'),
  3385. synepoch.hour,
  3386. synhtssep(':'),
  3387. synepoch.minute,
  3388. synhtssep(':'),
  3389. synepoch.second,
  3390. h(':'),
  3391. },
  3392. {
  3393. c(' # Expected array of maps'),
  3394. },
  3395. {
  3396. { { 'ShaDaEntryRawMsgpack' }, ' = ' },
  3397. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
  3398. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
  3399. {
  3400. {
  3401. 'ShaDaMsgpackArray',
  3402. 'ShaDaMsgpackMap',
  3403. 'ShaDaMsgpackBinaryString',
  3404. 'ShaDaMsgpackStringQuotes',
  3405. },
  3406. '"',
  3407. },
  3408. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' },
  3409. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
  3410. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
  3411. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
  3412. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' },
  3413. {
  3414. {
  3415. 'ShaDaMsgpackArray',
  3416. 'ShaDaMsgpackMap',
  3417. 'ShaDaMsgpackExt',
  3418. 'ShaDaMsgpackExtType',
  3419. },
  3420. '10',
  3421. },
  3422. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' },
  3423. {
  3424. {
  3425. 'ShaDaMsgpackArray',
  3426. 'ShaDaMsgpackMap',
  3427. 'ShaDaMsgpackBinaryString',
  3428. 'ShaDaMsgpackStringQuotes',
  3429. },
  3430. '"',
  3431. },
  3432. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' },
  3433. {
  3434. {
  3435. 'ShaDaMsgpackArray',
  3436. 'ShaDaMsgpackMap',
  3437. 'ShaDaMsgpackBinaryString',
  3438. 'ShaDaMsgpackBinaryStringEscape',
  3439. },
  3440. '\\0',
  3441. },
  3442. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' },
  3443. {
  3444. {
  3445. 'ShaDaMsgpackArray',
  3446. 'ShaDaMsgpackMap',
  3447. 'ShaDaMsgpackBinaryString',
  3448. 'ShaDaMsgpackBinaryStringEscape',
  3449. },
  3450. '\\n',
  3451. },
  3452. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' },
  3453. {
  3454. {
  3455. 'ShaDaMsgpackArray',
  3456. 'ShaDaMsgpackMap',
  3457. 'ShaDaMsgpackBinaryString',
  3458. 'ShaDaMsgpackBinaryStringEscape',
  3459. },
  3460. '\\"',
  3461. },
  3462. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' },
  3463. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
  3464. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' },
  3465. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
  3466. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' },
  3467. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
  3468. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
  3469. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' },
  3470. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' },
  3471. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
  3472. { { 'ShaDaMsgpackArray' }, ' ' },
  3473. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
  3474. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' },
  3475. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
  3476. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' },
  3477. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' },
  3478. {
  3479. {
  3480. 'ShaDaMsgpackArray',
  3481. 'ShaDaMsgpackArray',
  3482. 'ShaDaMsgpackExt',
  3483. 'ShaDaMsgpackExtType',
  3484. },
  3485. '-10',
  3486. },
  3487. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' },
  3488. {
  3489. {
  3490. 'ShaDaMsgpackArray',
  3491. 'ShaDaMsgpackArray',
  3492. 'ShaDaMsgpackBinaryString',
  3493. 'ShaDaMsgpackStringQuotes',
  3494. },
  3495. '"',
  3496. },
  3497. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
  3498. { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' },
  3499. { { 'ShaDaMsgpackArrayBraces' }, ']' },
  3500. },
  3501. {
  3502. hname('Buffer list'),
  3503. h(' with timestamp '),
  3504. synepoch.year,
  3505. synhtssep('-'),
  3506. synepoch.month,
  3507. synhtssep('-'),
  3508. synepoch.day,
  3509. synhtssep('T'),
  3510. synepoch.hour,
  3511. synhtssep(':'),
  3512. synepoch.minute,
  3513. synhtssep(':'),
  3514. synepoch.second,
  3515. h(':'),
  3516. },
  3517. {
  3518. mlh(' % Key Description Value'),
  3519. },
  3520. {},
  3521. {
  3522. mlh(' % Key Description Value'),
  3523. },
  3524. {
  3525. hname('Header'),
  3526. h(' with timestamp '),
  3527. synepoch.year,
  3528. synhtssep('-'),
  3529. synepoch.month,
  3530. synhtssep('-'),
  3531. synepoch.day,
  3532. synhtssep('T'),
  3533. synepoch.hour,
  3534. synhtssep(':'),
  3535. synepoch.minute,
  3536. synhtssep(':'),
  3537. synepoch.second,
  3538. h(':'),
  3539. },
  3540. {
  3541. mlh(' % Key Description________ Value'),
  3542. },
  3543. {
  3544. mles(' + '),
  3545. mlk('se '),
  3546. mld('place cursor at end '),
  3547. { { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' },
  3548. },
  3549. }
  3550. eq(exp, act)
  3551. end)
  3552. end)