diff options
Diffstat (limited to 'doc/api/libstd/fmt.txt')
-rw-r--r-- | doc/api/libstd/fmt.txt | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/doc/api/libstd/fmt.txt b/doc/api/libstd/fmt.txt new file mode 100644 index 0000000..40f1b3f --- /dev/null +++ b/doc/api/libstd/fmt.txt @@ -0,0 +1,201 @@ +{ + 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)) +} +``` + + + |