| author | nipkow | 
| Fri, 16 Jul 2004 17:32:34 +0200 | |
| changeset 15055 | aed573241bea | 
| parent 14981 | e73f8140af78 | 
| child 15159 | 2ef19a680646 | 
| permissions | -rw-r--r-- | 
| 6203 | 1 | (* Title: Pure/Thy/present.ML | 
| 2 | ID: $Id$ | |
| 9416 | 3 | Author: Markus Wenzel and Stefan Berghofer, TU Muenchen | 
| 6203 | 4 | |
| 9416 | 5 | Theory presentation: HTML, graph files, (PDF)LaTeX documents. | 
| 6203 | 6 | *) | 
| 7 | ||
| 8 | signature BASIC_PRESENT = | |
| 9 | sig | |
| 11057 | 10 |   val no_document: ('a -> 'b) -> 'a -> 'b
 | 
| 7727 | 11 | val section: string -> unit | 
| 6203 | 12 | end; | 
| 13 | ||
| 14 | signature PRESENT = | |
| 15 | sig | |
| 7727 | 16 | include BASIC_PRESENT | 
| 14922 | 17 |   val get_info: theory -> {name: string, session: string list, is_local: bool}
 | 
| 9452 | 18 |   val write_graph: {name: string, ID: string, dir: string, unfold: bool,
 | 
| 19 | path: string, parents: string list} list -> Path.T -> unit | |
| 11911 
6533ceee4cd7
build option enables most basic browser info (for proper recording of session);
 wenzelm parents: 
11856diff
changeset | 20 | val init: bool -> bool -> string -> bool -> string list -> string -> Path.T option | 
| 11580 | 21 | -> Url.T option * bool -> bool -> unit | 
| 7727 | 22 | val finish: unit -> unit | 
| 23 | val init_theory: string -> unit | |
| 8192 | 24 | val verbatim_source: string -> (unit -> Symbol.symbol list) -> unit | 
| 25 | val old_symbol_source: string -> (unit -> Symbol.symbol list) -> unit | |
| 9136 | 26 | val theory_output: string -> string -> unit | 
| 7727 | 27 | val begin_theory: string -> string list -> (Path.T * bool) list -> theory -> theory | 
| 13532 | 28 | val add_hook: (string -> (string * thm list) list -> unit) -> unit | 
| 29 | val results: string -> (string * thm list) list -> unit | |
| 7727 | 30 | val theorem: string -> thm -> unit | 
| 31 | val theorems: string -> thm list -> unit | |
| 8088 | 32 | val chapter: string -> unit | 
| 7727 | 33 | val subsection: string -> unit | 
| 34 | val subsubsection: string -> unit | |
| 14922 | 35 | val drafts: string -> Path.T list -> Path.T | 
| 7727 | 36 | val setup: (theory -> theory) list | 
| 6203 | 37 | end; | 
| 38 | ||
| 7685 | 39 | structure Present: PRESENT = | 
| 40 | struct | |
| 41 | ||
| 7727 | 42 | |
| 43 | (** paths **) | |
| 44 | ||
| 45 | val output_path = Path.variable "ISABELLE_BROWSER_INFO"; | |
| 46 | ||
| 47 | val tex_ext = Path.ext "tex"; | |
| 48 | val tex_path = tex_ext o Path.basic; | |
| 49 | val html_ext = Path.ext "html"; | |
| 50 | val html_path = html_ext o Path.basic; | |
| 51 | val index_path = Path.basic "index.html"; | |
| 11856 | 52 | val readme_html_path = Path.basic "README.html"; | 
| 53 | val readme_path = Path.basic "README"; | |
| 7727 | 54 | val doc_path = Path.basic "document"; | 
| 8196 | 55 | val doc_indexN = "session"; | 
| 11856 | 56 | val graph_path = Path.basic "session.graph"; | 
| 57 | val graph_pdf_path = Path.basic "session_graph.pdf"; | |
| 58 | val graph_eps_path = Path.basic "session_graph.eps"; | |
| 7727 | 59 | |
| 60 | val session_path = Path.basic ".session"; | |
| 61 | val session_entries_path = Path.unpack ".session/entries"; | |
| 62 | val pre_index_path = Path.unpack ".session/pre-index"; | |
| 63 | ||
| 9044 | 64 | fun mk_rel_path [] ys = Path.make ys | 
| 65 | | mk_rel_path xs [] = Path.appends (replicate (length xs) Path.parent) | |
| 9416 | 66 | | mk_rel_path (ps as x :: xs) (qs as y :: ys) = if x = y then mk_rel_path xs ys else | 
| 9044 | 67 | Path.appends (replicate (length ps) Path.parent @ [Path.make qs]); | 
| 7727 | 68 | |
| 11856 | 69 | fun show_path path = Path.pack (Path.append (File.pwd ()) path); | 
| 70 | ||
| 7727 | 71 | |
| 14922 | 72 | |
| 7727 | 73 | (** additional theory data **) | 
| 74 | ||
| 75 | structure BrowserInfoArgs = | |
| 76 | struct | |
| 77 | val name = "Pure/browser_info"; | |
| 9416 | 78 |   type T = {name: string, session: string list, is_local: bool};
 | 
| 7727 | 79 | |
| 9416 | 80 |   val empty = {name = "Pure", session = [], is_local = false};
 | 
| 7727 | 81 | val copy = I; | 
| 9452 | 82 |   fun prep_ext _ = {name = "", session = [], is_local = false};
 | 
| 7727 | 83 | fun merge _ = empty; | 
| 84 | fun print _ _ = (); | |
| 85 | end; | |
| 86 | ||
| 87 | structure BrowserInfoData = TheoryDataFun(BrowserInfoArgs); | |
| 88 | ||
| 89 | fun get_info thy = | |
| 90 | if Theory.eq_thy (thy, ProtoPure.thy) then BrowserInfoArgs.empty | |
| 91 | else BrowserInfoData.get thy; | |
| 92 | ||
| 93 | ||
| 94 | ||
| 95 | (** graphs **) | |
| 96 | ||
| 97 | type graph_node = | |
| 98 |   {name: string, ID: string, dir: string, unfold: bool,
 | |
| 99 | path: string, parents: string list}; | |
| 100 | ||
| 9416 | 101 | fun write_graph gr path = | 
| 102 |   File.write path (cat_lines (map (fn {name, ID, dir, unfold, path, parents} =>
 | |
| 103 | "\"" ^ name ^ "\" \"" ^ ID ^ "\" \"" ^ dir ^ (if unfold then "\" + \"" else "\" \"") ^ | |
| 14598 
7009f59711e3
Replaced quote by Library.quote, since quote now refers to Symbol.quote
 berghofe parents: 
14540diff
changeset | 104 | path ^ "\" > " ^ space_implode " " (map Library.quote parents) ^ " ;") gr)); | 
| 7727 | 105 | |
| 9416 | 106 | fun ID_of sess s = space_implode "/" (sess @ [s]); | 
| 7727 | 107 | |
| 9416 | 108 | (*retrieve graph data from initial theory loader database*) | 
| 109 | fun init_graph remote_path curr_sess = map (fn name => | |
| 7727 | 110 | let | 
| 9416 | 111 |     val {name = sess_name, session, is_local} = get_info (ThyInfo.theory name);
 | 
| 112 | val path' = Path.append (Path.make session) (html_path name); | |
| 7727 | 113 | in | 
| 9416 | 114 |    {name = name, ID = ID_of session name, dir = sess_name,
 | 
| 115 | path = | |
| 116 | if null session then "" else | |
| 117 | if is_some remote_path andalso not is_local then | |
| 14898 | 118 | Url.pack (Url.append (the remote_path) (Url.File | 
| 9416 | 119 | (Path.append (Path.make session) (html_path name)))) | 
| 120 | else Path.pack (Path.append (mk_rel_path curr_sess session) (html_path name)), | |
| 121 | unfold = false, | |
| 122 | parents = | |
| 123 | map (fn s => ID_of (#session (get_info (ThyInfo.theory s))) s) (ThyInfo.get_preds name)} | |
| 7727 | 124 | end) (ThyInfo.names ()); | 
| 125 | ||
| 9416 | 126 | fun ins_graph_entry (entry as {ID, ...}) (gr: graph_node list) =
 | 
| 7727 | 127 | filter_out (fn entry' => #ID entry' = ID) gr @ [entry]; | 
| 128 | ||
| 129 | ||
| 130 | ||
| 131 | (** global browser info state **) | |
| 132 | ||
| 133 | (* type theory_info *) | |
| 134 | ||
| 135 | type theory_info = {tex_source: Buffer.T, html_source: Buffer.T, html: Buffer.T};
 | |
| 136 | ||
| 137 | fun make_theory_info (tex_source, html_source, html) = | |
| 138 |   {tex_source = tex_source, html_source = html_source, html = html}: theory_info;
 | |
| 139 | ||
| 140 | val empty_theory_info = make_theory_info (Buffer.empty, Buffer.empty, Buffer.empty); | |
| 141 | ||
| 142 | fun map_theory_info f {tex_source, html_source, html} =
 | |
| 143 | make_theory_info (f (tex_source, html_source, html)); | |
| 144 | ||
| 145 | ||
| 146 | (* type browser_info *) | |
| 147 | ||
| 11856 | 148 | type browser_info = {theories: theory_info Symtab.table, files: (Path.T * string) list,
 | 
| 149 | tex_index: Buffer.T, html_index: Buffer.T, graph: graph_node list}; | |
| 7727 | 150 | |
| 11856 | 151 | fun make_browser_info (theories, files, tex_index, html_index, graph) = | 
| 152 |   {theories = theories, files = files, tex_index = tex_index, html_index = html_index,
 | |
| 9416 | 153 | graph = graph}: browser_info; | 
| 7727 | 154 | |
| 11856 | 155 | val empty_browser_info = make_browser_info (Symtab.empty, [], Buffer.empty, Buffer.empty, []); | 
| 7727 | 156 | |
| 9416 | 157 | fun init_browser_info remote_path curr_sess = make_browser_info | 
| 11856 | 158 | (Symtab.empty, [], Buffer.empty, Buffer.empty, init_graph remote_path curr_sess); | 
| 7727 | 159 | |
| 11856 | 160 | fun map_browser_info f {theories, files, tex_index, html_index, graph} =
 | 
| 161 | make_browser_info (f (theories, files, tex_index, html_index, graph)); | |
| 7727 | 162 | |
| 163 | ||
| 164 | (* state *) | |
| 165 | ||
| 166 | val browser_info = ref empty_browser_info; | |
| 11057 | 167 | fun change_browser_info f = browser_info := map_browser_info f (! browser_info); | 
| 7727 | 168 | |
| 11057 | 169 | val suppress_tex_source = ref false; | 
| 170 | fun no_document f x = Library.setmp suppress_tex_source true f x; | |
| 7727 | 171 | |
| 172 | fun init_theory_info name info = | |
| 11856 | 173 | change_browser_info (fn (theories, files, tex_index, html_index, graph) => | 
| 174 | (Symtab.update ((name, info), theories), files, tex_index, html_index, graph)); | |
| 7727 | 175 | |
| 176 | fun change_theory_info name f = | |
| 11856 | 177 | change_browser_info (fn (info as (theories, files, tex_index, html_index, graph)) => | 
| 7727 | 178 | (case Symtab.lookup (theories, name) of | 
| 179 |       None => (warning ("Browser info: cannot access theory document " ^ quote name); info)
 | |
| 11856 | 180 | | Some info => (Symtab.update ((name, map_theory_info f info), theories), files, | 
| 9416 | 181 | tex_index, html_index, graph))); | 
| 7727 | 182 | |
| 183 | ||
| 11856 | 184 | fun add_file file = | 
| 185 | change_browser_info (fn (theories, files, tex_index, html_index, graph) => | |
| 186 | (theories, file :: files, tex_index, html_index, graph)); | |
| 187 | ||
| 7727 | 188 | fun add_tex_index txt = | 
| 11856 | 189 | change_browser_info (fn (theories, files, tex_index, html_index, graph) => | 
| 190 | (theories, files, Buffer.add txt tex_index, html_index, graph)); | |
| 7727 | 191 | |
| 192 | fun add_html_index txt = | |
| 11856 | 193 | change_browser_info (fn (theories, files, tex_index, html_index, graph) => | 
| 194 | (theories, files, tex_index, Buffer.add txt html_index, graph)); | |
| 7727 | 195 | |
| 196 | fun add_graph_entry e = | |
| 11856 | 197 | change_browser_info (fn (theories, files, tex_index, html_index, graph) => | 
| 198 | (theories, files, tex_index, html_index, ins_graph_entry e graph)); | |
| 7727 | 199 | |
| 11057 | 200 | fun add_tex_source name txt = | 
| 201 | if ! suppress_tex_source then () | |
| 202 | else change_theory_info name (fn (tex_source, html_source, html) => | |
| 203 | (Buffer.add txt tex_source, html_source, html)); | |
| 7727 | 204 | |
| 205 | fun add_html_source name txt = change_theory_info name (fn (tex_source, html_source, html) => | |
| 206 | (tex_source, Buffer.add txt html_source, html)); | |
| 207 | ||
| 208 | fun add_html name txt = change_theory_info name (fn (tex_source, html_source, html) => | |
| 209 | (tex_source, html_source, Buffer.add txt html)); | |
| 210 | ||
| 211 | ||
| 212 | ||
| 213 | (** global session state **) | |
| 214 | ||
| 215 | (* session_info *) | |
| 216 | ||
| 217 | type session_info = | |
| 218 |   {name: string, parent: string, session: string, path: string list, html_prefix: Path.T,
 | |
| 11856 | 219 | info: bool, doc_format: string, doc_graph: bool, doc_prefix1: Path.T option, | 
| 220 | doc_prefix2: Path.T option, remote_path: Url.T option, verbose: bool, readme: Path.T option}; | |
| 7727 | 221 | |
| 9416 | 222 | fun make_session_info | 
| 11856 | 223 | (name, parent, session, path, html_prefix, info, doc_format, doc_graph, doc_prefix1, | 
| 224 | doc_prefix2, remote_path, verbose, readme) = | |
| 7802 | 225 |   {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix,
 | 
| 11856 | 226 | info = info, doc_format = doc_format, doc_graph = doc_graph, doc_prefix1 = doc_prefix1, | 
| 227 | doc_prefix2 = doc_prefix2, remote_path = remote_path, verbose = verbose, | |
| 228 | readme = readme}: session_info; | |
| 7685 | 229 | |
| 230 | ||
| 7727 | 231 | (* state *) | 
| 232 | ||
| 233 | val session_info = ref (None: session_info option); | |
| 234 | ||
| 235 | fun with_session x f = (case ! session_info of None => x | Some info => f info); | |
| 236 | fun with_context f = f (PureThy.get_name (Context.the_context ())); | |
| 237 | ||
| 238 | ||
| 239 | ||
| 14922 | 240 | (** document preparation **) | 
| 7727 | 241 | |
| 242 | (* maintain index *) | |
| 243 | ||
| 244 | val session_entries = | |
| 245 | HTML.session_entries o | |
| 14898 | 246 | map (fn name => (Url.File (Path.append (Path.basic name) index_path), name)); | 
| 7727 | 247 | |
| 248 | fun get_entries dir = | |
| 249 | split_lines (File.read (Path.append dir session_entries_path)); | |
| 250 | ||
| 251 | fun put_entries entries dir = | |
| 252 | File.write (Path.append dir session_entries_path) (cat_lines entries); | |
| 253 | ||
| 254 | ||
| 255 | fun create_index dir = | |
| 256 | File.read (Path.append dir pre_index_path) ^ | |
| 257 | session_entries (get_entries dir) ^ HTML.end_index | |
| 258 | |> File.write (Path.append dir index_path); | |
| 259 | ||
| 260 | fun update_index dir name = | |
| 261 | (case try get_entries dir of | |
| 262 |     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)); | |
| 264 | ||
| 265 | ||
| 266 | (* init session *) | |
| 267 | ||
| 12895 | 268 | fun copy_files path1 path2 = | 
| 269 | (File.mkdir path2; | |
| 270 |   system ("cp " ^ File.sysify_path path1 ^ " " ^ File.sysify_path path2));  (*FIXME: quote!?*)
 | |
| 7727 | 271 | |
| 12895 | 272 | fun copy_all path1 path2 = | 
| 14922 | 273 | (File.mkdir path2; | 
| 12898 | 274 |   system ("cp -r " ^ File.quote_sysify_path path1 ^ "/. " ^
 | 
| 275 | File.quote_sysify_path path2)); | |
| 9044 | 276 | |
| 9416 | 277 | |
| 12895 | 278 | fun name_of_session elems = space_implode "/" ("Isabelle" :: elems);
 | 
| 279 | ||
| 11911 
6533ceee4cd7
build option enables most basic browser info (for proper recording of session);
 wenzelm parents: 
11856diff
changeset | 280 | fun init build info doc doc_graph path name doc_prefix2 (remote_path, first_time) verbose = | 
| 
6533ceee4cd7
build option enables most basic browser info (for proper recording of session);
 wenzelm parents: 
11856diff
changeset | 281 | if not build andalso not info andalso doc = "" andalso is_none doc_prefix2 then | 
| 11856 | 282 | (browser_info := empty_browser_info; session_info := None) | 
| 283 | else | |
| 284 | let | |
| 285 | val parent_name = name_of_session (Library.take (length path - 1, path)); | |
| 286 | val session_name = name_of_session path; | |
| 287 | val sess_prefix = Path.make path; | |
| 288 | val html_prefix = Path.append (Path.expand output_path) sess_prefix; | |
| 7727 | 289 | |
| 11856 | 290 | val (doc_prefix1, document_path) = | 
| 291 | if doc = "" then (None, None) | |
| 292 | else if not (File.exists doc_path) then (conditional verbose (fn () => | |
| 293 | std_error "Warning: missing document directory\n"); (None, None)) | |
| 294 | else (Some (Path.append html_prefix doc_path), Some (Path.ext doc doc_path)); | |
| 7727 | 295 | |
| 11856 | 296 | val parent_index_path = Path.append Path.parent index_path; | 
| 297 | val index_up_lnk = if first_time then | |
| 14898 | 298 | Url.append (the remote_path) (Url.File (Path.append sess_prefix parent_index_path)) | 
| 299 | else Url.File parent_index_path; | |
| 11856 | 300 | val readme = | 
| 301 | if File.exists readme_html_path then Some readme_html_path | |
| 302 | else if File.exists readme_path then Some readme_path | |
| 303 | else None; | |
| 7727 | 304 | |
| 11856 | 305 | val index_text = HTML.begin_index (index_up_lnk, parent_name) | 
| 14898 | 306 | (Url.File index_path, session_name) (apsome Url.File readme) | 
| 307 | (apsome Url.File document_path) (Url.unpack "medium.html"); | |
| 11856 | 308 | in | 
| 309 | session_info := Some (make_session_info (name, parent_name, session_name, path, html_prefix, | |
| 310 | info, doc, doc_graph, doc_prefix1, doc_prefix2, remote_path, verbose, readme)); | |
| 311 | browser_info := init_browser_info remote_path path; | |
| 312 | add_html_index index_text | |
| 313 | end; | |
| 7727 | 314 | |
| 315 | ||
| 11856 | 316 | (* finish session -- output all generated text *) | 
| 317 | ||
| 14922 | 318 | fun write_tex src name path = | 
| 319 | Buffer.write (Path.append path (tex_path name)) src; | |
| 320 | ||
| 321 | fun write_tex_index tex_index path = | |
| 322 | write_tex (Buffer.add Latex.tex_trailer tex_index) doc_indexN path; | |
| 323 | ||
| 7685 | 324 | |
| 14967 | 325 | fun isatool_document verbose doc_format path = | 
| 14958 | 326 | let | 
| 327 | val s = "\"$ISATOOL\" document -c -o '" ^ doc_format ^ "' " ^ | |
| 14967 | 328 | File.quote_sysify_path path ^ " 2>&1" ^ (if verbose then "" else " >/dev/null"); | 
| 14972 | 329 | val doc_path = Path.ext doc_format path; | 
| 12632 | 330 | in | 
| 14967 | 331 | if verbose then writeln s else (); | 
| 332 | system s; | |
| 14972 | 333 | if File.exists doc_path then () | 
| 334 |     else error ("No document: " ^ quote (Path.pack (Path.expand doc_path)))
 | |
| 8646 
1a2c5ccebfdb
isatool document: check output file (workaround PolyML problem with RC);
 wenzelm parents: 
8499diff
changeset | 335 | end; | 
| 7802 | 336 | |
| 11856 | 337 | fun isatool_browser graph = | 
| 338 | let | |
| 339 | val pdfpath = File.tmp_path graph_pdf_path; | |
| 340 | val epspath = File.tmp_path graph_eps_path; | |
| 341 | val gpath = File.tmp_path graph_path; | |
| 342 | val s = "\"$ISATOOL\" browser -o " ^ File.quote_sysify_path pdfpath ^ " " ^ | |
| 343 | File.quote_sysify_path gpath; | |
| 344 | in | |
| 345 | write_graph graph gpath; | |
| 14958 | 346 | if system s <> 0 orelse not (File.exists epspath) orelse not (File.exists pdfpath) | 
| 347 | then error "Failed to prepare dependency graph" | |
| 11856 | 348 | else | 
| 349 | let val pdf = File.read pdfpath and eps = File.read epspath | |
| 350 | in File.rm pdfpath; File.rm epspath; File.rm gpath; (pdf, eps) end | |
| 351 | end; | |
| 8196 | 352 | |
| 11856 | 353 | fun finish () = with_session () (fn {name, info, html_prefix, doc_format, doc_graph,
 | 
| 354 | doc_prefix1, doc_prefix2, path, verbose, readme, ...} => | |
| 7727 | 355 | let | 
| 11856 | 356 |     val {theories, files, tex_index, html_index, graph} = ! browser_info;
 | 
| 357 | val thys = Symtab.dest theories; | |
| 9416 | 358 | val parent_html_prefix = Path.append html_prefix Path.parent; | 
| 7727 | 359 | |
| 11856 | 360 |     fun finish_tex path (a, {tex_source, ...}: theory_info) = write_tex tex_source a path;
 | 
| 361 |     fun finish_html (a, {html, ...}: theory_info) =
 | |
| 362 | Buffer.write (Path.append html_prefix (html_path a)) (Buffer.add HTML.end_theory html); | |
| 363 | ||
| 364 | val opt_graphs = | |
| 365 | if doc_graph andalso (is_some doc_prefix1 orelse is_some doc_prefix2) then | |
| 366 | Some (isatool_browser graph) | |
| 367 | else None; | |
| 368 | ||
| 12895 | 369 | fun prepare_sources path = | 
| 370 | (copy_all doc_path path; | |
| 371 | copy_files (Path.unpack "~~/lib/texinputs/*.sty") path; | |
| 12849 | 372 | (case opt_graphs of None => () | Some (pdf, eps) => | 
| 11856 | 373 | (File.write (Path.append path graph_pdf_path) pdf; | 
| 374 | File.write (Path.append path graph_eps_path) eps)); | |
| 14922 | 375 | write_tex_index tex_index path; | 
| 11856 | 376 | seq (finish_tex path) thys); | 
| 7727 | 377 | in | 
| 11856 | 378 | conditional info (fn () => | 
| 379 | (File.mkdir (Path.append html_prefix session_path); | |
| 380 | Buffer.write (Path.append html_prefix pre_index_path) html_index; | |
| 381 | File.write (Path.append html_prefix session_entries_path) ""; | |
| 382 | create_index html_prefix; | |
| 383 | if length path > 1 then update_index parent_html_prefix name else (); | |
| 384 | (case readme of None => () | Some path => File.copy path (Path.append html_prefix path)); | |
| 385 | write_graph graph (Path.append html_prefix graph_path); | |
| 14540 | 386 | copy_files (Path.unpack "~~/lib/browser/GraphBrowser.jar") html_prefix; | 
| 11856 | 387 | seq (fn (a, txt) => File.write (Path.append html_prefix (Path.basic a)) txt) | 
| 14898 | 388 | (HTML.applet_pages name (Url.File index_path, name)); | 
| 14540 | 389 | copy_files (Path.unpack "~~/lib/html/isabelle.css") html_prefix; | 
| 11856 | 390 | seq finish_html thys; | 
| 391 | seq (uncurry File.write) files; | |
| 392 | conditional verbose (fn () => | |
| 393 |         std_error ("Browser info at " ^ show_path html_prefix ^ "\n"))));
 | |
| 394 | ||
| 12895 | 395 | (case doc_prefix2 of None => () | Some path => | 
| 396 | (prepare_sources path; | |
| 397 |       conditional verbose (fn () => std_error ("Document sources at " ^ show_path path ^ "\n"))));
 | |
| 398 | ||
| 11856 | 399 | (case doc_prefix1 of None => () | Some path => | 
| 12895 | 400 | (prepare_sources path; | 
| 14967 | 401 | isatool_document true doc_format path; | 
| 11856 | 402 | conditional verbose (fn () => | 
| 403 |         std_error ("Document at " ^ show_path (Path.ext doc_format path) ^ "\n"))));
 | |
| 404 | ||
| 7727 | 405 | browser_info := empty_browser_info; | 
| 406 | session_info := None | |
| 407 | end); | |
| 408 | ||
| 409 | ||
| 410 | (* theory elements *) | |
| 411 | ||
| 412 | fun init_theory name = with_session () (fn _ => init_theory_info name empty_theory_info); | |
| 413 | ||
| 414 | fun verbatim_source name mk_text = | |
| 415 | with_session () (fn _ => add_html_source name (HTML.verbatim_source (mk_text ()))); | |
| 416 | ||
| 8192 | 417 | fun old_symbol_source name mk_text = | 
| 14922 | 418 | with_session () (fn _ => add_tex_source name | 
| 419 | (Latex.symbol_source (K true, K true) name (mk_text ()))); | |
| 8192 | 420 | |
| 9136 | 421 | fun theory_output name s = | 
| 9917 | 422 | with_session () (fn _ => add_tex_source name (Latex.isabelle_file name s)); | 
| 7727 | 423 | |
| 424 | ||
| 425 | fun parent_link remote_path curr_session name = | |
| 9416 | 426 |   let val {name = _, session, is_local} = get_info (ThyInfo.theory name)
 | 
| 7727 | 427 | in (if null session then None else | 
| 428 | Some (if is_some remote_path andalso not is_local then | |
| 14898 | 429 | Url.append (the remote_path) (Url.File | 
| 9044 | 430 | (Path.append (Path.make session) (html_path name))) | 
| 14898 | 431 | else Url.File (Path.append (mk_rel_path curr_session session) | 
| 9044 | 432 | (html_path name))), name) | 
| 7727 | 433 | end; | 
| 434 | ||
| 435 | fun begin_theory name raw_parents orig_files thy = | |
| 9416 | 436 |     with_session thy (fn {name = sess_name, session, path, html_prefix, remote_path, ...} =>
 | 
| 7727 | 437 | let | 
| 438 | val parents = map (parent_link remote_path path) raw_parents; | |
| 439 | val ml_path = ThyLoad.ml_path name; | |
| 440 | val files = map (apsnd Some) orig_files @ | |
| 441 | (if is_some (ThyLoad.check_file ml_path) then [(ml_path, None)] else []); | |
| 442 | ||
| 443 | fun prep_file (raw_path, loadit) = | |
| 444 | (case ThyLoad.check_file raw_path of | |
| 445 | Some (path, _) => | |
| 446 | let | |
| 447 | val base = Path.base path; | |
| 448 | val base_html = html_ext base; | |
| 449 | in | |
| 11856 | 450 | add_file (Path.append html_prefix base_html, | 
| 14898 | 451 | HTML.ml_file (Url.File base) (File.read path)); | 
| 452 | (Some (Url.File base_html), Url.File raw_path, loadit) | |
| 7727 | 453 | end | 
| 454 |       | None => (warning ("Browser info: expected to find ML file" ^ quote (Path.pack raw_path));
 | |
| 14898 | 455 | (None, Url.File raw_path, loadit))); | 
| 7727 | 456 | |
| 457 | val files_html = map prep_file files; | |
| 458 | ||
| 459 | fun prep_html_source (tex_source, html_source, html) = | |
| 460 | let | |
| 14898 | 461 | val txt = HTML.begin_theory (Url.File index_path, session) | 
| 7727 | 462 | name parents files_html (Buffer.content html_source) | 
| 463 | in (tex_source, Buffer.empty, Buffer.add txt html) end; | |
| 464 | ||
| 9416 | 465 | val entry = | 
| 466 |      {name = name, ID = ID_of path name, dir = sess_name, unfold = true,
 | |
| 467 | path = Path.pack (html_path name), | |
| 468 | parents = map (fn s => ID_of (#session (get_info (ThyInfo.theory s))) s) raw_parents}; | |
| 7727 | 469 | |
| 470 | in | |
| 471 | change_theory_info name prep_html_source; | |
| 9416 | 472 | add_graph_entry entry; | 
| 14898 | 473 | add_html_index (HTML.theory_entry (Url.File (html_path name), name)); | 
| 7727 | 474 | add_tex_index (Latex.theory_entry name); | 
| 9416 | 475 |     BrowserInfoData.put {name = sess_name, session = path, is_local = is_some remote_path} thy
 | 
| 7727 | 476 | end); | 
| 477 | ||
| 478 | ||
| 13532 | 479 | val hooks = ref ([]: (string -> (string * thm list) list -> unit) list); | 
| 480 | fun add_hook f = hooks := (f :: ! hooks); | |
| 481 | ||
| 482 | fun results k xs = | |
| 483 | (seq (fn f => (try (fn () => f k xs) (); ())) (! hooks); | |
| 484 | with_session () (fn _ => with_context add_html (HTML.results k xs))); | |
| 485 | ||
| 486 | fun theorem a th = results "theorem" [(a, [th])]; | |
| 487 | fun theorems a ths = results "theorems" [(a, ths)]; | |
| 8088 | 488 | fun chapter s = with_session () (fn _ => with_context add_html (HTML.chapter s)); | 
| 7727 | 489 | fun section s = with_session () (fn _ => with_context add_html (HTML.section s)); | 
| 490 | fun subsection s = with_session () (fn _ => with_context add_html (HTML.subsection s)); | |
| 491 | fun subsubsection s = with_session () (fn _ => with_context add_html (HTML.subsubsection s)); | |
| 492 | ||
| 493 | ||
| 494 | ||
| 14922 | 495 | (** draft document output **) | 
| 496 | ||
| 497 | fun drafts doc_format src_paths = | |
| 498 | let | |
| 14935 | 499 | fun prep_draft (tex_index, path) = | 
| 500 | let | |
| 501 | val base = Path.base path; | |
| 14972 | 502 | val name = | 
| 503 | (case Path.pack (#1 (Path.split_ext base)) of "" => gensym "DUMMY" | s => s); | |
| 14935 | 504 | in | 
| 505 | if File.exists path then | |
| 506 | (Buffer.add (Latex.theory_entry name) tex_index, (name, base, File.read path)) | |
| 507 |         else error ("Bad file: " ^ quote (Path.pack path))
 | |
| 508 | end; | |
| 509 | val (tex_index, srcs) = foldl_map prep_draft (Buffer.empty, src_paths); | |
| 510 | ||
| 14922 | 511 | val doc_path = File.tmp_path (Path.basic "document"); | 
| 512 | val _ = File.mkdir doc_path; | |
| 513 | val root_path = Path.append doc_path (Path.basic "root.tex"); | |
| 514 | val _ = File.copy (Path.unpack "~~/lib/texinputs/draft.tex") root_path; | |
| 515 | val _ = File.system_command | |
| 516 |       ("\"$ISATOOL\" latex -o sty " ^ File.quote_sysify_path root_path);
 | |
| 517 | val _ = File.system_command | |
| 518 |       ("\"$ISATOOL\" latex -o syms " ^ File.quote_sysify_path root_path);
 | |
| 519 | ||
| 520 | fun known name = | |
| 521 | let val ss = split_lines (File.read (Path.append doc_path (Path.basic name))) | |
| 522 | in fn s => s mem_string ss end; | |
| 523 | val known_syms = known "syms.lst"; | |
| 524 | val known_ctrls = known "ctrls.lst"; | |
| 525 | ||
| 14935 | 526 | val _ = srcs |> seq (fn (name, base, txt) => | 
| 527 | Symbol.explode txt | |
| 528 | |> Latex.symbol_source (known_syms, known_ctrls) (Path.pack base) | |
| 529 | |> File.write (Path.append doc_path (tex_path name))); | |
| 14922 | 530 | val _ = write_tex_index tex_index doc_path; | 
| 14967 | 531 | val _ = isatool_document false doc_format doc_path; | 
| 14922 | 532 | in Path.ext doc_format doc_path end; | 
| 533 | ||
| 534 | ||
| 535 | ||
| 7727 | 536 | (** theory setup **) | 
| 537 | ||
| 538 | val setup = [BrowserInfoData.init]; | |
| 7685 | 539 | |
| 540 | end; | |
| 541 | ||
| 6203 | 542 | structure BasicPresent: BASIC_PRESENT = Present; | 
| 543 | open BasicPresent; |