]> gitweb.factorcode.org Git - factor.git/blob - basis/tools/scaffold/scaffold.factor
tools.scaffold: change scaffold-vocab to scaffold-vocab-in.
[factor.git] / basis / tools / scaffold / scaffold.factor
1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3
4 USING: accessors alien arrays assocs byte-arrays calendar
5 classes classes.error combinators combinators.short-circuit
6 hashtables help.markup interpolate io io.directories
7 io.encodings.utf8 io.files io.pathnames io.streams.string kernel
8 math math.parser math.ranges namespaces prettyprint quotations
9 sequences sets sorting splitting strings system timers unicode
10 urls vocabs vocabs.loader vocabs.metadata words words.symbol ;
11 IN: tools.scaffold
12
13 SYMBOL: developer-name
14 SYMBOL: using
15
16 ERROR: not-a-vocab-root string ;
17
18 ERROR: vocab-must-not-exist string ;
19
20 <PRIVATE
21
22 : vocab-root? ( string -- ? )
23     trim-tail-separators vocab-roots get member? ;
24
25 : ensure-vocab-exists ( string -- string )
26     dup lookup-vocab [ no-vocab ] unless ;
27
28 : check-vocab-root ( string -- string )
29     dup vocab-root? [ not-a-vocab-root ] unless ;
30
31 : check-vocab-root/name ( vocab-root string -- vocab-root string )
32     [ check-vocab-root ] [ check-vocab-name ] bi* ;
33
34 : replace-vocab-separators ( vocab -- path )
35     path-separator first CHAR: . associate substitute ;
36
37 : vocab-root/vocab>path ( vocab-root vocab -- path )
38     check-vocab-root/name
39     [ ] [ replace-vocab-separators ] bi* append-path ;
40
41 : vocab>path ( vocab -- path )
42     check-vocab [ find-vocab-root ] keep vocab-root/vocab>path ;
43
44 : vocab-root/vocab/file>path ( vocab-root vocab file -- path )
45     [ vocab-root/vocab>path ] dip append-path ;
46
47 : vocab-root/vocab/suffix>path ( vocab-root vocab suffix -- path )
48     [ vocab-root/vocab>path dup file-name append-path ] dip append ;
49
50 : vocab/file>path ( vocab file -- path )
51     [ vocab>path ] dip append-path ;
52
53 : vocab/suffix>path ( vocab suffix -- path )
54     [ vocab>path dup file-name append-path ] dip append ;
55
56 : directory-exists ( path -- )
57     "Not creating a directory, it already exists: " write print ;
58
59 : scaffold-directory ( vocab-root vocab -- )
60     vocab-root/vocab>path
61     dup exists? [ directory-exists ] [ make-directories ] if ;
62
63 : not-scaffolding ( path -- path )
64     "Not creating scaffolding for " write dup <pathname> . ;
65
66 : scaffolding ( path -- path )
67     "Creating scaffolding for " write dup <pathname> . ;
68
69 : scaffolding? ( path -- path ? )
70     dup exists? [ not-scaffolding f ] [ scaffolding t ] if ;
71
72 : scaffold-copyright ( -- )
73     "! Copyright (C) " write now year>> number>string write
74     developer-name get [ "Your name" ] unless* bl write "." print
75     "! See http://factorcode.org/license.txt for BSD license." print ;
76
77 : main-file-string ( vocab -- string )
78     [
79         scaffold-copyright
80         "USING: ;" print
81         "IN: " write print
82     ] with-string-writer ;
83
84 : set-scaffold-main-file ( vocab path -- )
85     [ main-file-string 1array ] dip utf8 set-file-lines ;
86
87 : scaffold-main ( vocab-root vocab -- )
88     [ ".factor" vocab-root/vocab/suffix>path ] keep swap scaffolding? [
89         set-scaffold-main-file
90     ] [
91         2drop
92     ] if ;
93
94 : scaffold-metadata ( vocab file contents -- )
95     [ ensure-vocab-exists ] 2dip
96     [
97         [ vocab/file>path ] dip 1array swap scaffolding? [
98             utf8 set-file-lines
99         ] [
100             2drop
101         ] if
102     ] [
103         2drop
104     ] if* ;
105
106 : lookup-type ( string -- object/string ? )
107     "/f" ?tail swap
108     "new" ?head drop [ { [ CHAR: ' = ] [ digit? ] } 1|| ] trim-tail
109     H{
110         { "object" object }
111         { "obj" object }
112         { "quot" quotation }
113         { "string" string }
114         { "str" string }
115         { "hash" hashtable }
116         { "hashtable" hashtable }
117         { "?" boolean }
118         { "ch" "a character" }
119         { "word" word }
120         { "array" array }
121         { "byte-array" byte-array }
122         { "timer" timer }
123         { "duration" duration }
124         { "path" "a pathname string" }
125         { "vocab" "a vocabulary specifier" }
126         { "vocab-root" "a vocabulary root string" }
127         { "c-ptr" c-ptr }
128         { "sequence" sequence }
129         { "seq" sequence }
130         { "exemplar" object }
131         { "assoc" assoc }
132         { "alist" "an array of key/value pairs" }
133         { "keys" sequence }
134         { "values" sequence }
135         { "class" class }
136         { "tuple" tuple }
137         { "url" url }
138     } at* [ swap [ \ $maybe swap 2array ] when ] dip ;
139
140 GENERIC: add-using ( object -- )
141
142 M: array add-using [ add-using ] each ;
143
144 M: string add-using drop ;
145
146 M: object add-using
147     vocabulary>> using get [ adjoin ] [ drop ] if* ;
148
149 : ($values.) ( array -- )
150     [
151         "    " write
152         [ bl ] [
153             "{ " write
154             dup array? [ first ] when
155             dup lookup-type [
156                 [ unparse write bl ]
157                 [ [ pprint ] [ add-using ] bi ] bi*
158             ] [
159                 drop unparse write bl null pprint
160                 null add-using
161             ] if
162             " }" write
163         ] interleave
164     ] unless-empty ;
165
166 : ?print-nl ( seq1 seq2 -- )
167     [ empty? ] either? [ nl ] unless ;
168
169 : $values. ( word -- )
170     "declared-effect" word-prop [
171         [ in>> ] [ out>> ] bi
172         2dup [ empty? ] both? [
173             2drop
174         ] [
175             [ members ] dip over diff
176             "{ $values" print
177             [ drop ($values.) ]
178             [ ?print-nl ]
179             [ nip ($values.) ] 2tri
180             nl "}" print
181         ] if
182     ] when* ;
183
184 : error-description. ( word -- )
185     [ $values. ] [
186         "{ $description \"Throws " write
187         name>> dup a/an write " \" { $link " write
188         write " } \" error.\" }" print
189     ] bi "{ $error-description \"\" } ;" print ;
190
191 : class-description. ( word -- )
192     drop "{ $class-description \"\" } ;" print ;
193
194 : symbol-description. ( word -- )
195     drop "{ $var-description \"\" } ;" print ;
196
197 : $description. ( word -- )
198     drop "{ $description \"\" } ;" print ;
199
200 : docs-body. ( word/symbol -- )
201     {
202         { [ dup error-class? ] [ error-description. ] }
203         { [ dup class? ] [ class-description. ] }
204         { [ dup symbol? ] [ symbol-description. ] }
205         [ [ $values. ] [ $description. ] bi ]
206     } cond ;
207
208 : docs-header. ( word -- )
209     "HELP: " write name>> print ;
210
211 : (help.) ( word -- )
212     [ docs-header. ] [ docs-body. ] bi ;
213
214 : interesting-words ( vocab -- array )
215     vocab-words
216     [ { [ "help" word-prop ] [ predicate? ] } 1|| ] reject
217     natural-sort ;
218
219 : interesting-words. ( vocab -- )
220     interesting-words [ (help.) nl ] each ;
221
222 : docs-file-string ( vocab -- str2 )
223     [
224         {
225             [ "IN: " write print nl ]
226             [ interesting-words. ]
227             [
228                 [ "ARTICLE: " write unparse dup write bl print ]
229                 [ "{ $vocab-link " write pprint " }" print ] bi
230                 ";" print nl
231             ]
232             [ "ABOUT: " write unparse print ]
233         } cleave
234     ] with-string-writer ;
235
236 : write-using ( vocab -- )
237     "USING:" write
238     using get members
239     { "help.markup" "help.syntax" } append natural-sort remove
240     [ bl write ] each
241     " ;" print ;
242
243 : set-scaffold-docs-file ( vocab path -- )
244     utf8 <file-writer> [
245         scaffold-copyright
246         [ docs-file-string ] [ write-using ] bi
247         write
248     ] with-output-stream ;
249
250 : with-scaffold ( quot -- )
251     [ HS{ } clone using ] dip with-variable ; inline
252
253 : link-vocab ( vocab -- )
254     check-vocab
255     "Edit documentation: " write
256     "-docs.factor" vocab/suffix>path <pathname> . ;
257
258 PRIVATE>
259
260 : help. ( word -- )
261     [ (help.) ] [ nl vocabulary>> link-vocab ] bi ;
262
263 : scaffold-docs ( vocab -- )
264     ensure-vocab-exists
265     [
266         dup "-docs.factor" vocab/suffix>path scaffolding? [
267             set-scaffold-docs-file
268         ] [
269             2drop
270         ] if
271     ] with-scaffold ;
272
273 : scaffold-undocumented ( string -- )
274     [ interesting-words. ] [ link-vocab ] bi ;
275
276 : scaffold-authors ( vocab -- )
277     "authors.txt" developer-name get scaffold-metadata ;
278
279 : scaffold-tags ( vocab tags -- )
280     [ "tags.txt" ] dip scaffold-metadata ;
281
282 : scaffold-summary ( vocab summary -- )
283     [ "summary.txt" ] dip scaffold-metadata ;
284
285 : scaffold-platforms ( vocab platforms -- )
286     [ "platforms.txt" ] dip scaffold-metadata ;
287
288 : delete-from-root-cache ( string -- )
289     root-cache get delete-at ;
290
291 : scaffold-vocab-in ( vocab-root string -- )
292     dup delete-from-root-cache
293     {
294         [ scaffold-directory ]
295         [ scaffold-main ]
296         [ nip require ]
297         [ nip scaffold-authors ]
298     } 2cleave ;
299
300 : scaffold-core ( string -- )
301     "resource:core" swap scaffold-vocab-in ;
302
303 : scaffold-basis ( string -- )
304     "resource:basis" swap scaffold-vocab-in ;
305
306 : scaffold-extra ( string -- )
307     "resource:extra" swap scaffold-vocab-in ;
308
309 : scaffold-work ( string -- )
310     "resource:work" swap scaffold-vocab-in  ;
311
312 <PRIVATE
313
314 : find-vocab-root-for  ( string -- vocab-root/f )
315     "." split dup length [1,b) [ head "." join ] with map
316     [ find-vocab-root ] map-find-last drop ;
317
318 PRIVATE>
319
320 : scaffold-vocab ( string -- )
321     [ find-vocab-root-for ] [ scaffold-vocab-in ] bi ;
322
323 <PRIVATE
324
325 : tests-file-string ( vocab -- string )
326     [
327         scaffold-copyright
328         "USING: tools.test " write dup write " ;" print
329         "IN: " write write ".tests" print
330     ] with-string-writer ;
331
332 : set-scaffold-tests-file ( vocab path -- )
333     [ tests-file-string ] dip utf8 set-file-contents ;
334
335 PRIVATE>
336
337 : scaffold-tests ( vocab -- )
338     ensure-vocab-exists
339     dup "-tests.factor" vocab/suffix>path
340     scaffolding? [
341         set-scaffold-tests-file
342     ] [
343         2drop
344     ] if ;
345
346 SYMBOL: nested-examples
347
348 : example-using ( using -- )
349     " " join "example-using" [
350         nested-examples get 4 0 ? CHAR: \s <string> "example-indent" [
351             "${example-indent}\"Example:\"
352 ${example-indent}{ $example \"USING: ${example-using} ;\"
353 ${example-indent}    \"\"
354 ${example-indent}    \"\"
355 ${example-indent}}
356 "
357             interpolate
358         ] with-variable
359     ] with-variable ;
360
361 : n-examples-using ( n using -- )
362     '[ _ example-using ] times ;
363
364 : scaffold-n-examples ( n word -- )
365     vocabulary>> "prettyprint" 2array
366     [ t nested-examples ] 2dip
367     '[
368         "{ $examples" print
369         _ _ n-examples-using
370         "}" print
371     ] with-variable ;
372
373 : scaffold-examples ( word -- )
374     2 swap scaffold-n-examples ;
375
376 : scaffold-file ( path -- )
377     [ touch-file ]
378     [ "Click to edit: " write <pathname> . ] bi ;
379
380 : scaffold-rc ( path -- )
381     [ home ] dip append-path scaffold-file ;
382
383 : scaffold-factor-boot-rc ( -- )
384     ".factor-boot-rc" scaffold-rc ;
385
386 : scaffold-factor-rc ( -- )
387     ".factor-rc" scaffold-rc ;
388
389 : scaffold-mason-rc ( -- )
390     ".factor-mason-rc" scaffold-rc ;
391
392 : scaffold-factor-roots ( -- )
393     ".factor-roots" scaffold-rc ;
394
395 HOOK: scaffold-emacs os ( -- )
396
397 M: unix scaffold-emacs ".emacs" scaffold-rc ;