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