summary refs log tree commit diff stats
path: root/tests/stdlib/tunicode.nim
blob: 3a8206c8f7efc297065083da3dc836adeb8c7fbf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #00
import std/unicode


proc asRune(s: static[string]): Rune =
  ## Compile-time conversion proc for converting string literals to a Rune
  ## value. Returns the first Rune of the specified string.
  ##
  ## Shortcuts code like ``"å".runeAt(0)`` to ``"å".asRune`` and returns a
  ## compile-time constant.
  if s.len == 0: Rune(0)
  else: s.runeAt(0)

let
  someString = "öÑ"
  someRunes = toRunes(someString)
  compared = (someString == $someRunes)
doAssert compared == true

proc testReplacements(word: string): string =
  case word
  of "two":
    return "2"
  of "foo":
    return "BAR"
  of "βeta":
    return "beta"
  of "alpha":
    return "αlpha"
  else:
    return "12345"

doAssert translate("two not alpha foo βeta", testReplacements) == "2 12345 αlpha BAR beta"
doAssert translate("  two not foo βeta  ", testReplacements) == "  2 12345 BAR beta  "

doAssert title("foo bar") == "Foo Bar"
doAssert title("αlpha βeta γamma") == "Αlpha Βeta Γamma"
doAssert title("") == ""

doAssert capitalize("βeta") == "Βeta"
doAssert capitalize("foo") == "Foo"
doAssert capitalize("") == ""

doAssert swapCase("FooBar") == "fOObAR"
doAssert swapCase(" ") == " "
doAssert swapCase("Αlpha Βeta Γamma") == "αLPHA βETA γAMMA"
doAssert swapCase("a✓B") == "A✓b"
doAssert swapCase("Јамогујестистаклоитоминештети") == "јАМОГУЈЕСТИСТАКЛОИТОМИНЕШТЕТИ"
doAssert swapCase("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ὝΑΛΟΝΦΑΓΕῖΝΔΎΝΑΜΑΙΤΟῦΤΟΟὔΜΕΒΛΆΠΤΕΙ"
doAssert swapCase("Կրնամապակիուտեևինծիանհանգիստչըներ") == "կՐՆԱՄԱՊԱԿԻՈՒՏԵևԻՆԾԻԱՆՀԱՆԳԻՍՏՉԸՆԵՐ"
doAssert swapCase("") == ""

doAssert isAlpha("r")
doAssert isAlpha("α")
doAssert isAlpha("ϙ")
doAssert isAlpha("ஶ")
doAssert(not isAlpha("$"))
doAssert(not isAlpha(""))

doAssert isAlpha("Βeta")
doAssert isAlpha("Args")
doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽")
doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει")
doAssert isAlpha("Јамогујестистаклоитоминештети")
doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ")
doAssert(not isAlpha("$Foo✓"))
doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞"))

doAssert isSpace("\t")
doAssert isSpace("\l")
doAssert(not isSpace("Β"))
doAssert(not isSpace("Βeta"))

doAssert isSpace("\t\l \v\r\f")
doAssert isSpace("       ")
doAssert(not isSpace(""))
doAssert(not isSpace("ΑΓc   \td"))

doAssert(not isLower(' '.Rune))

doAssert(not isUpper(' '.Rune))

doAssert toUpper("Γ") == "Γ"
doAssert toUpper("b") == "B"
doAssert toUpper("α") == "Α"
doAssert toUpper("✓") == "✓"
doAssert toUpper("ϙ") == "Ϙ"
doAssert toUpper("") == ""

doAssert toUpper("ΑΒΓ") == "ΑΒΓ"
doAssert toUpper("AAccβ") == "AACCΒ"
doAssert toUpper("A✓") == "A✓"

doAssert toLower("a") == "a"
doAssert toLower("γ") == "γ"
doAssert toLower("Γ") == "γ"
doAssert toLower("4") == "4"
doAssert toLower("Ϙ") == "ϙ"
doAssert toLower("") == ""

doAssert toLower("abcdγ") == "abcdγ"
doAssert toLower("abCDΓ") == "abcdγ"
doAssert toLower("33aaΓ") == "33aaγ"

doAssert reversed("Reverse this!") == "!siht esreveR"
doAssert reversed("先秦兩漢") == "漢兩秦先"
doAssert reversed("as⃝df̅") == "f̅ds⃝a"
doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
doAssert reversed("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") == "ιετπάλβεμὔοοτῦοτιαμανύδνῖεγαϕνολαὕ"
doAssert reversed("Јамогујестистаклоитоминештети") == "итетшенимотиолкатситсејугомаЈ"
doAssert reversed("Կրնամապակիուտեևինծիանհանգիստչըներ") == "րենըչտսիգնահնաիծնիևետւոիկապամանրԿ"
doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
const test = "as⃝"
doAssert lastRune(test, test.len-1)[1] == 3
doAssert graphemeLen("è", 0) == 2

# test for rune positioning and runeSubStr()
let s = "Hänsel  ««: 10,00€"

var t = ""
for c in s.utf8:
  t.add c

doAssert(s == t)

doAssert(runeReverseOffset(s, 1) == (20, 18))
doAssert(runeReverseOffset(s, 19) == (-1, 18))

doAssert(runeStrAtPos(s, 0) == "H")
doAssert(runeSubStr(s, 0, 1) == "H")
doAssert(runeStrAtPos(s, 10) == ":")
doAssert(runeSubStr(s, 10, 1) == ":")
doAssert(runeStrAtPos(s, 9) == "«")
doAssert(runeSubStr(s, 9, 1) == "«")
doAssert(runeStrAtPos(s, 17) == "€")
doAssert(runeSubStr(s, 17, 1) == "€")
# echo runeStrAtPos(s, 18) # index error

doAssert(runeSubStr(s, 0) == "Hänsel  ««: 10,00€")
doAssert(runeSubStr(s, -18) == "Hänsel  ««: 10,00€")
doAssert(runeSubStr(s, 10) == ": 10,00€")
doAssert(runeSubStr(s, 18) == "")
doAssert(runeSubStr(s, 0, 10) == "Hänsel  ««")

doAssert(runeSubStr(s, 12) == "10,00€")
doAssert(runeSubStr(s, -6) == "10,00€")

doAssert(runeSubStr(s, 12, 5) == "10,00")
doAssert(runeSubStr(s, 12, -1) == "10,00")
doAssert(runeSubStr(s, -6, 5) == "10,00")
doAssert(runeSubStr(s, -6, -1) == "10,00")

doAssert(runeSubStr(s, 0, 100) == "Hänsel  ««: 10,00€")
doAssert(runeSubStr(s, -100, 100) == "Hänsel  ««: 10,00€")
doAssert(runeSubStr(s, 0, -100) == "")
doAssert(runeSubStr(s, 100, -100) == "")

block splitTests:
  let s = " this is an example  "
  let s2 = ":this;is;an:example;;"
  let s3 = ":this×is×an:example××"
  doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
  doAssert s2.split(seps = [':'.Rune, ';'.Rune]) == @["", "this", "is", "an",
      "example", "", ""]
  doAssert s3.split(seps = [':'.Rune, "×".asRune]) == @["", "this", "is",
      "an", "example", "", ""]
  doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example  "]
  doAssert s.split(' '.Rune, maxsplit = 1) == @["", "this is an example  "]
  doAssert s3.split("×".runeAt(0)) == @[":this", "is", "an:example", "", ""]

block stripTests:
  doAssert(strip("") == "")
  doAssert(strip(" ") == "")
  doAssert(strip("y") == "y")
  doAssert(strip("  foofoofoo  ") == "foofoofoo")
  doAssert(strip("sfoofoofoos", runes = ['s'.Rune]) == "foofoofoo")

  block:
    let stripTestRunes = ['b'.Rune, 'a'.Rune, 'r'.Rune]
    doAssert(strip("barfoofoofoobar", runes = stripTestRunes) == "foofoofoo")
  doAssert(strip("sfoofoofoos", leading = false, runes = ['s'.Rune]) == "sfoofoofoo")
  doAssert(strip("sfoofoofoos", trailing = false, runes = ['s'.Rune]) == "foofoofoos")

  block:
    let stripTestRunes = ["«".asRune, "»".asRune]
    doAssert(strip("«TEXT»", runes = stripTestRunes) == "TEXT")
  doAssert(strip("copyright©", leading = false, runes = ["©".asRune]) == "copyright")
  doAssert(strip("¿Question?", trailing = false, runes = ["¿".asRune]) == "Question?")
  doAssert(strip("×text×", leading = false, runes = ["×".asRune]) == "×text")
  doAssert(strip("×text×", trailing = false, runes = ["×".asRune]) == "text×")

block repeatTests:
  doAssert repeat('c'.Rune, 5) == "ccccc"
  doAssert repeat("×".asRune, 5) == "×××××"

block alignTests:
  doAssert align("abc", 4) == " abc"
  doAssert align("a", 0) == "a"
  doAssert align("1232", 6) == "  1232"
  doAssert align("1232", 6, '#'.Rune) == "##1232"
  doAssert align("1232", 6, "×".asRune) == "××1232"
  doAssert alignLeft("abc", 4) == "abc "
  doAssert alignLeft("a", 0) == "a"
  doAssert alignLeft("1232", 6) == "1232  "
  doAssert alignLeft("1232", 6, '#'.Rune) == "1232##"
  doAssert alignLeft("1232", 6, "×".asRune) == "1232××"

block differentSizes:
  # upper and lower variants have different number of bytes
  doAssert toLower("AẞC") == "aßc"
  doAssert toLower("ȺẞCD") == "ⱥßcd"
  doAssert toUpper("ⱥbc") == "ȺBC"
  doAssert toUpper("rsⱦuv") == "RSȾUV"
  doAssert swapCase("ⱥbCd") == "ȺBcD"
  doAssert swapCase("XyꟆaB") == "xYᶎAb"
  doAssert swapCase("aᵹcᲈd") == "AꝽCꙊD"

block: # bug #17768
  let s1 = "abcdef"
  let s2 = "abcdéf"

  doAssert s1.runeSubStr(0, -1) == "abcde"
  doAssert s2.runeSubStr(0, -1) == "abcdé"