|
| 1 | +@static if VERSION > v"1.6.0-DEV.854" |
| 2 | + |
| 3 | +const NoCommas = 0 |
| 4 | +const CheckCommas = 1 |
| 5 | +const CheckRat = 2 |
| 6 | +const AddCommas = 3 |
| 7 | + |
| 8 | +const formatters = Dict{ ASCIIStr, Tuple{Printf.Format, Int} }() |
| 9 | + |
| 10 | +function _checkfmt(fmt) |
| 11 | + test = Printf.Format(fmt) |
| 12 | + len = length(test.formats) |
| 13 | + len === 0 && error("Invalid format string $fmt") |
| 14 | + len === 1 || error("Only one undecorated format string is allowed") |
| 15 | + test |
| 16 | +end |
| 17 | + |
| 18 | +function _get_formatter(fmt) |
| 19 | + global formatters |
| 20 | + |
| 21 | + chkfmt = get(formatters, fmt, nothing) |
| 22 | + chkfmt === nothing || return chkfmt |
| 23 | + # Check for thousands separator |
| 24 | + if occursin("'", fmt) |
| 25 | + conversion = fmt[end] |
| 26 | + conversion in "sduifFgG" || |
| 27 | + error( string("thousand separator not defined for ", conversion, " conversion") ) |
| 28 | + typ = conversion in "dui" ? CheckCommas : conversion === 's' ? CheckRat : AddCommas |
| 29 | + formatters[fmt] = (_checkfmt( replace( fmt, "'" => ""; count=1 ) ), typ) |
| 30 | + else |
| 31 | + formatters[fmt] = (_checkfmt(fmt), NoCommas) |
| 32 | + end |
| 33 | +end |
| 34 | + |
| 35 | +function cfmt(fmt::ASCIIStr, x::T) where {T} |
| 36 | + formatter, typ = _get_formatter(fmt) |
| 37 | + s = Printf.format(formatter, x) |
| 38 | + typ === NoCommas ? s : |
| 39 | + typ === CheckCommas ? checkcommas(s) : |
| 40 | + (typ === CheckRat && T <: Rational) ? addcommasrat(s) : addcommasreal(s) |
| 41 | +end |
| 42 | + |
| 43 | +function _checkrat(formatter, x::T) where {T} |
| 44 | + s = Printf.format(formatter, x) |
| 45 | + T <: Rational ? addcommasrat(s) : addcommasreal(s) |
| 46 | +end |
| 47 | + |
| 48 | +function generate_formatter( fmt::ASCIIStr ) |
| 49 | + formatter, typ = _get_formatter(fmt) |
| 50 | + typ === NoCommas ? x -> Printf.format(formatter, x) : |
| 51 | + typ === CheckCommas ? x -> checkcomma(Printf.format(formatter, x)) : |
| 52 | + typ === CheckRat ? x -> _checkrat(formatter, x) : |
| 53 | + x -> addcommasreal(Printf.format(formatter, x)) |
| 54 | +end |
| 55 | + |
| 56 | +else |
1 | 57 | formatters = Dict{ ASCIIStr, Function }()
|
2 | 58 |
|
3 | 59 | cfmt( fmt::ASCIIStr, x ) = m_eval(Expr(:call, generate_formatter( fmt ), x))
|
4 | 60 |
|
5 | 61 | function checkfmt(fmt)
|
6 |
| - @static if VERSION > v"1.6.0-DEV.854" |
7 |
| - test = Printf.Format(fmt) |
8 |
| - length(test.formats) == 1 || |
9 |
| - error( "Only one AND undecorated format string is allowed") |
10 |
| - else |
11 |
| - test = @static VERSION >= v"1.4.0-DEV.180" ? Printf.parse(fmt) : Base.Printf.parse( fmt ) |
12 |
| - (length( test ) == 1 && typeof( test[1] ) <: Tuple) || |
13 |
| - error( "Only one AND undecorated format string is allowed") |
14 |
| - end |
| 62 | + test = @static VERSION >= v"1.4.0-DEV.180" ? Printf.parse(fmt) : Base.Printf.parse( fmt ) |
| 63 | + (length( test ) == 1 && typeof( test[1] ) <: Tuple) || |
| 64 | + error( "Only one AND undecorated format string is allowed") |
15 | 65 | end
|
16 | 66 |
|
17 | 67 | function generate_formatter( fmt::ASCIIStr )
|
@@ -43,6 +93,7 @@ function generate_formatter( fmt::ASCIIStr )
|
43 | 93 | end
|
44 | 94 | return (formatters[ fmt ] = x->Base.invokelatest(formatter, x))
|
45 | 95 | end
|
| 96 | +end |
46 | 97 |
|
47 | 98 | function addcommasreal(s)
|
48 | 99 | len = length(s)
|
|
0 commit comments