chickadee » fmt » columnar

columnar <column> ...procedure

Formats each <column> side-by-side, i.e. as though each were formatted separately and then the individual lines concatenated together. The current column width is divided evenly among the columns, and all but the last column are right-padded. For example

(fmt #t (columnar (dsp "abc\ndef\n") (dsp "123\n456\n")))


    abc     123
    def     456

assuming a 16-char width (the left side gets half the width, or 8 spaces, and is left aligned). Note that we explicitly use DSP instead of the strings directly. This is because columnar treats raw strings as literals inserted into the given location on every line, to be used as borders, for example:

  (fmt #t (columnar "/* " (dsp "abc\ndef\n")
                    " | " (dsp "123\n456\n")
                    " */"))

would output

 /* abc | 123 */
 /* def | 456 */

You may also prefix any column with any of the symbols 'left, 'right or 'center to control the justification. The symbol 'infinite can be used to indicate the column generates an infinite stream of output.

You can further prefix any column with a width modifier. Any positive integer is treated as a fixed width, ignoring the available width. Any real number between 0 and 1 indicates a fraction of the available width (after subtracting out any fixed widths). Columns with unspecified width divide up the remaining width evenly.

Note that columnar builds its output incrementally, interleaving calls to the generators until each has produced a line, then concatenating that line together and outputting it. This is important because as noted above, some columns may produce an infinite stream of output, and in general you may want to format data larger than can fit into memory. Thus columnar would be suitable for line numbering a file of arbitrary size, or implementing the Unix yes(1) command, etc.

As an implementation detail, columnar uses first-class continuations to interleave the column output. The core fmt itself has no knowledge of or special support for columnar, which could complicate and potentially slow down simpler fmt operations. This is a testament to the power of call/cc - it can be used to implement coroutines or arbitrary control structures even where they were not planned for.