std/format
import std/format to use it. Source: src/std/format.iyi at v0.18.0.
Provides sprintf, printf, and String.format / String#% with standard format specifiers:
`%[flags][width][.precision]specifier`Supported specifiers:
%s - string (Object#to_s)
%p - inspected value (Object#inspect)
%c - character (Char or integer ASCII code)
%d, %i - signed decimal integer
%u - unsigned decimal integer
%x - hexadecimal lowercase
%X - hexadecimal uppercase
%o - octal integer
%b - binary integer
%f - floating point in fixed-point decimal notation
%e - floating point in scientific notation (lowercase e)
%E - floating point in scientific notation (uppercase E)
%g - the shorter of %f and %e, trailing zeros trimmed (C's rule)
%G - the same, with an uppercase E
%% - literal percent signFlags:
- left-align within field (default right-align)
+ always show sign (+ or -)
(space) space before non-negative numbers if no sign
0 pad with zeros instead of spaces (between sign/prefix and digits)
# alternate format (0x, 0X, 0o, 0b prefixes, trailing dot for float prec 0)Width: minimum field width; values wider than field are never truncated. Precision:
integers: minimum digits to appear (padded with leading zeros);
precision 0 on value 0 produces zero digits.
floats: fractional decimal places, exact and rounded half to even.
strings: maximum characters to include (truncated if longer).Where it lives: Outside the prelude, for the reason socket is: nothing in src/iyi/ calls sprintf, and a program that formats no string should not carry the engine that would. import std/format brings sprintf, printf, String.format and String#% with it, and the reopenings below travel with the import the way std/text's do (SPEC.md III.9).
And against iyi's own prelude only: String#% is a name Crystal has, so import std/format in a --crystal program is refused rather than replacing the library's under the whole program (SPEC.md III.6).
printfdef
The argument list as one array or tuple, as sprintf takes it.
pub def printf(format_string : String, args : Array) : Nilprintfdef
pub def printf(format_string : String, args : Tuple) : Nilprintfdef
pub def printf(format_string : String, *args : *T) : Nil forall Tsprintfdef
The argument list may be one array or tuple, as the other library takes it: "%s, %s, %s, D" % ['A', 'B', 'C'], its own example, panicked "too few arguments for format string" here, and "[%s]" % ["A"] printed [["A"]] where it prints [A]. Two overloads rather than one taking Array | Tuple: a union with Array in it cannot be written into an artifact ("can't use Array(T) in unions yet").
pub def sprintf(format_string : String, args : Array) : Stringsprintfdef
pub def sprintf(format_string : String, args : Tuple) : Stringsprintfdef
pub def sprintf(format_string : String, *args : *T) : String forall TIyiBigclass, reopened
class ::IyiBig
# self / small for a `small` under 2^32, self reduced to the quotient,
# the remainder answered. A limb is 32 bits in a 64-bit word, so the
# running remainder shifted up by a limb still fits the word.
def div_small(small : UInt64) : UInt64
# Base ten, most significant digit first, nine digits per division.
def to_decimal : String
endIyiFloatTextmodule, reopened
module ::IyiFloatText
# Extracts Dragon4 digits for a non-zero, finite double.
# Returns {digits_pointer, count, k} where value = 0.d1 d2 ... dn * 10^k.
def self.dragon4(value : Float64) : ::Tuple(Pointer(UInt8), Int32, Int32)
# Scientific notation with exact places, half to even.
def self.format_exp(value : Float64, uppercase : Bool, precision : Int32, hash_flag : Bool) : String
# Fixed-point decimal format with exact places, half to even.
def self.format_fixed(value : Float64, precision : Int32) : String
# a * b as its high and low words, from 32-bit halves.
def self.mul_wide(a : UInt64, b : UInt64) : ::Tuple(UInt64, UInt64)
# Every digit the double has, not the shortest ones padded with zeros:
# `round(f * 2^e * 10^places)`, half to even, as decimal digits. This is
# what a fixed or scientific format prints, and what it did not print:
# `%.0f` of 1e23 answered 100000000000000000000000 where the double is
# 99999999999999991611392, `%.20f` of 0.1 answered twenty zeros where
# the value's digits are 0.10000000000000000555, and `%e` of the
# smallest denormal answered 5.000000e-324 for 4.940656e-324 - the
# shortest digits, which round-trip, are not the value, and past them
# there was nothing but zeros. `places` may be negative, a scale down.
def self.scaled_digits(f : UInt64, e : Int32, places : Int32) : String
# `scaled_digits` in two words, when they hold it: f * 10^places is
# under 2^117 for the places a word of ten's powers reaches, and the
# quotient by 2^-e and its half-to-even rounding are shifts and one
# comparison of the remainder with the half. The same integer the
# bignum's division gives - it is the same arithmetic, exact - where
# that division made `%.2f` three times what Go's takes. nil when the
# value, the places or the answer do not fit.
def self.scaled_quick(f : UInt64, e : Int32, places : Int32) : UInt64 | ::Nil
endIyiFormatmodule, reopened
module ::IyiFormat
# Any integer: an `Int64` or a `UInt64`, whose top half `to_i64` refuses.
def self.code_point(code) : Char
# A width or a precision, which an `Int32` holds: read into one, the
# digits of `%99999999999d` panicked "arithmetic overflow".
def self.field_number(format_string : String, start : Int32, stop : Int32, what : String) : Int32
def self.format_arg(val, verb : Char, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
# A number is a code point, as Crystal's `%c` has it: `%c` of 233 is
# `é`, where it panicked "233 is out of char range" (`chr` is ASCII).
# Anything else is its first character, not its first byte, which cut
# `é` in half.
def self.format_char_arg(val, minus : Bool, width : Int32) : String
# Digits as `to_s(base)` writes them, a `-` first when negative, given
# the verb's sign, prefix, precision and width.
def self.format_digits(text : String, verb : Char, base : Int32, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
def self.format_float64(val : Float64, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
def self.format_float_exp(val : Float64, uppercase : Bool, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
# `%g`: the shorter of the two notations, C's rule. With P the precision
# (6 when none is given, 1 when it is 0) and X the exponent `%e` would
# write at P - 1 places, it is `%e` at P - 1 places when X < -4 or X >= P
# and `%f` at P - 1 - X places otherwise; either way the trailing zeros
# of the fraction go, and its point with them, unless `#` keeps them.
# NaN and the infinities are written as `%e` writes them.
def self.format_float_general(val : Float64, uppercase : Bool, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
def self.format_int64(val : Int64, base : Int32, uppercase : Bool, signed : Bool, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
# Width and precision in characters, because `size` is and because
# `%-10s` is a column: counted in bytes, a multi-byte string came out
# short by one space per extra byte, and a precision cut a character in
# half. The prelude's `ljust`/`rjust` decided the same thing.
#
# The characters a precision keeps are written into one buffer, as
# `each_char` decodes them and `size` counts them: added one at a time
# onto a string of their own, the text was copied once per character,
# and `%.800000s` of a megabyte took 12.8 s, four times as long for
# every doubling.
def self.format_string_arg(str : String, minus : Bool, width : Int32, precision : Int32) : String
# A float under an integer verb is truncated, which is what Ruby, Python
# and the other language answer to it. Past an `Int64` the truncation is
# the double's own integer, f * 2^e, written whole as Python writes it:
# `%d` of 1e30 is 1000000000000000019884624838656, where `to_i64`
# panicked "arithmetic overflow". NaN and the infinities have no
# integer, and the refusal says that rather than "arithmetic overflow".
def self.format_truncated(val : Float64, verb : Char, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
def self.format_uint64(val : UInt64, base : Int32, uppercase : Bool, signed : Bool, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
# An `Int128` or `UInt128`: an integer verb writes its digits, which may
# not fit 64 bits; a float verb its nearest double, as `%f` of an
# `Int64` is.
def self.format_wide(val, verb : Char, minus : Bool, plus : Bool, space : Bool, zero : Bool, hash : Bool, width : Int32, precision : Int32) : String
# A numeric verb is a claim about the argument, and an argument that is
# not a number contradicts it: `%d` of "abc" printed abc, `%f` of a
# `Char` printed the character, and the caller who had mistyped the
# argument order saw their strings where their numbers should be and
# nothing said so.
def self.not_a_number(val, verb : Char) : NoReturn
# A decimal's fraction without its trailing zeros, and without its point
# when nothing is left after it: `%g`'s trim.
def self.trim_fraction(text : String) : String
endStringclass, reopened
class ::String
def %(args : Tuple) : String
def %(arg) : String
def %(*args : *T) : String forall T
def self.format(format_string : String, *args : *T) : String forall T
end
Format strings for iyi.