1before: 2 base_module = "string" 3 this_module = "std.string" 4 global_table = "_G" 5 6 extend_base = { "__concat", "__index", 7 "caps", "chomp", "escape_pattern", "escape_shell", 8 "finds", "format", "ltrim", "monkey_patch", 9 "numbertosi", "ordinal_suffix", "pad", "pickle", 10 "prettytostring", "render", "rtrim", "split", 11 "tfind", "trim", "wrap" } 12 deprecations = { "assert", "require_version", "tostring" } 13 14 M = require (this_module) 15 getmetatable ("").__concat = M.__concat 16 getmetatable ("").__index = M.__index 17 18specify std.string: 19- before: 20 subject = "a string \n\n" 21 22- context when required: 23 - context by name: 24 - it does not touch the global table: 25 expect (show_apis {added_to=global_table, by=this_module}). 26 to_equal {} 27 - it does not touch the core string table: 28 expect (show_apis {added_to=base_module, by=this_module}). 29 to_equal {} 30 - it contains apis from the core string table: 31 apis = require "std.base".copy (extend_base) 32 for _, v in ipairs (deprecations) do 33 apis[#apis + 1] = v 34 end 35 expect (show_apis {from=base_module, not_in=this_module}). 36 to_contain.a_permutation_of (apis) 37 38 - context via the std module: 39 - it does not touch the global table: 40 expect (show_apis {added_to=global_table, by="std"}). 41 to_equal {} 42 - it does not touch the core string table: 43 expect (show_apis {added_to=base_module, by="std"}). 44 to_equal {} 45 46- describe ..: 47 - it concatenates string arguments: 48 target = "a string \n\n another string" 49 expect (subject .. " another string").to_be (target) 50 - it stringifies non-string arguments: 51 argument = { "a table" } 52 expect (subject .. argument). 53 to_be (string.format ("%s%s", subject, require "std".tostring (argument))) 54 - it stringifies nil arguments: 55 argument = nil 56 expect (subject .. argument). 57 to_be (string.format ("%s%s", subject, require "std".tostring (argument))) 58 - it does not perturb the original subject: 59 original = subject 60 newstring = subject .. " concatenate something" 61 expect (subject).to_be (original) 62 63 64- describe assert: 65 - before: 66 f = M.assert 67 68 - it writes a deprecation warning: 69 setdebug { deprecate = "nil" } 70 expect (capture (f, {"std.string"})).to_contain_error "was deprecated" 71 setdebug { deprecate = false } 72 expect (capture (f, {"std.string"})).not_to_contain_error "was deprecated" 73 74 - context when it does not trigger: 75 - it has a truthy initial argument: 76 expect (f (1)).not_to_raise "any error" 77 expect (f (true)).not_to_raise "any error" 78 expect (f "yes").not_to_raise "any error" 79 expect (f (false == false)).not_to_raise "any error" 80 - it returns the initial argument: 81 expect (f (1)).to_be (1) 82 expect (f (true)).to_be (true) 83 expect (f "yes").to_be "yes" 84 expect (f (false == false)).to_be (true) 85 - context when it triggers: 86 - it has a falsey initial argument: 87 expect (f ()).to_raise () 88 expect (f (false)).to_raise () 89 expect (f (1 == 0)).to_raise () 90 - it throws an optional error string: 91 expect (f (false, "ah boo")).to_raise "ah boo" 92 - it plugs specifiers with string.format: | 93 expect (f (nil, "%s %d: %q", "here", 42, "a string")). 94 to_raise (string.format ("%s %d: %q", "here", 42, "a string")) 95 96 97- describe caps: 98 - before: 99 f = M.caps 100 101 - context with bad arguments: 102 badargs.diagnose (f, "std.string.caps (string)") 103 104 - it capitalises words of a string: 105 target = "A String \n\n" 106 expect (f (subject)).to_be (target) 107 - it changes only the first letter of each word: 108 expect (f "a stRiNg").to_be "A StRiNg" 109 - it is available as a string metamethod: 110 expect (("a stRiNg"):caps ()).to_be "A StRiNg" 111 - it does not perturb the original subject: 112 original = subject 113 newstring = f (subject) 114 expect (subject).to_be (original) 115 116 117- describe chomp: 118 - before: 119 target = "a string \n" 120 f = M.chomp 121 122 - context with bad arguments: 123 badargs.diagnose (f, "std.string.chomp (string)") 124 125 - it removes a single trailing newline from a string: 126 expect (f (subject)).to_be (target) 127 - it does not change a string with no trailing newline: 128 subject = "a string " 129 expect (f (subject)).to_be (subject) 130 - it is available as a string metamethod: 131 expect (subject:chomp ()).to_be (target) 132 - it does not perturb the original subject: 133 original = subject 134 newstring = f (subject) 135 expect (subject).to_be (original) 136 137 138- describe escape_pattern: 139 - before: 140 magic = {} 141 meta = "^$()%.[]*+-?" 142 for i = 1, string.len (meta) do 143 magic[meta:sub (i, i)] = true 144 end 145 f = M.escape_pattern 146 147 - context with bad arguments: 148 badargs.diagnose (f, "std.string.escape_pattern (string)") 149 150 - context with each printable ASCII char: 151 - before: 152 subject, target = "", "" 153 for c = 32, 126 do 154 s = string.char (c) 155 subject = subject .. s 156 if magic[s] then target = target .. "%" end 157 target = target .. s 158 end 159 - "it inserts a % before any non-alphanumeric in a string": 160 expect (f (subject)).to_be (target) 161 - it is available as a string metamethod: 162 expect (subject:escape_pattern ()).to_be (target) 163 - it does not perturb the original subject: 164 original = subject 165 newstring = f (subject) 166 expect (subject).to_be (original) 167 168 169- describe escape_shell: 170 - before: 171 f = M.escape_shell 172 173 - context with bad arguments: 174 badargs.diagnose (f, "std.string.escape_shell (string)") 175 176 - context with each printable ASCII char: 177 - before: 178 subject, target = "", "" 179 for c = 32, 126 do 180 s = string.char (c) 181 subject = subject .. s 182 if s:match ("[][ ()\\\"']") then target = target .. "\\" end 183 target = target .. s 184 end 185 - "it inserts a \\ before any shell metacharacters": 186 expect (f (subject)).to_be (target) 187 - it is available as a string metamethod: 188 expect (subject:escape_shell ()).to_be (target) 189 - it does not perturb the original subject: 190 original = subject 191 newstring = f (subject) 192 expect (subject).to_be (original) 193 - "it diagnoses non-string arguments": 194 expect (f ()).to_raise ("string expected") 195 expect (f {"a table"}).to_raise ("string expected") 196 197 198- describe finds: 199 - before: 200 subject = "abcd" 201 f = M.finds 202 203 - context with bad arguments: 204 badargs.diagnose (f, "std.string.finds (string, string, ?int, ?boolean|:plain)") 205 206 - context given a complex nested list: 207 - before: 208 target = { { 1, 2; capt = { "a", "b" } }, { 3, 4; capt = { "c", "d" } } } 209 - it creates a list of pattern captures: 210 expect ({f (subject, "(.)(.)")}).to_equal ({ target }) 211 - it is available as a string metamethod: 212 expect ({subject:finds ("(.)(.)")}).to_equal ({ target }) 213 - it creates an empty list where no captures are matched: 214 target = {} 215 expect ({f (subject, "(x)")}).to_equal ({ target }) 216 - it creates an empty list for a pattern without captures: 217 target = { { 1, 1; capt = {} } } 218 expect ({f (subject, "a")}).to_equal ({ target }) 219 - it starts the search at a specified index into the subject: 220 target = { { 8, 9; capt = { "a", "b" } }, { 10, 11; capt = { "c", "d" } } } 221 expect ({f ("garbage" .. subject, "(.)(.)", 8)}).to_equal ({ target }) 222 - it does not perturb the original subject: 223 original = subject 224 newstring = f (subject, "...") 225 expect (subject).to_be (original) 226 227 228- describe format: 229 - before: 230 subject = "string=%s, number=%d" 231 232 f = M.format 233 234 - context with bad arguments: 235 badargs.diagnose (f, "std.string.format (string, ?any*)") 236 237 - it returns a single argument without attempting formatting: 238 expect (f (subject)).to_be (subject) 239 - it is available as a string metamethod: 240 expect (subject:format ()).to_be (subject) 241 - it does not perturb the original subject: 242 original = subject 243 newstring = f (subject) 244 expect (subject).to_be (original) 245 246 247- describe ltrim: 248 - before: 249 subject = " \t\r\n a short string \t\r\n " 250 251 f = M.ltrim 252 253 - context with bad arguments: 254 badargs.diagnose (f, "std.string.ltrim (string, ?string)") 255 256 - it removes whitespace from the start of a string: 257 target = "a short string \t\r\n " 258 expect (f (subject)).to_equal (target) 259 - it supports custom removal patterns: 260 target = "\r\n a short string \t\r\n " 261 expect (f (subject, "[ \t\n]+")).to_equal (target) 262 - it is available as a string metamethod: 263 target = "\r\n a short string \t\r\n " 264 expect (subject:ltrim ("[ \t\n]+")).to_equal (target) 265 - it does not perturb the original subject: 266 original = subject 267 newstring = f (subject, "%W") 268 expect (subject).to_be (original) 269 270 271- describe monkey_patch: 272 - before: 273 f = M.monkey_patch 274 275 - context with bad arguments: 276 badargs.diagnose (f, "std.string.monkey_patch (?table)") 277 278 # Ideally, `.to_be (M)`, except that M is cloned from a nested context 279 # by Specl to prevent us from affecting any other examples, thus the 280 # address is different by now. 281 - it returns std.string module table: 282 expect (f {}).to_equal (M) 283 - it injects std.string apis into given namespace: 284 namespace = {} 285 f (namespace) 286 for _, api in ipairs (extend_base) do 287 expect (namespace.string[api]).to_be (M[api]) 288 end 289 - it installs string metamethods: 290 # FIXME: string metatable monkey-patches leak out! 291 mt = getmetatable "" 292 expect (mt.__concat).to_be (M.__concat) 293 expect (mt.__index).to_be (M.__index) 294 295 296- describe numbertosi: 297 - before: 298 f = M.numbertosi 299 300 - context with bad arguments: 301 badargs.diagnose (f, "std.string.numbertosi (number|string)") 302 303 - it returns a number using SI suffixes: 304 target = {"1e-9", "1y", "1z", "1a", "1f", "1p", "1n", "1mu", "1m", "1", 305 "1k", "1M", "1G", "1T", "1P", "1E", "1Z", "1Y", "1e9"} 306 subject = {} 307 for n = -28, 28, 3 do 308 m = 10 * (10 ^ n) 309 table.insert (subject, f (m)) 310 end 311 expect (subject).to_equal (target) 312 - it coerces string arguments to a number: 313 expect (f "1000").to_be "1k" 314 315 316- describe ordinal_suffix: 317 - before: 318 f = M.ordinal_suffix 319 320 - context with bad arguments: 321 badargs.diagnose (f, "std.string.ordinal_suffix (int|string)") 322 323 - it returns the English suffix for a number: 324 subject, target = {}, {} 325 for n = -120, 120 do 326 suffix = "th" 327 m = math.abs (n) % 10 328 if m == 1 and math.abs (n) % 100 ~= 11 then suffix = "st" 329 elseif m == 2 and math.abs (n) % 100 ~= 12 then suffix = "nd" 330 elseif m == 3 and math.abs (n) % 100 ~= 13 then suffix = "rd" 331 end 332 table.insert (target, n .. suffix) 333 table.insert (subject, n .. f (n)) 334 end 335 expect (subject).to_equal (target) 336 - it coerces string arguments to a number: 337 expect (f "-91").to_be "st" 338 339 340- describe pad: 341 - before: 342 width = 20 343 344 f = M.pad 345 346 - context with bad arguments: 347 badargs.diagnose (f, "std.string.pad (string, int, ?string)") 348 349 - context when string is shorter than given width: 350 - before: 351 subject = "short string" 352 - it right pads a string to the given width with spaces: 353 target = "short string " 354 expect (f (subject, width)).to_be (target) 355 - it left pads a string to the given negative width with spaces: 356 width = -width 357 target = " short string" 358 expect (f (subject, width)).to_be (target) 359 - it is available as a string metamethod: 360 target = "short string " 361 expect (subject:pad (width)).to_be (target) 362 363 - context when string is longer than given width: 364 - before: 365 subject = "a string that's longer than twenty characters" 366 - it truncates a string to the given width: 367 target = "a string that's long" 368 expect (f (subject, width)).to_be (target) 369 - it left pads a string to given width with spaces: 370 width = -width 371 target = "an twenty characters" 372 expect (f (subject, width)).to_be (target) 373 - it is available as a string metamethod: 374 target = "a string that's long" 375 expect (subject:pad (width)).to_be (target) 376 377 - it does not perturb the original subject: 378 original = subject 379 newstring = f (subject, width) 380 expect (subject).to_be (original) 381 382 383- describe pickle: 384 - before: 385 loadstring = loadstring or load 386 function unpickle (s) return loadstring ("return " .. s) () end 387 t = {1, {{2, 3}, 4, {5}}} 388 f = M.pickle 389 - it converts a primitive to a representative string: 390 expect (f (nil)).to_be "nil" 391 expect (f (false)).to_be "false" 392 expect (f (42)).to_be "42" 393 expect (f "string").to_be '"string"' 394 - it returns a loadable string that results in the original value: 395 expect (unpickle (f (nil))).to_be (nil) 396 expect (unpickle (f (false))).to_be (false) 397 expect (unpickle (f (42))).to_be (42) 398 expect (unpickle (f "string")).to_be "string" 399 - it converts a table to a representative string: 400 expect (f {"table", 42}).to_be '{[1]="table",[2]=42}' 401 - it returns a loadable string that results in the original table: 402 expect (unpickle (f {"table", 42})).to_equal {"table", 42} 403 - it converts a nested table to a representative string: 404 expect (f (t)). 405 to_be "{[1]=1,[2]={[1]={[1]=2,[2]=3},[2]=4,[3]={[1]=5}}}" 406 - it returns a loadable string that results in the original nested table: 407 expect (unpickle (f (t))).to_equal (t) 408 409 410- describe prettytostring: 411 - before: 412 f = M.prettytostring 413 414 - context with bad arguments: 415 badargs.diagnose (f, "std.string.prettytostring (?any, ?string, ?string)") 416 417 - it renders nil exactly like system tostring: 418 expect (f (nil)).to_be (tostring (nil)) 419 - it renders booleans exactly like system tostring: 420 expect (f (true)).to_be (tostring (true)) 421 expect (f (false)).to_be (tostring (false)) 422 - it renders numbers exactly like system tostring: 423 n = 8723643 424 expect (f (n)).to_be (tostring (n)) 425 - it renders functions exactly like system tostring: 426 expect (f (f)).to_be (tostring (f)) 427 - it renders strings with format "%q" styling: 428 s = "a string" 429 expect (f (s)).to_be (string.format ("%q", s)) 430 - it renders empty tables as a pair of braces: 431 expect (f {}).to_be ("{\n}") 432 - it renders an array prettily: 433 a = {"one", "two", "three"} 434 expect (f (a, "")). 435 to_be '{\n[1] = "one",\n[2] = "two",\n[3] = "three",\n}' 436 - it renders a table prettily: 437 t = { one = true, two = 2, three = {3}} 438 expect (f (t, "")). 439 to_be '{\none = true,\nthree =\n{\n[1] = 3,\n},\ntwo = 2,\n}' 440 - it renders table keys in table.sort order: 441 t = { one = 3, two = 5, three = 4, four = 2, five = 1 } 442 expect (f (t, "")). 443 to_be '{\nfive = 1,\nfour = 2,\none = 3,\nthree = 4,\ntwo = 5,\n}' 444 - it renders keys with invalid symbol names in long hand: 445 t = { _ = 0, word = 0, ["?"] = 1, ["a-key"] = 1, ["[]"] = 1 } 446 expect (f (t, "")). 447 to_be '{\n["?"] = 1,\n["[]"] = 1,\n_ = 0,\n["a-key"] = 1,\nword = 0,\n}' 448 449 450- describe render: 451 - before: 452 term = function (s) return function () return s end end 453 pair = function (_, _, _, i, v) return i .. "=" .. v end 454 sep = function (_, i, _, j) return (i and j) and "," or "" end 455 r = function (x) 456 return M.render (x, term "{", term "}", tostring, pair, sep) 457 end 458 t = {1, {{2, 3}, 4, {5}}} 459 460 f = M.render 461 462 - context with bad arguments: 463 badargs.diagnose (f, "std.string.render (?any, func, func, func, func, func, ?table)") 464 465 - it converts a primitive to a representative string: 466 expect (r (nil)).to_be "nil" 467 expect (r (false)).to_be "false" 468 expect (r (42)).to_be "42" 469 expect (r ("string")).to_be "string" 470 - it converts a table to a representative string: 471 expect (r ({"table", 42})).to_be '{1=table,2=42}' 472 - it converts a nested table to a representative string: 473 expect (r (t)). 474 to_be "{1=1,2={1={1=2,2=3},2=4,3={1=5}}}" 475 - it converts a recursive table to a representative string: 476 t[1] = t 477 expect (r (t)). 478 to_be ("{1="..tostring (t)..",2={1={1=2,2=3},2=4,3={1=5}}}") 479 480 481- describe require_version: 482 - before: 483 f = M.require_version 484 485 - it writes a deprecation warning: 486 setdebug { deprecate = "nil" } 487 expect (capture (f, {"std.string"})).to_contain_error "was deprecated" 488 setdebug { deprecate = false } 489 expect (capture (f, {"std.string"})).not_to_contain_error "was deprecated" 490 491 - it diagnoses non-existent module: 492 expect (f ("module-not-exists", "", "")).to_raise "module-not-exists" 493 - it diagnoses module too old: 494 expect (f ("std", "9999", "9999")).to_raise () 495 - it diagnoses module too new: 496 expect (f ("std", "0", "0")).to_raise () 497 - context when the module version is compatible: 498 - it returns the module table: 499 expect (f ("std", "0", "9999")).to_be (require "std") 500 - it places no upper bound by default: 501 expect (f ("std", "41")).to_be (require "std") 502 - it places no lower bound by default: 503 expect (f "std").to_be (require "std") 504 - it uses _VERSION when version field is nil: 505 std = require "std" 506 std._VERSION, std.version = std.version, std._VERSION 507 expect (f ("std", "41", "9999")).to_be (require "std") 508 std._VERSION, std.version = std.version, std._VERSION 509 - context with semantic versioning: 510 - before: 511 std = require "std" 512 ver = std.version 513 std.version = "1.2.3" 514 - after: 515 std.version = ver 516 - it diagnoses module too old: 517 expect (f ("std", "1.2.4")).to_raise () 518 expect (f ("std", "1.3")).to_raise () 519 expect (f ("std", "2.1.2")).to_raise () 520 expect (f ("std", "2")).to_raise () 521 expect (f ("std", "1.2.10")).to_raise () 522 - it diagnoses module too new: 523 expect (f ("std", nil, "1.2.2")).to_raise () 524 expect (f ("std", nil, "1.1")).to_raise () 525 expect (f ("std", nil, "1.1.2")).to_raise () 526 expect (f ("std", nil, "1")).to_raise () 527 - it returns modules with version in range: 528 expect (f ("std")).to_be (std) 529 expect (f ("std", "1")).to_be (std) 530 expect (f ("std", "1.2.3")).to_be (std) 531 expect (f ("std", nil, "2")).to_be (std) 532 expect (f ("std", nil, "1.3")).to_be (std) 533 expect (f ("std", nil, "1.2.10")).to_be (std) 534 expect (f ("std", "1.2.3", "1.2.4")).to_be (std) 535 536 537- describe rtrim: 538 - before: 539 subject = " \t\r\n a short string \t\r\n " 540 541 f = M.rtrim 542 543 - context with bad arguments: 544 badargs.diagnose (f, "std.string.rtrim (string, ?string)") 545 546 - it removes whitespace from the end of a string: 547 target = " \t\r\n a short string" 548 expect (f (subject)).to_equal (target) 549 - it supports custom removal patterns: 550 target = " \t\r\n a short string \t\r" 551 expect (f (subject, "[ \t\n]+")).to_equal (target) 552 - it is available as a string metamethod: 553 target = " \t\r\n a short string \t\r" 554 expect (subject:rtrim ("[ \t\n]+")).to_equal (target) 555 - it does not perturb the original subject: 556 original = subject 557 newstring = f (subject, "%W") 558 expect (subject).to_be (original) 559 560 561- describe split: 562 - before: 563 target = { "first", "the second one", "final entry" } 564 subject = table.concat (target, ", ") 565 566 f = M.split 567 568 - context with bad arguments: 569 badargs.diagnose (f, "std.string.split (string, ?string)") 570 571 - it falls back to "%s+" when no pattern is given: 572 expect (f (subject)). 573 to_equal {"first,", "the", "second", "one,", "final", "entry"} 574 - it returns a one-element list for an empty string: 575 expect (f ("", ", ")).to_equal {""} 576 - it makes a table of substrings delimited by a separator: 577 expect (f (subject, ", ")).to_equal (target) 578 - it returns n+1 elements for n separators: 579 expect (f (subject, "zero")).to_have_size (1) 580 expect (f (subject, "c")).to_have_size (2) 581 expect (f (subject, "s")).to_have_size (3) 582 expect (f (subject, "t")).to_have_size (4) 583 expect (f (subject, "e")).to_have_size (5) 584 - it returns an empty string element for consecutive separators: 585 expect (f ("xyzyzxy", "yz")).to_equal {"x", "", "xy"} 586 - it returns an empty string element when starting with separator: 587 expect (f ("xyzyzxy", "xyz")).to_equal {"", "yzxy"} 588 - it returns an empty string element when ending with separator: 589 expect (f ("xyzyzxy", "zxy")).to_equal {"xyzy", ""} 590 - it returns a table of 1-character strings for "" separator: 591 expect (f ("abcdef", "")).to_equal {"", "a", "b", "c", "d", "e", "f", ""} 592 - it is available as a string metamethod: 593 expect (subject:split ", ").to_equal (target) 594 expect (("/foo/bar/baz.quux"):split "/"). 595 to_equal {"", "foo", "bar", "baz.quux"} 596 - it does not perturb the original subject: 597 original = subject 598 newstring = f (subject, "e") 599 expect (subject).to_be (original) 600 - it takes a Lua pattern as a separator: 601 expect (f (subject, "%s+")). 602 to_equal {"first,", "the", "second", "one,", "final", "entry"} 603 604 605- describe tfind: 606 - before: 607 subject = "abc" 608 609 f = M.tfind 610 611 - context with bad arguments: 612 badargs.diagnose (f, "std.string.tfind (string, string, ?int, ?boolean|:plain)") 613 614 - it creates a list of pattern captures: 615 target = { 1, 3, { "a", "b", "c" } } 616 expect ({f (subject, "(.)(.)(.)")}).to_equal (target) 617 - it creates an empty list where no captures are matched: 618 target = { nil, nil, {} } 619 expect ({f (subject, "(x)(y)(z)")}).to_equal (target) 620 - it creates an empty list for a pattern without captures: 621 target = { 1, 1, {} } 622 expect ({f (subject, "a")}).to_equal (target) 623 - it starts the search at a specified index into the subject: 624 target = { 8, 10, { "a", "b", "c" } } 625 expect ({f ("garbage" .. subject, "(.)(.)(.)", 8)}).to_equal (target) 626 - it is available as a string metamethod: 627 target = { 8, 10, { "a", "b", "c" } } 628 expect ({("garbage" .. subject):tfind ("(.)(.)(.)", 8)}).to_equal (target) 629 - it does not perturb the original subject: 630 original = subject 631 newstring = f (subject, "...") 632 expect (subject).to_be (original) 633 634 635- describe tostring: 636 - before: 637 f = M.tostring 638 639 - it writes a deprecation warning: 640 setdebug { deprecate = "nil" } 641 expect (capture (f, {"std.string"})).to_contain_error "was deprecated" 642 setdebug { deprecate = false } 643 expect (capture (f, {"std.string"})).not_to_contain_error "was deprecated" 644 645 - it renders primitives exactly like system tostring: 646 expect (f (nil)).to_be (tostring (nil)) 647 expect (f (false)).to_be (tostring (false)) 648 expect (f (42)).to_be (tostring (42)) 649 expect (f (f)).to_be (tostring (f)) 650 expect (f "a string").to_be "a string" 651 - it renders empty tables as a pair of braces: 652 expect (f {}).to_be ("{}") 653 - it renders table array part compactly: 654 expect (f {"one", "two", "five"}). 655 to_be '{1=one,2=two,3=five}' 656 - it renders a table dictionary part compactly: 657 expect (f { one = true, two = 2, three = {3}}). 658 to_be '{one=true,three={1=3},two=2}' 659 - it renders table keys in table.sort order: 660 expect (f { one = 3, two = 5, three = 4, four = 2, five = 1 }). 661 to_be '{five=1,four=2,one=3,three=4,two=5}' 662 - it renders keys with invalid symbol names compactly: 663 expect (f { _ = 0, word = 0, ["?"] = 1, ["a-key"] = 1, ["[]"] = 1 }). 664 to_be '{?=1,[]=1,_=0,a-key=1,word=0}' 665 666 667- describe trim: 668 - before: 669 subject = " \t\r\n a short string \t\r\n " 670 671 f = M.trim 672 673 - context with bad arguments: 674 badargs.diagnose (f, "std.string.trim (string, ?string)") 675 676 - it removes whitespace from each end of a string: 677 target = "a short string" 678 expect (f (subject)).to_equal (target) 679 - it supports custom removal patterns: 680 target = "\r\n a short string \t\r" 681 expect (f (subject, "[ \t\n]+")).to_equal (target) 682 - it is available as a string metamethod: 683 target = "\r\n a short string \t\r" 684 expect (subject:trim ("[ \t\n]+")).to_equal (target) 685 - it does not perturb the original subject: 686 original = subject 687 newstring = f (subject, "%W") 688 expect (subject).to_be (original) 689 690 691- describe wrap: 692 - before: 693 subject = "This is a collection of Lua libraries for Lua 5.1 " .. 694 "and 5.2. The libraries are copyright by their authors 2000" .. 695 "-2015 (see the AUTHORS file for details), and released und" .. 696 "er the MIT license (the same license as Lua itself). There" .. 697 " is no warranty." 698 699 f = M.wrap 700 701 - context with bad arguments: 702 badargs.diagnose (f, "std.string.wrap (string, ?int, ?int, ?int)") 703 704 - it inserts newlines to wrap a string: 705 target = "This is a collection of Lua libraries for Lua 5.1 a" .. 706 "nd 5.2. The libraries are\ncopyright by their authors 2000" .. 707 "-2015 (see the AUTHORS file for details), and\nreleased un" .. 708 "der the MIT license (the same license as Lua itself). Ther" .. 709 "e is no\nwarranty." 710 expect (f (subject)).to_be (target) 711 - it honours a column width parameter: 712 target = "This is a collection of Lua libraries for Lua 5.1 a" .. 713 "nd 5.2. The libraries\nare copyright by their authors 2000" .. 714 "-2015 (see the AUTHORS file for\ndetails), and released un" .. 715 "der the MIT license (the same license as Lua\nitself). The" .. 716 "re is no warranty." 717 expect (f (subject, 72)).to_be (target) 718 - it supports indenting by a fixed number of columns: 719 target = " This is a collection of Lua libraries for L" .. 720 "ua 5.1 and 5.2. The\n libraries are copyright by th" .. 721 "eir authors 2000-2015 (see the\n AUTHORS file for d" .. 722 "etails), and released under the MIT license\n (the " .. 723 "same license as Lua itself). There is no warranty." 724 expect (f (subject, 72, 8)).to_be (target) 725 - context given a long unwrapped string: 726 - before: 727 target = " This is a collection of Lua libraries for Lua 5" .. 728 ".1 and 5.2.\n The libraries are copyright by their author" .. 729 "s 2000-2015 (see\n the AUTHORS file for details), and rel" .. 730 "eased under the MIT\n license (the same license as Lua it" .. 731 "self). There is no\n warranty." 732 - it can indent the first line differently: 733 expect (f (subject, 64, 2, 4)).to_be (target) 734 - it is available as a string metamethod: 735 expect (subject:wrap (64, 2, 4)).to_be (target) 736 - it does not perturb the original subject: 737 original = subject 738 newstring = f (subject, 55, 5) 739 expect (subject).to_be (original) 740 - it diagnoses indent greater than line width: 741 expect (f (subject, 10, 12)).to_raise ("less than the line width") 742 expect (f (subject, 99, 99)).to_raise ("less than the line width") 743 - it diagnoses non-string arguments: 744 expect (f ()).to_raise ("string expected") 745 expect (f {"a table"}).to_raise ("string expected") 746