Skip to content

Commit

Permalink
Merge pull request #49 from JuliaString/spj/addcommas
Browse files Browse the repository at this point in the history
Improve addcommas processing
  • Loading branch information
ScottPJones committed Oct 22, 2019
2 parents b486b35 + 45eee87 commit c4d2f61
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 33 deletions.
70 changes: 38 additions & 32 deletions src/cformat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ function generate_formatter( fmt::ASCIIStr )

if !occursin("'", fmt)
checkfmt(fmt)
return (formatters[ fmt ] = @eval(x->@sprintf( $fmt, x )))
formatter = @eval(x->@sprintf( $fmt, x ))
return (formatters[ fmt ] = x->Base.invokelatest(formatter, x))
end

conversion = fmt[end]
Expand All @@ -24,60 +25,65 @@ function generate_formatter( fmt::ASCIIStr )

fmtactual = replace( fmt, "'" => ""; count=1 )
checkfmt( fmtactual )
conversion in "sfF" ||
return (formatters[ fmt ] = @eval(x->checkcommas(@sprintf( $fmtactual, x ))))

formatters[ fmt ] =
if endswith( fmtactual, 's')
formatter =
if !(conversion in "sfF")
@eval(x->checkcommas(@sprintf( $fmtactual, x )))
elseif endswith( fmtactual, 's')
@eval((x::Real)->((eltype(x) <: Rational)
? addcommasrat(@sprintf( $fmtactual, x ))
: addcommasreal(@sprintf( $fmtactual, x ))))
else
@eval((x::Real)->addcommasreal(@sprintf( $fmtactual, x )))
end
return (formatters[ fmt ] = x->Base.invokelatest(formatter, x))
end

function addcommasreal(s)
len = length(s)
dpos = findfirst( isequal('.'), s )
dpos !== nothing && return string(addcommas( s[1:dpos-1] ), s[ dpos:end ])
dpos !== nothing && return addcommas(s, len, dpos-1)
# find the rightmost digit
for i in length( s ):-1:1
isdigit( s[i] ) && return string(addcommas( s[1:i] ), s[i+1:end])
for i in len:-1:1
isdigit( s[i] ) && return addcommas(s, len, i)
end
s
end

function addcommasrat(s)
# commas are added to only the numerator
spos = findfirst( isequal('/'), s )
string(addcommas( s[1:spos-1] ), s[spos:end])
end
# commas are added to only the numerator
addcommasrat(s) = addcommas(s, length(s), findfirst( isequal('/'), s )-1)

function checkcommas(s)
for i in length( s ):-1:1
if isdigit( s[i] )
s = string(addcommas( s[1:i] ), s[i+1:end])
break
end
len = length(s)
for i in len:-1:1
isdigit( s[i] ) && return addcommas(s, len, i)
end
s
end

function addcommas( s::ASCIIStr )
len = length(s)
t = ""
for i in 1:3:len
subs = s[max(1,len-i-1):len-i+1]
if i == 1
t = subs
elseif match( r"[0-9]", subs ) != nothing
t = string(subs, ',', t)
else
t = string(subs, t)
end
function addcommas(s::T, len, lst) where {T<:AbstractString}
lst < 4 && return s
beg = 1
while beg < len
isdigit(s[beg]) && break
beg += 1
end
dig = lst - beg + 1
dig < 4 && return s

commas = div(dig - 1, 3)
sv = Base.StringVector(len + commas)

for i = 1:beg-1; sv[i] = s[i]; end
cnt = dig - commas*3
pos = beg - 1
for i = beg:lst-3
sv[pos += 1] = s[i]
(cnt -= 1) == 0 && (cnt = 3; sv[pos += 1] = ',')
end
t
for i = lst-2:len; sv[i+commas] = s[i]; end
T(sv)
end
addcommas(s) = (l = length(s); addcommas(s, l, l))

function generate_format_string(;
width::Int=-1,
Expand Down
2 changes: 1 addition & 1 deletion src/fmt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ end
function _optional_commas(x::Real, s::AbstractString, fspec::FormatSpec)
prevwidth = length(s)
dpos = findfirst( isequal('.'), s)
s = dpos === nothing ? addcommas(s) : string(addcommas(s[1:dpos-1]), '.', s[dpos+1:end])
s = addcommas(s, prevwidth, dpos === nothing ? prevwidth : dpos - 1)

# check for excess width from commas
w = length(s)
Expand Down

2 comments on commit c4d2f61

@ScottPJones
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/4939

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if Julia TagBot is installed, or can be done manually through the github interface, or via:

git tag -a v1.0.1 -m "<description of version>" c4d2f61847a12ae6abd2f2849cb0320a2f2e3e30
git push origin v1.0.1

Please sign in to comment.