Implemented sprintf as String sprintf*. This supports most Python/Ruby format specifi...
authorBrian T. Rice <briantrice@gmail.com>
Thu, 11 Mar 2010 01:10:25 +0000 (17:10 -0800)
committerBrian T. Rice <briantrice@gmail.com>
Thu, 11 Mar 2010 01:10:25 +0000 (17:10 -0800)
src/core/string.slate

index 5932254..54e3d22 100644 (file)
@@ -452,6 +452,82 @@ an array argument. Curly open-brackets may be escaped by doubling them."
    ] writingAs: s
 ].
 
+s@(String traits) sprintf*
+[| *args input argsIndex |
+  input: s reader.
+  argsIndex: args indexFirst.
+  [| :result |
+   input do:
+     [| :char |
+      char == $%
+        ifTrue: "Placeholder"
+          [| nextChar arg |
+           nextChar: input next.
+           nextChar == $%
+             ifTrue: [result nextPut: nextChar]
+             ifFalse:
+               [| specifier width precision space position alternative plus minus zero star |
+                input skip: -1.
+                specifier: (input upToAnyOf: 'diueEfFgGxXoscpn') reader.
+
+                [specifier isAtEnd] whileFalse:
+                  [nextChar: specifier next.
+                   "Check for a parameter index spec:"
+                   ('123456789' includes: nextChar)
+                     ifTrue:
+                       [(specifier peek: 1) == $$
+                          ifTrue:
+                            [specifier skip: -1.
+                             position: (Integer readFrom: specifier).
+                             specifier next]
+                          ifFalse:
+                            [specifier skip: -1.
+                             width: (Integer readFrom: specifier).
+                             ]]
+                     ifFalse:
+                       ["Check for flags:"
+                        nextChar caseOf: {
+                          $\s -> [space: True].
+                          $#  -> [alternative: True].
+                          $+  -> [plus: True].
+                          $-  -> [minus: True].
+                          $0  -> [zero: True].
+                          $*  -> [star: True].
+                          $. -> [precision: (Integer readFrom: specifier)]}]].
+
+                input skip: -1.
+                "Check for type specifiers:"
+                position ifNil:
+                  [position: argsIndex.
+                   argsIndex: argsIndex + 1].
+                width isNil /\ [star isNotNil] ifTrue:
+                  [width: (args at: position).
+                   position: position + 1.
+                   argsIndex: argsIndex + 1].
+                arg: (args at: position).
+                nextChar: input next.
+                ('diu' includes: nextChar) ifTrue:
+                  [arg: (arg printString &radix: 10 &precision: precision &forceSign: plus isNotNil)].
+                ('xX' includes: nextChar) ifTrue:
+                  [arg: (arg printString &radix: 16 &precision: precision &forceSign: plus isNotNil).
+                   nextChar = $X ifTrue: [arg toUppercase]].
+                ('o' includes: nextChar) ifTrue:
+                  [arg: (arg printString &radix: 8 &precision: precision &forceSign: plus isNotNil)].
+                ('fFeE' includes: nextChar) ifTrue:
+                  [arg: (arg printString &precision: precision &forceSign: plus isNotNil).
+                   ('FE' includes: nextChar) ifTrue: [arg toUppercase]].
+                nextChar == $r ifTrue:
+                  [arg: arg printString].
+                nextChar == $s ifTrue:
+                  [arg: (arg as: s)].
+                width ifNotNil:
+                  [arg: (arg truncateTo: width paddedBy: (zero ifNil: [$\s] ifNotNil: [$0]) &onRight: minus isNotNil)].
+                result ; arg.
+          ]]
+        ifFalse: [result nextPut: char]]
+  ] writingAs: s
+].
+
 s@(String traits) evaluate
 [
   s evaluateIn: lobby