ref: 3a5ddf0610add4ea0663c4bf2d7f569ac723ad81
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)) } ```