Console output (io)
Plan 11 step 40 (2026-10-07): io:format/1,2 and io:put_chars/1 write to
standard output. They are runtime builtins of module io in the bridge catalog
(builtins); the runtime implements OTP's io_lib_format and
io_lib_pretty rules in C++ (io_format.cpp,
io_pretty.cpp).
Calls
io:format(Format)isio:format(Format, []). Both returnok.io:put_chars(Chardata)writes chardata: Unicode characters, UTF-8 binaries and nested lists ending in[]or a binary. Anything else (an atom, a surrogate, invalid UTF-8, a bitstring) raisesbadarg.- Text is built whole, then written as UTF-8, as OTP's standard output device
does in
-noshellmode (encodingunicode). An error writes nothing. A rejected write is the runtime failureoutput_failure(exit 70). - Qualified calls,
fun io:format/2,apply(io, format, Args)andM:format(...)all reach the builtins. Otheriofunctions keep theunknown module iodiagnostic. A batch module namediodoes not replace the builtins (OTP'siois sticky).
Formats
Formatis an atom (its characters), a binary (its bytes as Latin-1 characters) or a list. A list element that is not a character is chardata written as it is, without control sequences, and moves the column by one (OTP's quirk).- Control sequences
~F.P.PadModC: field widthF(negative or-: left adjusted), precisionP, pad character,*taking an integer (or the pad) from the arguments, modifierst(Unicode),l(no string detection) andk(ordered maps; Clause always prints maps in key order). - Supported
C:~w,~p,~s,~c,~b,~B,~i,~n,~~, with OTP's field rules:~struncates or pads toPwithinF;~wand~bprint*characters when the text does not fitF;~crepeats the character;~b/~Btake the base fromP(2..36);~nwithFwritesFnewlines. - Without
t,~stakes Latin-1 characters only and~cwrites the low byte of its integer;~w/~pescape atom characters beyond Latin-1 as\x{...}. Witht,~sreads binaries as UTF-8 (falling back to Latin-1) and~pwrites<<"..."/utf8>>for printable UTF-8 binaries. badarg: an unknown control character, missing or extra arguments, an argument of the wrong type,Fsmaller thanPfor~s/~c, a left adjusted~por~n, a base outside 2..36, output that is not Unicode.- Not implemented (
badarg, see differences):~e,~f,~g,~x,~X,~+,~#,~W,~Pand theKmodifier.
Pretty printing (~p)
- Line length is
F(default 80, 0 writes one line); the first column isP, else the column the output has reached on its line (tabs to multiples of 8). - The term becomes OTP's intermediate form: each value with its one-line
length; strings (flat lists of printable Latin-1 characters, the default
io:printable_range()), printable binaries, atoms and numbers are text. - What fits on the rest of the line is written whole. Lists and tuples break
between elements, aligned after the bracket; tagged tuples (
{atom, ...}) align after the tag, or indent by 4 (or 1) when that would pass half the line; map pairs and native record fields that do not fit put the value on the next line; long binaries wrap between bytes. - Containers nested more than 256 deep raise
system_limit(the layout recurses on the native stack). - Formatting runs to completion, however large the term (portions).
Clause