summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stdlib/pic.tl54
-rw-r--r--txr.135
2 files changed, 83 insertions, 6 deletions
diff --git a/stdlib/pic.tl b/stdlib/pic.tl
index 57497152..96e78f2a 100644
--- a/stdlib/pic.tl
+++ b/stdlib/pic.tl
@@ -48,6 +48,51 @@
,str)))
code))))
+(defun comma-positions (fmt)
+ (let* ((fmtx (regsub #/,./ #\, fmt))
+ (len (len fmtx))
+ (ppos (or (pos #\. fmtx) len))
+ (out (vec)))
+ (each ((i len..0))
+ (if (meql [fmtx i] #\,)
+ (vec-push out (- ppos i))))
+ out))
+
+(defun insert-commas (num positions)
+ (let* ((len (len num))
+ (pn (len positions))
+ (ppos (or (pos #\. num) len))
+ (out (mkstring 0))
+ (j 0)
+ (comma #\,))
+ (each ((i len..0)
+ (p (- ppos len -1)))
+ (cond
+ ((meq comma #\- #\+ #\space)
+ (string-extend out comma)
+ (set comma #\space))
+ (t
+ (string-extend out [num i])))
+ (when (plusp i)
+ (when (< j pn)
+ (if (meq [num (pred i)] #\space #\- #\+)
+ (set comma [num (pred i)]))
+ (let ((pj [positions j]))
+ (cond
+ ((eql pj p)
+ (string-extend out comma)
+ (if (neq comma #\,)
+ (set comma #\space))
+ (inc j))
+ ((< pj p)
+ (inc j)))))))
+ (nreverse out)))
+
+(defun expand-pic-num-commas (fmt val)
+ (let* ((fmt-nc (remq #\, fmt))
+ (exp-nc (expand-pic-num fmt-nc val)))
+ ^(insert-commas ,exp-nc ,(comma-positions fmt))))
+
(defun expand-pic-align (chr fmt val)
^(fmt ,`~@(if chr chr)@(len fmt)a` ,val))
@@ -73,17 +118,20 @@
(unless (stringp fmt)
(compile-error f "~s is required to be a format string" fmt))
(cond
- ([m^$ #/\~[~#<>\|\-+0.!]/ fmt] [fmt 1..2])
+ ([m^$ #/\~[~#<>\|\-+0.!,]/ fmt] [fmt 1..2])
([m^$ #/\~./ fmt] (compile-error f "unrecognized escape sequence ~a" fmt))
([m^$ #/\~/ fmt] (compile-error f "incomplete ~~ escape"))
- ([m^$ #/[+\-]?0?#+([.!]#+|!)?/ fmt] (expand-pic-num fmt val))
+ ([m^$ #/[+\-]?(0,?)?#+(,#+)*([.!]#+(,#+)*|!)?/ fmt]
+ (if (contains "," fmt)
+ (expand-pic-num-commas fmt val)
+ (expand-pic-num fmt val)))
([m^$ #/<+/ fmt] (expand-pic-align "<" fmt val))
([m^$ #/>+/ fmt] (expand-pic-align nil fmt val))
([m^$ #/\|+/ fmt] (expand-pic-align "^" fmt val))
(t (compile-error f "unrecognized format string ~s" fmt))))
(defmacro pic (:form f :env e bigfmt . args)
- (let* ((regex #/[+\-]?0?#+([.!]#+|!)?| \
+ (let* ((regex #/[+\-]?(0,?)?#+(,#+)*([.!]#+(,#+)*|!)?| \
<+| \
>+| \
\|+| \
diff --git a/txr.1 b/txr.1
index e88765d1..36deb601 100644
--- a/txr.1
+++ b/txr.1
@@ -56547,12 +56547,23 @@ left side in respect to its right side.
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:
+patterns that do not contain any commas conform this simple rule:
.mono
.mets <> [ sign ] [0] {#}+ >> [ point {#}+ | !]
.onom
+or else if they contain commas, the placement of these commas is governed
+by the more complicated rule:
+
+.mono
+.mets <> [ sign ] [0 [,]] {#}+ {,{#}+}* >> [ point {#}+ {,{#}+}* | !]
+.onom
+
+Commas may be placed anywhere within the pattern of hash characters, except at
+the beginning or end, or adjacent to the decimal point. If the leading zero is
+present, a comma may appear immediately after it, before the first hash.
+
The pattern consists of an optional
.meta sign
which is one of the characters
@@ -56633,7 +56644,7 @@ is specified as
as the last character. In both cases, the numeric argument is rounded to
integer, and rendered without any decimal point or fractional part.
-Finally, there is a difference between
+There is a difference between
.meta point
being specified using the ordinary decimal point character
.code .
@@ -56648,6 +56659,24 @@ the field, then instead of showing any digits, the field is filled with
.code .
character permits overflow.
+If commas appear in the numeric pattern according to the more complex syntactic
+rule, they count toward the field width and specify the insertion of
+digit-separating commas at the indicated locations. Digit separators may be
+specified on either side of the decimal point, but not adjacent to it. In the
+output, a digit separating comma shall not appear if it would be immediately
+preceded by a
+.code +
+or
+.code -
+sign or space. In this situations, the sign character or space appears
+in place of the digit separator. A digit separator that appears in a position
+occupied by a space is also suppressed in favor of the space. Digit separators
+are included among leading zeros. It is not logically possible for a digit
+separator to appear as the first character of a pattern's output, because it
+may not be the first character of a pattern. However, if a numeric pattern is
+preceded or followed by a comma, those commas are ordinary characters which are
+copied to the output.
+
Escape patterns consist of a two-character sequence introduced by the
.code ~
(tilde)
@@ -56655,7 +56684,7 @@ character, which is followed by one of the characters that are special in
pic pattern syntax:
.verb
- < > | + - 0 # . ! ~
+ < > | + - 0 # . ! ~ ,
.brev
An escape pattern produces the second character as its output. For instance