ref: be27d7ef34e73a0289e786456c8aa60aec55e646
dir: /doc/api/libstd/fmt.txt/
{
title: Formatted I/O
description: libstd: Formatted I/O
}
Formatted I/O
-------
pkg std =
/* output to file descriptors */
const put : (fmt : byte[:], args : ... -> size)
const fput : (fd : fd, fmt : byte[:], args : ... -> size)
const putv : (fmt : byte[:], ap : valist# -> size)
const fputv : (fd : fd, fmt : byte[:], ap : valist# -> size)
/* formatting values */
const fmt : (fmt : byte[:], args : ... -> byte[:])
const fmtv : (fmt : byte[:], ap : valist# -> byte[:])
const bfmt : (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
const bfmtv : (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:])
const sbfmt : (buf : strbuf#, fmt : byte[:], args : ... -> size)
const sbfmtv : (buf : strbuf#, fmt : byte[:], ap : valist# -> size)
/* custom formatting */
const fmtinstall : (ty : byte[:], \
fn : (sb : strbuf#, \
ap : valist#, \
opts : (byte[:],byte[:])[:] \
-> void), \
optdesc : (byte[:], bool)[:] \
-> void)
;;
Overview
--------
Formatting in Myrddin is done with format strings. These are effectively
dynamically typed at runtime, using introspection to decide the best way to
format a type. Custom formatters are allowed and encouraged.
Formatting is specified with a `{}` pair, with any specifiers describing the
formatting passed in as a comma separated set of key value pairs. For example,
an integer can be padded with zeros and formatted in hex with the following
format specifier: `{p=0,x}`. If you want a literal '{' character, it can
be escaped by doubling it.
None of the format specifiers print a newline character by default.
Format Specifiers
--------------------------
The set of specifiers for the default types is sparse, and is fully
specified below.
<dl>
<dt>w=WIDTH</dt>
<dd><p>Fill out to at least width WIDTH, filling with pad
characters.</p></dd>
<dt>p=PAD</dt>
<dd>
<p>Fill spare width with this character. Defaults to a space
character.</p> </dd>
<dt>x</dt>
<dd>
<p>Format in hex. This is only valid for integer types.</p>
</dd>
<dt>j=joiner</dt>
<dd>
<p>Join slices with the joiner string. This leaves off the square
brackets from the ends, and replaces the default joiner string ", ".
</p>
</dd>
</dl>
Specifiers can be installed by custom specifiers, and can be any
arbitrary set of strings.
Functions
---------
All the format functions come in two variants: A variadic one, and one
that takes a variadic argument list. The latter is present for ease of
chaining from within a variadic function.
const put : (fmt : byte[:], args : ... -> size)
const fput : (fd : fd, fmt : byte[:], args : ... -> size)
const putv : (fmt : byte[:], ap : valist# -> size)
const fputv : (fd : fd, fmt : byte[:], ap : valist# -> size)
The `put` set of functions will format and output to a file descriptor. For
`put` and `putv`, the file descriptor is stdout. For `fput` and `fputv`, the
file descriptor is the one that is provided.
These functions write immediately, and do not buffer, although they do attempt
to do their writing in a single system call, and will only split the call if
the kernel indicates short writes.
The `v` variants will take a variadic argument list for printing.
Returns: the number of bytes written to the file descriptor.
const sbfmt : (buf : strbuf#, fmt : byte[:], args : ... -> size)
const sbfmtv : (buf : strbuf#, fmt : byte[:], ap : valist# -> size)
The sbfmt functions will append to a string buffer, instead of writing to an
output stream, but are otherwise similar to the `fmt` functions. These
functions will return the number of bytes formatted. If the string buffer is
statically sized, and gets filled, the truncated size will be returned.
const fmt : (fmt : byte[:], args : ... -> byte[:])
const fmtv : (fmt : byte[:], ap : valist# -> byte[:])
These functions will format according to the format string, and return a
freshly allocated string containing the formatted string. This string should
be freed with `slfree`.
const bfmt : (buf : byte[:], fmt : byte[:], args : ... -> byte[:])
const bfmtv : (buf : byte[:], fmt : byte[:], ap : valist# -> byte[:])
These functions will format according to the format string, putting the result
into `buf`. They return a slice into the buffer array.
const fmtinstall : (ty : byte[:], \
fn : (sb : strbuf#,
ap : valist#, \
opts : (byte[:],byte[:])[:] \
-> void), \
optdesc : (byte[:], bool)[:] \
-> void)
Fmtinstall installs a custom formatter for a type. The type `ty` is a type
description that you would want to format. It can be obtained
using `std.typeof(var)`, `fn` is a function that handles custom formatting,
and `optdesc` is a list of options that this custom formater takes. It is
in the form a list of strings -- the argument names -- and booleans that
define whether these arguments take values.
The custom formatter takes a string buffer `sb` which you are expected to
format the custom input into, as well as a valist that you are expected to
pull the value from. Finally, it takes an option list.
If a formatter is already installed for a type, it is replaced.
Examples
--------
This example demonstrates a bunch of formatting using the std.format API. It
covers all of the various format specifiers, escaping, as well as showing the
formatting of complex types.
```{runmyr fmtsimple}
use std
const main = {
/* default formats */
std.put("{} {}\n", "abcd", 123)
std.put("{}\n", [1,2,3][:])
std.put("{}\n", (1,"foo"))
/* mix in some format options */
std.put("{w=10}\n", "abcd")
std.put("{p=0,w=10}\n", "abcdefghijkl")
std.put("{w=10,x}\n", 10)
std.put("{p=0,w=10}\n", 10)
/* and now some escaping */
std.put("{}bar{}\n", "foo\n", "baz")
std.put("{{}}bar{}\n", "baz")
std.put("{{bar{}}}\n", "baz")
}
```
This example shows how you would set up a
```{runmyr customfmt}
use std
const main = {
var x : int = 0 /* dummy: used for typeof */
std.fmtinstall(std.typeof(x), goaway, [][:])
std.put("custom format: {}\n", 0x41)
}
const goaway = {sb, ap, opts
var i : int64
i = std.vanext(ap)
std.sbfmt(sb, "go away! char val={}\n", i castto(char))
}
```