[!WARNING] This package has been unmaintained for a while, and contains serious bugs. Format.jl is a new version of this package that supports a lot of new features and contains many bug fixes. To update, replace every instance of
Formatting
withFormat
, replacefmt
withpyfmt
, and replacesprintf1
withcfmt
.
This package offers Python-style general formatting and c-style numerical formatting (for speed).
PackageEvaluator | Build Status | Repo Status |
---|---|---|
This package is pure Julia. Setting up this package is like setting up other Julia packages:
Pkg.add("Formatting")
To start using the package, you can simply write
using Formatting
This package depends on Julia of version 0.7 or above. It has no other dependencies. The package is MIT-licensed.
This package has two types FormatSpec
and FormatExpr
to represent a format specification.
In particular, FormatSpec
is used to capture the specification of a single entry. One can compile a format specification string into a FormatSpec
instance as
fspec = FormatSpec("d")
fspec = FormatSpec("<8.4f")
Please refer to Python's format specification language for details.
FormatExpr
captures a formatting expression that may involve multiple items. One can compile a formatting string into a FormatExpr
instance as
fe = FormatExpr("{1} + {2}")
fe = FormatExpr("{1:d} + {2:08.4e} + {3|>abs2}")
Please refer to Python's format string syntax for details.
Note: If the same format is going to be applied for multiple times. It is more efficient to first compile it.
One can use printfmt
and printfmtln
for formatted printing:
printfmt(io, fe, args...)
printfmt(fe, args...)
Print given arguments using given format fe
. Here fe
can be a formatting string, an instance of FormatSpec
or FormatExpr
.
Examples
printfmt("{1:>4s} + {2:.2f}", "abc", 12) # --> print(" abc + 12.00")
printfmt("{} = {:#04x}", "abc", 12) # --> print("abc = 0x0c")
fs = FormatSpec("#04x")
printfmt(fs, 12) # --> print("0x0c")
fe = FormatExpr("{} = {:#04x}")
printfmt(fe, "abc", 12) # --> print("abc = 0x0c")
Notes
If the first argument is a string, it will be first compiled into a FormatExpr
, which implies that you can not use specification-only string in the first argument.
printfmt("{1:d}", 10) # OK, "{1:d}" can be compiled into a FormatExpr instance
printfmt("d", 10) # Error, "d" can not be compiled into a FormatExpr instance
# such a string to specify a format specification for single argument
printfmt(FormatSpec("d"), 10) # OK
printfmt(FormatExpr("{1:d}", 10)) # OK
printfmtln(io, fe, args...)
printfmtln(fe, args...)
Similar to printfmt
except that this function print a newline at the end.
One can use fmt
to format a single value into a string, or format
to format one to multiple arguments into a string using an format expression.
fmt(fspec, a)
Format a single value using a format specification given by fspec
, where fspec
can be either a string or an instance of FormatSpec
.
format(fe, args...)
Format arguments using a format expression given by fe
, where fe
can be either a string or an instance of FormatSpec
.
At this point, this package implements a subset of Python's formatting language (with slight modification). Here is a summary of the differences:
g
and G
for floating point formatting have not been supported yet. Please use f
, e
, or E
instead.
The package currently provides default alignment, left alignment <
and right alignment >
. Other form of alignment such as centered alignment ^
has not been supported yet.
In terms of argument specification, it supports natural ordering (e.g. {} + {}
), explicit position (e.g. {1} + {2}
). It hasn't supported named arguments or fields extraction yet. Note that mixing these two modes is not allowed (e.g. {1} + {}
).
The package provides support for filtering (for explicitly positioned arguments), such as {1|>lowercase}
by allowing one to embed the |>
operator, which the Python counter part does not support.
The c-style part of this package aims to get around the limitation that
@sprintf
has to take a literal string argument.
The core part is basically a c-style print formatter using the standard
@sprintf
macro.
It also adds functionalities such as commas separator (thousands), parenthesis for negatives,
stripping trailing zeros, and mixed fractions.
The idea here is that the package compiles a function only once for each unique
format string within the Formatting.*
name space, so repeated use is faster.
Unrelated parts of a session using the same format string would reuse the same
function, avoiding redundant compilation. To avoid the proliferation of
functions, we limit the usage to only 1 argument. Practical consideration
would suggest that only dozens of functions would be created in a session, which
seems manageable.
Usage
using Formatting
fmt = "%10.3f"
s = sprintf1( fmt, 3.14159 ) # usage 1. Quite performant. Easiest to switch to.
fmtrfunc = generate_formatter( fmt ) # usage 2. This bypass repeated lookup of cached function. Most performant.
s = fmtrfunc( 3.14159 )
s = format( 3.14159, precision=3 ) # usage 3. Most flexible, with some non-printf options. Least performant.
sprintf1
: Speed penalty is about 20% for floating point and 30% for integers.
If the formatter is stored and used instead (see the example using generate_formatter
above),
the speed penalty reduces to 10% for floating point and 15% for integers.
This package also supplements the lack of thousand separator e.g. "%'d"
, "%'f"
, "%'s"
.
Note: "%'s"
behavior is that for small enough floating point (but not too small),
thousand separator would be used. If the number needs to be represented by "%e"
, no
separator is used.
format
functionThis package contains a run-time number formatter format
function, which goes beyond
the standard sprintf
functionality.
An example:
s = format( 1234, commas=true ) # 1,234
s = format( -1234, commas=true, parens=true ) # (1,234)
The keyword arguments are (Bold keywards are not printf standard)
(1.01)
instead of -1.01
. Useful in finance. Note that
you cannot use signed
and parens
option at the same time.#
alternative form explanation in standard printf documentationaAeEfFoxX
. See standard
printf documentation.1_1/2
instead of 3/2
_
/
:none
. It could be :metric
, :binary
, or :finance
.
:metric
implements common SI symbols for large and small numbers e.g. M
, k
, μ
, n
:binary
implements common ISQ symbols for large numbers e.g. Ti
, Gi
, Mi
, Ki
:finance
implements common finance/news symbols for large numbers e.g. b
(billion), m
(millions)See the test script for more examples.