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