author | Thomas Lindae <thomas.lindae@in.tum.de> |
Sun, 30 Jun 2024 15:32:45 +0200 | |
changeset 81063 | a5d42b37331f |
parent 81062 | b2df8bf17071 |
child 81084 | 96eb20106a34 |
permissions | -rw-r--r-- |
64623 | 1 |
/* Title: Tools/VSCode/src/vscode_resources.scala |
64605 | 2 |
Author: Makarius |
3 |
||
64729 | 4 |
Resources for VSCode Language Server: file-system access and global state. |
64605 | 5 |
*/ |
6 |
||
7 |
package isabelle.vscode |
|
8 |
||
9 |
||
10 |
import isabelle._ |
|
11 |
||
12 |
import java.io.{File => JFile} |
|
13 |
||
64824 | 14 |
import scala.util.parsing.input.Reader |
64727
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
15 |
|
64605 | 16 |
|
75393 | 17 |
object VSCode_Resources { |
64703 | 18 |
/* internal state */ |
19 |
||
20 |
sealed case class State( |
|
72761 | 21 |
models: Map[JFile, VSCode_Model] = Map.empty, |
65926
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
22 |
caret: Option[(JFile, Line.Position)] = None, |
66101
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
23 |
overlays: Document.Overlays = Document.Overlays.empty, |
64777
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
24 |
pending_input: Set[JFile] = Set.empty, |
75393 | 25 |
pending_output: Set[JFile] = Set.empty |
26 |
) { |
|
73357 | 27 |
def update_models(changed: Iterable[(JFile, VSCode_Model)]): State = |
65111
3224a6f7bd6b
more robust treatment of pending input/output: these are often correlated;
wenzelm
parents:
65107
diff
changeset
|
28 |
copy( |
65113 | 29 |
models = models ++ changed, |
73359 | 30 |
pending_input = changed.foldLeft(pending_input) { case (set, (file, _)) => set + file }, |
31 |
pending_output = changed.foldLeft(pending_output) { case (set, (file, _)) => set + file }) |
|
65111
3224a6f7bd6b
more robust treatment of pending input/output: these are often correlated;
wenzelm
parents:
65107
diff
changeset
|
32 |
|
65926
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
33 |
def update_caret(new_caret: Option[(JFile, Line.Position)]): State = |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
34 |
if (caret == new_caret) this |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
35 |
else |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
36 |
copy( |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
37 |
caret = new_caret, |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
38 |
pending_input = pending_input ++ caret.map(_._1) ++ new_caret.map(_._1)) |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
39 |
|
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
40 |
def get_caret(file: JFile): Option[Line.Position] = |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
41 |
caret match { |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
42 |
case Some((caret_file, caret_pos)) if caret_file == file => Some(caret_pos) |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
43 |
case _ => None |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
44 |
} |
0f7821a07aa9
restricted perspective depending on the caret -- important for reactivity when editing big files;
wenzelm
parents:
65532
diff
changeset
|
45 |
|
64800 | 46 |
lazy val document_blobs: Document.Blobs = |
47 |
Document.Blobs( |
|
48 |
(for { |
|
49 |
(_, model) <- models.iterator |
|
50 |
blob <- model.get_blob |
|
51 |
} yield (model.node_name -> blob)).toMap) |
|
66101
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
52 |
|
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
53 |
def change_overlay(insert: Boolean, file: JFile, |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
54 |
command: Command, fn: String, args: List[String]): State = |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
55 |
copy( |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
56 |
overlays = |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
57 |
if (insert) overlays.insert(command, fn, args) |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
58 |
else overlays.remove(command, fn, args), |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
59 |
pending_input = pending_input + file) |
64800 | 60 |
} |
66086 | 61 |
|
62 |
||
63 |
/* caret */ |
|
64 |
||
75393 | 65 |
sealed case class Caret(file: JFile, model: VSCode_Model, offset: Text.Offset) { |
66086 | 66 |
def node_name: Document.Node.Name = model.node_name |
67 |
} |
|
64605 | 68 |
} |
69 |
||
64623 | 70 |
class VSCode_Resources( |
75393 | 71 |
val options: Options, |
76656 | 72 |
session_background: Sessions.Background, |
79777 | 73 |
log: Logger = new Logger) |
76657 | 74 |
extends Resources(session_background, log = log) { |
67292
386ddccfccbf
implicit thy_load context for bibtex files (VSCode);
wenzelm
parents:
67104
diff
changeset
|
75 |
resources => |
386ddccfccbf
implicit thy_load context for bibtex files (VSCode);
wenzelm
parents:
67104
diff
changeset
|
76 |
|
64703 | 77 |
private val state = Synchronized(VSCode_Resources.State()) |
78 |
||
79 |
||
65137 | 80 |
/* options */ |
81 |
||
82 |
def pide_extensions: Boolean = options.bool("vscode_pide_extensions") |
|
81024
d1535ba3b1ca
lsp: added vscode_html_output option;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
79777
diff
changeset
|
83 |
def html_output: Boolean = options.bool("vscode_html_output") |
65137 | 84 |
def tooltip_margin: Int = options.int("vscode_tooltip_margin") |
85 |
def message_margin: Int = options.int("vscode_message_margin") |
|
81041
b65931659364
lsp: added delay to dynamic_output updates after a set_margin;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81025
diff
changeset
|
86 |
def output_delay: Time = options.seconds("vscode_output_delay") |
65137 | 87 |
|
81062
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
88 |
def unicode_symbols_output: Boolean = options.bool("vscode_unicode_symbols_output") |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
89 |
def unicode_symbols_edits: Boolean = options.bool("vscode_unicode_symbols_edits") |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
90 |
|
65137 | 91 |
|
64703 | 92 |
/* document node name */ |
93 |
||
64777
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
94 |
def node_file(name: Document.Node.Name): JFile = new JFile(name.node) |
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
95 |
|
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
96 |
def node_name(file: JFile): Document.Node.Name = |
70718
5bb025e24224
clarified inversion of file name to theory name, notably for Windows;
wenzelm
parents:
70716
diff
changeset
|
97 |
find_theory(file) getOrElse { |
67060 | 98 |
val node = file.getPath |
67104
a2fa0c6a7aff
clarified theory_name vs. loaded_theory: proper import_name for already loaded theories from other sessions (amending 4c98c929a12a);
wenzelm
parents:
67060
diff
changeset
|
99 |
val theory = theory_name(Sessions.DRAFT, Thy_Header.theory_name(node)) |
76845 | 100 |
if (session_base.loaded_theory(theory)) Document.Node.Name.loaded_theory(theory) |
76860
f95ed5a0600c
clarified signature: uniform master_dir instead of separate field;
wenzelm
parents:
76858
diff
changeset
|
101 |
else Document.Node.Name(node, theory = theory) |
67060 | 102 |
} |
64703 | 103 |
|
76739
cb72b5996520
proper migrate_name between different kinds of Resources, notably for Windows;
wenzelm
parents:
76716
diff
changeset
|
104 |
override def migrate_name(standard_name: Document.Node.Name): Document.Node.Name = |
cb72b5996520
proper migrate_name between different kinds of Resources, notably for Windows;
wenzelm
parents:
76716
diff
changeset
|
105 |
node_name(Path.explode(standard_name.node).canonical_file) |
cb72b5996520
proper migrate_name between different kinds of Resources, notably for Windows;
wenzelm
parents:
76716
diff
changeset
|
106 |
|
76864 | 107 |
override def append_path(prefix: String, source_path: Path): String = { |
64759 | 108 |
val path = source_path.expand |
76864 | 109 |
if (prefix == "" || path.is_absolute) File.platform_path(path) |
110 |
else if (path.is_current) prefix |
|
111 |
else if (path.is_basic && !prefix.endsWith("/") && !prefix.endsWith(JFile.separator)) |
|
112 |
prefix + JFile.separator + File.platform_path(path) |
|
113 |
else if (path.is_basic) prefix + File.platform_path(path) |
|
77201 | 114 |
else File.absolute(new JFile(prefix + JFile.separator + File.platform_path(path))).getPath |
64716 | 115 |
} |
116 |
||
76890
d924a69e7d2b
more robust operations: avoid somewhat fragile Document.Node.Name.master_dir_path;
wenzelm
parents:
76864
diff
changeset
|
117 |
override def read_dir(dir: String): List[String] = |
d924a69e7d2b
more robust operations: avoid somewhat fragile Document.Node.Name.master_dir_path;
wenzelm
parents:
76864
diff
changeset
|
118 |
File.read_dir(Path.explode(File.standard_path(dir))) |
d924a69e7d2b
more robust operations: avoid somewhat fragile Document.Node.Name.master_dir_path;
wenzelm
parents:
76864
diff
changeset
|
119 |
|
76777 | 120 |
def get_models(): Iterable[VSCode_Model] = state.value.models.values |
121 |
def get_model(file: JFile): Option[VSCode_Model] = state.value.models.get(file) |
|
72761 | 122 |
def get_model(name: Document.Node.Name): Option[VSCode_Model] = get_model(node_file(name)) |
64834 | 123 |
|
124 |
||
76765
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
125 |
/* snapshot */ |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
126 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
127 |
def snapshot(model: VSCode_Model): Document.Snapshot = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
128 |
model.session.snapshot( |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
129 |
node_name = model.node_name, |
76777 | 130 |
pending_edits = Document.Pending_Edits.make(get_models())) |
76765
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
131 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
132 |
def get_snapshot(file: JFile): Option[Document.Snapshot] = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
133 |
get_model(file).map(snapshot) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
134 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
135 |
def get_snapshot(name: Document.Node.Name): Option[Document.Snapshot] = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
136 |
get_model(name).map(snapshot) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
137 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
138 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
139 |
/* rendering */ |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
140 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
141 |
def rendering(snapshot: Document.Snapshot, model: VSCode_Model): VSCode_Rendering = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
142 |
new VSCode_Rendering(snapshot, model) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
143 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
144 |
def rendering(model: VSCode_Model): VSCode_Rendering = rendering(snapshot(model), model) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
145 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
146 |
def get_rendering(file: JFile): Option[VSCode_Rendering] = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
147 |
get_model(file).map(rendering) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
148 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
149 |
def get_rendering(name: Document.Node.Name): Option[VSCode_Rendering] = |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
150 |
get_model(name).map(rendering) |
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
151 |
|
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
152 |
|
64834 | 153 |
/* file content */ |
154 |
||
75393 | 155 |
def read_file_content(name: Document.Node.Name): Option[String] = { |
69256
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
156 |
make_theory_content(name) orElse { |
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
157 |
try { Some(Line.normalize(File.read(node_file(name)))) } |
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
158 |
catch { case ERROR(_) => None } |
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
159 |
} |
67292
386ddccfccbf
implicit thy_load context for bibtex files (VSCode);
wenzelm
parents:
67104
diff
changeset
|
160 |
} |
64834 | 161 |
|
69256
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
162 |
def get_file_content(name: Document.Node.Name): Option[String] = |
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
163 |
get_model(name) match { |
64834 | 164 |
case Some(model) => Some(model.content.text) |
69256
c78c95d2a3d1
more uniform read_file_content for Isabelle/jEdit and Isabelle/VSCode: make_theory_content is required for semantic checking of user file-formats (e.g. bibtex);
wenzelm
parents:
69255
diff
changeset
|
165 |
case None => read_file_content(name) |
64834 | 166 |
} |
167 |
||
75393 | 168 |
override def with_thy_reader[A](name: Document.Node.Name, f: Reader[Char] => A): A = { |
64777
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
169 |
val file = node_file(name) |
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
170 |
get_model(file) match { |
64830 | 171 |
case Some(model) => f(Scan.char_reader(model.content.text)) |
69393
ed0824ef337e
static type for Library.using: avoid Java 11 warnings on "Illegal reflective access";
wenzelm
parents:
69256
diff
changeset
|
172 |
case None if file.isFile => using(Scan.byte_reader(file))(f) |
ed0824ef337e
static type for Library.using: avoid Java 11 warnings on "Illegal reflective access";
wenzelm
parents:
69256
diff
changeset
|
173 |
case None => error("No such file: " + quote(file.toString)) |
64727
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
174 |
} |
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
175 |
} |
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
176 |
|
64703 | 177 |
|
178 |
/* document models */ |
|
179 |
||
64800 | 180 |
def visible_node(name: Document.Node.Name): Boolean = |
181 |
get_model(name) match { |
|
182 |
case Some(model) => model.node_visible |
|
183 |
case None => false |
|
184 |
} |
|
185 |
||
66100 | 186 |
def change_model( |
187 |
session: Session, |
|
72761 | 188 |
editor: Language_Server.Editor, |
66100 | 189 |
file: JFile, |
66674 | 190 |
version: Long, |
66100 | 191 |
text: String, |
75393 | 192 |
range: Option[Line.Range] = None |
193 |
): Unit = { |
|
75394 | 194 |
state.change { st => |
75393 | 195 |
val model = st.models.getOrElse(file, VSCode_Model.init(session, editor, node_name(file))) |
196 |
val model1 = |
|
197 |
(model.change_text(text, range) getOrElse model).set_version(version).external(false) |
|
198 |
st.update_models(Some(file -> model1)) |
|
75394 | 199 |
} |
64703 | 200 |
} |
201 |
||
65111
3224a6f7bd6b
more robust treatment of pending input/output: these are often correlated;
wenzelm
parents:
65107
diff
changeset
|
202 |
def close_model(file: JFile): Boolean = |
64710 | 203 |
state.change_result(st => |
64777
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
wenzelm
parents:
64775
diff
changeset
|
204 |
st.models.get(file) match { |
65111
3224a6f7bd6b
more robust treatment of pending input/output: these are often correlated;
wenzelm
parents:
65107
diff
changeset
|
205 |
case None => (false, st) |
65113 | 206 |
case Some(model) => (true, st.update_models(Some(file -> model.external(true)))) |
64710 | 207 |
}) |
208 |
||
65116 | 209 |
def sync_models(changed_files: Set[JFile]): Unit = |
75394 | 210 |
state.change { st => |
75393 | 211 |
val changed_models = |
212 |
(for { |
|
213 |
(file, model) <- st.models.iterator |
|
214 |
if changed_files(file) && model.external_file |
|
215 |
text <- read_file_content(model.node_name) |
|
216 |
model1 <- model.change_text(text) |
|
217 |
} yield (file, model1)).toList |
|
218 |
st.update_models(changed_models) |
|
75394 | 219 |
} |
64710 | 220 |
|
64703 | 221 |
|
66101
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
222 |
/* overlays */ |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
223 |
|
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
224 |
def node_overlays(name: Document.Node.Name): Document.Node.Overlays = |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
225 |
state.value.overlays(name) |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
226 |
|
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
227 |
def insert_overlay(command: Command, fn: String, args: List[String]): Unit = |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
228 |
state.change(_.change_overlay(true, node_file(command.node_name), command, fn, args)) |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
229 |
|
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
230 |
def remove_overlay(command: Command, fn: String, args: List[String]): Unit = |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
231 |
state.change(_.change_overlay(false, node_file(command.node_name), command, fn, args)) |
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
232 |
|
0f0f294e314f
maintain overlays within main state of document models;
wenzelm
parents:
66100
diff
changeset
|
233 |
|
64727
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
234 |
/* resolve dependencies */ |
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
235 |
|
66100 | 236 |
def resolve_dependencies( |
237 |
session: Session, |
|
72761 | 238 |
editor: Language_Server.Editor, |
75393 | 239 |
file_watcher: File_Watcher |
240 |
): (Boolean, Boolean) = { |
|
75394 | 241 |
state.change_result { st => |
76766 | 242 |
val stable_tip_version = session.stable_tip_version(st.models.values) |
64800 | 243 |
|
76716
a7602257a825
clarified state document nodes for Theories_Status / Document_Dockable;
wenzelm
parents:
76657
diff
changeset
|
244 |
val thy_files = |
76767 | 245 |
resources.resolve_dependencies(st.models.values, editor.document_required()) |
76716
a7602257a825
clarified state document nodes for Theories_Status / Document_Dockable;
wenzelm
parents:
76657
diff
changeset
|
246 |
|
76590 | 247 |
val aux_files = stable_tip_version.toList.flatMap(undefined_blobs) |
64800 | 248 |
|
75393 | 249 |
val loaded_models = |
250 |
(for { |
|
76587 | 251 |
node_name <- thy_files.iterator ++ aux_files.iterator |
75393 | 252 |
file = node_file(node_name) |
253 |
if !st.models.isDefinedAt(file) |
|
254 |
text <- { file_watcher.register_parent(file); read_file_content(node_name) } |
|
255 |
} |
|
256 |
yield { |
|
257 |
val model = VSCode_Model.init(session, editor, node_name) |
|
258 |
val model1 = (model.change_text(text) getOrElse model).external(true) |
|
259 |
(file, model1) |
|
260 |
}).toList |
|
64731
84192ecae582
just one synchronized access to global state: works recursively on JVM;
wenzelm
parents:
64729
diff
changeset
|
261 |
|
75393 | 262 |
val invoke_input = loaded_models.nonEmpty |
263 |
val invoke_load = stable_tip_version.isEmpty |
|
64800 | 264 |
|
75393 | 265 |
((invoke_input, invoke_load), st.update_models(loaded_models)) |
75394 | 266 |
} |
64727
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
267 |
} |
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
268 |
|
13e37567a0d6
automatically resolve dependencies from document models and file-system;
wenzelm
parents:
64726
diff
changeset
|
269 |
|
64703 | 270 |
/* pending input */ |
271 |
||
75393 | 272 |
def flush_input(session: Session, channel: Channel): Unit = { |
75394 | 273 |
state.change { st => |
75393 | 274 |
val changed_models = |
275 |
(for { |
|
276 |
file <- st.pending_input.iterator |
|
277 |
model <- st.models.get(file) |
|
278 |
(edits, model1) <- |
|
81063
a5d42b37331f
lsp: removed code that is never run;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81062
diff
changeset
|
279 |
model.flush_edits(st.document_blobs, file, st.get_caret(file)) |
75393 | 280 |
} yield (edits, (file, model1))).toList |
64707 | 281 |
|
81063
a5d42b37331f
lsp: removed code that is never run;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81062
diff
changeset
|
282 |
session.update(st.document_blobs, changed_models.flatMap(res => res._1)) |
66676
39db5bb7eb0a
recode Unicode text on the spot, e.g. from copy-paste of output;
wenzelm
parents:
66674
diff
changeset
|
283 |
|
75393 | 284 |
st.copy( |
285 |
models = st.models ++ changed_models.iterator.map(_._2), |
|
286 |
pending_input = Set.empty) |
|
75394 | 287 |
} |
64703 | 288 |
} |
289 |
||
290 |
||
291 |
/* pending output */ |
|
292 |
||
73357 | 293 |
def update_output(changed_nodes: Iterable[JFile]): Unit = |
64703 | 294 |
state.change(st => st.copy(pending_output = st.pending_output ++ changed_nodes)) |
295 |
||
66138 | 296 |
def update_output_visible(): Unit = |
297 |
state.change(st => st.copy(pending_output = st.pending_output ++ |
|
298 |
(for ((file, model) <- st.models.iterator if model.node_visible) yield file))) |
|
299 |
||
75393 | 300 |
def flush_output(channel: Channel): Boolean = { |
75394 | 301 |
state.change_result { st => |
75393 | 302 |
val (postponed, flushed) = |
303 |
(for { |
|
304 |
file <- st.pending_output.iterator |
|
305 |
model <- st.models.get(file) |
|
76765
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
wenzelm
parents:
76739
diff
changeset
|
306 |
} yield (file, model, rendering(model))).toList.partition(_._3.snapshot.is_outdated) |
65232
ca571c8c0788
avoid race condition between current_state().stable_tip_version and model.rendering();
wenzelm
parents:
65198
diff
changeset
|
307 |
|
75393 | 308 |
val changed_iterator = |
309 |
for { |
|
310 |
(file, model, rendering) <- flushed.iterator |
|
311 |
(changed_diags, changed_decos, model1) = model.publish(rendering) |
|
312 |
if changed_diags.isDefined || changed_decos.isDefined |
|
313 |
} |
|
314 |
yield { |
|
315 |
for (diags <- changed_diags) |
|
316 |
channel.write(LSP.PublishDiagnostics(file, rendering.diagnostics_output(diags))) |
|
317 |
if (pide_extensions) { |
|
318 |
for (decos <- changed_decos) |
|
319 |
channel.write(rendering.decoration_output(decos).json(file)) |
|
65095 | 320 |
} |
75393 | 321 |
(file, model1) |
322 |
} |
|
65232
ca571c8c0788
avoid race condition between current_state().stable_tip_version and model.rendering();
wenzelm
parents:
65198
diff
changeset
|
323 |
|
75393 | 324 |
(postponed.nonEmpty, |
325 |
st.copy( |
|
326 |
models = st.models ++ changed_iterator, |
|
327 |
pending_output = postponed.map(_._1).toSet)) |
|
75394 | 328 |
} |
64703 | 329 |
} |
64870 | 330 |
|
331 |
||
332 |
/* output text */ |
|
333 |
||
81062
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
334 |
def output_text(content: String): String = |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
335 |
Symbol.output(unicode_symbols_output, content) |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
336 |
def output_edit(content: String): String = |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
337 |
Symbol.output(unicode_symbols_edits, content) |
64870 | 338 |
|
81062
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
339 |
def output_xml_text(body: XML.Tree): String = |
b2df8bf17071
lsp: created distinction for unicode symbols setting between output and edits and clarified output text functions;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81058
diff
changeset
|
340 |
output_text(XML.content(body)) |
65107 | 341 |
|
81025
d4eb94b46e83
lsp: added State and Dynamic Output html_output and margin handling;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81024
diff
changeset
|
342 |
def output_pretty(body: XML.Body, margin: Double): String = |
71649 | 343 |
output_text(Pretty.string_of(body, margin = margin, metric = Symbol.Metric)) |
65107 | 344 |
def output_pretty_tooltip(body: XML.Body): String = output_pretty(body, tooltip_margin) |
345 |
def output_pretty_message(body: XML.Body): String = output_pretty(body, message_margin) |
|
65142 | 346 |
|
347 |
||
65189 | 348 |
/* caret handling */ |
349 |
||
73340 | 350 |
def update_caret(caret: Option[(JFile, Line.Position)]): Unit = |
351 |
state.change(_.update_caret(caret)) |
|
65189 | 352 |
|
75393 | 353 |
def get_caret(): Option[VSCode_Resources.Caret] = { |
65189 | 354 |
val st = state.value |
355 |
for { |
|
356 |
(file, pos) <- st.caret |
|
357 |
model <- st.models.get(file) |
|
65191
4c9c83311cad
dynamic output, depending on caret focus (see also Tools/jEdit/src/output_dockable.scala);
wenzelm
parents:
65189
diff
changeset
|
358 |
offset <- model.content.doc.offset(pos) |
65189 | 359 |
} |
66086 | 360 |
yield VSCode_Resources.Caret(file, model, offset) |
65189 | 361 |
} |
362 |
||
363 |
||
81043
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
364 |
/* decoration requests */ |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
365 |
|
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
366 |
def force_decorations(channel: Channel, file: JFile): Unit = { |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
367 |
val model = state.value.models(file) |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
368 |
val rendering1 = rendering(model) |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
369 |
val (_, decos, model1) = model.publish_full(rendering1) |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
370 |
if (pide_extensions) { |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
371 |
channel.write(rendering1.decoration_output(decos).json(file)) |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
372 |
} |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
373 |
} |
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
374 |
|
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
375 |
|
2174ec5f0d0c
lsp: added decoration_request notification;
Thomas Lindae <thomas.lindae@in.tum.de>
parents:
81041
diff
changeset
|
376 |
|
65142 | 377 |
/* spell checker */ |
378 |
||
379 |
val spell_checker = new Spell_Checker_Variable |
|
380 |
spell_checker.update(options) |
|
64605 | 381 |
} |