src/Pure/Thy/present.ML
changeset 17082 b0e9462db0b4
parent 16503 24491bde68df
child 17177 53cc9e134f40
equal deleted inserted replaced
17081:e19963723262 17082:b0e9462db0b4
    15 sig
    15 sig
    16   include BASIC_PRESENT
    16   include BASIC_PRESENT
    17   val get_info: theory -> {name: string, session: string list, is_local: bool}
    17   val get_info: theory -> {name: string, session: string list, is_local: bool}
    18   val write_graph: {name: string, ID: string, dir: string, unfold: bool,
    18   val write_graph: {name: string, ID: string, dir: string, unfold: bool,
    19    path: string, parents: string list} list -> Path.T -> unit
    19    path: string, parents: string list} list -> Path.T -> unit
    20   val init: bool -> bool -> string -> bool -> string list -> string -> Path.T option
    20   val init: bool -> bool -> string -> bool -> string list -> string list ->
    21     -> Url.T option * bool -> bool -> unit
    21     string -> Path.T option -> Url.T option * bool -> bool -> unit
    22   val finish: unit -> unit
    22   val finish: unit -> unit
    23   val init_theory: string -> unit
    23   val init_theory: string -> unit
    24   val verbatim_source: string -> (unit -> Symbol.symbol list) -> unit
    24   val verbatim_source: string -> (unit -> Symbol.symbol list) -> unit
    25   val old_symbol_source: string -> (unit -> Symbol.symbol list) -> unit
    25   val old_symbol_source: string -> (unit -> Symbol.symbol list) -> unit
    26   val theory_output: string -> string -> unit
    26   val theory_output: string -> string -> unit
    49 val html_ext = Path.ext "html";
    49 val html_ext = Path.ext "html";
    50 val html_path = html_ext o Path.basic;
    50 val html_path = html_ext o Path.basic;
    51 val index_path = Path.basic "index.html";
    51 val index_path = Path.basic "index.html";
    52 val readme_html_path = Path.basic "README.html";
    52 val readme_html_path = Path.basic "README.html";
    53 val readme_path = Path.basic "README";
    53 val readme_path = Path.basic "README";
    54 val doc_path = Path.basic "document";
    54 val documentN = "document";
       
    55 val document_path = Path.basic documentN;
    55 val doc_indexN = "session";
    56 val doc_indexN = "session";
    56 val graph_path = Path.basic "session.graph";
    57 val graph_path = Path.basic "session.graph";
    57 val graph_pdf_path = Path.basic "session_graph.pdf";
    58 val graph_pdf_path = Path.basic "session_graph.pdf";
    58 val graph_eps_path = Path.basic "session_graph.eps";
    59 val graph_eps_path = Path.basic "session_graph.eps";
    59 
    60 
   214 
   215 
   215 (* session_info *)
   216 (* session_info *)
   216 
   217 
   217 type session_info =
   218 type session_info =
   218   {name: string, parent: string, session: string, path: string list, html_prefix: Path.T,
   219   {name: string, parent: string, session: string, path: string list, html_prefix: Path.T,
   219     info: bool, doc_format: string, doc_graph: bool, doc_prefix1: Path.T option,
   220     info: bool, doc_format: string, doc_graph: bool, documents: (string * string) list,
   220     doc_prefix2: Path.T option, remote_path: Url.T option, verbose: bool, readme: Path.T option};
   221     doc_prefix1: (Path.T * Path.T) option, doc_prefix2: Path.T option, remote_path: Url.T option,
       
   222     verbose: bool, readme: Path.T option};
   221 
   223 
   222 fun make_session_info
   224 fun make_session_info
   223   (name, parent, session, path, html_prefix, info, doc_format, doc_graph, doc_prefix1,
   225   (name, parent, session, path, html_prefix, info, doc_format, doc_graph, documents,
   224     doc_prefix2, remote_path, verbose, readme) =
   226     doc_prefix1, doc_prefix2, remote_path, verbose, readme) =
   225   {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix,
   227   {name = name, parent = parent, session = session, path = path, html_prefix = html_prefix,
   226     info = info, doc_format = doc_format, doc_graph = doc_graph, doc_prefix1 = doc_prefix1,
   228     info = info, doc_format = doc_format, doc_graph = doc_graph, documents = documents,
   227     doc_prefix2 = doc_prefix2, remote_path = remote_path, verbose = verbose,
   229     doc_prefix1 = doc_prefix1, doc_prefix2 = doc_prefix2, remote_path = remote_path,
   228     readme = readme}: session_info;
   230     verbose = verbose, readme = readme}: session_info;
   229 
   231 
   230 
   232 
   231 (* state *)
   233 (* state *)
   232 
   234 
   233 val session_info = ref (NONE: session_info option);
   235 val session_info = ref (NONE: session_info option);
   261   (case try get_entries dir of
   263   (case try get_entries dir of
   262     NONE => warning ("Browser info: cannot access session index of " ^ quote (Path.pack dir))
   264     NONE => warning ("Browser info: cannot access session index of " ^ quote (Path.pack dir))
   263   | SOME es => (put_entries ((es \ name) @ [name]) dir; create_index dir));
   265   | SOME es => (put_entries ((es \ name) @ [name]) dir; create_index dir));
   264 
   266 
   265 
   267 
       
   268 (* document versions *)
       
   269 
       
   270 fun read_version str =
       
   271   (case space_explode "=" str of
       
   272     [name] => (name, "")
       
   273   | [name, tags] => (name, tags)
       
   274   | _ => error ("Malformed document version specification: " ^ quote str));
       
   275 
       
   276 fun read_versions strs =
       
   277   rev (gen_distinct eq_fst (rev ((documentN, "") :: map read_version strs)))
       
   278   |> filter_out (equal "-" o #2);
       
   279 
       
   280 
   266 (* init session *)
   281 (* init session *)
   267 
   282 
   268 fun name_of_session elems = space_implode "/" ("Isabelle" :: elems);
   283 fun name_of_session elems = space_implode "/" ("Isabelle" :: elems);
   269 
   284 
   270 fun init build info doc doc_graph path name doc_prefix2 (remote_path, first_time) verbose =
   285 fun init build info doc doc_graph doc_versions path name doc_prefix2
       
   286     (remote_path, first_time) verbose =
   271   if not build andalso not info andalso doc = "" andalso is_none doc_prefix2 then
   287   if not build andalso not info andalso doc = "" andalso is_none doc_prefix2 then
   272     (browser_info := empty_browser_info; session_info := NONE)
   288     (browser_info := empty_browser_info; session_info := NONE)
   273   else
   289   else
   274     let
   290     let
   275       val parent_name = name_of_session (Library.take (length path - 1, path));
   291       val parent_name = name_of_session (Library.take (length path - 1, path));
   276       val session_name = name_of_session path;
   292       val session_name = name_of_session path;
   277       val sess_prefix = Path.make path;
   293       val sess_prefix = Path.make path;
   278       val html_prefix = Path.append (Path.expand output_path) sess_prefix;
   294       val html_prefix = Path.append (Path.expand output_path) sess_prefix;
   279 
   295 
   280       val (doc_prefix1, document_path) =
   296       val (doc_prefix1, documents) =
   281         if doc = "" then (NONE, NONE)
   297         if doc = "" then (NONE, [])
   282         else if not (File.exists doc_path) then (conditional verbose (fn () =>
   298         else if not (File.exists document_path) then (conditional verbose (fn () =>
   283           std_error "Warning: missing document directory\n"); (NONE, NONE))
   299           std_error "Warning: missing document directory\n"); (NONE, []))
   284         else (SOME (Path.append html_prefix doc_path), SOME (Path.ext doc doc_path));
   300         else (SOME (Path.append html_prefix document_path, html_prefix),
       
   301           read_versions doc_versions);
   285 
   302 
   286       val parent_index_path = Path.append Path.parent index_path;
   303       val parent_index_path = Path.append Path.parent index_path;
   287       val index_up_lnk = if first_time then
   304       val index_up_lnk = if first_time then
   288           Url.append (the remote_path) (Url.File (Path.append sess_prefix parent_index_path))
   305           Url.append (the remote_path) (Url.File (Path.append sess_prefix parent_index_path))
   289         else Url.File parent_index_path;
   306         else Url.File parent_index_path;
   290       val readme =
   307       val readme =
   291         if File.exists readme_html_path then SOME readme_html_path
   308         if File.exists readme_html_path then SOME readme_html_path
   292         else if File.exists readme_path then SOME readme_path
   309         else if File.exists readme_path then SOME readme_path
   293         else NONE;
   310         else NONE;
   294 
   311 
       
   312       val docs =
       
   313         (case readme of NONE => [] | SOME p => [(Url.File p, "README")]) @
       
   314         map (fn (name, _) => (Url.File (Path.ext doc (Path.basic name)), name)) documents;
   295       val index_text = HTML.begin_index (index_up_lnk, parent_name)
   315       val index_text = HTML.begin_index (index_up_lnk, parent_name)
   296         (Url.File index_path, session_name) (Option.map Url.File readme)
   316         (Url.File index_path, session_name) docs (Url.unpack "medium.html");
   297           (Option.map Url.File document_path) (Url.unpack "medium.html");
       
   298     in
   317     in
   299       session_info := SOME (make_session_info (name, parent_name, session_name, path, html_prefix,
   318       session_info := SOME (make_session_info (name, parent_name, session_name, path, html_prefix,
   300       info, doc, doc_graph, doc_prefix1, doc_prefix2, remote_path, verbose, readme));
   319       info, doc, doc_graph, documents, doc_prefix1, doc_prefix2, remote_path, verbose, readme));
   301       browser_info := init_browser_info remote_path path;
   320       browser_info := init_browser_info remote_path path;
   302       add_html_index index_text
   321       add_html_index index_text
   303     end;
   322     end;
   304 
   323 
   305 
   324 
       
   325 (* isatool wrappers *)
       
   326 
       
   327 fun isatool_document verbose format name tags path result_path =
       
   328   let
       
   329     val s = "\"$ISATOOL\" document -c -o '" ^ format ^ "' \
       
   330       \-n '" ^ name ^ "' -t '" ^ tags ^ "' " ^ File.shell_path path ^
       
   331       " 2>&1" ^ (if verbose then "" else " >/dev/null");
       
   332     val doc_path = Path.append result_path (Path.ext format (Path.basic name));
       
   333   in
       
   334     conditional verbose (fn () => writeln s);
       
   335     system s;
       
   336     conditional (not (File.exists doc_path)) (fn () =>
       
   337       error ("No document: " ^ quote (show_path doc_path)));
       
   338     doc_path
       
   339   end;
       
   340 
       
   341 fun isatool_browser graph =
       
   342   let
       
   343     val pdf_path = File.tmp_path graph_pdf_path;
       
   344     val eps_path = File.tmp_path graph_eps_path;
       
   345     val gr_path = File.tmp_path graph_path;
       
   346     val s = "browser -o " ^ File.shell_path pdf_path ^ " " ^ File.shell_path gr_path;
       
   347   in
       
   348     write_graph graph gr_path;
       
   349     if File.isatool s <> 0 orelse not (File.exists eps_path) orelse not (File.exists pdf_path)
       
   350     then error "Failed to prepare dependency graph"
       
   351     else
       
   352       let val pdf = File.read pdf_path and eps = File.read eps_path
       
   353       in File.rm pdf_path; File.rm eps_path; File.rm gr_path; (pdf, eps) end
       
   354   end;
       
   355 
       
   356 
   306 (* finish session -- output all generated text *)
   357 (* finish session -- output all generated text *)
   307 
   358 
   308 fun write_tex src name path =
   359 fun write_tex src name path =
   309   Buffer.write (Path.append path (tex_path name)) src;
   360   Buffer.write (Path.append path (tex_path name)) src;
   310 
   361 
   311 fun write_tex_index tex_index path =
   362 fun write_tex_index tex_index path =
   312   write_tex (Buffer.add Latex.tex_trailer tex_index) doc_indexN path;
   363   write_tex (Buffer.add Latex.tex_trailer tex_index) doc_indexN path;
   313 
   364 
   314 
   365 
   315 fun isatool_document verbose doc_format path =
       
   316   let
       
   317     val s = "\"$ISATOOL\" document -c -o '" ^ doc_format ^ "' " ^
       
   318       File.shell_path path ^ " 2>&1" ^ (if verbose then "" else " >/dev/null");
       
   319     val doc_path = Path.ext doc_format path;
       
   320   in
       
   321     if verbose then writeln s else ();
       
   322     system s;
       
   323     if File.exists doc_path then ()
       
   324     else error ("No document: " ^ quote (Path.pack (Path.expand doc_path)))
       
   325   end;
       
   326 
       
   327 fun isatool_browser graph =
       
   328   let
       
   329     val pdfpath = File.tmp_path graph_pdf_path;
       
   330     val epspath = File.tmp_path graph_eps_path;
       
   331     val gpath = File.tmp_path graph_path;
       
   332     val s = "browser -o " ^ File.shell_path pdfpath ^ " " ^ File.shell_path gpath;
       
   333   in
       
   334     write_graph graph gpath;
       
   335     if File.isatool s <> 0 orelse not (File.exists epspath) orelse not (File.exists pdfpath)
       
   336     then error "Failed to prepare dependency graph"
       
   337     else
       
   338       let val pdf = File.read pdfpath and eps = File.read epspath
       
   339       in File.rm pdfpath; File.rm epspath; File.rm gpath; (pdf, eps) end
       
   340   end;
       
   341 
       
   342 fun finish () = with_session () (fn {name, info, html_prefix, doc_format, doc_graph,
   366 fun finish () = with_session () (fn {name, info, html_prefix, doc_format, doc_graph,
   343     doc_prefix1, doc_prefix2, path, verbose, readme, ...} =>
   367     documents, doc_prefix1, doc_prefix2, path, verbose, readme, ...} =>
   344   let
   368   let
   345     val {theories, files, tex_index, html_index, graph} = ! browser_info;
   369     val {theories, files, tex_index, html_index, graph} = ! browser_info;
   346     val thys = Symtab.dest theories;
   370     val thys = Symtab.dest theories;
   347     val parent_html_prefix = Path.append html_prefix Path.parent;
   371     val parent_html_prefix = Path.append html_prefix Path.parent;
   348 
   372 
   355         SOME (isatool_browser graph)
   379         SOME (isatool_browser graph)
   356       else NONE;
   380       else NONE;
   357 
   381 
   358     fun prepare_sources path =
   382     fun prepare_sources path =
   359      (File.mkdir path;
   383      (File.mkdir path;
   360       File.copy_dir doc_path path;
   384       File.copy_dir document_path path;
   361       File.copy (Path.unpack "~~/lib/texinputs/isabelle.sty") path;
   385       File.copy (Path.unpack "~~/lib/texinputs/isabelle.sty") path;
   362       File.copy (Path.unpack "~~/lib/texinputs/isabellesym.sty") path;
   386       File.copy (Path.unpack "~~/lib/texinputs/isabellesym.sty") path;
   363       File.copy (Path.unpack "~~/lib/texinputs/pdfsetup.sty") path;
   387       File.copy (Path.unpack "~~/lib/texinputs/pdfsetup.sty") path;
   364       (case opt_graphs of NONE => () | SOME (pdf, eps) =>
   388       (case opt_graphs of NONE => () | SOME (pdf, eps) =>
   365         (File.write (Path.append path graph_pdf_path) pdf;
   389         (File.write (Path.append path graph_pdf_path) pdf;
   386 
   410 
   387     (case doc_prefix2 of NONE => () | SOME path =>
   411     (case doc_prefix2 of NONE => () | SOME path =>
   388      (prepare_sources path;
   412      (prepare_sources path;
   389       conditional verbose (fn () => std_error ("Document sources at " ^ show_path path ^ "\n"))));
   413       conditional verbose (fn () => std_error ("Document sources at " ^ show_path path ^ "\n"))));
   390 
   414 
   391     (case doc_prefix1 of NONE => () | SOME path =>
   415     (case doc_prefix1 of NONE => () | SOME (path, result_path) =>
   392      (prepare_sources path;
   416       documents |> List.app (fn (name, tags) =>
   393       isatool_document true doc_format path;
   417        let
   394       conditional verbose (fn () =>
   418          val _ = prepare_sources path;
   395         std_error ("Document at " ^ show_path (Path.ext doc_format path) ^ "\n"))));
   419          val doc_path = isatool_document true doc_format name tags path result_path;
       
   420        in
       
   421          conditional verbose (fn () => std_error ("Document at " ^ show_path doc_path ^ "\n"))
       
   422        end));
   396 
   423 
   397     browser_info := empty_browser_info;
   424     browser_info := empty_browser_info;
   398     session_info := NONE
   425     session_info := NONE
   399   end);
   426   end);
   400 
   427 
   498           (Buffer.add (Latex.theory_entry name) tex_index, (name, base, File.read path))
   525           (Buffer.add (Latex.theory_entry name) tex_index, (name, base, File.read path))
   499         else error ("Bad file: " ^ quote (Path.pack path))
   526         else error ("Bad file: " ^ quote (Path.pack path))
   500       end;
   527       end;
   501     val (tex_index, srcs) = foldl_map prep_draft (Buffer.empty, src_paths);
   528     val (tex_index, srcs) = foldl_map prep_draft (Buffer.empty, src_paths);
   502 
   529 
   503     val doc_path = File.tmp_path (Path.basic "document");
   530     val doc_path = File.tmp_path document_path;
       
   531     val result_path = Path.append doc_path Path.parent;
   504     val _ = File.mkdir doc_path;
   532     val _ = File.mkdir doc_path;
   505     val root_path = Path.append doc_path (Path.basic "root.tex");
   533     val root_path = Path.append doc_path (Path.basic "root.tex");
   506     val _ = File.copy (Path.unpack "~~/lib/texinputs/draft.tex") root_path;
   534     val _ = File.copy (Path.unpack "~~/lib/texinputs/draft.tex") root_path;
   507     val _ = File.isatool ("latex -o sty " ^ File.shell_path root_path);
   535     val _ = File.isatool ("latex -o sty " ^ File.shell_path root_path);
   508     val _ = File.isatool ("latex -o syms " ^ File.shell_path root_path);
   536     val _ = File.isatool ("latex -o syms " ^ File.shell_path root_path);
   516     val _ = srcs |> List.app (fn (name, base, txt) =>
   544     val _ = srcs |> List.app (fn (name, base, txt) =>
   517       Symbol.explode txt
   545       Symbol.explode txt
   518       |> Latex.symbol_source (known_syms, known_ctrls) (Path.pack base)
   546       |> Latex.symbol_source (known_syms, known_ctrls) (Path.pack base)
   519       |> File.write (Path.append doc_path (tex_path name)));
   547       |> File.write (Path.append doc_path (tex_path name)));
   520     val _ = write_tex_index tex_index doc_path;
   548     val _ = write_tex_index tex_index doc_path;
   521     val _ = isatool_document false doc_format doc_path;
   549   in isatool_document false doc_format documentN "" doc_path result_path end;
   522   in Path.ext doc_format doc_path end;
       
   523 
   550 
   524 
   551 
   525 end;
   552 end;
   526 
   553 
   527 structure BasicPresent: BASIC_PRESENT = Present;
   554 structure BasicPresent: BASIC_PRESENT = Present;