String Formatting

March 3, 2016 ยท View on GitHub

Standard string formatting functions format, print, and println are based on Common Lisp's format function. These functions accept a format string, containing text and formatting directives, and a series of arguments processed according to the format string.

The format function returns formatted output as a string; print writes formatted output to stdout; and println writes to stdout, followed by a newline.

Formatting string directives may consume an input argument in a variety of ways, including conditional, iteration, and transformation operations.

Formatting directives consist of a tilde (~), followed by optional flags indicated by the : and @ characters, zero or more optional comma-separated parameters, concluded with a single character.

Directive parameters may be literal numbers; character constants, preceded by a '; the character v, which indicates to consume an input argument for the parameter value; or the character #, which indicates to use the number of remaining arguments as the parameter value.

a - Aesthetic

Formats a value in a manner similar to the Rust fmt::Display trait.

Parameters are min-col,col-inc,min-pad,pad-char.

The string is right-padded (or left-padded if the @ flag is present) with min-pad pad-chars. Then, col-inc pad-chars are inserted until the result is at least min-col chars long.
min-col and min-pad default to 0; col-inc defaults to 1; pad-char defaults to space.

(format "~a" "foo") => "foo"
(format "~10a" "foo") => "foo       "
(format "~10@a" "foo") => "       foo"

s - Standard

Formats a value in a manner similar to the Rust fmt::Debug trait.

Parameters are identical to the a directive.

(format "~s" #'a') => "#'a'"

c - Character

Outputs the value of a character.

(format "~c~c~c" #'a' #'b' #'c') => "abc"

f - Float

Formats a floating point value in standard notation.

Parameters are width,precision,pad-char.

width and precision are passed to the Rust float formatter.
pad-char is used to pad the result and defaults to space.

If the @ flag is present, the sign of the value is always displayed.

(format "~5,2f" 3.14159) => " 3.14"

e - Exponent

Formats a floating point value in exponent notation.

Parameters are identical to f directive.

d, b, o, x - Integer

The d, b, o, and x directives format an integer in decimal, binary, octal, or hexadecimal, respectively.

Parameters are min-col,pad-char,comma-char,comma-interval.

The result is padded with pad-char to at least min-col characters.
min-col defaults to 0; pad-char defaults to space.

If the @ flag is present, the sign of the value is always displayed.

If the : flag is present, comma-char will be inserted into the result every comma-interval digits, starting from the least significant digit.
comma-char defaults to ,; comma-interval defaults to 3.

r - Radix

If given at least one parameter, the r directive will format an integer in a given base in the range [2, 36]. Remaining parameters are handled as for the above integer formatting directives.

With no parameters, ~r will produce the following output:

  • ~r will output the cardinal; e.g. one, two, etc.
  • ~:r will output the ordinal; e.g. first, second, etc.
  • ~@r will output Roman numerals; e.g. 4 as IV.
  • ~@:r will output old Roman numerals; e.g. 4 as IIII.

p - Plural

Formats a standard English plural or singular suffix based on a numeric value. If the value is 1, nothing is output; otherwise s is output. When the @ flag is present, y is output for a value of 1 and ies is output for any other value.

When the : flag is present, the directive will first back up one argument before consuming an argument.

(format "~d friend~:p, ~d enem~:@p" 1 2) => "1 friend, 2 enemies"
(format "~d friend~:p, ~d enem~:@p" 2 1) => "2 friends, 1 enemy"
(format "~d friend~:p, ~d enem~:@p" 3 0) => "3 friends, 0 enemies"

t - Tabulate

Spaces over to a given column.

Parameters are col-num,col-inc.
The directive will space over to at least col-numth column, in col-inc increments.

If the @ flag is present, the parameters are col-rel,col-inc.
the directive will output col-rel spaces, then output enough spaces to advance to a column that is a multiple of col-inc, if necessary.

z - Pretty Print

Formats a value in a human-readable fashion, inserting newlines and indentation into nested lists.

Accepts a single parameter, indent.
Values within lists are indented, starting at indent characters from the first column. The top level value is not indented.

(println "~z"    '(foo (bar (baz))))
(println "  ~2z" '(foo (bar (baz))))

? - Indirection

The directive will consume a string and a list, processing the string as a format string and using the list as arguments.

If the @ flag is present, only a format string argument is consumed and the arguments from the current formatting operation are used.

* - Goto

This directive adjusts which input argument will be consumed by the next formatting directive.

A single integer parameter, n, is accepted. The directive will advance n arguments forward. If the : flag is present, the directive will instead move backward.

If the @ flag is present, the integer argument is taken as an absolute index pointing to the next argument to be consumed.

< / > - Justification

Formats contained directives and left-, right-, or center-justifies resulting output.

The contents of ~< and ~> may be split into segments using ~;, in which case, spacing is evenly divided between segments.

With no flags, the leftmost text is left-justified and the rightmost text is right-justified; if there is only one segment, it is right-justified. If the : flag is present, spacing is added before the first segment. If the @ flag is present, spacing is added after the last segment.

Parameters are min-col,col-inc,min-pad,pad-char.
The text is padded with min-pad instances of pad-char. Then, col-inc padding characters are added until min-col is reached.
min-col and min-pad default to 0; col-inc defaults to 1; pad-char defaults to space.

( / ) - Case conversion

Performs case conversion on resulting text.

  • ~(...~) transforms all letters to lowercase.
  • ~@(...~) capitalizes the first letter.
  • ~:(...~) capitalizes the first letter of each word.
  • ~@:(...~) transforms all letters to uppercase.

[ / ] - Conditional

Given no flags, the directive consumes an integer argument and selects one of the contained branches, separated by ~;, starting at 0. If the argument index exceeds the branches contained, no text is output. However, the last branch may be indicated as a default branch by preceding it with ~:;.
If a parameter is given, it is used in place of consuming a value.

If the : flag is present, a boolean value is consumed. The first branch is output if the value is false; otherwise, the second branch is output.

If the @ flag is present, the next argument is tested. If it is (), nothing is output and the value is consumed; otherwise, the value is not consumed and the sole contained clause is output. Therefore, the clause should typically consume exactly one argument.

{ / } - Iteration

Consumes a list value and outputs the contained directives until the list is empty. Each iteration may consume as many arguments as it desires. The ~^ directive may be used to terminate iteration if no arguments remain.

If the : flag is present, the consumed list is instead a list of sublists. The values of each sublist are made available to each iteration.

If the @ flag is present, remaining arguments are used instead of a single list argument.

If both : and @ flags are present, the remaining arguments are used, each required to be a list.

^ - Terminate

Terminates a grouping directive if no arguments remain to be consumed.

If ~^ is used within a ~:{...~} group, only the current iteration is terminated. Use ~:^ instead to terminate the entire iteration.

| - Page

Inserts a page feed character (\x0c). If a parameter n is given, inserts n page feed characters.

% - Newline

Inserts a newline character (\n). If a parameter n is given, inserts n newline characters.

& - Fresh line

If output will be written an empty line, this directive does nothing; otherwise, it outputs a newline (\n). If a parameter n is given, it will then output n-1 newlines.

\n - Newline continuation

~ followed by a newline character (\n) will consume the newline and any following non-newline whitespace characters.

~ - Tilde

Outputs a literal tilde character (~). If a parameter n is given, outputs n tilde characters.