Browse code
Document and add aliases
fiddlerwoaroof authored on 06/12/2016 00:43:47
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -1,5 +1,11 @@ |
1 | 1 |
A simple package implementing a DSL for generating format strings. |
2 | 2 |
|
3 |
+- [Introduction](#introduction) |
|
4 |
+- [Api Reference](#api-reference) |
|
5 |
+- [DSL Reference](#dsl-reference) |
|
6 |
+ |
|
7 |
+# Introduction |
|
8 |
+ |
|
3 | 9 |
```lisp |
4 | 10 |
|
5 | 11 |
(make-format-string '(:str)) #| ==> "~a" |# |
... | ... |
@@ -11,3 +17,113 @@ A simple package implementing a DSL for generating format strings. |
11 | 17 |
(:map () :str)) |
12 | 18 |
|
13 | 19 |
``` |
20 |
+ |
|
21 |
+# Api Reference |
|
22 |
+ |
|
23 |
+```lisp |
|
24 |
+(make-format-string spec) #| function |# |
|
25 |
+``` |
|
26 |
+ |
|
27 |
+Takes a format string specification and turns it into a string. |
|
28 |
+ |
|
29 |
+```lisp |
|
30 |
+(format* stream spec &rest args) #| macro |# |
|
31 |
+``` |
|
32 |
+ |
|
33 |
+Use like CL:FORMAT, except translate a format specification to a string at macroexpansion time. |
|
34 |
+ |
|
35 |
+```lisp |
|
36 |
+(define-message (stream-symbol &rest format-args) &body spec) #| macro |# |
|
37 |
+``` |
|
38 |
+ |
|
39 |
+Defines a function that takes a stream and the arguments to be |
|
40 |
+formatted and then formats the arguments to the stream. The spec is |
|
41 |
+compiled to a string at macroexpansion time, so this should be |
|
42 |
+reasonably efficient. |
|
43 |
+ |
|
44 |
+TODO: document the API for defining directives. |
|
45 |
+ |
|
46 |
+# DSL Reference |
|
47 |
+ |
|
48 |
+A spec consists of operators and literals. Literals are either |
|
49 |
+strings, characters or integers and they are formatted as-is via |
|
50 |
+princ. There are two kinds of operators: simple operators and compound |
|
51 |
+ones. Simple operators correspond to format control directives and |
|
52 |
+represented in the spec by keywords such as `~A` or by lists |
|
53 |
+`(keyword . modifiers)` and they expand to the corresponding |
|
54 |
+directives. Compound operators correspond to format directives that |
|
55 |
+can contain other directives such as `~{~}`. In a spec, these are |
|
56 |
+formatted like flet function definitions: |
|
57 |
+ |
|
58 |
+```lisp |
|
59 |
+(keyword (&rest modifiers) &body spec) |
|
60 |
+``` |
|
61 |
+ |
|
62 |
+Compound operators are further divided into sectioned operators and |
|
63 |
+non-sectioned ones. The difference is that, in non sectioned |
|
64 |
+operators, the body is treated just as a normal spec. In sectioned |
|
65 |
+ones, the body is treated as a list of items to be divided with `~;`. |
|
66 |
+See CLHS 22.3 for a full guide to the modifiers for the various format |
|
67 |
+directives. |
|
68 |
+ |
|
69 |
+## Simple Format Operations |
|
70 |
+ |
|
71 |
+- :str --- Translates to ~a, format a lisp value for humans |
|
72 |
+- :repr --- Translates to ~s, format a lisp value in a way that can be read by the reader (?) |
|
73 |
+- :float --- Translates to ~f, format a float. |
|
74 |
+- :dec --- Translates to ~d, format a number as a base 10 number. |
|
75 |
+- :decimal --- Translates to ~d, format a number as a base 10 number. |
|
76 |
+- :hex --- Translates to ~x, format a number as a base 16 number. |
|
77 |
+- :hexadecimal --- Translates to ~x, format a number as a base 16 number. |
|
78 |
+- :oct --- Translates to ~o, format a number as a base 8 number. |
|
79 |
+- :octal --- Translates to ~o, format a number as a base 8 number. |
|
80 |
+- :currency --- Translates to ~$, format a number in a manner suitable for currency |
|
81 |
+- :exit --- Translates to ~^, leaves a iteration construct |
|
82 |
+- :end-section --- Translates to ~;, divides sections of a construct (TODO: maybe this will go away?) |
|
83 |
+- :goto --- Translates to ~*, moves within the list of arguments |
|
84 |
+- :fresh-line --- Translates to ~&, ensures we're at the beginning of a line and, possibly adds Modifier-1 linebreaks |
|
85 |
+- :ensure-line --- Translates to ~7, alias for :fresh-line |
|
86 |
+- :new-line --- Adds a linebreak |
|
87 |
+ |
|
88 |
+## Compound Format Operations |
|
89 |
+ |
|
90 |
+### Iteration |
|
91 |
+ |
|
92 |
+- :map --- Translates to ~{~}, iterate over a list passed in |
|
93 |
+- :rest --- Translates to ~@{~}, iterate over the rest of the arguments |
|
94 |
+- :ap --- Translates to ~:{~}, apply a list to the corresponding enclosed format directives |
|
95 |
+- :apply --- Alias for :ap |
|
96 |
+- :aprest --- Translates to ~:@{~}, apply the rest of the arguments to the corresponding enclosed format directives |
|
97 |
+- :apply-rest --- Translates to ~:@{~}, apply the rest of the arguments to the corresponding enclosed format directives |
|
98 |
+ |
|
99 |
+### Conditional Output (Sectioned Operators) |
|
100 |
+ |
|
101 |
+- :y-or-n --- Translates to ~:[~], if the argument is nil, print first spec otherwise print second |
|
102 |
+- TODO: add others here... |
|
103 |
+ |
|
104 |
+### Case Control |
|
105 |
+ |
|
106 |
+- :lowercase --- Translates to ~(~), lowercase all alphabetic characters. |
|
107 |
+- :downcase --- Translates to ~(~), alias for :lowercase |
|
108 |
+- :uppercase --- Translates to ~:@(~), uppercase all alphabetic characters. |
|
109 |
+- :upcase --- Translates to ~:@(~), alias for :uppercase |
|
110 |
+- :titlecase --- Translates to ~:(~), titlecase all alphabetic characters. |
|
111 |
+- :capitalize --- Translates to ~:(~), alias for :titlecase |
|
112 |
+- :initialcap --- Translates to ~@(~), uppercase first character |
|
113 |
+ |
|
114 |
+### Justification |
|
115 |
+TODO: finish documenting this and switch them to sectioned operators. |
|
116 |
+ |
|
117 |
+- :spread --- Translates to ~<~> |
|
118 |
+- :ljust --- Translates to ~@<~> |
|
119 |
+- :left --- Translates to ~@<~> |
|
120 |
+- :rjust --- Translates to ~:<~> |
|
121 |
+- :right --- Translates to ~:<~> |
|
122 |
+- :cjust --- Translates to ~:@<~> |
|
123 |
+- :center --- Translates to ~:@<~> |
|
124 |
+ |
|
125 |
+### Miscellaneous |
|
126 |
+ |
|
127 |
+These are not part of Format, but are defined just to be helpful |
|
128 |
+ |
|
129 |
+- :own-line --- Translates to ~&~%, ensure that the included text is on its own line, without unnecessary gaps. |
... | ... |
@@ -43,6 +43,9 @@ |
43 | 43 |
(defmethod print-format-representation ((literal character) s) |
44 | 44 |
(princ literal s)) |
45 | 45 |
|
46 |
+(defmethod print-format-representation ((literal integer) s) |
|
47 |
+ (princ literal s)) |
|
48 |
+ |
|
46 | 49 |
(defmethod print-format-representation ((literal string) s) |
47 | 50 |
(princ literal s)) |
48 | 51 |
|
... | ... |
@@ -182,6 +185,9 @@ |
182 | 185 |
,@args)) |
183 | 186 |
|
184 | 187 |
(defmacro define-message (name (stream-arg &rest args) &body spec) |
188 |
+ "Define a function called NAME that takes a stream argument and a |
|
189 |
+variable argument list that formats the arguments according to the |
|
190 |
+spec passed as the body." |
|
185 | 191 |
(flet ((get-argument-names (arg-list) |
186 | 192 |
(loop for s in arg-list |
187 | 193 |
when (and (symbolp s) (not (char= (elt (symbol-name s) 0) #\&))) collect s |
... | ... |
@@ -223,8 +229,11 @@ |
223 | 229 |
;; Case printing characters. |
224 | 230 |
(:compounds |
225 | 231 |
(:lowercase (#\( #\))) |
232 |
+ (:downcase (#\( #\))) |
|
226 | 233 |
(:uppercase (#\( #\)) :at-p t :colon-p t) |
234 |
+ (:upcase (#\( #\)) :at-p t :colon-p t) |
|
227 | 235 |
(:titlecase (#\( #\)) :colon-p t) |
236 |
+ (:capitalize (#\( #\)) :colon-p t) |
|
228 | 237 |
(:initialcap (#\( #\)) :at-p t)) |
229 | 238 |
|
230 | 239 |
(:compounds |
... | ... |
@@ -237,7 +246,9 @@ |
237 | 246 |
(:dec (#\d)) |
238 | 247 |
(:decimal (#\d)) |
239 | 248 |
(:hex (#\x)) |
249 |
+ (:hexadecimal (#\d)) |
|
240 | 250 |
(:oct (#\o)) |
251 |
+ (:octal (#\o)) |
|
241 | 252 |
(:currency (#\$)) |
242 | 253 |
(:exit (#\^)) |
243 | 254 |
(:go-to (#\*)) |