| 6203 |      1 | (*  Title:      Pure/Thy/present.ML
 | 
|  |      2 |     ID:         $Id$
 | 
| 7727 |      3 |     Author:     Stefan Berghofer and Markus Wenzel, TU Muenchen
 | 
| 6203 |      4 | 
 | 
| 7727 |      5 | Theory presentation (HTML, graph files, simple LaTeX documents).
 | 
| 6203 |      6 | *)
 | 
|  |      7 | 
 | 
|  |      8 | signature BASIC_PRESENT =
 | 
|  |      9 | sig
 | 
| 7727 |     10 |   val section: string -> unit
 | 
| 6203 |     11 | end;
 | 
|  |     12 | 
 | 
|  |     13 | signature PRESENT =
 | 
|  |     14 | sig
 | 
| 7727 |     15 |   include BASIC_PRESENT
 | 
|  |     16 |   val init: bool -> string -> string list -> string -> Url.T option * bool -> unit
 | 
|  |     17 |   val finish: unit -> unit
 | 
|  |     18 |   val init_theory: string -> unit
 | 
|  |     19 |   val verbatim_source: string -> (unit -> string list) -> unit
 | 
| 7757 |     20 |   type token
 | 
|  |     21 |   val basic_token: OuterLex.token -> token
 | 
|  |     22 |   val markup_token: string * string -> token
 | 
| 7789 |     23 |   val verbatim_token: string -> token
 | 
| 7757 |     24 |   val token_source: string -> (unit -> token list) -> unit
 | 
| 7727 |     25 |   val begin_theory: string -> string list -> (Path.T * bool) list -> theory -> theory
 | 
|  |     26 |   val result: string -> string -> thm -> unit
 | 
|  |     27 |   val results: string -> string -> thm list -> unit
 | 
|  |     28 |   val theorem: string -> thm -> unit
 | 
|  |     29 |   val theorems: string -> thm list -> unit
 | 
|  |     30 |   val subsection: string -> unit
 | 
|  |     31 |   val subsubsection: string -> unit
 | 
|  |     32 |   val setup: (theory -> theory) list
 | 
| 7763 |     33 |   val get_info: theory -> {session: string list, is_local: bool}
 | 
| 6203 |     34 | end;
 | 
|  |     35 | 
 | 
| 7685 |     36 | structure Present: PRESENT =
 | 
|  |     37 | struct
 | 
|  |     38 | 
 | 
| 7727 |     39 | 
 | 
|  |     40 | (** paths **)
 | 
|  |     41 | 
 | 
|  |     42 | val output_path = Path.variable "ISABELLE_BROWSER_INFO";
 | 
|  |     43 | 
 | 
|  |     44 | fun top_path sess_path offset =
 | 
|  |     45 |   Path.append (Path.appends (replicate (offset + length sess_path) Path.parent));
 | 
|  |     46 | 
 | 
|  |     47 | val tex_ext = Path.ext "tex";
 | 
|  |     48 | val tex_path = tex_ext o Path.basic;
 | 
|  |     49 | val html_ext = Path.ext "html";
 | 
|  |     50 | val html_path = html_ext o Path.basic;
 | 
|  |     51 | val graph_path = Path.ext "graph" o Path.basic;
 | 
|  |     52 | val index_path = Path.basic "index.html";
 | 
|  |     53 | val doc_path = Path.basic "document";
 | 
|  |     54 | val doc_index_path = tex_path "session";
 | 
|  |     55 | 
 | 
|  |     56 | val session_path = Path.basic ".session";
 | 
|  |     57 | val session_entries_path = Path.unpack ".session/entries";
 | 
|  |     58 | val pre_index_path = Path.unpack ".session/pre-index";
 | 
|  |     59 | 
 | 
|  |     60 | 
 | 
|  |     61 | 
 | 
|  |     62 | (** additional theory data **)
 | 
|  |     63 | 
 | 
|  |     64 | structure BrowserInfoArgs =
 | 
|  |     65 | struct
 | 
|  |     66 |   val name = "Pure/browser_info";
 | 
|  |     67 |   type T = {session: string list, is_local: bool};
 | 
|  |     68 | 
 | 
|  |     69 |   val empty = {session = [], is_local = false};
 | 
|  |     70 |   val copy = I;
 | 
| 7763 |     71 |   fun prep_ext _ = empty;
 | 
| 7727 |     72 |   fun merge _ = empty;
 | 
|  |     73 |   fun print _ _ = ();
 | 
|  |     74 | end;
 | 
|  |     75 | 
 | 
|  |     76 | structure BrowserInfoData = TheoryDataFun(BrowserInfoArgs);
 | 
|  |     77 | 
 | 
|  |     78 | fun get_info thy =
 | 
|  |     79 |   if Theory.eq_thy (thy, ProtoPure.thy) then BrowserInfoArgs.empty
 | 
|  |     80 |   else BrowserInfoData.get thy;
 | 
|  |     81 | 
 | 
|  |     82 | 
 | 
|  |     83 | 
 | 
|  |     84 | (** graphs **)
 | 
|  |     85 | 
 | 
|  |     86 | type graph_node =
 | 
|  |     87 |   {name: string, ID: string, dir: string, unfold: bool,
 | 
|  |     88 |    path: string, parents: string list};
 | 
|  |     89 | 
 | 
|  |     90 | fun get_graph path = map (fn (a :: b :: c :: d :: e :: r) =>
 | 
|  |     91 |   {name = unenclose a, ID = unenclose b,
 | 
|  |     92 |    dir = unenclose c, unfold = (d = "+"),
 | 
|  |     93 |    path = unenclose (if d = "+" then e else d),
 | 
|  |     94 |    parents = map unenclose (fst (split_last (if d = "+" then tl r else r)))})
 | 
|  |     95 |      (map (filter_out (equal "") o space_explode " ") (split_lines (File.read path)));
 | 
|  |     96 | 
 | 
|  |     97 | fun put_graph gr path =
 | 
|  |     98 |     File.write path (cat_lines (map (fn {name, ID, dir, unfold, path, parents} =>
 | 
|  |     99 |       "\"" ^ name ^ "\" \"" ^ ID ^ "\" \"" ^ dir ^ (if unfold then "\" + \"" else "\" \"") ^
 | 
|  |    100 |       path ^ "\" > " ^ space_implode " " (map quote parents) ^ " ;") gr));
 | 
|  |    101 | 
 | 
|  |    102 | fun dir_of sess = space_implode "/" (case sess of
 | 
|  |    103 |   [] => ["Pure"] | [x] => [x, "base"] | xs => xs);
 | 
|  |    104 | 
 | 
|  |    105 | fun ID_of sess s = dir_of sess ^ "/" ^ s;
 | 
|  |    106 | 
 | 
|  |    107 | 
 | 
|  |    108 | (* retrieve graph data from theory loader database *)
 | 
|  |    109 | 
 | 
|  |    110 | fun make_graph remote_path unfold curr_sess = map (fn name =>
 | 
|  |    111 |   let
 | 
|  |    112 |     val {session, is_local} = get_info (ThyInfo.theory name);
 | 
|  |    113 |     val path' = Path.append (Path.make session) (html_path name)
 | 
|  |    114 |   in
 | 
|  |    115 |     {name = name, ID = ID_of session name, dir = dir_of session,
 | 
|  |    116 |      path = if null session then "" else
 | 
|  |    117 |             if is_some remote_path andalso not is_local then
 | 
|  |    118 |               Url.pack (Url.append (the remote_path) (Url.file path'))
 | 
|  |    119 |             else Path.pack (top_path curr_sess 2 path'),
 | 
|  |    120 |      unfold = unfold andalso (length session = 1),
 | 
|  |    121 |      parents = map (fn s => ID_of (#session (get_info (ThyInfo.theory s))) s)
 | 
|  |    122 |        (ThyInfo.get_preds name)}
 | 
|  |    123 |   end) (ThyInfo.names ());
 | 
|  |    124 | 
 | 
|  |    125 | fun add_graph_entry' (entry as {ID, ...}) (gr : graph_node list) =
 | 
|  |    126 |   filter_out (fn entry' => #ID entry' = ID) gr @ [entry];
 | 
|  |    127 | 
 | 
|  |    128 | 
 | 
|  |    129 | 
 | 
|  |    130 | (** global browser info state **)
 | 
|  |    131 | 
 | 
|  |    132 | (* type theory_info *)
 | 
|  |    133 | 
 | 
|  |    134 | type theory_info = {tex_source: Buffer.T, html_source: Buffer.T, html: Buffer.T};
 | 
|  |    135 | 
 | 
|  |    136 | fun make_theory_info (tex_source, html_source, html) =
 | 
|  |    137 |   {tex_source = tex_source, html_source = html_source, html = html}: theory_info;
 | 
|  |    138 | 
 | 
|  |    139 | val empty_theory_info = make_theory_info (Buffer.empty, Buffer.empty, Buffer.empty);
 | 
|  |    140 | 
 | 
|  |    141 | fun map_theory_info f {tex_source, html_source, html} =
 | 
|  |    142 |   make_theory_info (f (tex_source, html_source, html));
 | 
|  |    143 | 
 | 
|  |    144 | 
 | 
|  |    145 | (* type browser_info *)
 | 
|  |    146 | 
 | 
|  |    147 | type browser_info = {theories: theory_info Symtab.table, tex_index: Buffer.T,
 | 
|  |    148 |   html_index: Buffer.T, graph: graph_node list, all_graph: graph_node list};
 | 
|  |    149 | 
 | 
|  |    150 | fun make_browser_info (theories, tex_index, html_index, graph, all_graph) =
 | 
|  |    151 |   {theories = theories, tex_index = tex_index, html_index = html_index,
 | 
|  |    152 |     graph = graph, all_graph = all_graph}: browser_info;
 | 
|  |    153 | 
 | 
|  |    154 | val empty_browser_info = make_browser_info (Symtab.empty, Buffer.empty, Buffer.empty, [], []);
 | 
|  |    155 | 
 | 
|  |    156 | fun initial_browser_info remote_path graph_path curr_sess = make_browser_info
 | 
|  |    157 |   (Symtab.empty, Buffer.empty, Buffer.empty, make_graph remote_path false curr_sess,
 | 
|  |    158 |    if_none (try get_graph graph_path) (make_graph remote_path true [""]));
 | 
|  |    159 | 
 | 
|  |    160 | fun map_browser_info f {theories, tex_index, html_index, graph, all_graph} =
 | 
|  |    161 |   make_browser_info (f (theories, tex_index, html_index, graph, all_graph));
 | 
|  |    162 | 
 | 
|  |    163 | 
 | 
|  |    164 | (* state *)
 | 
|  |    165 | 
 | 
|  |    166 | val browser_info = ref empty_browser_info;
 | 
|  |    167 | 
 | 
|  |    168 | fun change_browser_info f = browser_info := map_browser_info f (! browser_info);
 | 
|  |    169 | 
 | 
|  |    170 | fun init_theory_info name info =
 | 
|  |    171 |   change_browser_info (fn (theories, tex_index, html_index, graph, all_graph) =>
 | 
|  |    172 |     (Symtab.update ((name, info), theories), tex_index, html_index, graph, all_graph));
 | 
|  |    173 | 
 | 
|  |    174 | fun change_theory_info name f =
 | 
|  |    175 |   change_browser_info (fn (info as (theories, tex_index, html_index, graph, all_graph)) =>
 | 
|  |    176 |     (case Symtab.lookup (theories, name) of
 | 
|  |    177 |       None => (warning ("Browser info: cannot access theory document " ^ quote name); info)
 | 
|  |    178 |     | Some info => (Symtab.update ((name, map_theory_info f info), theories),
 | 
|  |    179 |         tex_index, html_index, graph, all_graph)));
 | 
|  |    180 | 
 | 
|  |    181 | 
 | 
|  |    182 | fun add_tex_index txt =
 | 
|  |    183 |   change_browser_info (fn (theories, tex_index, html_index, graph, all_graph) =>
 | 
|  |    184 |     (theories, Buffer.add txt tex_index, html_index, graph, all_graph));
 | 
|  |    185 | 
 | 
|  |    186 | fun add_html_index txt =
 | 
|  |    187 |   change_browser_info (fn (theories, tex_index, html_index, graph, all_graph) =>
 | 
|  |    188 |     (theories, tex_index, Buffer.add txt html_index, graph, all_graph));
 | 
|  |    189 | 
 | 
|  |    190 | (*add entry to graph for current session*)
 | 
|  |    191 | fun add_graph_entry e =
 | 
|  |    192 |   change_browser_info (fn (theories, tex_index, html_index, graph, all_graph) =>
 | 
|  |    193 |     (theories, tex_index, html_index, add_graph_entry' e graph, all_graph));
 | 
|  |    194 | 
 | 
|  |    195 | (*add entry to graph for all sessions*)
 | 
|  |    196 | fun add_all_graph_entry e =
 | 
|  |    197 |   change_browser_info (fn (theories, tex_index, html_index, graph, all_graph) =>
 | 
|  |    198 |     (theories, tex_index, html_index, graph, add_graph_entry' e all_graph));
 | 
|  |    199 | 
 | 
|  |    200 | fun add_tex_source name txt = change_theory_info name (fn (tex_source, html_source, html) =>
 | 
|  |    201 |   (Buffer.add txt tex_source, html_source, html));
 | 
|  |    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,
 | 
| 7802 |    217 |     doc_format: string, doc_prefix: Path.T option, graph_path: Path.T, all_graph_path: Path.T,
 | 
| 7727 |    218 |     remote_path: Url.T option};
 | 
|  |    219 | 
 | 
| 7802 |    220 | fun make_session_info (name, parent, session, path, html_prefix, doc_format, doc_prefix,
 | 
| 7727 |    221 |     graph_path, all_graph_path, remote_path) =
 | 
| 7802 |    222 |   {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix,
 | 
|  |    223 |     doc_format = doc_format, doc_prefix = doc_prefix, graph_path = graph_path,
 | 
| 7727 |    224 |     all_graph_path = all_graph_path, remote_path = remote_path}: session_info;
 | 
| 7685 |    225 | 
 | 
|  |    226 | 
 | 
| 7727 |    227 | (* state *)
 | 
|  |    228 | 
 | 
|  |    229 | val session_info = ref (None: session_info option);
 | 
|  |    230 | 
 | 
|  |    231 | fun with_session x f = (case ! session_info of None => x | Some info => f info);
 | 
|  |    232 | fun with_context f = f (PureThy.get_name (Context.the_context ()));
 | 
|  |    233 | 
 | 
|  |    234 | 
 | 
|  |    235 | 
 | 
|  |    236 | (** HTML output **)
 | 
|  |    237 | 
 | 
|  |    238 | (* maintain index *)
 | 
|  |    239 | 
 | 
|  |    240 | val session_entries =
 | 
|  |    241 |   HTML.session_entries o
 | 
|  |    242 |     map (fn name => (Url.file (Path.append (Path.basic name) index_path), name));
 | 
|  |    243 | 
 | 
|  |    244 | fun get_entries dir =
 | 
|  |    245 |   split_lines (File.read (Path.append dir session_entries_path));
 | 
|  |    246 | 
 | 
|  |    247 | fun put_entries entries dir =
 | 
|  |    248 |   File.write (Path.append dir session_entries_path) (cat_lines entries);
 | 
|  |    249 | 
 | 
|  |    250 | 
 | 
|  |    251 | fun create_index dir =
 | 
|  |    252 |   File.read (Path.append dir pre_index_path) ^
 | 
|  |    253 |     session_entries (get_entries dir) ^ HTML.end_index
 | 
|  |    254 |   |> File.write (Path.append dir index_path);
 | 
|  |    255 | 
 | 
|  |    256 | fun update_index dir name =
 | 
|  |    257 |   (case try get_entries dir of
 | 
|  |    258 |     None => warning ("Browser info: cannot access session index of " ^ quote (Path.pack dir))
 | 
|  |    259 |   | Some es => (put_entries ((es \ name) @ [name]) dir; create_index dir));
 | 
|  |    260 | 
 | 
|  |    261 | 
 | 
|  |    262 | (* init session *)
 | 
|  |    263 | 
 | 
|  |    264 | fun name_of_session elems = space_implode "/" ("Isabelle" :: elems);
 | 
|  |    265 | 
 | 
|  |    266 | fun could_copy inpath outpath =
 | 
|  |    267 |   if File.exists inpath then (File.copy inpath outpath; true)
 | 
|  |    268 |   else false;
 | 
|  |    269 | 
 | 
|  |    270 | fun init false _ _ _ _ = (browser_info := empty_browser_info; session_info := None)
 | 
|  |    271 |   | init true doc path name (remote_path, first_time) =
 | 
|  |    272 |       let
 | 
|  |    273 |         val parent_name = name_of_session (take (length path - 1, path));
 | 
|  |    274 |         val session_name = name_of_session path;
 | 
|  |    275 |         val sess_prefix = Path.make path;
 | 
|  |    276 | 
 | 
|  |    277 |         val out_path = Path.expand output_path;
 | 
|  |    278 |         val html_prefix = Path.append out_path sess_prefix;
 | 
|  |    279 | 
 | 
|  |    280 |         val (doc_prefix, document_path) =
 | 
|  |    281 |           if doc = "" then (None, None)
 | 
|  |    282 |           else (Some (Path.append html_prefix doc_path), Some (Path.ext doc doc_path));
 | 
|  |    283 | 
 | 
|  |    284 |         val graph_prefix = Path.appends [out_path, Path.unpack "graph/data", sess_prefix];
 | 
|  |    285 |         val graph_path = Path.append graph_prefix (Path.basic "session.graph");
 | 
|  |    286 |         val graph_lnk = Url.file (top_path path 0 (Path.appends
 | 
|  |    287 |           [Path.unpack "graph/data", sess_prefix, Path.basic "medium.html"]));
 | 
|  |    288 |         val graph_up_lnk =
 | 
|  |    289 |           (Url.file (top_path path 2 (Path.append sess_prefix index_path)), session_name);
 | 
|  |    290 |         val codebase = Url.file (top_path path 1 Path.current);
 | 
|  |    291 |         val all_graph_path = Path.appends [out_path, Path.unpack "graph/data",
 | 
|  |    292 |           Path.basic (hd path), Path.basic "all_sessions.graph"];
 | 
|  |    293 | 
 | 
|  |    294 |         val _ = (File.mkdir html_prefix; File.mkdir graph_prefix);
 | 
|  |    295 | 
 | 
|  |    296 |         fun prep_readme readme =
 | 
|  |    297 |           let val readme_path = Path.basic readme in
 | 
|  |    298 |             if could_copy readme_path (Path.append html_prefix readme_path) then Some readme_path
 | 
|  |    299 |             else None
 | 
|  |    300 |           end;
 | 
|  |    301 |         val opt_readme =
 | 
|  |    302 |           (case prep_readme "README.html" of None => prep_readme "README" | some => some);
 | 
|  |    303 | 
 | 
|  |    304 |         val parent_index_path = Path.append Path.parent index_path;
 | 
|  |    305 |         val index_up_lnk = if first_time then
 | 
|  |    306 |             Url.append (the remote_path) (Url.file (Path.append sess_prefix parent_index_path))
 | 
|  |    307 |           else Url.file parent_index_path;
 | 
|  |    308 | 
 | 
|  |    309 |         val index_text = HTML.begin_index (index_up_lnk, parent_name)
 | 
|  |    310 |           (Url.file index_path, session_name) (apsome Url.file opt_readme)
 | 
|  |    311 |             (apsome Url.file document_path) graph_lnk;
 | 
|  |    312 |       in
 | 
|  |    313 |         File.mkdir (Path.append html_prefix session_path);
 | 
|  |    314 |         File.write (Path.append html_prefix session_entries_path) "";
 | 
|  |    315 |         if is_some doc_prefix then File.copy_all doc_path html_prefix else ();
 | 
|  |    316 |         seq (fn (name, txt) => File.write (Path.append graph_prefix (Path.basic name)) txt)
 | 
|  |    317 |           (HTML.applet_pages session_name codebase graph_up_lnk (length path = 1));
 | 
|  |    318 |         session_info := Some (make_session_info (name, parent_name, session_name, path,
 | 
| 7802 |    319 |           html_prefix, doc, doc_prefix, graph_path, all_graph_path, remote_path));
 | 
| 7727 |    320 |         browser_info := initial_browser_info remote_path all_graph_path path;
 | 
|  |    321 |         add_html_index index_text
 | 
|  |    322 |       end;
 | 
|  |    323 | 
 | 
|  |    324 | 
 | 
|  |    325 | (* finish session *)
 | 
| 7685 |    326 | 
 | 
| 7802 |    327 | fun isatool_document doc_format doc_prefix =
 | 
|  |    328 |   let val cmd = "$ISATOOL document -o '" ^ doc_format ^ "' '" ^ File.sysify_path doc_prefix ^ "'"
 | 
| 7853 |    329 |   in writeln cmd; if system cmd <> 0 then error "Failed to build document" else () end;
 | 
| 7802 |    330 | 
 | 
| 7727 |    331 | fun finish () = with_session ()
 | 
| 7802 |    332 |     (fn {name, html_prefix, doc_format, doc_prefix, graph_path, all_graph_path, path, ...} =>
 | 
| 7727 |    333 |   let
 | 
|  |    334 |     val {theories, tex_index, html_index, graph, all_graph} = ! browser_info;
 | 
|  |    335 | 
 | 
|  |    336 |     fun finish_node (a, {tex_source, html_source = _, html}) =
 | 
| 7802 |    337 |      (doc_prefix |> apsome (fn p => Buffer.write (Path.append p (tex_path a)) tex_source);
 | 
| 7727 |    338 |       Buffer.write (Path.append html_prefix (html_path a)) (Buffer.add HTML.end_theory html));
 | 
|  |    339 |   in
 | 
|  |    340 |     seq finish_node (Symtab.dest theories);
 | 
|  |    341 |     Buffer.write (Path.append html_prefix pre_index_path) html_index;
 | 
| 7802 |    342 |     doc_prefix |> apsome (fn p =>
 | 
|  |    343 |      (Buffer.write (Path.append p doc_index_path) tex_index; isatool_document doc_format p));
 | 
| 7727 |    344 |     put_graph graph graph_path;
 | 
|  |    345 |     put_graph all_graph all_graph_path;
 | 
|  |    346 |     create_index html_prefix;
 | 
|  |    347 |     update_index (Path.append html_prefix Path.parent) name;
 | 
|  |    348 |     browser_info := empty_browser_info;
 | 
|  |    349 |     session_info := None
 | 
|  |    350 |   end);
 | 
|  |    351 | 
 | 
|  |    352 | 
 | 
|  |    353 | (* theory elements *)
 | 
|  |    354 | 
 | 
|  |    355 | fun init_theory name = with_session () (fn _ => init_theory_info name empty_theory_info);
 | 
|  |    356 | 
 | 
|  |    357 | fun verbatim_source name mk_text =
 | 
|  |    358 |   with_session () (fn _ => add_html_source name (HTML.verbatim_source (mk_text ())));
 | 
|  |    359 | 
 | 
| 7757 |    360 | 
 | 
|  |    361 | type token = Latex.token;
 | 
|  |    362 | val basic_token = Latex.Basic;
 | 
|  |    363 | val markup_token = Latex.Markup;
 | 
| 7789 |    364 | val verbatim_token = Latex.Verbatim;
 | 
| 7757 |    365 | 
 | 
| 7727 |    366 | fun token_source name mk_toks =
 | 
|  |    367 |   with_session () (fn _ => add_tex_source name (Latex.token_source (mk_toks ())));
 | 
|  |    368 | 
 | 
|  |    369 | 
 | 
|  |    370 | fun parent_link remote_path curr_session name =
 | 
|  |    371 |   let
 | 
|  |    372 |     val {session, is_local} = get_info (ThyInfo.theory name);
 | 
|  |    373 |     val path = Path.append (Path.make session) (html_path name)
 | 
|  |    374 |   in (if null session then None else
 | 
|  |    375 |      Some (if is_some remote_path andalso not is_local then
 | 
|  |    376 |        Url.append (the remote_path) (Url.file path)
 | 
|  |    377 |      else Url.file (top_path curr_session 0 path)), name)
 | 
|  |    378 |   end;
 | 
|  |    379 | 
 | 
|  |    380 | fun begin_theory name raw_parents orig_files thy =
 | 
|  |    381 |   with_session thy (fn {session, path, html_prefix, remote_path, ...} =>
 | 
|  |    382 |   let
 | 
|  |    383 |     val parents = map (parent_link remote_path path) raw_parents;
 | 
|  |    384 |     val ml_path = ThyLoad.ml_path name;
 | 
|  |    385 |     val files = map (apsnd Some) orig_files @
 | 
|  |    386 |       (if is_some (ThyLoad.check_file ml_path) then [(ml_path, None)] else []);
 | 
|  |    387 | 
 | 
|  |    388 |     fun prep_file (raw_path, loadit) =
 | 
|  |    389 |       (case ThyLoad.check_file raw_path of
 | 
|  |    390 |         Some (path, _) =>
 | 
|  |    391 |           let
 | 
|  |    392 |             val base = Path.base path;
 | 
|  |    393 |             val base_html = html_ext base;
 | 
|  |    394 |           in
 | 
|  |    395 |             File.write (Path.append html_prefix base_html)
 | 
|  |    396 |               (HTML.ml_file (Url.file base) (File.read path));
 | 
|  |    397 |             (Some (Url.file base_html), Url.file raw_path, loadit)
 | 
|  |    398 |           end
 | 
|  |    399 |       | None => (warning ("Browser info: expected to find ML file" ^ quote (Path.pack raw_path));
 | 
|  |    400 |           (None, Url.file raw_path, loadit)));
 | 
|  |    401 | 
 | 
|  |    402 |     val files_html = map prep_file files;
 | 
|  |    403 | 
 | 
|  |    404 |     fun prep_html_source (tex_source, html_source, html) =
 | 
|  |    405 |       let
 | 
|  |    406 |         val txt = HTML.begin_theory (Url.file index_path, session)
 | 
|  |    407 |           name parents files_html (Buffer.content html_source)
 | 
|  |    408 |       in (tex_source, Buffer.empty, Buffer.add txt html) end;
 | 
|  |    409 | 
 | 
|  |    410 |     fun make_entry unfold all =
 | 
|  |    411 |       {name = name, ID = ID_of path name, dir = dir_of path, unfold = unfold,
 | 
|  |    412 |        path = Path.pack (top_path (if all then [""] else path) 2
 | 
|  |    413 |          (Path.append (Path.make path) (html_path name))),
 | 
|  |    414 |        parents = map (fn s => ID_of (#session (get_info (ThyInfo.theory s))) s) raw_parents};
 | 
|  |    415 | 
 | 
|  |    416 |   in
 | 
|  |    417 |     change_theory_info name prep_html_source;
 | 
|  |    418 |     add_all_graph_entry (make_entry (length path = 1) true);
 | 
|  |    419 |     add_graph_entry (make_entry true false);
 | 
|  |    420 |     add_html_index (HTML.theory_entry (Url.file (html_path name), name));
 | 
|  |    421 |     add_tex_index (Latex.theory_entry name);
 | 
|  |    422 |     BrowserInfoData.put {session = path, is_local = is_some remote_path} thy
 | 
|  |    423 |   end);
 | 
|  |    424 | 
 | 
|  |    425 | 
 | 
|  |    426 | fun result k a thm = with_session () (fn _ => with_context add_html (HTML.result k a thm));
 | 
|  |    427 | fun results k a thms = with_session () (fn _ => with_context add_html (HTML.results k a thms));
 | 
|  |    428 | fun theorem a thm = with_session () (fn _ => with_context add_html (HTML.theorem a thm));
 | 
|  |    429 | fun theorems a thms = with_session () (fn _ => with_context add_html (HTML.theorems a thms));
 | 
|  |    430 | fun section s = with_session () (fn _ => with_context add_html (HTML.section s));
 | 
|  |    431 | fun subsection s = with_session () (fn _ => with_context add_html (HTML.subsection s));
 | 
|  |    432 | fun subsubsection s = with_session () (fn _ => with_context add_html (HTML.subsubsection s));
 | 
|  |    433 | 
 | 
|  |    434 | 
 | 
|  |    435 | 
 | 
|  |    436 | (** theory setup **)
 | 
|  |    437 | 
 | 
|  |    438 | val setup = [BrowserInfoData.init];
 | 
| 7685 |    439 | 
 | 
|  |    440 | 
 | 
|  |    441 | end;
 | 
|  |    442 | 
 | 
| 6203 |    443 | 
 | 
|  |    444 | structure BasicPresent: BASIC_PRESENT = Present;
 | 
|  |    445 | open BasicPresent;
 |