@@ -15,7 +15,8 @@ function generate_formatter( fmt::ASCIIStr )
1515
1616 if ! occursin (" '" , fmt)
1717 checkfmt (fmt)
18- return (formatters[ fmt ] = @eval (x-> @sprintf ( $ fmt, x )))
18+ formatter = @eval (x-> @sprintf ( $ fmt, x ))
19+ return (formatters[ fmt ] = x-> Base. invokelatest (formatter, x))
1920 end
2021
2122 conversion = fmt[end ]
@@ -24,60 +25,65 @@ function generate_formatter( fmt::ASCIIStr )
2425
2526 fmtactual = replace ( fmt, " '" => " " ; count= 1 )
2627 checkfmt ( fmtactual )
27- conversion in " sfF" ||
28- return (formatters[ fmt ] = @eval (x-> checkcommas (@sprintf ( $ fmtactual, x ))))
29-
30- formatters[ fmt ] =
31- if endswith ( fmtactual, ' s' )
28+ formatter =
29+ if ! (conversion in " sfF" )
30+ @eval (x-> checkcommas (@sprintf ( $ fmtactual, x )))
31+ elseif endswith ( fmtactual, ' s' )
3232 @eval ((x:: Real )-> ((eltype (x) <: Rational )
3333 ? addcommasrat (@sprintf ( $ fmtactual, x ))
3434 : addcommasreal (@sprintf ( $ fmtactual, x ))))
3535 else
3636 @eval ((x:: Real )-> addcommasreal (@sprintf ( $ fmtactual, x )))
3737 end
38+ return (formatters[ fmt ] = x-> Base. invokelatest (formatter, x))
3839end
3940
4041function addcommasreal (s)
42+ len = length (s)
4143 dpos = findfirst ( isequal (' .' ), s )
42- dpos != = nothing && return string ( addcommas ( s[ 1 : dpos - 1 ] ), s[ dpos: end ] )
44+ dpos != = nothing && return addcommas (s, len, dpos- 1 )
4345 # find the rightmost digit
44- for i in length ( s ) : - 1 : 1
45- isdigit ( s[i] ) && return string ( addcommas ( s[ 1 : i] ), s[i + 1 : end ] )
46+ for i in len : - 1 : 1
47+ isdigit ( s[i] ) && return addcommas (s, len, i )
4648 end
4749 s
4850end
4951
50- function addcommasrat (s)
51- # commas are added to only the numerator
52- spos = findfirst ( isequal (' /' ), s )
53- string (addcommas ( s[1 : spos- 1 ] ), s[spos: end ])
54- end
52+ # commas are added to only the numerator
53+ addcommasrat (s) = addcommas (s, length (s), findfirst ( isequal (' /' ), s )- 1 )
5554
5655function checkcommas (s)
57- for i in length ( s ): - 1 : 1
58- if isdigit ( s[i] )
59- s = string (addcommas ( s[1 : i] ), s[i+ 1 : end ])
60- break
61- end
56+ len = length (s)
57+ for i in len: - 1 : 1
58+ isdigit ( s[i] ) && return addcommas (s, len, i)
6259 end
6360 s
6461end
6562
66- function addcommas ( s:: ASCIIStr )
67- len = length (s)
68- t = " "
69- for i in 1 : 3 : len
70- subs = s[max (1 ,len- i- 1 ): len- i+ 1 ]
71- if i == 1
72- t = subs
73- elseif match ( r" [0-9]" , subs ) != nothing
74- t = string (subs, ' ,' , t)
75- else
76- t = string (subs, t)
77- end
63+ function addcommas (s:: T , len, lst) where {T<: AbstractString }
64+ lst < 4 && return s
65+ beg = 1
66+ while beg < len
67+ isdigit (s[beg]) && break
68+ beg += 1
69+ end
70+ dig = lst - beg + 1
71+ dig < 4 && return s
72+
73+ commas = div (dig - 1 , 3 )
74+ sv = Base. StringVector (len + commas)
75+
76+ for i = 1 : beg- 1 ; sv[i] = s[i]; end
77+ cnt = dig - commas* 3
78+ pos = beg - 1
79+ for i = beg: lst- 3
80+ sv[pos += 1 ] = s[i]
81+ (cnt -= 1 ) == 0 && (cnt = 3 ; sv[pos += 1 ] = ' ,' )
7882 end
79- t
83+ for i = lst- 2 : len; sv[i+ commas] = s[i]; end
84+ T (sv)
8085end
86+ addcommas (s) = (l = length (s); addcommas (s, l, l))
8187
8288function generate_format_string (;
8389 width:: Int = - 1 ,
0 commit comments