The minimal base formatting combinators and show interface.
Raw output - displays str to the formatter output port and updates row and col.
Run the combinators args
, accumulating the output to
out
, which is either an output port or a boolean, with
#t
indicating current-output-port
and
#f
to collect the output as a string.
Temporarily bind the parameters in the body x
.
The noop formatter. Generates no output and leaves the state unmodified.
Formats a displayed version of x - if a string or char, outputs the raw characters (as with `display'), if x is already a formatter defers to that, otherwise outputs a written version of x.
Formats a written version of x, as with `write'. The formatting
can be updated with the 'writer
field.
Takes a single list of formatters, combined in sequence with
each
.
Combines each of the formatters in a sequence using
displayed
, so that strings and chars will be output
directly and other objects will be written
.
Captures the output of producer
and formats the result with
consumer
.
Outputs the string str, escaping any quote or escape characters. If esc-ch, which defaults to #\, is #f, escapes only the quote-ch, which defaults to #, by doubling it, as in SQL strings and CSV values. If renamer is provided, it should be a procedure of one character which maps that character to its escape value, e.g. #newline => #n, or #f if there is no escape value.
Only escape if there are special characters, in which case also wrap in quotes. For writing symbols in |...| escapes, or CSV fields, etc. The predicate indicates which characters cause slashification - this is in addition to automatic slashifying when either the quote or escape char is present.
A library of procedures for formatting Scheme objects to text in various ways, and for easily concatenating, composing and extending these formatters.
There are several approaches to text formatting. Building strings
to display
is not acceptable, since it doesn't scale to
very large output. The simplest realistic idea, and what people
resort to in typical portable Scheme, is to interleave
display
and write
and manual loops, but this is
both extremely verbose and doesn't compose well. A simple concept
such as padding space can't be achieved directly without somehow
capturing intermediate output.
The traditional approach is to use templates - typically strings,
though in theory any object could be used and indeed Emacs'
mode-line format templates allow arbitrary sexps. Templates can
use either escape sequences (as in C's printf
and
CL's
format
) or pattern matching (as in Visual Basic's
Format
,
Perl6's
form
, and SQL date formats). The primary disadvantage of
templates is the relative difficulty (usually impossibility) of
extending them, their opaqueness, and the unreadability that
arises with complex formats. Templates are not without their
advantages, but they are already addressed by other libraries such
as
SRFI-28
and
SRFI-48.
This library takes a combinator approach. Formats are nested chains of closures, which are called to produce their output as needed. The primary goal of this library is to have, first and foremost, a maximally expressive and extensible formatting library. The next most important goal is scalability - to be able to handle arbitrarily large output and not build intermediate results except where necessary. The third goal is brevity and ease of use.
The primary interface. Analogous to CL's format
, the first
argument is either an output port or a boolean, with #t
indicating current-output-port
and #f
indicating a
string port. The remaining arguments are formatters, combined as with
each
, run with output to the given destination. If out
is #f
then the accumulated output is returned, otherwise
the result is unspecified.
Output a single newline.
"Fresh line" - output a newline iff we're not at the start of a fresh line.
Move to a given tab-stop (using spaces, not tabs).
Move to an explicit column.
Pad the result of (each-in-list ls)
to at least
width
characters, equally applied to the left and right,
with any extra odd padding applied to the right. Uses the value
of pad-char
for padding, defaulting to #\space
.
As padded/both
but only applies padding on the right.
As padded/both
but only applies padding on the left.
An alias for padded/left
.
Trims the result of (each-in-list ls)
to at most
width
characters, removed from the right. If any characters
are removed, then the value of ellipsis
(default empty)
is used in its place (trimming additional characters as needed to
be sure the final output doesn't exceed width
).
As trimmed/right
but removes from the left.
An alias for trimmed/left
.
As trimmed
but removes equally from both the left and the
right, removing extra odd characters from the right, and inserting
ellipsis
on both sides.
A trimmed
, but truncates and terminates immediately if
more than width
characters are generated by ls
. Thus
ls
may lazily generate an infinite amount of output safely
(e.g. write-simple
on an infinite list). The nature of
this procedure means only truncating on the right is meaningful.
Fits the result of (each-in-list ls)
to exactly
width
characters, padding or trimming on the right as
needed.
As fitted
but pads/trims from the left.
An alias for fitted/left
.
As fitted
but pads/trims equally from both the left and
the right.
Joins the result of applying elt-f
to each element of the
list ls
together with sep
, which defaults to the empty
string.
As joined
but treats the separator as a prefix, inserting
before every element instead of between.
As joined
but treats the separator as a suffix, inserting
after every element instead of between.
As joined
but applies last-f
, instead of
elt-f
, to the last element of ls
, useful for
e.g. commas separating a list with "and" before the final element.
As joined
but if ls
is a dotted list applies
dot-f
to the dotted tail as a final element.
As joined
but counts from start
to end
(exclusive), formatting each integer in the range. If end
is #f
or unspecified, produces an infinite stream of
output.