You are looking at historical revision 6454 of this page. It may differ significantly from its current revision.


Code to generate format functions. It is relatively flexible, supporting inheritance and allowing you to extend your formatters. It is accompanied by an implementation of Common Lisp's format function which is thread safe and extendible (meaning you could define new format characters).



(use format-modular)
(format #f "Found: [~D]: ~A~%" 12 "objects")


(use format-modular)

(define fprintf
  (make-format-function #f #\%
    `(((#\d ,(formatter-padded display))
       (#\s ,(formatter-padded write))))))

(fprintf #t "Found: [%d]: %s\n" 12 "objects")

Known limitations

Chicken doesn't have support for output port column position. Since a new state is created upon each invocation the format output column position has no "memory", thus ~& is accurate only within a single invocation.


[procedure] (make-format-function CASE-SENSITIVE ESCAPE FORMATTERS)

Create and return a procedure that can be used as a format function. The resulting procedure receives a port, a format string and optional arguments. It parses the format string according to the FORMATTERS parameter and outputs a result to the port specified. If, instead of a port, #t is specified, the results will be sent to the current output port. If, on the other hand, #f is passed, the procedure will store its output on a new string and return it.

CASE-SENSITIVE is a boolean. Are the format directives and modifiers case-sensitive?

The returned procedure parses the format string looking for occurrences of the ESCAPE character (usually #\~); when one is found, a function from the formatters argument is called.

FORMATTERS is a list of formatters. Each formatter is itself a list of (char function) pairs, where char is the character for the escape sequence being defined and function the function to call when the character, preceeded by escape, is found in the format string.

To produce the functions included in the formatters, use (formatter-function PROC), where PROC is a procedure that receives the following parameters:

A structure with internal information. You won't normally inspect this directly but rather pass it to other functions that require it (such as *formatter-out-char and *formatter-out-string).
The position in the format string where the beginning of the escape sequence was found. You'll normally just ignore this.
A list with paramters that occur between escape and char (for example, in a format string such as ~23,33,12A).
colon, atsign
Booleans indicating whether those characters occur between escape and char.

To output info at the current position, the formatter functions should use the *formatter-out-char and *formatter-out-string functions. They receive the state parameter (as passed to the formatter function) and a character and string respectively.

For convenience, you can also use (formatter-padded PROC) when you want to create a function to display an object in some representation. In this case, PROC should be a procedure receiving one argument, an object, and write the desired representation to the current output port.


[procedure] (format PORT FORMAT-STRING . ARGS)

PORT is #f or a string for an output to a string, #t for output to the current output port, or a port.

FORMAT-STRING is a string composed of DIRECTIVEs and/or characters.

ARGS are the data for the FORMAT-STRING DIRECTIVEs.

DIRECTIVE-PARAMETER ::= [ [-|+]{0-9}+ | 'CHARACTER | v | # ]

This implementation supports directive parameters and modifiers (`:' and `@' characters). Multiple parameters must be separated by a comma (`,'). Parameters can be numerical parameters (positive or negative), character parameters (prefixed by a quote character (`''), variable parameters (`v'), number of rest arguments parameter (`#'), empty and default parameters. Directive characters are case independent.

Implemented CL Format Control Directives

Documentation syntax: Uppercase characters represent the corresponding control directive characters. Lowercase characters represent control directive parameter descriptions.


Aesthetic (print as `display' does).
left pad.
full padding.


S-expression (print as `write' does).
left pad.
full padding.


print number sign always.
print comma separated.


print number sign always.
print comma separated.


print number sign always.
print comma separated.


print number sign always.
print comma separated.


Radix N.
print a number as a Roman numeral.
print a number as an "old fashioned" Roman numeral.
print a number as an ordinal English number.
print a number as a cardinal English number.


prints `y' and `ies'.
as ~P but jumps 1 argument backward.
as ~@P but jumps 1 argument backward.


prints a character as the reader can understand it (i.e. #\ prefixing).
prints a character as emacs does (eg. `^C' for ASCII 03).


Fixed-format floating-point (prints a flonum like MMM.NNN).
If the number is positive a plus sign is printed.


Exponential floating-point (prints a flonum like MMM.NNNEEE).
If the number is positive a plus sign is printed.


General floating-point (prints a flonum either fixed or exponential).
If the number is positive a plus sign is printed.


Dollars floating-point (prints a flonum in fixed with signs separated).
If the number is positive a plus sign is printed.
A sign is always printed and appears before the padding.
The sign appears before the padding.


print N newlines.


print newline if not at the beginning of the output line.
prints `~&' and then N-1 newlines.


Page Separator.
print N page separators.


print N tildes.


relative tabulation.
full tabulation.


Indirection (expects indirect arguments as a list).
extracts indirect arguments from format arguments.

~( ... ~)

Case conversion (converts by `string-downcase').
converts by `string-capitalize'.
converts by `string-capitalize-first'.
converts by `string-upcase'.


Argument Jumping (jumps 1 argument forward).
jumps N arguments forward.
jumps 1 argument backward.
jumps N arguments backward.
jumps to the 0th argument.
jumps to the Nth argument (beginning from 0)

~[ ... ~]

Conditional Expression (numerical clause conditional).
take argument from N.
true test conditional.
if-else-then conditional.
clause separator.
default clause follows.

~{ ... ~}

Iteration (args come from the next argument (a list)). Iteration bounding is controlled by configuration variables format:iteration-bounded and format:max-iterations. With both variables default, a maximum of 100 iterations will be performed.
at most N iterations.
args from next arg (a list of lists).
args from the rest of arguments.
args from the rest args (lists).


Up and out.
aborts if N = 0
aborts if N = M
aborts if N <= M <= K


Continuation Line.
newline is ignored, whitespace left.
newline is left, whitespace ignored.

Extended, Replaced and Additional Control Directives

Option maybe the character #\V, where the option value is from the argument list.
TABCHAR may be specified.
print a R4RS complex number as `~F~@Fi' with passed parameters for `~F'.
Pretty print formatting of an argument for scheme code lists.
Same as `~?.'
Flushes the output if format DESTINATION is a port.
Print a `#\space' character
print N `#\space' characters.
Print a `#\tab' character
print N `#\tab' characters.
Prints information and a copyright notice on the format implementation.
prints format version.

Not Implemented (Both Common LISP & SLIB)

Terminate the iteration process iff the command it would terminate is ~:{ or ~:@{.
Pretty-print, with support for depth abbreviation, circularity, and sharing.
Print out readproof. Prints out internal objects represented as #<...> as strings "#<...>" so that the format output can always be processed by `read'.
Print out readproof. Prints out internal objects represented as `#<...>' as strings `"#<...>"' so that the format output can always be processed by `read'.
~... parameter-char ...
PARAMETER-CHAR maybe an integer representation for a character.
Argument maybe an integer representation for a character.
Takes N as an integer representation for a character. No arguments are consumed. N is converted to a character by `integer->char'. N must be a positive decimal number.
~F, ~E, ~G, ~$, ~I
May also print number strings, i.e. passing a number as a string and format it accordingly.

Configuration Variables

Format has some configuration variables. There should be no modification necessary for the default configuration. If modification is desired the variable should be set after the format code is loaded.


The following variables are supported by this format implementation:

format:floats (default #t)
System has floating-point numbers.
format:complex-numbers (default #f)
System has complex numbers.
format:expch (default #\E)
The character prefixing the exponent value in ~E printing.
format:iteration-bounded (default #t)
When #t, a ~{...~} control will iterate no more than the number of times specified by format:max-iterations regardless of the number of iterations implied by modifiers and arguments. When #f, a ~{...~} control will iterate the number of times implied by modifiers and arguments, unless termination is forced by language or system limitations.
format:max-iterations (default 100)
The maximum number of iterations performed by a ~{...~} control. Has effect only when format:iteration-bounded is #t.

Not Implemented

The following variables are still not supported by this format implementation:

format:fn-max (default 200)
Maximum number of number digits.
format:en-max (default 10)
Maximum number of exponent digits.
Does number->string add a radix prefix?
format:symbol-case-conv (default #f)
Symbols are converted by symbol->string so the case type of the printed symbols is implementation dependent. format:symbol-case-conv is a one arg closure which is either #f (no conversion), string-upcase, string-downcase or string-capitalize.
format:iobj-case-conv (default #f)
As format:symbol-case-conv but applies for the representation of implementation internal objects.
format:unprocessed-arguments-error? (default #f)
Are superfluous arguments treated as an error.

Pre-defined Formatters

Many predefined formatters that are used for the implementation of format are exported and can be reused to make new format functions:

Parameter escapes.
Iteration escapes.
Case-conversion escapes.
Character escapes.
Number escapes.
Conditional escapes.
Indirection escapes.
Jump escapes.
Object escapes.
Flush escapes.
Plural escapes.
Tabulate escapes.
All of the above.


Restore optimization (build the vector of formatter characters when the formatter is built, not whenever it is called). Export formatter-padded. Use doc-from-wiki.
Added KY$I&\\n escapes, V parameter, commawidth, tabchar, localization, bugfixes [Kon Lovett]
Added support for static linking
Bug fix for numbers egg use & float/expon format, made port optional [Kon Lovett]
Minor doc fixes, rename out-* to *formatter-out-*, works with utf8, uses vectors & fixnum arithmetic where possible [Kon Lovett]
bugfix in formatter-jump
Small bug fixes, more annotations to the source code
First public release