comparison src/demo.sml @ 380:758304561b60

Demo HTML generation, minus source code
author Adam Chlipala <adamc@hcoop.net>
date Sun, 19 Oct 2008 14:05:00 -0400
parents
children 1fe85b58c9ba
comparison
equal deleted inserted replaced
379:2b604ae76611 380:758304561b60
1 (* Copyright (c) 2008, Adam Chlipala
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - The names of contributors may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *)
27
28 structure Demo :> DEMO = struct
29
30 fun make {prefix, dirname} =
31 let
32 val prose = OS.Path.joinDirFile {dir = dirname,
33 file = "prose"}
34 val inf = TextIO.openIn prose
35
36 val demo_urp = OS.Path.joinDirFile {dir = dirname,
37 file = "demo.urp"}
38
39 val outDir = OS.Path.concat (dirname, "out")
40
41 val () = if OS.FileSys.access (outDir, []) then
42 ()
43 else
44 OS.FileSys.mkDir outDir
45
46 val fname = OS.Path.joinDirFile {dir = outDir,
47 file = "index.html"}
48
49 val out = TextIO.openOut fname
50 val () = (TextIO.output (out, "<frameset cols=\"15%,90%\">\n");
51 TextIO.output (out, "<frame src=\"demos.html\">\n");
52 TextIO.output (out, "<frame src=\"intro.html\" name=\"staging\">\n");
53 TextIO.output (out, "</frameset>\n");
54 TextIO.closeOut out)
55
56 val fname = OS.Path.joinDirFile {dir = outDir,
57 file = "demos.html"}
58
59 val demosOut = TextIO.openOut fname
60 val () = (TextIO.output (demosOut, "<html><body><ul>\n\n");
61 TextIO.output (demosOut, "<li> <a target=\"staging\" href=\"intro.html\">Intro</a></li>\n\n"))
62
63 fun mergeWith f (o1, o2) =
64 case (o1, o2) of
65 (NONE, _) => o2
66 | (_, NONE) => o1
67 | (SOME v1, SOME v2) => SOME (f (v1, v2))
68
69 fun combiner (combined : Compiler.job, urp : Compiler.job) = {
70 database = mergeWith (fn (v1, v2) =>
71 if v1 = v2 then
72 v1
73 else
74 raise Fail "Different demos want to use different database strings")
75 (#database combined, #database urp),
76 sources = foldl (fn (file, files) =>
77 if List.exists (fn x => x = file) files then
78 files
79 else
80 files @ [file])
81 (#sources combined) (#sources urp),
82 exe = OS.Path.joinDirFile {dir = dirname,
83 file = "demo.exe"},
84 sql = SOME (OS.Path.joinDirFile {dir = dirname,
85 file = "demo.sql"}),
86 debug = false
87 }
88
89 val parse = Compiler.run (Compiler.transform Compiler.parseUrp "Demo parseUrp")
90
91 fun capitalize "" = ""
92 | capitalize s = str (Char.toUpper (String.sub (s, 0)))
93 ^ String.extract (s, 1, NONE)
94
95 fun startUrp urp =
96 let
97 val base = OS.Path.base urp
98 val name = capitalize base
99
100 val () = (TextIO.output (demosOut, "<li> <a target=\"staging\" href=\"");
101 TextIO.output (demosOut, base);
102 TextIO.output (demosOut, ".html\">");
103 TextIO.output (demosOut, name);
104 TextIO.output (demosOut, "</a></li>\n"))
105
106 val urp_file = OS.Path.joinDirFile {dir = dirname,
107 file = urp}
108
109 val out = OS.Path.joinBaseExt {base = base,
110 ext = SOME "html"}
111 val out = OS.Path.joinDirFile {dir = outDir,
112 file = out}
113 val out = TextIO.openOut out
114
115 val () = (TextIO.output (out, "<frameset rows=\"75%,25%\">\n");
116 TextIO.output (out, "<frame src=\"");
117 TextIO.output (out, prefix);
118 TextIO.output (out, "/");
119 TextIO.output (out, name);
120 TextIO.output (out, "/main\" name=\"showcase\">\n");
121 TextIO.output (out, "<frame src=\"");
122 TextIO.output (out, base);
123 TextIO.output (out, ".desc.html\">\n");
124 TextIO.output (out, "</frameset>\n");
125 TextIO.closeOut out)
126 val () = TextIO.closeOut out
127
128 val out = OS.Path.joinBaseExt {base = base,
129 ext = SOME "desc"}
130 val out = OS.Path.joinBaseExt {base = out,
131 ext = SOME "html"}
132 val out = TextIO.openOut (OS.Path.joinDirFile {dir = outDir,
133 file = out})
134 in
135 case parse (OS.Path.base urp_file) of
136 NONE => raise Fail ("Can't parse " ^ urp_file)
137 | SOME urpData =>
138 (TextIO.output (out, "<html><head>\n<title>");
139 TextIO.output (out, name);
140 TextIO.output (out, "</title>\n</head><body>\n\n<h1>");
141 TextIO.output (out, name);
142 TextIO.output (out, "</h1>\n\n<center>[ <a target=\"showcase\" href=\"");
143 TextIO.output (out, urp);
144 TextIO.output (out, ".html\"><tt>");
145 TextIO.output (out, urp);
146 TextIO.output (out, "</tt></a>");
147 app (fn file =>
148 let
149 fun ifEx s =
150 let
151 val src = OS.Path.joinBaseExt {base = file,
152 ext = SOME s}
153 val src' = OS.Path.file src
154 in
155 if OS.FileSys.access (src, []) then
156 (TextIO.output (out, " | <a target=\"showcase\" href=\"");
157 TextIO.output (out, src');
158 TextIO.output (out, ".html\"><tt>");
159 TextIO.output (out, src');
160 TextIO.output (out, "</tt></a>"))
161 else
162 ()
163 end
164 in
165 ifEx "urs";
166 ifEx "ur"
167 end) (#sources urpData);
168 TextIO.output (out, " ]</center>\n\n");
169
170 (urpData, out))
171 end
172
173 fun endUrp out =
174 (TextIO.output (out, "\n</body></html>\n");
175 TextIO.closeOut out)
176
177 fun readUrp (combined, out) =
178 let
179 fun finished () = endUrp out
180
181 fun readUrp' () =
182 case TextIO.inputLine inf of
183 NONE => finished ()
184 | SOME line =>
185 if String.isSuffix ".urp\n" line then
186 let
187 val urp = String.substring (line, 0, size line - 1)
188 val (urpData, out) = startUrp urp
189 in
190 finished ();
191
192 readUrp (combiner (combined, urpData),
193 out)
194 end
195 else
196 (TextIO.output (out, line);
197 readUrp' ())
198 in
199 readUrp' ()
200 end
201
202 val indexFile = OS.Path.joinDirFile {dir = outDir,
203 file = "intro.html"}
204
205 val out = TextIO.openOut indexFile
206 val () = TextIO.output (out, "<html><head>\n<title>Ur/Web Demo</title>\n</head><body>\n\n")
207
208 fun readIndex () =
209 let
210 fun finished () = (TextIO.output (out, "\n</body></html>\n");
211 TextIO.closeOut out)
212 in
213 case TextIO.inputLine inf of
214 NONE => finished ()
215 | SOME line =>
216 if String.isSuffix ".urp\n" line then
217 let
218 val urp = String.substring (line, 0, size line - 1)
219 val (urpData, out) = startUrp urp
220 in
221 finished ();
222
223 readUrp (urpData,
224 out)
225 end
226 else
227 (TextIO.output (out, line);
228 readIndex ())
229 end
230 in
231 readIndex ();
232
233 TextIO.output (demosOut, "\n</ul></body></html>\n");
234 TextIO.closeOut demosOut
235 end
236
237 end