diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-06-11 07:46:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-06-11 07:46:11 -0700 |
commit | 2c72da160c2f43828316c262855c92e638872a70 (patch) | |
tree | 99f6815576b25ad7931fa40d95f2fd0de87e1d37 | |
parent | 607a764714e1d0391c663146a0c4701c19e15e35 (diff) | |
download | txr-2c72da160c2f43828316c262855c92e638872a70.tar.gz txr-2c72da160c2f43828316c262855c92e638872a70.tar.bz2 txr-2c72da160c2f43828316c262855c92e638872a70.zip |
pic: support quasiliteral as format string.
* share/txr/stdlib/pic.tl (pic): Refactor string compilation
code into local function which has access to the overall
argument list. Recognize the quasiliteral case and translate
by compiling all the string parts, then forming a recombined
quasiliteral where the compiled parts are substituted.
* tests/018/format.tl: test case for this.
* txr.1: Documented.
-rw-r--r-- | share/txr/stdlib/pic.tl | 46 | ||||
-rw-r--r-- | tests/018/format.tl | 5 | ||||
-rw-r--r-- | txr.1 | 51 |
3 files changed, 80 insertions, 22 deletions
diff --git a/share/txr/stdlib/pic.tl b/share/txr/stdlib/pic.tl index a6228334..f2805554 100644 --- a/share/txr/stdlib/pic.tl +++ b/share/txr/stdlib/pic.tl @@ -88,23 +88,37 @@ (t (compile-error f "unrecognized format string ~s" fmt)))) (defmacro pic (:form f :env e bigfmt . args) - (unless (stringp bigfmt) - (compile-error f "~s is required to be a format string" bigfmt)) (let* ((regex #/[+\-]?0?#+([.!]#+|!)?| \ <+| \ >+| \ \|+| \ - \~.|\~/) - (items (collect-each ((piece (tok regex t bigfmt))) - (cond - ((m^$ regex piece) - (cond - ((starts-with "~" piece) - (expand-pic f piece nil)) - (args - (expand-pic f piece (pop args))) - (t (compile-error f "insufficient arguments for format")))) - (t piece))))) - (if args - (compile-warning f "excess arguments")) - (pic-join-opt ^(join ,*items)))) + \~.|\~/)) + (labels ((pic-compile-string (fmtstr) + (let ((items (collect-each ((piece (tok regex t fmtstr))) + (cond + ((m^$ regex piece) + (cond + ((starts-with "~" piece) + (expand-pic f piece nil)) + (args + (expand-pic f piece (pop args))) + (t (compile-error + f "insufficient arguments for format")))) + (t piece))))) + (pic-join-opt ^(join ,*items))))) + (match-case bigfmt + (@(stringp @s) + (let ((out (pic-compile-string s))) + (if args + (compile-warning f "excess arguments")) + out)) + ((@(or sys:quasi) . @qargs) + (let ((nqargs (build (each ((q qargs)) + (if (stringp q) + (add (pic-compile-string q)) + (add q)))))) + (if args + (compile-warning f "excess arguments")) + ^(sys:quasi ,*nqargs))) + (@else (compile-error + f "~s is required to be a string or quasiliteral" else)))))) diff --git a/tests/018/format.tl b/tests/018/format.tl index 2e7f8b26..b8cf7445 100644 --- a/tests/018/format.tl +++ b/tests/018/format.tl @@ -126,3 +126,8 @@ (test (mapcar (do pic "foo~-0##.jpg") (rlist 0..5 8 12)) ("foo-000.jpg" "foo-001.jpg" "foo-002.jpg" "foo-003.jpg" "foo-004.jpg" "foo-005.jpg" "foo-008.jpg" "foo-012.jpg")) + +(test + (let ((a 2) (b "###") (c 13.5)) + (pic `abc@(+ a a)###.##@b>>>>` c "x")) + "abc4 13.50### x") @@ -54814,8 +54814,8 @@ and .desc The .code pic -macro provides a notation for constructing a character string under the -control of +macro ("picture based formatting") provides a notation for constructing a +character string under the control of .meta format-string which indicates the insertion of zero or more .meta format-arg @@ -54823,7 +54823,7 @@ argument values. Like the .code fmt -function or quasistring syntax, the +function or quasiliteral syntax, the .code pic macro returns a character string. @@ -54837,7 +54837,12 @@ notation is different from quasiliterals or from The .code pic .meta format-string -is scanned left to right in search of +argument isn't an evaluated expression, but syntax. It must be either a string +literal or else a string quasiliteral. No other syntax is permitted. + +If +.meta pic +is a string, is scanned left to right in search of .IR "pic patterns" . Any characters not belonging to a pic pattern are copied into the output string verbatim. When a pic pattern is found, it is removed from @@ -54850,11 +54855,43 @@ When the .meta format-string is exhausted, the constructed string is returned. +If +.meta format-string +is a quasiliteral, then all of the text strings embedded within the +quasiliteral are examined in the same way, in left to right order. Each such +string is transformed into an expression which produces a character string +according to the semantics of the pic patterns it contains, and the resulting +expressions are substituted into the original quasiliteral to produce a +transformed quasiliteral. + There must be exactly as many .meta format-arg arguments as there are pic patterns in .metn format-string . +The +.code pic +macro arranges for the left-to-right evaluation of the +.meta format-arg +expressions. If +.meta format-string +is a quasiliteral, the evaluation of these expressions is interleaved +into the quasiliterals expressions and variables, in the order implied +by the placement of the corresponding pic patterns relative to the +quasiliteral elements. For instance, if +.meta format-string +is +.code `@(abc)<<<@(xyz)` +then the function +.code abc +is called first, then the +.meta format-argument +is evaluated which produces a value for the +.code <<< +pic pattern, after which the +.code xyz +function is called. + There are two kinds of pic patterns: alignment patterns, numeric patterns and escape patterns. @@ -54891,8 +54928,10 @@ field width, it is centered slightly to the left: one less space appears on its left side in respect to its right side. .RE .IP -The numeric patterns are more complex. They conform to one of the two -following syntactic rule: +The numeric patterns, by means of their visual pattern and several optional +prefix codes, specify the parameters for the conversion of a numeric +argument, which is rendered right-aligned in a fixed-width field. Numeric +patterns conform to one of the two following syntactic rule: .mono .mets <> [ sign ] [0] {#}+ >> [ point {#}+ | !] |