214 |
215 |
215 (* session_info *) |
216 (* session_info *) |
216 |
217 |
217 type session_info = |
218 type session_info = |
218 {name: string, parent: string, session: string, path: string list, html_prefix: Path.T, |
219 {name: string, parent: string, session: string, path: string list, html_prefix: Path.T, |
219 info: bool, doc_format: string, doc_graph: bool, doc_prefix1: Path.T option, |
220 info: bool, doc_format: string, doc_graph: bool, documents: (string * string) list, |
220 doc_prefix2: Path.T option, remote_path: Url.T option, verbose: bool, readme: Path.T option}; |
221 doc_prefix1: (Path.T * Path.T) option, doc_prefix2: Path.T option, remote_path: Url.T option, |
|
222 verbose: bool, readme: Path.T option}; |
221 |
223 |
222 fun make_session_info |
224 fun make_session_info |
223 (name, parent, session, path, html_prefix, info, doc_format, doc_graph, doc_prefix1, |
225 (name, parent, session, path, html_prefix, info, doc_format, doc_graph, documents, |
224 doc_prefix2, remote_path, verbose, readme) = |
226 doc_prefix1, doc_prefix2, remote_path, verbose, readme) = |
225 {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix, |
227 {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix, |
226 info = info, doc_format = doc_format, doc_graph = doc_graph, doc_prefix1 = doc_prefix1, |
228 info = info, doc_format = doc_format, doc_graph = doc_graph, documents = documents, |
227 doc_prefix2 = doc_prefix2, remote_path = remote_path, verbose = verbose, |
229 doc_prefix1 = doc_prefix1, doc_prefix2 = doc_prefix2, remote_path = remote_path, |
228 readme = readme}: session_info; |
230 verbose = verbose, readme = readme}: session_info; |
229 |
231 |
230 |
232 |
231 (* state *) |
233 (* state *) |
232 |
234 |
233 val session_info = ref (NONE: session_info option); |
235 val session_info = ref (NONE: session_info option); |
261 (case try get_entries dir of |
263 (case try get_entries dir of |
262 NONE => warning ("Browser info: cannot access session index of " ^ quote (Path.pack dir)) |
264 NONE => warning ("Browser info: cannot access session index of " ^ quote (Path.pack dir)) |
263 | SOME es => (put_entries ((es \ name) @ [name]) dir; create_index dir)); |
265 | SOME es => (put_entries ((es \ name) @ [name]) dir; create_index dir)); |
264 |
266 |
265 |
267 |
|
268 (* document versions *) |
|
269 |
|
270 fun read_version str = |
|
271 (case space_explode "=" str of |
|
272 [name] => (name, "") |
|
273 | [name, tags] => (name, tags) |
|
274 | _ => error ("Malformed document version specification: " ^ quote str)); |
|
275 |
|
276 fun read_versions strs = |
|
277 rev (gen_distinct eq_fst (rev ((documentN, "") :: map read_version strs))) |
|
278 |> filter_out (equal "-" o #2); |
|
279 |
|
280 |
266 (* init session *) |
281 (* init session *) |
267 |
282 |
268 fun name_of_session elems = space_implode "/" ("Isabelle" :: elems); |
283 fun name_of_session elems = space_implode "/" ("Isabelle" :: elems); |
269 |
284 |
270 fun init build info doc doc_graph path name doc_prefix2 (remote_path, first_time) verbose = |
285 fun init build info doc doc_graph doc_versions path name doc_prefix2 |
|
286 (remote_path, first_time) verbose = |
271 if not build andalso not info andalso doc = "" andalso is_none doc_prefix2 then |
287 if not build andalso not info andalso doc = "" andalso is_none doc_prefix2 then |
272 (browser_info := empty_browser_info; session_info := NONE) |
288 (browser_info := empty_browser_info; session_info := NONE) |
273 else |
289 else |
274 let |
290 let |
275 val parent_name = name_of_session (Library.take (length path - 1, path)); |
291 val parent_name = name_of_session (Library.take (length path - 1, path)); |
276 val session_name = name_of_session path; |
292 val session_name = name_of_session path; |
277 val sess_prefix = Path.make path; |
293 val sess_prefix = Path.make path; |
278 val html_prefix = Path.append (Path.expand output_path) sess_prefix; |
294 val html_prefix = Path.append (Path.expand output_path) sess_prefix; |
279 |
295 |
280 val (doc_prefix1, document_path) = |
296 val (doc_prefix1, documents) = |
281 if doc = "" then (NONE, NONE) |
297 if doc = "" then (NONE, []) |
282 else if not (File.exists doc_path) then (conditional verbose (fn () => |
298 else if not (File.exists document_path) then (conditional verbose (fn () => |
283 std_error "Warning: missing document directory\n"); (NONE, NONE)) |
299 std_error "Warning: missing document directory\n"); (NONE, [])) |
284 else (SOME (Path.append html_prefix doc_path), SOME (Path.ext doc doc_path)); |
300 else (SOME (Path.append html_prefix document_path, html_prefix), |
|
301 read_versions doc_versions); |
285 |
302 |
286 val parent_index_path = Path.append Path.parent index_path; |
303 val parent_index_path = Path.append Path.parent index_path; |
287 val index_up_lnk = if first_time then |
304 val index_up_lnk = if first_time then |
288 Url.append (the remote_path) (Url.File (Path.append sess_prefix parent_index_path)) |
305 Url.append (the remote_path) (Url.File (Path.append sess_prefix parent_index_path)) |
289 else Url.File parent_index_path; |
306 else Url.File parent_index_path; |
290 val readme = |
307 val readme = |
291 if File.exists readme_html_path then SOME readme_html_path |
308 if File.exists readme_html_path then SOME readme_html_path |
292 else if File.exists readme_path then SOME readme_path |
309 else if File.exists readme_path then SOME readme_path |
293 else NONE; |
310 else NONE; |
294 |
311 |
|
312 val docs = |
|
313 (case readme of NONE => [] | SOME p => [(Url.File p, "README")]) @ |
|
314 map (fn (name, _) => (Url.File (Path.ext doc (Path.basic name)), name)) documents; |
295 val index_text = HTML.begin_index (index_up_lnk, parent_name) |
315 val index_text = HTML.begin_index (index_up_lnk, parent_name) |
296 (Url.File index_path, session_name) (Option.map Url.File readme) |
316 (Url.File index_path, session_name) docs (Url.unpack "medium.html"); |
297 (Option.map Url.File document_path) (Url.unpack "medium.html"); |
|
298 in |
317 in |
299 session_info := SOME (make_session_info (name, parent_name, session_name, path, html_prefix, |
318 session_info := SOME (make_session_info (name, parent_name, session_name, path, html_prefix, |
300 info, doc, doc_graph, doc_prefix1, doc_prefix2, remote_path, verbose, readme)); |
319 info, doc, doc_graph, documents, doc_prefix1, doc_prefix2, remote_path, verbose, readme)); |
301 browser_info := init_browser_info remote_path path; |
320 browser_info := init_browser_info remote_path path; |
302 add_html_index index_text |
321 add_html_index index_text |
303 end; |
322 end; |
304 |
323 |
305 |
324 |
|
325 (* isatool wrappers *) |
|
326 |
|
327 fun isatool_document verbose format name tags path result_path = |
|
328 let |
|
329 val s = "\"$ISATOOL\" document -c -o '" ^ format ^ "' \ |
|
330 \-n '" ^ name ^ "' -t '" ^ tags ^ "' " ^ File.shell_path path ^ |
|
331 " 2>&1" ^ (if verbose then "" else " >/dev/null"); |
|
332 val doc_path = Path.append result_path (Path.ext format (Path.basic name)); |
|
333 in |
|
334 conditional verbose (fn () => writeln s); |
|
335 system s; |
|
336 conditional (not (File.exists doc_path)) (fn () => |
|
337 error ("No document: " ^ quote (show_path doc_path))); |
|
338 doc_path |
|
339 end; |
|
340 |
|
341 fun isatool_browser graph = |
|
342 let |
|
343 val pdf_path = File.tmp_path graph_pdf_path; |
|
344 val eps_path = File.tmp_path graph_eps_path; |
|
345 val gr_path = File.tmp_path graph_path; |
|
346 val s = "browser -o " ^ File.shell_path pdf_path ^ " " ^ File.shell_path gr_path; |
|
347 in |
|
348 write_graph graph gr_path; |
|
349 if File.isatool s <> 0 orelse not (File.exists eps_path) orelse not (File.exists pdf_path) |
|
350 then error "Failed to prepare dependency graph" |
|
351 else |
|
352 let val pdf = File.read pdf_path and eps = File.read eps_path |
|
353 in File.rm pdf_path; File.rm eps_path; File.rm gr_path; (pdf, eps) end |
|
354 end; |
|
355 |
|
356 |
306 (* finish session -- output all generated text *) |
357 (* finish session -- output all generated text *) |
307 |
358 |
308 fun write_tex src name path = |
359 fun write_tex src name path = |
309 Buffer.write (Path.append path (tex_path name)) src; |
360 Buffer.write (Path.append path (tex_path name)) src; |
310 |
361 |
311 fun write_tex_index tex_index path = |
362 fun write_tex_index tex_index path = |
312 write_tex (Buffer.add Latex.tex_trailer tex_index) doc_indexN path; |
363 write_tex (Buffer.add Latex.tex_trailer tex_index) doc_indexN path; |
313 |
364 |
314 |
365 |
315 fun isatool_document verbose doc_format path = |
|
316 let |
|
317 val s = "\"$ISATOOL\" document -c -o '" ^ doc_format ^ "' " ^ |
|
318 File.shell_path path ^ " 2>&1" ^ (if verbose then "" else " >/dev/null"); |
|
319 val doc_path = Path.ext doc_format path; |
|
320 in |
|
321 if verbose then writeln s else (); |
|
322 system s; |
|
323 if File.exists doc_path then () |
|
324 else error ("No document: " ^ quote (Path.pack (Path.expand doc_path))) |
|
325 end; |
|
326 |
|
327 fun isatool_browser graph = |
|
328 let |
|
329 val pdfpath = File.tmp_path graph_pdf_path; |
|
330 val epspath = File.tmp_path graph_eps_path; |
|
331 val gpath = File.tmp_path graph_path; |
|
332 val s = "browser -o " ^ File.shell_path pdfpath ^ " " ^ File.shell_path gpath; |
|
333 in |
|
334 write_graph graph gpath; |
|
335 if File.isatool s <> 0 orelse not (File.exists epspath) orelse not (File.exists pdfpath) |
|
336 then error "Failed to prepare dependency graph" |
|
337 else |
|
338 let val pdf = File.read pdfpath and eps = File.read epspath |
|
339 in File.rm pdfpath; File.rm epspath; File.rm gpath; (pdf, eps) end |
|
340 end; |
|
341 |
|
342 fun finish () = with_session () (fn {name, info, html_prefix, doc_format, doc_graph, |
366 fun finish () = with_session () (fn {name, info, html_prefix, doc_format, doc_graph, |
343 doc_prefix1, doc_prefix2, path, verbose, readme, ...} => |
367 documents, doc_prefix1, doc_prefix2, path, verbose, readme, ...} => |
344 let |
368 let |
345 val {theories, files, tex_index, html_index, graph} = ! browser_info; |
369 val {theories, files, tex_index, html_index, graph} = ! browser_info; |
346 val thys = Symtab.dest theories; |
370 val thys = Symtab.dest theories; |
347 val parent_html_prefix = Path.append html_prefix Path.parent; |
371 val parent_html_prefix = Path.append html_prefix Path.parent; |
348 |
372 |