| author | wenzelm | 
| Tue, 23 Jan 2024 19:56:52 +0100 | |
| changeset 79521 | db2b5c04075d | 
| parent 79502 | c7a98469c0e7 | 
| child 81555 | 4eba973e8a7b | 
| permissions | -rw-r--r-- | 
| 79502 | 1 | /* Title: Pure/Build/browser_info.scala | 
| 50707 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 3 | |
| 75949 
b09dab301d72
tuned comments, following "isabelle build" usage;
 wenzelm parents: 
75947diff
changeset | 4 | HTML/PDF presentation of PIDE document information. | 
| 50707 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 6 | |
| 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 8 | |
| 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 9 | |
| 74677 | 10 | import scala.annotation.tailrec | 
| 51402 | 11 | import scala.collection.immutable.SortedMap | 
| 74677 | 12 | import scala.collection.mutable | 
| 51402 | 13 | |
| 14 | ||
| 75941 | 15 | object Browser_Info {
 | 
| 75945 | 16 | /* browser_info store configuration */ | 
| 75943 | 17 | |
| 18 |   object Config {
 | |
| 19 |     val none: Config = new Config { def enabled: Boolean = false }
 | |
| 20 |     val standard: Config = new Config { def enabled: Boolean = true }
 | |
| 21 | ||
| 22 | def dir(path: Path): Config = | |
| 23 |       new Config {
 | |
| 24 | def enabled: Boolean = true | |
| 78178 | 25 | override def presentation_dir(store: Store): Path = path | 
| 75943 | 26 | } | 
| 72957 | 27 | |
| 75943 | 28 | def make(s: String): Config = | 
| 29 | if (s == ":") standard else dir(Path.explode(s)) | |
| 30 | } | |
| 31 | ||
| 32 |   abstract class Config private {
 | |
| 33 | def enabled: Boolean | |
| 34 | def enabled(info: Sessions.Info): Boolean = enabled || info.browser_info | |
| 78178 | 35 | def presentation_dir(store: Store): Path = store.presentation_dir | 
| 75943 | 36 | } | 
| 37 | ||
| 38 | ||
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 39 | /* meta info within the file-system */ | 
| 75961 | 40 | |
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 41 |   object Meta_Info {
 | 
| 75961 | 42 | /* directory */ | 
| 43 | ||
| 44 |     val PATH: Path = Path.explode(".browser_info")
 | |
| 45 | ||
| 46 |     def check_directory(dir: Path): Unit = {
 | |
| 47 |       if (dir.is_dir && !(dir + PATH).is_dir && File.read_dir(dir).nonEmpty) {
 | |
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 48 |         error("Existing content in " + dir.expand + " lacks " + PATH + " meta info.\n" +
 | 
| 75961 | 49 | "To avoid potential disaster, it has not been changed automatically.\n" + | 
| 50 | "If this is the intended directory, please move/remove/empty it manually.") | |
| 51 | } | |
| 52 | } | |
| 53 | ||
| 54 |     def init_directory(dir: Path): Path = {
 | |
| 55 | check_directory(dir) | |
| 56 | Isabelle_System.make_directory(dir + PATH) | |
| 57 | dir | |
| 58 | } | |
| 59 | ||
| 75982 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 60 |     def clean_directory(dir: Path): Path = {
 | 
| 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 61 | check_directory(dir) | 
| 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 62 | Isabelle_System.rm_tree(dir) // guarded by check_directory! | 
| 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 63 | Isabelle_System.new_directory(dir + PATH) | 
| 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 64 | } | 
| 
2fff9ce6b460
more aggressive clean_directory(session_dir), while rm_tree is guarded by check_directory, i.e. it is presumably "owned" by Browser_Info.build_session();
 wenzelm parents: 
75981diff
changeset | 65 | |
| 75961 | 66 | |
| 67 | /* content */ | |
| 68 | ||
| 69 | def make_path(dir: Path, name: String): Path = | |
| 70 | dir + PATH + Path.basic(name) | |
| 71 | ||
| 72 |     def value(dir: Path, name: String): String = {
 | |
| 73 | val path = make_path(dir, name) | |
| 74 | if (path.is_file) File.read(path) else "" | |
| 75 | } | |
| 76 | ||
| 77 |     def change(dir: Path, name: String)(f: String => String): Unit = {
 | |
| 78 | val path = make_path(dir, name) | |
| 79 | val x = value(dir, name) | |
| 80 | val y = | |
| 81 |         try { f(x) }
 | |
| 82 |         catch { case ERROR(msg) => error("Failed to change " + path.expand + ":\n" + msg)}
 | |
| 83 | if (x != y) File.write(path, y) | |
| 84 | } | |
| 85 | ||
| 86 | ||
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 87 | /* build_uuid */ | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 88 | |
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 89 | val BUILD_UUID = "build_uuid" | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 90 | |
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 91 |     def check_build_uuid(dir: Path, uuid: String): Boolean = {
 | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 92 | val uuid0 = value(dir, BUILD_UUID) | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 93 | uuid0.nonEmpty && uuid.nonEmpty && uuid0 == uuid | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 94 | } | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 95 | |
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 96 | def set_build_uuid(dir: Path, uuid: String): Unit = | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 97 | change(dir, BUILD_UUID)(_ => uuid) | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 98 | |
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 99 | |
| 75961 | 100 | /* index */ | 
| 101 | ||
| 102 | val INDEX = "index.json" | |
| 103 | ||
| 104 |     object Item {
 | |
| 105 |       def parse(json: JSON.T): Item = {
 | |
| 106 | def err(): Nothing = | |
| 107 |           error("Bad JSON object for item:\n" + JSON.Format.pretty_print(json))
 | |
| 108 | val obj = JSON.Object.unapply(json) getOrElse err() | |
| 109 | ||
| 110 | val name = JSON.string(obj, "name") getOrElse err() | |
| 111 | val description = JSON.string(obj, "description") getOrElse "" | |
| 112 | Item(name, description = Symbol.trim_blank_lines(description)) | |
| 113 | } | |
| 114 | } | |
| 115 | ||
| 116 |     sealed case class Item(name: String, description: String = "") {
 | |
| 75994 | 117 | override def toString: String = name | 
| 118 | ||
| 75961 | 119 |       def json: JSON.T = JSON.Object("name" -> name, "description" -> description)
 | 
| 120 | } | |
| 121 | ||
| 122 |     object Index {
 | |
| 123 |       def parse(s: JSON.S, kind: String): Index = {
 | |
| 124 | if (s.isEmpty) Index(kind, Nil) | |
| 125 |         else {
 | |
| 126 |           def err(): Nothing = error("Bad JSON object " + kind + " index:\n" + s)
 | |
| 127 | ||
| 128 | val json = JSON.parse(s) | |
| 129 | val obj = JSON.Object.unapply(json) getOrElse err() | |
| 130 | ||
| 131 | val kind1 = JSON.string(obj, "kind") getOrElse err() | |
| 132 | val items = JSON.list(obj, "items", x => Some(Item.parse(x))) getOrElse err() | |
| 133 | if (kind == kind1) Index(kind, items) | |
| 134 |           else error("Expected index kind " + quote(kind) + " but found " + quote(kind1))
 | |
| 135 | } | |
| 136 | } | |
| 137 | } | |
| 138 | ||
| 139 |     sealed case class Index(kind: String, items: List[Item]) {
 | |
| 75991 | 140 | def is_empty: Boolean = items.isEmpty | 
| 141 | ||
| 75999 
b831a0bdd751
clarified signature of Sessions.Session: chapter_defs: vs. known_chapters (in declaration order) vs. chapters (covered by visible sessions);
 wenzelm parents: 
75994diff
changeset | 142 | def + (item: Item): Index = | 
| 
b831a0bdd751
clarified signature of Sessions.Session: chapter_defs: vs. known_chapters (in declaration order) vs. chapters (covered by visible sessions);
 wenzelm parents: 
75994diff
changeset | 143 | Index(kind, (item :: items.filterNot(_.name == item.name)).sortBy(_.name)) | 
| 75961 | 144 | |
| 145 |       def json: JSON.T = JSON.Object("kind" -> kind, "items" -> items.map(_.json))
 | |
| 146 | def print_json: JSON.S = JSON.Format.pretty_print(json) | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | ||
| 75945 | 151 | /* presentation elements */ | 
| 152 | ||
| 153 | sealed case class Elements( | |
| 154 | html: Markup.Elements = Markup.Elements.empty, | |
| 155 | entity: Markup.Elements = Markup.Elements.empty, | |
| 156 | language: Markup.Elements = Markup.Elements.empty) | |
| 157 | ||
| 75979 | 158 | val default_elements: Elements = | 
| 75945 | 159 | Elements( | 
| 160 | html = Rendering.foreground_elements ++ Rendering.text_color_elements + | |
| 76009 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 161 | Markup.NUMERAL + Markup.COMMENT + Markup.ENTITY + Markup.LANGUAGE + | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 162 | Markup.PATH + Markup.URL, | 
| 75945 | 163 | entity = Markup.Elements(Markup.THEORY, Markup.TYPE_NAME, Markup.CONSTANT, Markup.FACT, | 
| 164 | Markup.CLASS, Markup.LOCALE, Markup.FREE)) | |
| 165 | ||
| 75979 | 166 | val extra_elements: Elements = | 
| 75945 | 167 | Elements( | 
| 75979 | 168 | html = default_elements.html ++ Rendering.markdown_elements, | 
| 75945 | 169 | language = Markup.Elements(Markup.Language.DOCUMENT)) | 
| 170 | ||
| 171 | ||
| 75943 | 172 | |
| 75949 
b09dab301d72
tuned comments, following "isabelle build" usage;
 wenzelm parents: 
75947diff
changeset | 173 | /** HTML/PDF presentation context **/ | 
| 73718 | 174 | |
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 175 | def context( | 
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 176 | sessions_structure: Sessions.Structure, | 
| 75979 | 177 | elements: Elements = default_elements, | 
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 178 | root_dir: Path = Path.current, | 
| 75907 | 179 | document_info: Document_Info = Document_Info.empty | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 180 | ): Context = new Context(sessions_structure, elements, root_dir, document_info) | 
| 72957 | 181 | |
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 182 | class Context private[Browser_Info]( | 
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 183 | sessions_structure: Sessions.Structure, | 
| 75897 | 184 | val elements: Elements, | 
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 185 | val root_dir: Path, | 
| 75907 | 186 | val document_info: Document_Info | 
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 187 |   ) {
 | 
| 74818 
3064e165c660
clarified HTML_Context.theory_exports: prefer value-oriented parallelism;
 wenzelm parents: 
74816diff
changeset | 188 | /* directory structure and resources */ | 
| 74770 
32c2587cda4f
clarified HTML_Context: more explicit directory structure;
 wenzelm parents: 
74769diff
changeset | 189 | |
| 75907 | 190 | def theory_by_name(session: String, theory: String): Option[Document_Info.Theory] = | 
| 191 | document_info.theory_by_name(session, theory) | |
| 75894 | 192 | |
| 75907 | 193 | def theory_by_file(session: String, file: String): Option[Document_Info.Theory] = | 
| 194 | document_info.theory_by_file(session, file) | |
| 75897 | 195 | |
| 75980 | 196 | def session_chapter(session: String): String = | 
| 197 | sessions_structure(session).chapter | |
| 198 | ||
| 75981 | 199 | def chapter_dir(session: String): Path = | 
| 200 | root_dir + Path.basic(session_chapter(session)) | |
| 74770 
32c2587cda4f
clarified HTML_Context: more explicit directory structure;
 wenzelm parents: 
74769diff
changeset | 201 | |
| 75981 | 202 | def session_dir(session: String): Path = | 
| 203 | chapter_dir(session) + Path.basic(session) | |
| 75961 | 204 | |
| 75946 | 205 | def theory_dir(theory: Document_Info.Theory): Path = | 
| 206 | session_dir(theory.dynamic_session) | |
| 207 | ||
| 75907 | 208 | def theory_html(theory: Document_Info.Theory): Path = | 
| 75917 
20b918404aa3
evade clash with index.html (allow "Index.thy" even on case-insensitive file-systems);
 wenzelm parents: 
75916diff
changeset | 209 |     {
 | 
| 75926 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 210 |       def check(name: String): Option[Path] = {
 | 
| 75977 
59aa034220bf
more robust: ensure that chapter/session/theory do not contain special notation (like "/" or "..");
 wenzelm parents: 
75971diff
changeset | 211 | val path = Path.basic(name).html | 
| 75926 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 212 | if (Path.eq_case_insensitive(path, Path.index_html)) None | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 213 | else Some(path) | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 214 | } | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 215 | check(theory.print_short) orElse check(theory.name) getOrElse | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 216 |         error("Illegal global theory name " + quote(theory.name) +
 | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 217 | " (conflict with " + Path.index_html + ")") | 
| 75917 
20b918404aa3
evade clash with index.html (allow "Index.thy" even on case-insensitive file-systems);
 wenzelm parents: 
75916diff
changeset | 218 | } | 
| 75900 | 219 | |
| 75915 
95d7459e5bc0
clarified directory layout (again): mimic original directory layout, notably ISABELLE_HOME;
 wenzelm parents: 
75914diff
changeset | 220 | def file_html(file: String): Path = | 
| 
95d7459e5bc0
clarified directory layout (again): mimic original directory layout, notably ISABELLE_HOME;
 wenzelm parents: 
75914diff
changeset | 221 | Path.explode(file).squash.html | 
| 75900 | 222 | |
| 75914 
4da80799352f
more robust treatment of Document.Node.Name, following stored data;
 wenzelm parents: 
75913diff
changeset | 223 | def smart_html(theory: Document_Info.Theory, file: String): Path = | 
| 75915 
95d7459e5bc0
clarified directory layout (again): mimic original directory layout, notably ISABELLE_HOME;
 wenzelm parents: 
75914diff
changeset | 224 | if (File.is_thy(file)) theory_html(theory) else file_html(file) | 
| 74770 
32c2587cda4f
clarified HTML_Context: more explicit directory structure;
 wenzelm parents: 
74769diff
changeset | 225 | |
| 
32c2587cda4f
clarified HTML_Context: more explicit directory structure;
 wenzelm parents: 
74769diff
changeset | 226 | |
| 74769 | 227 | /* HTML content */ | 
| 228 | ||
| 72962 | 229 | def head(title: String, rest: XML.Body = Nil): XML.Tree = | 
| 230 |       HTML.div("head", HTML.chapter(title) :: rest)
 | |
| 231 | ||
| 232 |     def source(body: XML.Body): XML.Tree = HTML.pre("source", body)
 | |
| 233 | ||
| 75393 | 234 | def contents( | 
| 235 | heading: String, | |
| 236 | items: List[XML.Body], | |
| 237 | css_class: String = "contents" | |
| 238 |     ) : List[XML.Elem] = {
 | |
| 72962 | 239 | if (items.isEmpty) Nil | 
| 240 | else List(HTML.div(css_class, List(HTML.section(heading), HTML.itemize(items)))) | |
| 241 | } | |
| 242 | ||
| 75944 | 243 | |
| 244 | /* preview PIDE document */ | |
| 245 | ||
| 75969 | 246 | lazy val isabelle_css: String = File.read(HTML.isabelle_css) | 
| 74768 | 247 | |
| 75393 | 248 |     def html_document(title: String, body: XML.Body, fonts_css: String): HTML_Document = {
 | 
| 74709 | 249 | val content = | 
| 250 | HTML.output_document( | |
| 251 | List( | |
| 74768 | 252 | HTML.style(fonts_css + "\n\n" + isabelle_css), | 
| 74709 | 253 | HTML.title(title)), | 
| 254 | List(HTML.source(body)), css = "", structural = false) | |
| 255 | HTML_Document(title, content) | |
| 256 | } | |
| 75944 | 257 | |
| 258 | def preview_document( | |
| 259 | snapshot: Document.Snapshot, | |
| 260 | plain_text: Boolean = false, | |
| 261 | fonts_css: String = HTML.fonts_css() | |
| 262 |     ): HTML_Document = {
 | |
| 263 | require(!snapshot.is_outdated, "document snapshot outdated") | |
| 264 | ||
| 265 | val name = snapshot.node_name | |
| 266 |       if (plain_text) {
 | |
| 76829 
f2a8ba0b8c96
more robust: avoid detour via somewhat fragile Node.Name.path;
 wenzelm parents: 
76656diff
changeset | 267 | val title = "File " + Symbol.cartouche_decoded(name.file_name) | 
| 76933 | 268 | val body = HTML.text(snapshot.node.source) | 
| 75944 | 269 | html_document(title, body, fonts_css) | 
| 270 | } | |
| 271 |       else {
 | |
| 272 |         Resources.html_document(snapshot) getOrElse {
 | |
| 273 | val title = | |
| 274 | if (name.is_theory) "Theory " + quote(name.theory_base_name) | |
| 76829 
f2a8ba0b8c96
more robust: avoid detour via somewhat fragile Node.Name.path;
 wenzelm parents: 
76656diff
changeset | 275 | else "File " + Symbol.cartouche_decoded(name.file_name) | 
| 75944 | 276 | val xml = snapshot.xml_markup(elements = elements.html) | 
| 277 | val body = Node_Context.empty.make_html(elements, xml) | |
| 278 | html_document(title, body, fonts_css) | |
| 279 | } | |
| 280 | } | |
| 281 | } | |
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 282 | |
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 283 | |
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 284 | /* maintain presentation structure */ | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 285 | |
| 75980 | 286 |     def update_chapter(session_name: String, session_description: String): Unit = synchronized {
 | 
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 287 | val dir = Meta_Info.init_directory(chapter_dir(session_name)) | 
| 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 288 |       Meta_Info.change(dir, Meta_Info.INDEX) { text =>
 | 
| 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 289 | val index0 = Meta_Info.Index.parse(text, "chapter") | 
| 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 290 | val item = Meta_Info.Item(session_name, description = session_description) | 
| 75961 | 291 | val index = index0 + item | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 292 | |
| 75961 | 293 |         if (index != index0) {
 | 
| 75981 | 294 | val title = "Isabelle/" + session_chapter(session_name) + " sessions" | 
| 75961 | 295 | HTML.write_document(dir, "index.html", | 
| 296 | List(HTML.title(title + Isabelle_System.isabelle_heading())), | |
| 297 | HTML.chapter(title) :: | |
| 75991 | 298 | (if (index.is_empty) Nil | 
| 75961 | 299 | else | 
| 300 |                 List(HTML.div("sessions",
 | |
| 301 | List(HTML.description( | |
| 75991 | 302 | index.items.map(item => | 
| 303 | (List(HTML.link(item.name + "/index.html", HTML.text(item.name))), | |
| 304 | if (item.description.isEmpty) Nil | |
| 305 | else HTML.break ::: List(HTML.pre(HTML.text(item.description)))))))))), | |
| 75961 | 306 | root = Some(root_dir)) | 
| 307 | } | |
| 75953 
32c4f8766831
clarified synchronized operations: approximate file-system transactions;
 wenzelm parents: 
75952diff
changeset | 308 | |
| 75961 | 309 | index.print_json | 
| 310 | } | |
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 311 | } | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 312 | |
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 313 |     def update_root(): Unit = synchronized {
 | 
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 314 | Meta_Info.init_directory(root_dir) | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 315 | HTML.init_fonts(root_dir) | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 316 |       Isabelle_System.copy_file(Path.explode("~~/lib/logo/isabelle.gif"),
 | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 317 |         root_dir + Path.explode("isabelle.gif"))
 | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 318 | |
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 319 |       Meta_Info.change(root_dir, Meta_Info.INDEX) { text =>
 | 
| 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 320 | val index0 = Meta_Info.Index.parse(text, "root") | 
| 75989 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 321 |         val index = {
 | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 322 | val items1 = | 
| 75999 
b831a0bdd751
clarified signature of Sessions.Session: chapter_defs: vs. known_chapters (in declaration order) vs. chapters (covered by visible sessions);
 wenzelm parents: 
75994diff
changeset | 323 | sessions_structure.known_chapters | 
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 324 | .map(ch => Meta_Info.Item(ch.name, description = ch.description)) | 
| 75999 
b831a0bdd751
clarified signature of Sessions.Session: chapter_defs: vs. known_chapters (in declaration order) vs. chapters (covered by visible sessions);
 wenzelm parents: 
75994diff
changeset | 325 | val items2 = index0.items.filterNot(item => items1.exists(_.name == item.name)) | 
| 
b831a0bdd751
clarified signature of Sessions.Session: chapter_defs: vs. known_chapters (in declaration order) vs. chapters (covered by visible sessions);
 wenzelm parents: 
75994diff
changeset | 326 | index0.copy(items = items1 ::: items2) | 
| 75989 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 327 | } | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 328 | |
| 75989 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 329 |         if (index != index0) {
 | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 330 | val title = "The " + XML.text(Isabelle_System.isabelle_name()) + " Library" | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 331 | HTML.write_document(root_dir, "index.html", | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 332 | List(HTML.title(title + Isabelle_System.isabelle_heading())), | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 333 | HTML.chapter(title) :: | 
| 75991 | 334 | (if (index.is_empty) Nil | 
| 75989 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 335 | else | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 336 |                 List(HTML.div("sessions",
 | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 337 | List(HTML.description( | 
| 75991 | 338 | index.items.map(item => | 
| 339 | (List(HTML.link(item.name + "/index.html", HTML.text(item.name))), | |
| 340 | if (item.description.isEmpty) Nil | |
| 341 | else HTML.break ::: List(HTML.pre(HTML.text(item.description)))))))))), | |
| 75989 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 342 | root = Some(root_dir)) | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 343 | } | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 344 | |
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 345 | index.print_json | 
| 
46c6f649a943
produce root index based on sessions_structure.chapter_defs;
 wenzelm parents: 
75982diff
changeset | 346 | } | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 347 | } | 
| 72959 | 348 | } | 
| 349 | ||
| 75884 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 350 | sealed case class HTML_Document(title: String, content: String) | 
| 
3d8b37b1d798
clarified signature: avoid object-oriented HTML_Context;
 wenzelm parents: 
75792diff
changeset | 351 | |
| 72957 | 352 | |
| 74678 | 353 | /* formal entities */ | 
| 74677 | 354 | |
| 75891 | 355 |   object Theory_Ref {
 | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 356 | def unapply(props: Properties.T): Option[String] = | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 357 |       (props, props) match {
 | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 358 | case (Markup.Kind(Markup.THEORY), Markup.Name(theory)) => Some(theory) | 
| 75891 | 359 | case _ => None | 
| 360 | } | |
| 361 | } | |
| 74765 | 362 | |
| 75891 | 363 |   object Entity_Ref {
 | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 364 | def unapply(props: Properties.T): Option[(String, String, String)] = | 
| 75891 | 365 |       (props, props, props, props) match {
 | 
| 75913 | 366 | case (Markup.Entity.Ref.Prop(_), Position.Def_File(file), Markup.Kind(kind), Markup.Name(name)) | 
| 367 | if Path.is_wellformed(file) => Some((file, kind, name)) | |
| 75891 | 368 | case _ => None | 
| 369 | } | |
| 370 | } | |
| 74765 | 371 | |
| 75927 | 372 |   object Node_Context {
 | 
| 373 | val empty: Node_Context = new Node_Context | |
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 374 | |
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 375 | def make( | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 376 | context: Context, | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 377 | session_name: String, | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 378 | theory_name: String, | 
| 75929 
811092261546
proper node_dir within presentation_dir, not source file directory;
 wenzelm parents: 
75928diff
changeset | 379 | file_name: String, | 
| 
811092261546
proper node_dir within presentation_dir, not source file directory;
 wenzelm parents: 
75928diff
changeset | 380 | node_dir: Path, | 
| 75927 | 381 | ): Node_Context = | 
| 382 |       new Node_Context {
 | |
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 383 | private val seen_ranges: mutable.Set[Symbol.Range] = mutable.Set.empty | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 384 | |
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 385 | override def make_def(range: Symbol.Range, body: XML.Body): Option[XML.Elem] = | 
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 386 |           body match {
 | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 387 |             case List(XML.Elem(Markup("span", List("id" -> _)), _)) => None
 | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 388 | case _ => | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 389 | for (theory <- context.theory_by_name(session_name, theory_name)) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 390 |               yield {
 | 
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 391 | val body1 = | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 392 |                   if (seen_ranges.contains(range)) {
 | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 393 | HTML.entity_def(HTML.span(HTML.id(offset_id(range)), body)) | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 394 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 395 | else HTML.span(body) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 396 |                 theory.get_defs(file_name, range).foldLeft(body1) {
 | 
| 75896 | 397 | case (elem, entity) => | 
| 398 | HTML.entity_def(HTML.span(HTML.id(entity.kname), List(elem))) | |
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 399 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 400 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 401 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 402 | |
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 403 | private def offset_id(range: Text.Range): String = | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 404 | "offset_" + range.start + ".." + range.stop | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 405 | |
| 76009 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 406 |         override def make_file_ref(file: String, body: XML.Body): Option[XML.Elem] = {
 | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 407 | for (theory <- context.theory_by_file(session_name, file)) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 408 |           yield {
 | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 409 | val html_path = context.theory_dir(theory) + context.smart_html(theory, file) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 410 | val html_link = HTML.relative_href(html_path, base = Some(node_dir)) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 411 | HTML.link(html_link, body) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 412 | } | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 413 | } | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 414 | |
| 75393 | 415 |         override def make_ref(props: Properties.T, body: XML.Body): Option[XML.Elem] = {
 | 
| 74765 | 416 |           props match {
 | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 417 | case Theory_Ref(thy_name) => | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 418 | for (theory <- context.theory_by_name(session_name, thy_name)) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 419 |               yield {
 | 
| 75946 | 420 | val html_path = context.theory_dir(theory) + context.theory_html(theory) | 
| 75933 | 421 | val html_link = HTML.relative_href(html_path, base = Some(node_dir)) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 422 | HTML.link(html_link, body) | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 423 | } | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 424 | case Entity_Ref(def_file, kind, name) => | 
| 75907 | 425 | def logical_ref(theory: Document_Info.Theory): Option[String] = | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 426 | theory.get_def(def_file, kind, name).map(_.kname) | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 427 | |
| 75907 | 428 | def physical_ref(theory: Document_Info.Theory): Option[String] = | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 429 |                 props match {
 | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 430 | case Position.Def_Range(range) if theory.name == theory_name => | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 431 | seen_ranges += range | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 432 | Some(offset_id(range)) | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 433 | case _ => None | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 434 | } | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 435 | |
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 436 |               for {
 | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 437 | theory <- context.theory_by_file(session_name, def_file) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 438 | html_ref <- logical_ref(theory) orElse physical_ref(theory) | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 439 | } | 
| 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 440 |               yield {
 | 
| 75946 | 441 | val html_path = context.theory_dir(theory) + context.smart_html(theory, def_file) | 
| 75933 | 442 | val html_link = HTML.relative_href(html_path, base = Some(node_dir)) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 443 | HTML.entity_ref(HTML.link(html_link + "#" + html_ref, body)) | 
| 74752 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 444 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 445 | case _ => None | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 446 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 447 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 448 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 449 | } | 
| 
ebd3a685bfc9
clarified signature: more explicit class Entity_Context with private state + operations;
 wenzelm parents: 
74751diff
changeset | 450 | |
| 75927 | 451 |   class Node_Context {
 | 
| 74753 | 452 | def make_def(range: Symbol.Range, body: XML.Body): Option[XML.Elem] = None | 
| 453 | def make_ref(props: Properties.T, body: XML.Body): Option[XML.Elem] = None | |
| 76009 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 454 | def make_file_ref(file: String, body: XML.Body): Option[XML.Elem] = None | 
| 73055 | 455 | |
| 75928 | 456 | val div_elements: Set[String] = | 
| 457 | Set(HTML.div.name, HTML.pre.name, HTML.par.name, HTML.list.name, HTML.`enum`.name, | |
| 458 | HTML.descr.name) | |
| 72957 | 459 | |
| 75928 | 460 |     def make_html(elements: Elements, xml: XML.Body): XML.Body = {
 | 
| 461 | def html_div(html: XML.Body): Boolean = | |
| 462 |         html exists {
 | |
| 463 | case XML.Elem(markup, body) => div_elements.contains(markup.name) || html_div(body) | |
| 464 | case XML.Text(_) => false | |
| 465 | } | |
| 466 | ||
| 467 | def html_class(c: String, html: XML.Body): XML.Body = | |
| 468 | if (c == "") html | |
| 469 | else if (html_div(html)) List(HTML.div(c, html)) | |
| 470 | else List(HTML.span(c, html)) | |
| 72957 | 471 | |
| 75928 | 472 | def html_body(xml_body: XML.Body, end_offset: Symbol.Offset): (XML.Body, Symbol.Offset) = | 
| 473 |         xml_body.foldRight((List.empty[XML.Tree], end_offset)) { case (tree, (res, end_offset1)) =>
 | |
| 474 | val (res1, offset) = html_body_single(tree, end_offset1) | |
| 475 | (res1 ++ res, offset) | |
| 476 | } | |
| 74677 | 477 | |
| 75928 | 478 | @tailrec | 
| 479 | def html_body_single(xml_tree: XML.Tree, end_offset: Symbol.Offset): (XML.Body, Symbol.Offset) = | |
| 480 |         xml_tree match {
 | |
| 481 | case XML.Wrapped_Elem(markup, _, body) => html_body_single(XML.Elem(markup, body), end_offset) | |
| 482 | case XML.Elem(Markup(Markup.ENTITY, props @ Markup.Kind(kind)), body) => | |
| 483 | val (body1, offset) = html_body(body, end_offset) | |
| 484 |             if (elements.entity(kind)) {
 | |
| 485 |               make_ref(props, body1) match {
 | |
| 486 | case Some(link) => (List(link), offset) | |
| 487 | case None => (body1, offset) | |
| 488 | } | |
| 73056 | 489 | } | 
| 75928 | 490 | else (body1, offset) | 
| 76009 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 491 | case XML.Elem(Markup.Path(file), body) => | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 492 | val (body1, offset) = html_body(body, end_offset) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 493 |             make_file_ref(file, body1) match {
 | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 494 | case Some(link) => (List(link), offset) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 495 | case None => (body1, offset) | 
| 
adf9c4d68581
more links, for files that formally belong to this session;
 wenzelm parents: 
76008diff
changeset | 496 | } | 
| 76008 | 497 | case XML.Elem(Markup.Url(href), body) => | 
| 498 | val (body1, offset) = html_body(body, end_offset) | |
| 499 | (List(HTML.link(href, body1)), offset) | |
| 75928 | 500 | case XML.Elem(Markup(Markup.LANGUAGE, Markup.Name(name)), body) => | 
| 501 | val (body1, offset) = html_body(body, end_offset) | |
| 502 | (html_class(if (elements.language(name)) name else "", body1), offset) | |
| 503 | case XML.Elem(Markup(Markup.MARKDOWN_PARAGRAPH, _), body) => | |
| 504 | val (body1, offset) = html_body(body, end_offset) | |
| 505 | (List(HTML.par(body1)), offset) | |
| 506 | case XML.Elem(Markup(Markup.MARKDOWN_ITEM, _), body) => | |
| 507 | val (body1, offset) = html_body(body, end_offset) | |
| 508 | (List(HTML.item(body1)), offset) | |
| 509 | case XML.Elem(Markup(Markup.Markdown_Bullet.name, _), text) => | |
| 510 | (Nil, end_offset - XML.symbol_length(text)) | |
| 511 | case XML.Elem(Markup.Markdown_List(kind), body) => | |
| 512 | val (body1, offset) = html_body(body, end_offset) | |
| 513 | if (kind == Markup.ENUMERATE) (List(HTML.`enum`(body1)), offset) | |
| 514 | else (List(HTML.list(body1)), offset) | |
| 515 | case XML.Elem(markup, body) => | |
| 516 | val name = markup.name | |
| 517 | val (body1, offset) = html_body(body, end_offset) | |
| 518 | val html = | |
| 519 |               markup.properties match {
 | |
| 520 | case Markup.Kind(kind) if kind == Markup.COMMAND || kind == Markup.KEYWORD => | |
| 521 | html_class(kind, body1) | |
| 522 | case _ => | |
| 523 | body1 | |
| 524 | } | |
| 525 |             Rendering.foreground.get(name) orElse Rendering.text_color.get(name) match {
 | |
| 526 | case Some(c) => (html_class(c.toString, html), offset) | |
| 527 | case None => (html_class(name, html), offset) | |
| 73054 | 528 | } | 
| 75928 | 529 | case XML.Text(text) => | 
| 530 | val offset = end_offset - Symbol.length(text) | |
| 531 | val body = HTML.text(Symbol.decode(text)) | |
| 532 |             make_def(Text.Range(offset, end_offset), body) match {
 | |
| 533 | case Some(body1) => (List(body1), offset) | |
| 534 | case None => (body, offset) | |
| 535 | } | |
| 536 | } | |
| 73054 | 537 | |
| 75928 | 538 | html_body(xml, XML.symbol_length(xml) + 1)._1 | 
| 539 | } | |
| 73054 | 540 | } | 
| 72957 | 541 | |
| 542 | ||
| 543 | ||
| 75945 | 544 | /** build presentation **/ | 
| 72649 | 545 | |
| 75888 | 546 |   val session_graph_path: Path = Path.explode("session_graph.pdf")
 | 
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 547 | |
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 548 | def build_session( | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 549 | context: Context, | 
| 75778 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 wenzelm parents: 
75774diff
changeset | 550 | session_context: Export.Session_Context, | 
| 72992 | 551 | progress: Progress = new Progress, | 
| 75393 | 552 |   ): Unit = {
 | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 553 | progress.expose_interrupt() | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 554 | |
| 75902 | 555 | val session_name = session_context.session_name | 
| 556 | val session_info = session_context.sessions_structure(session_name) | |
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 557 | |
| 75961 | 558 | val session_dir = context.session_dir(session_name).expand | 
| 559 |     progress.echo("Presenting " + session_name + " in " + session_dir + " ...")
 | |
| 75899 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 560 | |
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 561 | Meta_Info.init_directory(context.chapter_dir(session_name)) | 
| 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 562 | Meta_Info.clean_directory(session_dir) | 
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 563 | |
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 564 | val session = context.document_info.the_session(session_name) | 
| 75905 
2ee3ea69e8f1
clarified Presentation.Nodes, with explicit Nodes.Session and Nodes.Theory;
 wenzelm parents: 
75902diff
changeset | 565 | |
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 566 | Bytes.write(session_dir + session_graph_path, | 
| 75902 | 567 | graphview.Graph_File.make_pdf(session_info.options, | 
| 568 | session_context.session_base.session_graph_display)) | |
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 569 | |
| 75925 | 570 | val document_variants = | 
| 72683 | 571 |       for {
 | 
| 75902 | 572 | doc <- session_info.document_variants | 
| 75780 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 wenzelm parents: 
75778diff
changeset | 573 | db <- session_context.session_db() | 
| 75902 | 574 | document <- Document_Build.read_document(db, session_name, doc.name) | 
| 75899 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 575 | } | 
| 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 576 |       yield {
 | 
| 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 577 | val doc_path = session_dir + doc.path.pdf | 
| 75926 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 578 |         if (Path.eq_case_insensitive(doc.path.pdf, session_graph_path)) {
 | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 579 |           error("Illegal document variant " + quote(doc.name) +
 | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 580 | " (conflict with " + session_graph_path + ")") | 
| 
b8ee1ef948c2
more thorough checks of browser_info file conflicts;
 wenzelm parents: 
75925diff
changeset | 581 | } | 
| 77521 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77202diff
changeset | 582 |         progress.echo("Presenting document " + session_name + "/" + doc.name, verbose = true)
 | 
| 75902 | 583 |         if (session_info.document_echo) progress.echo("Document at " + doc_path)
 | 
| 74732 
015282fb3e31
clarified messages, depending on option "document_echo";
 wenzelm parents: 
74731diff
changeset | 584 | Bytes.write(doc_path, document.pdf) | 
| 73022 
38528017e4c8
more verbosity for potentially bulky presentation;
 wenzelm parents: 
72992diff
changeset | 585 | doc | 
| 
38528017e4c8
more verbosity for potentially bulky presentation;
 wenzelm parents: 
72992diff
changeset | 586 | } | 
| 72673 
8ff7a0e394f9
clarified PDF/HTML presentation, based on pdf blobs from session database (e.g. from earlier builds);
 wenzelm parents: 
72670diff
changeset | 587 | |
| 75925 | 588 |     val document_links = {
 | 
| 589 |       val link1 = HTML.link(session_graph_path, HTML.text("theory dependencies"))
 | |
| 590 | val links2 = document_variants.map(doc => HTML.link(doc.path.pdf, HTML.text(doc.name))) | |
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 591 | Library.separate(HTML.break ::: HTML.nl, | 
| 75925 | 592 |         (link1 :: links2).map(link => HTML.text("View ") ::: List(link))).flatten
 | 
| 72622 
830222403681
HTML presentation in Isabelle/Scala, based on theory html exports from Isabelle/ML;
 wenzelm parents: 
72600diff
changeset | 593 | } | 
| 62971 
087e36ce0593
back to exact copy of non-text file (amending dcc8e1d34b18);
 wenzelm parents: 
62631diff
changeset | 594 | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 595 |     def present_theory(theory_name: String): XML.Body = {
 | 
| 74795 
5eac4b13d1f1
less ambitious parallelism: more direct read/write saves overall heap space and GC time;
 wenzelm parents: 
74782diff
changeset | 596 | progress.expose_interrupt() | 
| 73215 | 597 | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 598 | def err(): Nothing = | 
| 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 599 |         error("Missing document information for theory: " + quote(theory_name))
 | 
| 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 600 | |
| 78280 | 601 | val snapshot = Build.read_theory(session_context.theory(theory_name)) getOrElse err() | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 602 | val theory = context.theory_by_name(session_name, theory_name) getOrElse err() | 
| 74795 
5eac4b13d1f1
less ambitious parallelism: more direct read/write saves overall heap space and GC time;
 wenzelm parents: 
74782diff
changeset | 603 | |
| 77521 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77202diff
changeset | 604 |       progress.echo("Presenting theory " + quote(theory_name), verbose = true)
 | 
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 605 | |
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 606 | val thy_elements = theory.elements(context.elements) | 
| 73215 | 607 | |
| 75929 
811092261546
proper node_dir within presentation_dir, not source file directory;
 wenzelm parents: 
75928diff
changeset | 608 | def node_context(file_name: String, node_dir: Path): Node_Context = | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 609 | Node_Context.make(context, session_name, theory_name, file_name, node_dir) | 
| 75928 | 610 | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 611 | val thy_html = | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 612 | context.source( | 
| 75929 
811092261546
proper node_dir within presentation_dir, not source file directory;
 wenzelm parents: 
75928diff
changeset | 613 | node_context(theory.thy_file, session_dir). | 
| 75928 | 614 | make_html(thy_elements, snapshot.xml_markup(elements = thy_elements.html))) | 
| 75899 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 615 | |
| 76937 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 616 | val master_dir = Path.explode(snapshot.node_name.master_dir) | 
| 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 617 | |
| 75931 | 618 | val files = | 
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 619 |         for {
 | 
| 76930 | 620 | blob_name <- snapshot.node_files.tail | 
| 621 | xml = snapshot.switch(blob_name).xml_markup(elements = thy_elements.html) | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 622 | if xml.nonEmpty | 
| 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 623 | } | 
| 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 624 |         yield {
 | 
| 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 625 | progress.expose_interrupt() | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 626 | |
| 76937 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 627 | val file = blob_name.node | 
| 77521 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77202diff
changeset | 628 |           progress.echo("Presenting file " + quote(file), verbose = true)
 | 
| 74715 
129fb11b357f
use all entity kinds from theory export, e.g. "method", "attribute";
 wenzelm parents: 
74714diff
changeset | 629 | |
| 76937 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 630 | val file_html = session_dir + context.file_html(file) | 
| 75932 | 631 | val file_dir = file_html.dir | 
| 75933 | 632 | val html_link = HTML.relative_href(file_html, base = Some(session_dir)) | 
| 76937 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 633 | val html = context.source(node_context(file, file_dir).make_html(thy_elements, xml)) | 
| 75931 | 634 | |
| 76937 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 635 | val path = Path.explode(file) | 
| 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 636 | val src_path = File.relative_path(master_dir, path).getOrElse(path) | 
| 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 637 | |
| 
099486b09c0e
prefer relative src_path (if possible) -- in contrast to 9ce0aa145d21:
 wenzelm parents: 
76933diff
changeset | 638 | val file_title = "File " + Symbol.cartouche_decoded(src_path.implode_short) | 
| 75932 | 639 | HTML.write_document(file_dir, file_html.file_name, | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 640 | List(HTML.title(file_title)), List(context.head(file_title), html), | 
| 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 641 | root = Some(context.root_dir)) | 
| 75931 | 642 | List(HTML.link(html_link, HTML.text(file_title))) | 
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 643 | } | 
| 73215 | 644 | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 645 | val thy_title = "Theory " + theory.print_short | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 646 | HTML.write_document(session_dir, context.theory_html(theory).implode, | 
| 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 647 | List(HTML.title(thy_title)), List(context.head(thy_title), thy_html), | 
| 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 648 | root = Some(context.root_dir)) | 
| 73215 | 649 | |
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 650 | List(HTML.link(context.theory_html(theory), | 
| 75925 | 651 | HTML.text(theory.print_short) ::: | 
| 652 | (if (files.isEmpty) Nil else List(HTML.itemize(files))))) | |
| 72989 | 653 | } | 
| 61500 | 654 | |
| 75924 
1402a1696dca
prefer strict operations with explicit errors (instead of missing HTML output);
 wenzelm parents: 
75917diff
changeset | 655 | val theories = session.used_theories.map(present_theory) | 
| 74795 
5eac4b13d1f1
less ambitious parallelism: more direct read/write saves overall heap space and GC time;
 wenzelm parents: 
74782diff
changeset | 656 | |
| 75902 | 657 | val title = "Session " + session_name | 
| 75899 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 658 | HTML.write_document(session_dir, "index.html", | 
| 
d50c2129e73a
more robust directory structure: always relative to session_dir;
 wenzelm parents: 
75898diff
changeset | 659 | List(HTML.title(title + Isabelle_System.isabelle_heading())), | 
| 75942 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 660 | context.head(title, List(HTML.par(document_links))) :: | 
| 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 661 |           context.contents("Theories", theories),
 | 
| 
603852abed8f
clarified names: Browser_Info.Config vs. Browser_Info.Context;
 wenzelm parents: 
75941diff
changeset | 662 | root = Some(context.root_dir)) | 
| 75961 | 663 | |
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 664 | Meta_Info.set_build_uuid(session_dir, session.build_uuid) | 
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 665 | |
| 75980 | 666 | context.update_chapter(session_name, session_info.description) | 
| 61372 | 667 | } | 
| 75947 | 668 | |
| 669 | def build( | |
| 670 | browser_info: Config, | |
| 78178 | 671 | store: Store, | 
| 75947 | 672 | deps: Sessions.Deps, | 
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 673 | sessions: List[String], | 
| 78379 | 674 | progress: Progress = new Progress, | 
| 675 | server: SSH.Server = SSH.no_server | |
| 75947 | 676 |   ): Unit = {
 | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 677 | val root_dir = browser_info.presentation_dir(store).absolute | 
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 678 |     progress.echo("Presentation in " + root_dir)
 | 
| 75947 | 679 | |
| 78379 | 680 |     using(Export.open_database_context(store, server = server)) { database_context =>
 | 
| 75979 | 681 | val context0 = context(deps.sessions_structure, root_dir = root_dir) | 
| 75947 | 682 | |
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 683 | val sessions1 = | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 684 |         deps.sessions_structure.build_requirements(sessions).filter { session_name =>
 | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 685 |           using(database_context.open_database(session_name)) { session_database =>
 | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 686 |             database_context.store.read_build(session_database.db, session_name) match {
 | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 687 | case None => false | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 688 | case Some(build) => | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 689 | val session_dir = context0.session_dir(session_name) | 
| 77202 
064566bc1f35
clarified signature: follow terminology of isabelle.Sessions and isabelle.Build;
 wenzelm parents: 
76937diff
changeset | 690 | !Meta_Info.check_build_uuid(session_dir, build.uuid) | 
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 691 | } | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 692 | } | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 693 | } | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 694 | |
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 695 | val context1 = | 
| 75979 | 696 | context(deps.sessions_structure, root_dir = root_dir, | 
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 697 | document_info = Document_Info.read(database_context, deps, sessions1)) | 
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 698 | |
| 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 699 | context1.update_root() | 
| 75952 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 700 | |
| 
864b10457a7d
more robust concurrency: use shared Browser_Info.Context with synchronized file-system operations;
 wenzelm parents: 
75949diff
changeset | 701 |       Par_List.map({ (session: String) =>
 | 
| 76656 | 702 |         using(database_context.open_session(deps.background(session))) { session_context =>
 | 
| 77521 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77202diff
changeset | 703 | build_session(context1, session_context, progress = progress) | 
| 75947 | 704 | } | 
| 75971 
cec22f403c25
more accurate management of dependencies: change of build_uuid causes output of HTML, but already existing/current HTML is not produced again;
 wenzelm parents: 
75969diff
changeset | 705 | }, sessions1) | 
| 75947 | 706 | } | 
| 707 | } | |
| 50707 
5b2bf7611662
maintain session index on Scala side, for more determistic results;
 wenzelm parents: diff
changeset | 708 | } |