summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-06-11 07:46:11 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-06-11 07:46:11 -0700
commit2c72da160c2f43828316c262855c92e638872a70 (patch)
tree99f6815576b25ad7931fa40d95f2fd0de87e1d37
parent607a764714e1d0391c663146a0c4701c19e15e35 (diff)
downloadtxr-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.tl46
-rw-r--r--tests/018/format.tl5
-rw-r--r--txr.151
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")
diff --git a/txr.1 b/txr.1
index 60b36805..8f07ae8f 100644
--- a/txr.1
+++ b/txr.1
@@ -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 {#}+ | !]