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