| 6324 |      1 | (*  Title:      Pure/Thy/HTML.ML
 | 
|  |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Markus Wenzel, TU Muenchen
 | 
|  |      4 | 
 | 
| 6338 |      5 | HTML presentation primitives.
 | 
| 6324 |      6 | *)
 | 
|  |      7 | 
 | 
|  |      8 | signature HTML =
 | 
|  |      9 | sig
 | 
|  |     10 |   val output: string -> string
 | 
|  |     11 |   val output_width: string -> string * real
 | 
|  |     12 |   type text (* = string *)
 | 
|  |     13 |   val plain: string -> text
 | 
|  |     14 |   val name: string -> text
 | 
|  |     15 |   val keyword: string -> text
 | 
|  |     16 |   val file_name: string -> text
 | 
| 6649 |     17 |   val file_path: Url.T -> text
 | 
| 6324 |     18 |   val href_name: string -> text -> text
 | 
| 6649 |     19 |   val href_path: Url.T -> text -> text
 | 
| 6376 |     20 |   val href_opt_name: string option -> text -> text
 | 
| 6649 |     21 |   val href_opt_path: Url.T option -> text -> text
 | 
| 6376 |     22 |   val para: text -> text
 | 
| 6324 |     23 |   val preform: text -> text
 | 
|  |     24 |   val verbatim: string -> text
 | 
| 7725 |     25 |   val begin_index: Url.T * string -> Url.T * string -> Url.T option
 | 
|  |     26 |     -> Url.T option -> Url.T -> text
 | 
| 6338 |     27 |   val end_index: text
 | 
| 6649 |     28 |   val applet_pages: string -> Url.T -> Url.T * string -> bool -> (string * string) list
 | 
|  |     29 |   val theory_entry: Url.T * string -> text
 | 
|  |     30 |   val session_entries: (Url.T * string) list -> text
 | 
| 8190 |     31 |   val verbatim_source: Symbol.symbol list -> text
 | 
| 6649 |     32 |   val begin_theory: Url.T * string -> string -> (Url.T option * string) list ->
 | 
| 7408 |     33 |     (Url.T option * Url.T * bool option) list -> text -> text
 | 
| 6324 |     34 |   val end_theory: text
 | 
| 6649 |     35 |   val ml_file: Url.T -> string -> text
 | 
| 7572 |     36 |   val result: string -> string -> thm -> text
 | 
|  |     37 |   val results: string -> string -> thm list -> text
 | 
| 6324 |     38 |   val theorem: string -> thm -> text
 | 
| 7408 |     39 |   val theorems: string -> thm list -> text
 | 
| 8088 |     40 |   val chapter: string -> text
 | 
| 6324 |     41 |   val section: string -> text
 | 
| 7634 |     42 |   val subsection: string -> text
 | 
|  |     43 |   val subsubsection: string -> text
 | 
| 6324 |     44 |   val setup: (theory -> theory) list
 | 
|  |     45 | end;
 | 
|  |     46 | 
 | 
|  |     47 | structure HTML: HTML =
 | 
|  |     48 | struct
 | 
|  |     49 | 
 | 
|  |     50 | 
 | 
|  |     51 | (** HTML print modes **)
 | 
|  |     52 | 
 | 
|  |     53 | (* mode *)
 | 
|  |     54 | 
 | 
|  |     55 | val htmlN = "HTML";
 | 
|  |     56 | fun html_mode f x = setmp print_mode [htmlN] f x;
 | 
|  |     57 | 
 | 
|  |     58 | 
 | 
|  |     59 | (* symbol output *)
 | 
|  |     60 | 
 | 
| 6338 |     61 | local
 | 
|  |     62 |   val escape = fn "<" => "<" | ">" => ">" | "&" => "&" | c => c;
 | 
| 6324 |     63 | 
 | 
| 6338 |     64 |   val output_sym =
 | 
|  |     65 |     fn "\\<not>" => (1.0, "¬")
 | 
|  |     66 |      | "\\<hyphen>" => (1.0, "­")
 | 
|  |     67 |      | "\\<cdot>" => (1.0, "·")
 | 
|  |     68 |      | "\\<times>" => (1.0, "×")
 | 
|  |     69 |      | "\\<copyright>" => (1.0, "©")
 | 
|  |     70 |      | "\\<mu>" => (1.0, "µ")
 | 
|  |     71 |      | s => (real (size s), implode (map escape (explode s)));
 | 
| 6324 |     72 | 
 | 
| 6338 |     73 |   fun add_sym (width, (w: real, s)) = (width + w, s);
 | 
|  |     74 | in
 | 
| 6324 |     75 | 
 | 
| 6338 |     76 | fun output_width str =
 | 
|  |     77 |   if not (exists_string (equal "<" orf equal ">" orf equal "&") str) then (str, real (size str))
 | 
|  |     78 |   else
 | 
|  |     79 |     let val (width, syms) = foldl_map add_sym (0.0, map output_sym (Symbol.explode str))
 | 
|  |     80 |     in (implode syms, width) end;
 | 
|  |     81 | 
 | 
|  |     82 | val output = #1 o output_width;
 | 
|  |     83 | val output_symbols = map (#2 o output_sym);
 | 
|  |     84 | 
 | 
|  |     85 | end;
 | 
|  |     86 | 
 | 
| 6324 |     87 | 
 | 
|  |     88 | val _ = Symbol.add_mode htmlN output_width;
 | 
|  |     89 | 
 | 
|  |     90 | 
 | 
|  |     91 | (* token translations *)
 | 
|  |     92 | 
 | 
| 6347 |     93 | fun color col =
 | 
|  |     94 |   apfst (enclose ("<font color=" ^ quote col ^ ">") "</font>") o output_width;
 | 
| 6324 |     95 | 
 | 
|  |     96 | val html_trans =
 | 
|  |     97 |  [("class", color "red"),
 | 
|  |     98 |   ("tfree", color "purple"),
 | 
|  |     99 |   ("tvar",  color "purple"),
 | 
|  |    100 |   ("free",  color "blue"),
 | 
|  |    101 |   ("bound", color "green"),
 | 
|  |    102 |   ("var",   color "blue"),
 | 
|  |    103 |   ("xnum",  color "yellow"),
 | 
|  |    104 |   ("xstr",  color "brown")];
 | 
|  |    105 | 
 | 
|  |    106 | 
 | 
|  |    107 | 
 | 
|  |    108 | (** HTML markup **)
 | 
|  |    109 | 
 | 
|  |    110 | type text = string;
 | 
|  |    111 | 
 | 
|  |    112 | 
 | 
|  |    113 | (* atoms *)
 | 
|  |    114 | 
 | 
|  |    115 | val plain = output;
 | 
|  |    116 | fun name s = "<i>" ^ output s ^ "</i>";
 | 
|  |    117 | fun keyword s = "<b>" ^ output s ^ "</b>";
 | 
|  |    118 | fun file_name s = "<tt>" ^ output s ^ "</tt>";
 | 
| 6649 |    119 | val file_path = file_name o Url.pack;
 | 
| 6324 |    120 | 
 | 
|  |    121 | 
 | 
|  |    122 | (* misc *)
 | 
|  |    123 | 
 | 
|  |    124 | fun href_name s txt = "<a href=" ^ quote s ^ ">" ^ txt ^ "</a>";
 | 
| 6649 |    125 | fun href_path path txt = href_name (Url.pack path) txt;
 | 
| 6376 |    126 | 
 | 
|  |    127 | fun href_opt_name None txt = txt
 | 
|  |    128 |   | href_opt_name (Some s) txt = href_name s txt;
 | 
|  |    129 | 
 | 
|  |    130 | fun href_opt_path None txt = txt
 | 
|  |    131 |   | href_opt_path (Some p) txt = href_path p txt;
 | 
|  |    132 | 
 | 
|  |    133 | fun para txt = "\n<p>\n" ^ txt ^ "\n</p>\n";
 | 
| 6324 |    134 | fun preform txt = "<pre>" ^ txt ^ "</pre>";
 | 
|  |    135 | val verbatim = preform o output;
 | 
|  |    136 | 
 | 
|  |    137 | 
 | 
|  |    138 | (* document *)
 | 
|  |    139 | 
 | 
|  |    140 | fun begin_document title =
 | 
| 6405 |    141 |   "<html>\n\
 | 
|  |    142 |   \<head>\n\
 | 
|  |    143 |   \<title>" ^ plain (title ^ " (" ^ version ^ ")") ^ "</title>\n\
 | 
|  |    144 |   \</head>\n\
 | 
|  |    145 |   \\n\
 | 
|  |    146 |   \<body>\n\
 | 
|  |    147 |   \<h1>" ^ plain title ^ "</h1>\n"
 | 
| 6324 |    148 | 
 | 
| 6405 |    149 | val end_document = "\n</body>\n</html>\n";
 | 
| 6324 |    150 | 
 | 
| 6754 |    151 | fun gen_link how (path, name) = para (href_path path how ^ " to index of " ^ plain name);
 | 
|  |    152 | val up_link = gen_link "Up";
 | 
|  |    153 | val back_link = gen_link "Back";
 | 
| 6338 |    154 | 
 | 
|  |    155 | 
 | 
|  |    156 | (* session index *)
 | 
|  |    157 | 
 | 
| 7725 |    158 | fun begin_index up (index_path, session) opt_readme opt_doc graph =
 | 
| 6754 |    159 |   begin_document ("Index of " ^ session) ^ up_link up ^
 | 
|  |    160 |   para ("View " ^ href_path graph "theory dependencies" ^
 | 
| 7725 |    161 |     (case opt_readme of None => "" | Some p => "<br>\nView " ^ href_path p "README") ^
 | 
|  |    162 |     (case opt_doc of None => "" | Some p => "<br>\nView " ^ href_path p "document")) ^
 | 
| 6405 |    163 |   "\n<hr>\n\n<h2>Theories</h2>\n<ul>\n";
 | 
| 6338 |    164 | 
 | 
|  |    165 | val end_index = end_document;
 | 
|  |    166 | 
 | 
| 6649 |    167 | fun choice chs s = space_implode " " (map (fn (s', lnk) =>
 | 
|  |    168 |   enclose "[" "]" (if s = s' then keyword s' else href_name lnk s')) chs);
 | 
|  |    169 | 
 | 
| 6754 |    170 | fun applet_pages session codebase back alt_graph =
 | 
| 6649 |    171 |   let
 | 
|  |    172 |     val choices = [("none", "small",  "small.html"),
 | 
|  |    173 |                    ("none", "medium", "medium.html"),
 | 
|  |    174 |                    ("none", "large",  "large.html"),
 | 
|  |    175 |                    ("all",  "small",  "small_all.html"),
 | 
|  |    176 |                    ("all",  "medium", "medium_all.html"),
 | 
|  |    177 |                    ("all",  "large",  "large_all.html")];
 | 
|  |    178 | 
 | 
|  |    179 |     val sizes = [("small",  ("500", "400")),
 | 
|  |    180 |                  ("medium", ("650", "520")),
 | 
|  |    181 |                  ("large",  ("800", "640"))];
 | 
|  |    182 | 
 | 
|  |    183 |     fun applet_page (gtype, size, name) =
 | 
| 6754 |    184 |       let
 | 
|  |    185 |         val (width, height) = the (assoc (sizes, size));
 | 
|  |    186 |         val subsessions =
 | 
|  |    187 |           if alt_graph then
 | 
|  |    188 |             "View subsessions: " ^ choice (map (fn (x, _, z) => (x, z))
 | 
|  |    189 |               (filter (fn (_, y, _) => y = size) choices)) gtype ^ "<br>\n"
 | 
|  |    190 |           else "";
 | 
|  |    191 |         val browser_size = "Set browser size: " ^
 | 
|  |    192 |           choice (map (fn (_, y, z) => (y, z)) (filter (fn (x, _, _) => x = gtype) choices)) size;
 | 
|  |    193 |       in
 | 
|  |    194 |         (name, begin_document ("Theory dependencies of " ^ session) ^
 | 
|  |    195 |           back_link back ^
 | 
|  |    196 |           para (subsessions ^ browser_size) ^
 | 
|  |    197 |           "\n<hr>\n<applet code=\"GraphBrowser/GraphBrowser.class\" \
 | 
|  |    198 |           \codebase=\"" ^ Url.pack codebase ^ "\" width=" ^ width ^ " height=" ^ height ^ ">\n\
 | 
|  |    199 |           \<param name=\"graphfile\" value=\"" ^
 | 
|  |    200 |           (if gtype = "all" then "all_sessions.graph" else "session.graph") ^ "\">\n\
 | 
|  |    201 |           \</applet>\n<hr>" ^ end_document)
 | 
| 6649 |    202 |       end;
 | 
| 6754 |    203 |   in map applet_page (take (if alt_graph then 6 else 3, choices)) end;
 | 
| 6649 |    204 | 
 | 
|  |    205 | 
 | 
| 6405 |    206 | fun entry (p, s) = "<li>" ^ href_path p (plain s) ^ "\n";
 | 
|  |    207 | 
 | 
| 6338 |    208 | val theory_entry = entry;
 | 
|  |    209 | 
 | 
| 6405 |    210 | fun session_entries [] = "</ul>"
 | 
|  |    211 |   | session_entries es =
 | 
|  |    212 |       "</ul>\n<hr>\n\n<h2>Sessions</h2>\n<ul>\n" ^ implode (map entry es) ^ "</ul>";
 | 
| 6324 |    213 | 
 | 
|  |    214 | 
 | 
|  |    215 | (* theory *)
 | 
|  |    216 | 
 | 
| 7725 |    217 | fun verbatim_source ss = "\n<hr>\n<pre>" ^ implode (output_symbols ss)  ^ "</pre>\n<hr>\n";
 | 
| 6324 |    218 | 
 | 
|  |    219 | 
 | 
|  |    220 | local
 | 
| 7408 |    221 |   fun encl None = enclose "[" "]"
 | 
|  |    222 |     | encl (Some false) = enclose "(" ")"
 | 
|  |    223 |     | encl (Some true) = I;
 | 
| 6324 |    224 | 
 | 
| 7408 |    225 |   fun file (opt_ref, path, loadit) = href_opt_path opt_ref (encl loadit (file_path path));
 | 
| 7831 |    226 |   val files = space_implode " " o map file;
 | 
| 6376 |    227 |   val parents = space_implode " + " o map (uncurry href_opt_path o apsnd name);
 | 
| 6361 |    228 | 
 | 
| 6376 |    229 |   fun theory up A =
 | 
|  |    230 |     begin_document ("Theory " ^ A) ^ "\n" ^ up_link up ^
 | 
| 6324 |    231 |     keyword "theory" ^ " " ^ name A ^ " = ";
 | 
|  |    232 | in
 | 
|  |    233 | 
 | 
| 6376 |    234 | fun begin_theory up A Bs [] body = theory up A ^ parents Bs ^ ":\n" ^ body
 | 
|  |    235 |   | begin_theory up A Bs Ps body = theory up A ^ parents Bs ^ "<br>" ^ keyword "files" ^
 | 
|  |    236 |       " " ^ files Ps ^ ":" ^ "\n" ^ body;
 | 
| 6324 |    237 | end;
 | 
|  |    238 | 
 | 
| 6338 |    239 | val end_theory = end_document;
 | 
| 6324 |    240 | 
 | 
|  |    241 | 
 | 
|  |    242 | (* ML file *)
 | 
|  |    243 | 
 | 
|  |    244 | fun ml_file path str =
 | 
| 6649 |    245 |   begin_document ("File " ^ Url.pack path) ^
 | 
| 6324 |    246 |   "\n<hr>\n" ^ verbatim str ^ "\n<hr>\n" ^ end_document;
 | 
|  |    247 | 
 | 
|  |    248 | 
 | 
| 7408 |    249 | (* theorems *)
 | 
| 6324 |    250 | 
 | 
| 7572 |    251 | local
 | 
|  |    252 | 
 | 
| 7408 |    253 | val string_of_thm =
 | 
| 6324 |    254 |   Pretty.setmp_margin 80 Pretty.string_of o
 | 
|  |    255 |     Display.pretty_thm_no_quote o #1 o Drule.freeze_thaw;
 | 
|  |    256 | 
 | 
|  |    257 | fun thm th = preform (prefix_lines "  " (html_mode string_of_thm th));
 | 
| 7408 |    258 | 
 | 
| 7572 |    259 | fun thm_name "" = ""
 | 
|  |    260 |   | thm_name a = " " ^ name (a ^ ":");
 | 
|  |    261 | 
 | 
|  |    262 | in
 | 
|  |    263 | 
 | 
|  |    264 | fun result k a th = para (keyword k ^ thm_name a ^ "\n" ^ thm th);
 | 
|  |    265 | fun results k a ths = para (cat_lines ((keyword k ^ thm_name a) :: map thm ths));
 | 
|  |    266 | 
 | 
|  |    267 | val theorem = result "theorem";
 | 
|  |    268 | val theorems = results "theorems";
 | 
|  |    269 | 
 | 
|  |    270 | end;
 | 
| 6324 |    271 | 
 | 
|  |    272 | 
 | 
| 7634 |    273 | (* sections *)
 | 
| 6324 |    274 | 
 | 
| 8088 |    275 | fun chapter heading = "\n\n<h1>" ^ plain heading ^ "</h1>\n";
 | 
| 6324 |    276 | fun section heading = "\n\n<h2>" ^ plain heading ^ "</h2>\n";
 | 
| 7634 |    277 | fun subsection heading = "\n\n<h3>" ^ plain heading ^ "</h3>\n";
 | 
|  |    278 | fun subsubsection heading = "\n\n<h4>" ^ plain heading ^ "</h4>\n";
 | 
| 6324 |    279 | 
 | 
|  |    280 | 
 | 
|  |    281 | 
 | 
|  |    282 | (** theory setup **)
 | 
|  |    283 | 
 | 
|  |    284 | val setup =
 | 
|  |    285 |  [Theory.add_mode_tokentrfuns htmlN html_trans];
 | 
|  |    286 | 
 | 
|  |    287 | 
 | 
|  |    288 | end;
 |