Skip to content

Commit 8f5b65b

Browse files
authored
Merge pull request #43 from jmkuhn/pull-request/4f33e042
Fix #39 Unicode String indexing
2 parents b502b76 + e29cf3d commit 8f5b65b

File tree

4 files changed

+45
-11
lines changed

4 files changed

+45
-11
lines changed

src/fmtspec.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function FormatSpec(s::AbstractString)
102102
_align = a1[1]
103103
else
104104
_fill = a1[1]
105-
_align = a1[2]
105+
_align = a1[nextind(a1, 1)]
106106
end
107107
end
108108

src/formatexpr.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function make_argspec(s::AbstractString, pos::Int)
3030
if ifil == 0
3131
iarg = parse(Int,s)
3232
else
33-
iarg = ifil > 1 ? parse(Int,s[1:ifil-1]) : -1
33+
iarg = ifil > 1 ? parse(Int,s[1:prevind(s, ifil)]) : -1
3434
hasfil = true
3535
ff = eval(Symbol(s[ifil+2:end]))
3636
end
@@ -62,14 +62,14 @@ end
6262

6363
function make_formatentry(s::AbstractString, pos::Int)
6464
@assert s[1] == '{' && s[end] == '}'
65-
sc = s[2:end-1]
65+
sc = s[2:prevind(s, endof(s))]
6666
icolon = search(sc, ':')
6767
if icolon == 0 # no colon
6868
(argspec, pos) = make_argspec(sc, pos)
6969
spec = FormatSpec('s')
7070
else
71-
(argspec, pos) = make_argspec(sc[1:icolon-1], pos)
72-
spec = FormatSpec(sc[icolon+1:end])
71+
(argspec, pos) = make_argspec(sc[1:prevind(sc, icolon)], pos)
72+
spec = FormatSpec(sc[nextind(sc, icolon):end])
7373
end
7474
return (FormatEntry(argspec, spec), pos)
7575
end
@@ -87,15 +87,15 @@ end
8787
_raise_unmatched_lbrace() = error("Unmatched { in format expression.")
8888

8989
function find_next_entry_open(s::AbstractString, si::Int)
90-
slen = length(s)
90+
slen = endof(s)
9191
p = search(s, '{', si)
9292
p < slen || _raise_unmatched_lbrace()
9393
while p > 0 && s[p+1] == '{' # escape `{{`
9494
p = search(s, '{', p+2)
9595
p < slen || _raise_unmatched_lbrace()
9696
end
9797
# println("open at $p")
98-
pre = p > 0 ? s[si:p-1] : s[si:end]
98+
pre = p > 0 ? s[si:prevind(s, p)] : s[si:end]
9999
if !isempty(pre)
100100
pre = replace(pre, "{{", '{')
101101
pre = replace(pre, "}}", '}')
@@ -104,15 +104,15 @@ function find_next_entry_open(s::AbstractString, si::Int)
104104
end
105105

106106
function find_next_entry_close(s::AbstractString, si::Int)
107-
slen = length(s)
107+
slen = endof(s)
108108
p = search(s, '}', si)
109109
p > 0 || _raise_unmatched_lbrace()
110110
# println("close at $p")
111111
return p
112112
end
113113

114114
function FormatExpr(s::AbstractString)
115-
slen = length(s)
115+
slen = endof(s)
116116

117117
# init
118118
prefix = ""

test/fmtspec.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,40 @@ fs = FormatSpec("d")
3232
@test FormatSpec(".6f") == FormatSpec('f'; prec=6)
3333
@test FormatSpec("<8d") == FormatSpec('d'; width=8, align='<')
3434
@test FormatSpec("#<8d") == FormatSpec('d'; width=8, fill='#', align='<')
35+
@test FormatSpec("⋆<8d") == FormatSpec('d'; width=8, fill='', align='<')
3536
@test FormatSpec("#8,d") == FormatSpec('d'; width=8, ipre=true, tsep=true)
3637

3738
# format string
3839

3940
@test fmt("", "abc") == "abc"
41+
@test fmt("", "αβγ") == "αβγ"
4042
@test fmt("s", "abc") == "abc"
43+
@test fmt("s", "αβγ") == "αβγ"
4144
@test fmt("2s", "abc") == "abc"
45+
@test fmt("2s", "αβγ") == "αβγ"
4246
@test fmt("5s", "abc") == "abc "
47+
@test fmt("5s", "αβγ") == "αβγ "
4348
@test fmt(">5s", "abc") == " abc"
49+
@test fmt(">5s", "αβγ") == " αβγ"
4450
@test fmt("*>5s", "abc") == "**abc"
51+
@test fmt("⋆>5s", "αβγ") == "⋆⋆αβγ"
4552
@test fmt("*<5s", "abc") == "abc**"
53+
@test fmt("⋆<5s", "αβγ") == "αβγ⋆⋆"
4654

4755
# format char
4856

4957
@test fmt("", 'c') == "c"
58+
@test fmt("", 'γ') == "γ"
5059
@test fmt("c", 'c') == "c"
60+
@test fmt("c", 'γ') == "γ"
5161
@test fmt("3c", 'c') == "c "
62+
@test fmt("3c", 'γ') == "γ "
5263
@test fmt(">3c", 'c') == " c"
64+
@test fmt(">3c", 'γ') == " γ"
5365
@test fmt("*>3c", 'c') == "**c"
66+
@test fmt("⋆>3c", 'γ') == "⋆⋆γ"
5467
@test fmt("*<3c", 'c') == "c**"
68+
@test fmt("⋆<3c", 'γ') == "γ⋆⋆"
5569

5670
# format integer
5771

@@ -78,7 +92,9 @@ fs = FormatSpec("d")
7892
@test fmt("<6d", 123) == "123 "
7993
@test fmt(">6d", 123) == " 123"
8094
@test fmt("*<6d", 123) == "123***"
95+
@test fmt("⋆<6d", 123) == "123⋆⋆⋆"
8196
@test fmt("*>6d", 123) == "***123"
97+
@test fmt("⋆>6d", 123) == "⋆⋆⋆123"
8298
@test fmt("< 6d", 123) == " 123 "
8399
@test fmt("<+6d", 123) == "+123 "
84100
@test fmt("> 6d", 123) == " 123"
@@ -117,9 +133,13 @@ fs = FormatSpec("d")
117133
@test fmt("<08.2f", -8.376) == "-0008.38"
118134
@test fmt(">08.2f", -8.376) == "-0008.38"
119135
@test fmt("*<8.2f", 8.376) == "8.38****"
136+
@test fmt("⋆<8.2f", 8.376) == "8.38⋆⋆⋆⋆"
120137
@test fmt("*>8.2f", 8.376) == "****8.38"
138+
@test fmt("⋆>8.2f", 8.376) == "⋆⋆⋆⋆8.38"
121139
@test fmt("*<8.2f", -8.376) == "-8.38***"
140+
@test fmt("⋆<8.2f", -8.376) == "-8.38⋆⋆⋆"
122141
@test fmt("*>8.2f", -8.376) == "***-8.38"
142+
@test fmt("⋆>8.2f", -8.376) == "⋆⋆⋆-8.38"
123143

124144
@test fmt(".2f", 0.999) == "1.00"
125145
@test fmt(".2f", 0.996) == "1.00"
@@ -142,7 +162,9 @@ fs = FormatSpec("d")
142162
@test fmt("<12.2e", 13.89) == "1.39e+01 "
143163
@test fmt(">12.2e", 13.89) == " 1.39e+01"
144164
@test fmt("*<12.2e", 13.89) == "1.39e+01****"
165+
@test fmt("⋆<12.2e", 13.89) == "1.39e+01⋆⋆⋆⋆"
145166
@test fmt("*>12.2e", 13.89) == "****1.39e+01"
167+
@test fmt("⋆>12.2e", 13.89) == "⋆⋆⋆⋆1.39e+01"
146168
@test fmt("012.2e", 13.89) == "00001.39e+01"
147169
@test fmt("012.2e", -13.89) == "-0001.39e+01"
148170
@test fmt("+012.2e", 13.89) == "+0001.39e+01"
@@ -175,5 +197,7 @@ fs = FormatSpec("d")
175197
@test fmt("<5f", Inf) == "Inf "
176198
@test fmt(">5f", Inf) == " Inf"
177199
@test fmt("*<5f", Inf) == "Inf**"
200+
@test fmt("⋆<5f", Inf) == "Inf⋆⋆"
178201
@test fmt("*>5f", Inf) == "**Inf"
202+
@test fmt("⋆>5f", Inf) == "⋆⋆Inf"
179203

test/formatexpr.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@ using Base.Test
55

66
@test format("{1}", 10) == "10"
77
@test format("abc {1}", 10) == "abc 10"
8+
@test format("αβγ {1}", 10) == "αβγ 10"
89
@test format("{1} efg", 10) == "10 efg"
10+
@test format("{1} ϵζη", 10) == "10 ϵζη"
911
@test format("abc {1} efg", 10) == "abc 10 efg"
12+
@test format("αβγ{1}ϵζη", 10) == "αβγ10ϵζη"
1013
@test format("{1} + {2}", 10, "xyz") == "10 + xyz"
14+
@test format("{1} + {2}", 10, "χψω") == "10 + χψω"
1115
@test format("abc {1} + {2}", 10, "xyz") == "abc 10 + xyz"
16+
@test format("αβγ {1} + {2}", 10, "χψω") == "αβγ 10 + χψω"
1217
@test format("{1} + {2} efg", 10, "xyz") == "10 + xyz efg"
18+
@test format("{1} + {2} ϵζη", 10, "χψω") == "10 + χψω ϵζη"
1319
@test format("abc {1} + {2} efg", 10, "xyz") == "abc 10 + xyz efg"
14-
@test format("abc {1}{2} efg", 10, "xyz") == "abc 10xyz efg"
20+
@test format("αβγ {1} + {2} ϵζη", 10, "χψω") == "αβγ 10 + χψω ϵζη"
21+
@test format("αβγ {1}{2} ϵζη", 10, "χψω") == "αβγ 10χψω ϵζη"
1522

1623
@test format("{1:d} + {2:s}", 10, "xyz") == "10 + xyz"
24+
@test format("{1:d} + {2:s}", 10, "χψω") == "10 + χψω"
1725
@test format("{1:04d} + {2:*>5}", 10, "xyz") == "0010 + **xyz"
18-
@test format("let {2:<5} := {1:.4f};", 12.3, "var") == "let var := 12.3000;"
26+
@test format("{1:04d} + {2:⋆>5}", 10, "χψω") == "0010 + ⋆⋆χψω"
27+
@test format("let {2:<5} := {1:.4f};", 12.3, "χψω") == "let χψω := 12.3000;"
1928

2029
@test format("{}", 10) == "10"
2130
@test format("{} + {}", 10, 20) == "10 + 20"
@@ -30,6 +39,7 @@ using Base.Test
3039
@test format("{{}}") == "{}"
3140
@test format("{{{1}}}", 10) == "{10}"
3241
@test format("v: {{{2}}} = {1:.4f}", 1.2, "ab") == "v: {ab} = 1.2000"
42+
@test format("χ: {{{2}}} = {1:.4f}", 1.2, "αβ") == "χ: {αβ} = 1.2000"
3343

3444
# with filter
3545
@test format("{1|>abs2} + {2|>abs2:.2f}", 2, 3) == "4 + 9.00"

0 commit comments

Comments
 (0)