|
1 /* Title: Pure/PIDE/resources.scala |
|
2 Author: Makarius |
|
3 |
|
4 Resources for theories and auxiliary files. |
|
5 */ |
|
6 |
|
7 package isabelle |
|
8 |
|
9 |
|
10 import scala.annotation.tailrec |
|
11 |
|
12 import java.io.{File => JFile} |
|
13 |
|
14 |
|
15 object Resources |
|
16 { |
|
17 /* paths */ |
|
18 |
|
19 def thy_path(path: Path): Path = path.ext("thy") |
|
20 |
|
21 def is_wellformed_thy_path(str: String): Boolean = |
|
22 try { thy_path(Path.explode(str)); true } |
|
23 catch { case ERROR(_) => false } |
|
24 } |
|
25 |
|
26 |
|
27 class Resources(val loaded_theories: Set[String] = Set.empty, val base_syntax: Outer_Syntax) |
|
28 { |
|
29 /* document node names */ |
|
30 |
|
31 def node_name(raw_path: Path): Document.Node.Name = |
|
32 { |
|
33 val path = raw_path.expand |
|
34 val node = path.implode |
|
35 val theory = Thy_Header.thy_name(node).getOrElse("") |
|
36 val master_dir = if (theory == "") "" else path.dir.implode |
|
37 Document.Node.Name(node, master_dir, theory) |
|
38 } |
|
39 |
|
40 |
|
41 /* file-system operations */ |
|
42 |
|
43 def append(dir: String, source_path: Path): String = |
|
44 (Path.explode(dir) + source_path).expand.implode |
|
45 |
|
46 def with_thy_text[A](name: Document.Node.Name, f: CharSequence => A): A = |
|
47 { |
|
48 val path = Path.explode(name.node) |
|
49 if (!path.is_file) error("No such file: " + path.toString) |
|
50 |
|
51 val text = File.read(path) |
|
52 Symbol.decode_strict(text) |
|
53 f(text) |
|
54 } |
|
55 |
|
56 |
|
57 /* theory files */ |
|
58 |
|
59 def body_files_test(syntax: Outer_Syntax, text: String): Boolean = |
|
60 syntax.thy_load_commands.exists({ case (cmd, _) => text.containsSlice(cmd) }) |
|
61 |
|
62 def body_files(syntax: Outer_Syntax, text: String): List[String] = |
|
63 { |
|
64 val spans = Thy_Syntax.parse_spans(syntax.scan(text)) |
|
65 spans.iterator.map(Thy_Syntax.span_files(syntax, _)).flatten.toList |
|
66 } |
|
67 |
|
68 def import_name(master: Document.Node.Name, s: String): Document.Node.Name = |
|
69 { |
|
70 val theory = Thy_Header.base_name(s) |
|
71 if (loaded_theories(theory)) Document.Node.Name(theory + ".thy", "", theory) |
|
72 else { |
|
73 val path = Path.explode(s) |
|
74 val node = append(master.master_dir, Resources.thy_path(path)) |
|
75 val master_dir = append(master.master_dir, path.dir) |
|
76 Document.Node.Name(node, master_dir, theory) |
|
77 } |
|
78 } |
|
79 |
|
80 def check_thy_text(name: Document.Node.Name, text: CharSequence): Document.Node.Header = |
|
81 { |
|
82 try { |
|
83 val header = Thy_Header.read(text) |
|
84 |
|
85 val name1 = header.name |
|
86 if (name.theory != name1) |
|
87 error("Bad file name " + Resources.thy_path(Path.basic(name.theory)) + |
|
88 " for theory " + quote(name1)) |
|
89 |
|
90 val imports = header.imports.map(import_name(name, _)) |
|
91 Document.Node.Header(imports, header.keywords, Nil) |
|
92 } |
|
93 catch { case exn: Throwable => Document.Node.bad_header(Exn.message(exn)) } |
|
94 } |
|
95 |
|
96 def check_thy(name: Document.Node.Name): Document.Node.Header = |
|
97 with_thy_text(name, check_thy_text(name, _)) |
|
98 |
|
99 |
|
100 /* theory text edits */ |
|
101 |
|
102 def text_edits( |
|
103 reparse_limit: Int, |
|
104 previous: Document.Version, |
|
105 doc_blobs: Document.Blobs, |
|
106 edits: List[Document.Edit_Text]): (Boolean, List[Document.Edit_Command], Document.Version) = |
|
107 Thy_Syntax.text_edits(this, reparse_limit, previous, doc_blobs, edits) |
|
108 |
|
109 def syntax_changed() { } |
|
110 } |
|
111 |