|
1 /* Title: Pure/Build/file_format.scala |
|
2 Author: Makarius |
|
3 |
|
4 Support for user-defined file formats, associated with active session. |
|
5 */ |
|
6 |
|
7 package isabelle |
|
8 |
|
9 |
|
10 object File_Format { |
|
11 object No_Data extends AnyRef { |
|
12 override def toString: String = "File_Format.No_Data" |
|
13 } |
|
14 |
|
15 sealed case class Theory_Context(name: Document.Node.Name, content: String) |
|
16 |
|
17 |
|
18 /* registry */ |
|
19 |
|
20 lazy val registry: Registry = |
|
21 new Registry(Isabelle_System.make_services(classOf[File_Format])) |
|
22 |
|
23 final class Registry private [File_Format](file_formats: List[File_Format]) { |
|
24 override def toString: String = file_formats.mkString("File_Format.Environment(", ",", ")") |
|
25 |
|
26 def get(name: String): Option[File_Format] = file_formats.find(_.detect(name)) |
|
27 def get(name: Document.Node.Name): Option[File_Format] = get(name.node) |
|
28 def get_theory(name: Document.Node.Name): Option[File_Format] = get(name.theory) |
|
29 def is_theory(name: Document.Node.Name): Boolean = get_theory(name).isDefined |
|
30 |
|
31 def theory_excluded(name: String): Boolean = file_formats.exists(_.theory_excluded(name)) |
|
32 |
|
33 def parse_data(name: String, text: String): AnyRef = |
|
34 get(name) match { |
|
35 case Some(file_format) => file_format.parse_data(name, text) |
|
36 case None => No_Data |
|
37 } |
|
38 def parse_data(name: Document.Node.Name, text: String): AnyRef = parse_data(name.node, text) |
|
39 |
|
40 def start_session(session: isabelle.Session): Session = |
|
41 new Session(file_formats.map(_.start(session)).filterNot(_ == No_Agent)) |
|
42 } |
|
43 |
|
44 |
|
45 /* session */ |
|
46 |
|
47 final class Session private[File_Format](agents: List[Agent]) { |
|
48 override def toString: String = |
|
49 agents.mkString("File_Format.Session(", ", ", ")") |
|
50 |
|
51 def prover_options(options: Options): Options = |
|
52 agents.foldLeft(options) { case (opts, agent) => agent.prover_options(opts) } |
|
53 |
|
54 def stop_session(): Unit = agents.foreach(_.stop()) |
|
55 } |
|
56 |
|
57 trait Agent { |
|
58 def prover_options(options: Options): Options = options |
|
59 def stop(): Unit = {} |
|
60 } |
|
61 |
|
62 object No_Agent extends Agent |
|
63 } |
|
64 |
|
65 abstract class File_Format extends Isabelle_System.Service { |
|
66 def format_name: String |
|
67 override def toString: String = "File_Format(" + format_name + ")" |
|
68 |
|
69 def file_ext: String |
|
70 def detect(name: String): Boolean = name.endsWith("." + file_ext) |
|
71 |
|
72 def parse_data(name: String, text: String): AnyRef = File_Format.No_Data |
|
73 |
|
74 |
|
75 /* implicit theory context: name and content */ |
|
76 |
|
77 def theory_suffix: String = "" |
|
78 def theory_content(name: String): String = "" |
|
79 def theory_excluded(name: String): Boolean = false |
|
80 |
|
81 def make_theory_name( |
|
82 resources: Resources, |
|
83 name: Document.Node.Name |
|
84 ): Option[Document.Node.Name] = { |
|
85 for { |
|
86 theory <- Url.get_base_name(name.node) |
|
87 if detect(name.node) && theory_suffix.nonEmpty |
|
88 } |
|
89 yield { |
|
90 val node = resources.append_path(name.node, Path.explode(theory_suffix)) |
|
91 Document.Node.Name(node, theory = theory) |
|
92 } |
|
93 } |
|
94 |
|
95 def make_theory_content(resources: Resources, thy_name: Document.Node.Name): Option[String] = { |
|
96 for { |
|
97 prefix <- Url.strip_base_name(thy_name.node) |
|
98 suffix <- Url.get_base_name(thy_name.node) |
|
99 if detect(prefix) && suffix == theory_suffix |
|
100 thy <- Url.get_base_name(prefix) |
|
101 s <- proper_string(theory_content(thy)) |
|
102 } yield s |
|
103 } |
|
104 |
|
105 def html_document(snapshot: Document.Snapshot): Option[Browser_Info.HTML_Document] = None |
|
106 |
|
107 |
|
108 /* PIDE session agent */ |
|
109 |
|
110 def start(session: isabelle.Session): File_Format.Agent = File_Format.No_Agent |
|
111 } |