diff options
-rw-r--r-- | stdlib/pic.tl | 54 | ||||
-rw-r--r-- | txr.1 | 35 |
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,?)?#+(,#+)*([.!]#+(,#+)*|!)?| \ <+| \ >+| \ \|+| \ @@ -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 |