This package offers Python-style general formatting and c-style numerical formatting (for speed).
Julia Version | Unit Tests | Coverage |
---|---|---|
Julia Latest |
This package is pure Julia. Setting up this package is like setting up other Julia packages:
import Pkg; Pkg.add("Format")
or
]add Format
It is forked off of Formatting.jl, and I try to keep the oldmaster branch up to date with the master branch of that, and cherry pick or port all necessary changes to Format
).
To start using the package, you can simply write
using Format
This package depends on Julia of version 1.4 or above, and. 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 pyfmt
to format a single value into a string, or format
to format one to multiple arguments into a string using an format expression.
pyfmt(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:
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 Format.*
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 Format
fmt = "%10.3f"
s = cfmt( 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.
This package also supplements the lack of thousand separator e.g. "%'d"
, "%'f"
, "%'g"
.
Note: "%'g"
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 keywords 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.