source: project/wiki/format-modular @ 9363

Last change on this file since 9363 was 9363, checked in by Kon Lovett, 12 years ago

BSD for fspath. Fix for testbase. Update for format-modular.

File size: 15.3 KB
Line 
1[[tags:eggs]]
2[[toc:]]
3
4== Introduction
5
6Code 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).
7
8== make-format-function
9
10 [procedure] (make-format-function CASE-SENSITIVE ESCAPE FORMATTERS)
11
12Create and return a procedure that can be used as a format function. The
13resulting procedure receives a port, a format string and optional arguments. It
14parses the format string according to the {{FORMATTERS}} parameter and outputs
15a result to the port specified. If, instead of a port, {{#t}} is specified, the
16results will be sent to the current output port. If, on the other hand, {{#f}}
17is passed, the procedure will store its output on a new string and return it.
18
19{{CASE-SENSITIVE}} is a boolean. Are the format directives and modifiers
20case-sensitive?
21
22The returned procedure parses the format string looking for occurrences of the
23{{ESCAPE}} character (usually {{#\~}}); when one is found, a function from the
24{{formatters}} argument is called.
25
26{{FORMATTERS}} is a list of formatters. Each formatter is itself a list of
27(char function) pairs, where char is the character for the escape sequence
28being defined and function the function to call when the character, preceeded
29by escape, is found in the format string.
30
31To produce the functions included in the formatters, use the {{formatter-function}} procedure.
32
33To output info at the current position, the formatter functions should use the
34{{*formatter-out-foo}} procedures.
35
36To access an argument use the {{*formatter-next-argument}} procedure.
37
38For convenience, you can also use {{formatter-padded}} procedure when you
39want to create a function to display an object with padding.
40
41== formatter-function
42
43 [procedure] (formatter-function PROC)
44
45{{PROC}} is a procedure that receives the following parameters:
46
47; state : 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-foo}} procedures).
48; start : The position in the format string where the beginning of the escape sequence was found. You'll normally just ignore this.
49; params : A list with paramters that occur between {{escape}} and {{char}} (for example, in a format string such as {{~23,33,12A}}).
50; colon, atsign : Booleans indicating whether those characters occur between {{escape}} and {{char}}.
51
52== formatter-padded
53
54 [procedure] (formatter-padded SHOW-FUNC)
55
56{{SHOW-FUNC}} is a one-argument function, the object, which should write (to the
57current-output-port) a representation of the object.
58
59The object representation is padded according to the padding parameters - {{mincol,colinc,minpad,padchar}}.
60
61== *formatter-out-char
62
63 [procedure] (*formatter-out-char STATE CHAR)
64
65Output the {{CHAR}}. {{STATE}} is the internal formatter state object as passed to a {{formatter-function}}.
66
67== *formatter-out-char-times
68
69 [procedure] (*formatter-out-char-times STATE TIMES CHAR)
70
71Output the {{CHAR}} N {{TIMES}}. {{STATE}} is the internal formatter state object as passed to a {{formatter-function}}.
72
73== *formatter-out-char-list
74
75 [procedure] (*formatter-out-char-list STATE LIST-OF-CHAR)
76
77Output the {{LIST-OF-CHAR}}. {{STATE}} is the internal formatter state object as passed to a {{formatter-function}}.
78
79== *formatter-out-string
80
81 [procedure] (*formatter-out-string STATE STRING)
82
83Output the {{STRING}}. {{STATE}} is the internal formatter state object as passed to a {{formatter-function}}.
84
85== *formatter-next-argument
86
87 [procedure] (*formatter-next-argument STATE [INCREMENT])
88
89Consumes and returns the next argument. When {{INCREMENT}} is supplied it is
90the number of arguments to consume, the default is {{1}}. {{STATE}} is the
91internal formatter state object as passed to a {{formatter-function}}.
92
93== format
94
95 [procedure] (format PORT FORMAT-STRING . ARGS)
96
97{{PORT}} is {{#f}} or a string for an output to a string, {{#t}} for output to
98the current output port, or a port.
99
100{{FORMAT-STRING}} is a string composed of {{DIRECTIVE}}s and/or characters.
101
102{{ARGS}} are the data for the {{FORMAT-STRING}} {{DIRECTIVE}}s.
103
104 DIRECTIVE ::= ~{DIRECTIVE-PARAMETER,}[:][@]DIRECTIVE-CHARACTER
105
106 DIRECTIVE-PARAMETER ::= [ [-|+]{0-9}+ | 'CHARACTER | v | # ]
107
108This implementation supports directive parameters and modifiers (`:'
109and `@' characters). Multiple parameters must be separated by a comma
110(`,'). Parameters can be numerical parameters (positive or negative),
111character parameters (prefixed by a quote character (`''), variable
112parameters (`v'), number of rest arguments parameter (`#'), empty and
113default parameters. Directive characters are case independent.
114
115=== Implemented CL Format Control Directives
116
117Documentation syntax: Uppercase characters represent the corresponding
118control directive characters. Lowercase characters represent control
119directive parameter descriptions.
120
121==== ~A
122
123;{{~A}}: Aesthetic (print as `display' does).
124
125;{{~@A}}:left pad.
126
127;{{~mincol,colinc,minpad,padcharA}}: full padding.
128
129==== ~S
130
131;{{~S}}: S-expression (print as `write' does).
132
133;{{~@S}}: left pad.
134
135;{{~mincol,colinc,minpad,padcharS}}: full padding.
136
137==== ~D
138
139;{{~D}}: Decimal.
140
141;{{~@D}}: print number sign always.
142
143;{{~:D}}: print comma separated.
144
145;{{~mincol,padchar,commachar,commawidthD}}: padding.
146
147==== ~X
148
149;{{~X}}: Hexadecimal.
150
151;{{~@X}}: print number sign always.
152
153;{{~:X}}: print comma separated.
154
155;{{~mincol,padchar,commachar,commawidthX}}: padding.
156
157==== ~O
158
159;{{~O}}: Octal.
160
161;{{~@O}}: print number sign always.
162
163;{{~:O}}: print comma separated.
164
165;{{~mincol,padchar,commachar,commawidthO}}: padding.
166
167==== ~B
168
169;{{~B}}: Binary.
170
171;{{~@B}}: print number sign always.
172
173;{{~:B}}: print comma separated.
174
175;{{~mincol,padchar,commachar,commawidthB}}: padding.
176
177==== ~R
178
179;{{~nR}}: Radix N.
180
181;{{~n,mincol,padchar,commachar,commawidthR}}: padding.
182
183;{{~@R}}: print a number as a Roman numeral.
184
185;{{~:@R}}: print a number as an "old fashioned" Roman numeral.
186
187;{{~:R}}: print a number as an ordinal English number.
188
189;{{~R}}: print a number as a cardinal English number.
190
191==== ~P
192
193;{{~P}}: Plural.
194
195;{{~@P}}: prints `y' and `ies'.
196
197;{{~:P}}: as {{~P}} but jumps 1 argument backward.
198
199;{{~:@P}}: as {{~@P}} but jumps 1 argument backward.
200
201==== ~C
202
203;{{~C}}: Character.
204
205;{{~@C}}: prints a character as the reader can understand it (i.e. {{#\}} prefixing).
206
207;{{~:C}}: prints a character as emacs does (eg. `^C' for ASCII 03).
208
209==== ~F
210
211;{{~F}}: Fixed-format floating-point (prints a flonum like MMM.NNN).
212
213;{{~width,digits,scale,overflowchar,padcharF}}: padding.
214
215;{{~@F}}: If the number is positive a plus sign is printed.
216
217==== ~E
218
219;{{~E}}: Exponential floating-point (prints a flonum like MMM.NNN''E''EE).
220
221;{{~width,digits,exponentdigits,scale,overflowchar,padchar,exponentcharE}}: padding
222
223;{{~@E}}: If the number is positive a plus sign is printed.
224
225==== ~G
226
227;{{~G}}: General floating-point (prints a flonum either fixed or exponential).
228
229;{{~width,digits,exponentdigits,scale,overflowchar,padchar,exponentcharG}}: padding.
230
231;{{~@G}}: If the number is positive a plus sign is printed.
232
233==== ~$
234
235;{{~$}}: Dollars floating-point (prints a flonum in fixed with signs separated).
236
237;{{~digits,scale,width,padchar$}}: padding
238
239;{{~@$}}: If the number is positive a plus sign is printed.
240
241;{{~:@$}}: A sign is always printed and appears before the padding.
242
243;{{~:$}}: The sign appears before the padding.
244
245==== ~%
246
247;{{~%}}: Newline.
248
249;{{~n%}}: print ''N'' newlines.
250
251==== ~&
252
253;{{~&}}: print newline if not at the beginning of the output line.
254
255;{{~n&}}: prints `~&' and then N-1 newlines.
256
257==== ~|
258
259;{{~|}}: Page Separator.
260
261;{{~n|}}: print N page separators.
262
263==== ~~
264
265;{{~~}}: Tilde.
266
267;{{~n~}}: print N tildes.
268
269==== ~T
270
271;{{~T}}: Tabulation.
272
273;{{~@T}}: relative tabulation.
274
275;{{~colnum,colincT}}: full tabulation.
276
277==== ~?
278
279;{{~?}}: Indirection (expects indirect arguments as a list).
280
281;{{~@?}}: extracts indirect arguments from format arguments.
282
283==== ~( ... ~)
284
285;{{~(str~)}}: Case conversion (converts by `string-downcase').
286
287;{{~:(str~)}}: converts by `string-capitalize'.
288
289;{{~@(str~)}}: converts by `string-capitalize-first'.
290
291;{{~:@(str~)}}: converts by `string-upcase'.
292
293==== ~*
294
295;{{~*}}: Argument Jumping (jumps 1 argument forward).
296
297;{{~n*}}: jumps N arguments forward.
298
299;{{~:*}}: jumps 1 argument backward.
300
301;{{~n:*}}: jumps N arguments backward.
302
303;{{~@*}}: jumps to the 0th argument.
304
305;{{~n@*}}: jumps to the Nth argument (beginning from 0)
306
307==== ~[ ... ~]
308
309;{{~[str0~;str1~;...~;strn~]}}: Conditional Expression (numerical clause conditional).
310
311;{{~n[}}: take argument from N.
312
313;{{~@[}}: true test conditional.
314
315;{{~:[}}: if-else-then conditional.
316
317;{{~;}}: clause separator.
318
319;{{~:;}}: default clause follows.
320
321==== ~{ ... ~}
322
323;{{~{STR~}}}: 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.
324
325;{{~n{}}: at most N iterations.
326
327;{{~:{}}: args from next arg (a list of lists).
328
329;{{~@{}}: args from the rest of arguments.
330
331;{{~:@{}}: args from the rest args (lists).
332
333==== ~^
334
335;{{~^}}: Up and out.
336
337;{{~n^}}: aborts if N = 0
338
339;{{~n,m^}}: aborts if N = M
340
341;{{~n,m,k^}}: aborts if N <= M <= K
342
343==== ~'<newline>
344
345;{{~'<newline>}}: Continuation Line.
346
347;{{~:'<newline>}}: newline is ignored, whitespace left.
348
349;{{~@'<newline>}}: newline is left, whitespace ignored.
350
351=== Extended, Replaced and Additional Control Directives
352
353;{{~...V...}}: Option maybe the character #\V, where the option value is from the argument list.
354
355;{{~colnum,colinc,tabcharT}}: TABCHAR may be specified.
356
357;{{~I}}: print a R4RS complex number as `~F~@Fi' with passed parameters for `~F'. {{DEPRECATED}} Use '~G', '~F', or '~E'.
358
359;{{~Y}}: Pretty print formatting of an argument for scheme code lists.
360
361;{{~K}}: Same as `~?.'
362
363;{{~!}}: Flushes the output if format DESTINATION is a port.
364
365;{{~_}}: Print a `#\space' character
366
367;{{~n_}}: print N `#\space' characters.
368
369;{{~/}}: Print a `#\tab' character
370
371;{{~n/}}: print N `#\tab' characters.
372
373;{{~Q}}: Prints information and a copyright notice on the format implementation.
374
375;{{~:Q}}: prints format version.
376
377=== Not Implemented (Both Common LISP & SLIB)
378
379;{{~<~>}}: Justification.
380
381;{{~:^}}: Terminate the iteration process iff the command it would terminate is ~:{ or ~:@{.
382
383;{{~W}}: Pretty-print, with support for depth abbreviation, circularity, and sharing.
384
385;{{~:S}}: Print out readproof. Prints out internal objects represented as {{#<...>}} as strings {{"#<...>"}} so that the format output can always be processed by `read'.
386
387;{{~:A}}: Print out readproof. Prints out internal objects represented as `#<...>' as strings `"#<...>"' so that the format output can always be processed by `read'.
388
389;{{~... parameter-char ...}}: PARAMETER-CHAR maybe an integer representation for a character.
390
391;{{~C}}: Argument maybe an integer representation for a character.
392
393;{{~nC}}: 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.
394
395;{{~F, ~E, ~G, ~$, ~I}}: May also print number strings, i.e. passing a number as a string and format it accordingly.
396
397=== Incompatible with Common LISP
398
399;{{~/}}: Call Function {{~/FUNC/}}.
400
401;{{~I}}: Indent.
402
403=== Configuration Variables
404
405Format has some configuration variables. There should be no modification
406necessary for the default configuration. If modification is
407desired the variable should be set after the format code is loaded.
408
409==== Implemented
410
411The following variables are supported by this {{format}} implementation:
412
413;{{format:floats}} (default {{#t}}): System has floating-point numbers.
414
415;{{format:complex-numbers}} (default {{#f}}): System has complex numbers.
416
417;{{format:expch}} (default {{#\E}}): The character prefixing the exponent value in ~E printing.
418
419;{{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.
420
421;{{format:max-iterations}} (default 100): The maximum number of iterations performed by a {{~{...~} }} control.  Has effect only when {{format:iteration-bounded}} is {{#t}}.
422
423==== Not Implemented
424
425The following variables are still not supported by this {{format}} implementation:
426
427;{{format:fn-max}} (default 200): Maximum number of number digits.
428
429;{{format:en-max}} (default 10): Maximum number of exponent digits.
430
431;{{format:radix-pref}}: Does number->string add a radix prefix?
432
433;{{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.
434
435;{{format:iobj-case-conv}} (default #f): As format:symbol-case-conv but applies for the representation of implementation internal objects.
436
437;{{format:unprocessed-arguments-error?}} (default #f): Are superfluous arguments treated as an error.
438
439== Pre-defined Formatters
440
441Many predefined formatters that are used for the implementation of
442{{format}} are exported and can be reused to make new format functions:
443
444;{{*formatter-params*}}: Parameter escapes.
445;{{*formatter-iteration*}}: Iteration escapes.
446;{{*formatter-caseconv*}}: Case-conversion escapes.
447;{{*formatter-chars*}}: Character escapes.
448;{{*formatter-numbers*}}: Number escapes.
449;{{*formatter-cond*}}: Conditional escapes.
450;{{*formatter-indirection*}}: Indirection escapes.
451;{{*formatter-jump*}}: Jump escapes.
452;{{*formatter-objs*}}: Object escapes.
453;{{*formatter-flush*}}: Flush escapes.
454;{{*formatter-plural*}}: Plural escapes.
455;{{*formatter-tabulate*}}: Tabulate escapes.
456;{{*formatter-cl*}}: All of the above.
457
458== Example
459
460=== format
461
462<enscript highlight=scheme>
463(use format-modular)
464(format #f "Found: [~D]: ~A~%" 12 "objects")
465</enscript>
466
467=== make-format-function
468
469<enscript highlight=scheme>
470(use format-modular)
471
472(define fprintf
473  (make-format-function #f #\%
474    `(((#\d ,(formatter-padded display))
475       (#\s ,(formatter-padded write))))))
476
477(fprintf #t "Found: [%d]: %s\n" 12 "objects")
478</enscript>
479
480== Known limitations
481
482Chicken doesn't have support for output port column position. Since a new state is created upon each invocation
483the format output column position has no "memory", thus {{~&}} is accurate only within a single invocation.
484
485== History
486
487; 1.8 : Added '*formatter-next-argument' for argument access by an external formatter. Deprecated '~I' escape sequence. [Kon Lovett]
488
489; 1.7 : 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.
490
491; 1.6 : Added KY$I&\\n escapes, V parameter, commawidth, tabchar, localization, bugfixes [Kon Lovett]
492
493; 1.5 : Added support for static linking
494
495; 1.4 : Bug fix for numbers egg use & float/expon format, made port optional [Kon Lovett]
496
497; 1.3 : Minor doc fixes, rename out-* to *formatter-out-*, works with utf8, uses vectors & fixnum arithmetic where possible [Kon Lovett]
498
499; 1.2 : bugfix in formatter-jump
500
501; 1.1 : Small bug fixes, more annotations to the source code
502
503; 1.0 : First public release
504
Note: See TracBrowser for help on using the repository browser.