| author | wenzelm | 
| Tue, 24 Jun 2025 21:05:48 +0200 | |
| changeset 82747 | 00828818a607 | 
| parent 82720 | 956ecf2c07a0 | 
| child 82758 | 414ebfd5389b | 
| permissions | -rw-r--r-- | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 1 | /* Title: Tools/jEdit/src/jedit_editor.scala | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 3 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 4 | PIDE editor operations for jEdit. | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 6 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 7 | package isabelle.jedit | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 8 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 9 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 10 | import isabelle._ | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 11 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 12 | |
| 58545 
30b75b7958d6
citation tooltip/hyperlink based on open buffers with .bib files;
 wenzelm parents: 
57878diff
changeset | 13 | import org.gjt.sp.jedit.{jEdit, View, Buffer}
 | 
| 54706 | 14 | import org.gjt.sp.jedit.browser.VFSBrowser | 
| 82418 | 15 | import org.gjt.sp.jedit.textarea.TextArea | 
| 70016 | 16 | import org.gjt.sp.jedit.io.{VFSManager, VFSFile}
 | 
| 82427 
1c646ad68bd8
eliminated patch: imitate jEdit.gotoMarker more directly;
 wenzelm parents: 
82426diff
changeset | 17 | import org.gjt.sp.util.AwtRunnableQueue | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 18 | |
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 19 | |
| 75393 | 20 | class JEdit_Editor extends Editor[View] {
 | 
| 76794 | 21 | /* PIDE session and document model */ | 
| 52977 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 22 | |
| 52980 | 23 | override def session: Session = PIDE.session | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 24 | |
| 66084 | 25 | def flush_edits(hidden: Boolean = false, purge: Boolean = false): Unit = | 
| 64817 | 26 |     GUI_Thread.require {
 | 
| 64867 | 27 | val (doc_blobs, edits) = Document_Model.flush_edits(hidden, purge) | 
| 64817 | 28 | session.update(doc_blobs, edits) | 
| 29 | } | |
| 66084 | 30 | override def flush(): Unit = flush_edits() | 
| 73340 | 31 | def purge(): Unit = flush_edits(purge = true) | 
| 64867 | 32 | |
| 76044 | 33 | private val delay_input: Delay = | 
| 76610 | 34 |     Delay.last(PIDE.session.input_delay, gui = true) { flush() }
 | 
| 54461 | 35 | |
| 76044 | 36 | private val delay_generated_input: Delay = | 
| 76610 | 37 |     Delay.first(PIDE.session.generated_input_delay, gui = true) { flush() }
 | 
| 64521 
1aef5a0e18d7
delay_first for machine generated editor events: avoid starvation, e.g. when operating on big sessions;
 wenzelm parents: 
62248diff
changeset | 38 | |
| 76044 | 39 | def invoke(): Unit = delay_input.invoke() | 
| 40 |   def invoke_generated(): Unit = { delay_input.invoke(); delay_generated_input.invoke() }
 | |
| 54461 | 41 | |
| 66458 
42d0d5c77c78
more robust shutdown, e.g. when plugin is stopped;
 wenzelm parents: 
66101diff
changeset | 42 | def shutdown(): Unit = | 
| 
42d0d5c77c78
more robust shutdown, e.g. when plugin is stopped;
 wenzelm parents: 
66101diff
changeset | 43 |     GUI_Thread.require {
 | 
| 76044 | 44 | delay_input.revoke() | 
| 45 | delay_generated_input.revoke() | |
| 66458 
42d0d5c77c78
more robust shutdown, e.g. when plugin is stopped;
 wenzelm parents: 
66101diff
changeset | 46 | Document_Model.flush_edits(hidden = false, purge = false) | 
| 
42d0d5c77c78
more robust shutdown, e.g. when plugin is stopped;
 wenzelm parents: 
66101diff
changeset | 47 | } | 
| 
42d0d5c77c78
more robust shutdown, e.g. when plugin is stopped;
 wenzelm parents: 
66101diff
changeset | 48 | |
| 64799 | 49 | def visible_node(name: Document.Node.Name): Boolean = | 
| 64840 | 50 |     (for {
 | 
| 51 | text_area <- JEdit_Lib.jedit_text_areas() | |
| 64882 | 52 | doc_view <- Document_View.get(text_area) | 
| 64840 | 53 | } yield doc_view.model.node_name).contains(name) | 
| 64799 | 54 | |
| 52977 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 55 | |
| 76794 | 56 | override def get_models(): Iterable[Document.Model] = Document_Model.get_models() | 
| 57 | ||
| 58 | ||
| 76706 | 59 | /* global changes */ | 
| 76705 
ddf5764684dd
proper state change, e.g. on open/close of "Document" panel;
 wenzelm parents: 
76610diff
changeset | 60 | |
| 76706 | 61 |   def state_changed(): Unit = {
 | 
| 76708 | 62 |     GUI_Thread.later { flush() }
 | 
| 76706 | 63 | PIDE.plugin.deps_changed() | 
| 64 | session.global_options.post(Session.Global_Options(PIDE.options.value)) | |
| 76705 
ddf5764684dd
proper state change, e.g. on open/close of "Document" panel;
 wenzelm parents: 
76610diff
changeset | 65 | } | 
| 
ddf5764684dd
proper state change, e.g. on open/close of "Document" panel;
 wenzelm parents: 
76610diff
changeset | 66 | |
| 76715 
bf5ff407f32f
clarified state of document model vs. document editor selection (again, see also a9d52d02bd83);
 wenzelm parents: 
76708diff
changeset | 67 | override def document_state_changed(): Unit = state_changed() | 
| 76706 | 68 | |
| 76705 
ddf5764684dd
proper state change, e.g. on open/close of "Document" panel;
 wenzelm parents: 
76610diff
changeset | 69 | |
| 52977 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 70 | /* current situation */ | 
| 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 71 | |
| 52980 | 72 | override def current_node(view: View): Option[Document.Node.Name] = | 
| 76768 
40c8275f0131
tuned signature: follow terminology of VSCode_Resources;
 wenzelm parents: 
76765diff
changeset | 73 |     GUI_Thread.require { Document_Model.get_model(view.getBuffer).map(_.node_name) }
 | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 74 | |
| 52980 | 75 | override def current_node_snapshot(view: View): Option[Document.Snapshot] = | 
| 76765 
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
 wenzelm parents: 
76715diff
changeset | 76 |     GUI_Thread.require { Document_Model.get_snapshot(view.getBuffer) }
 | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 77 | |
| 76765 
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
 wenzelm parents: 
76715diff
changeset | 78 | override def node_snapshot(name: Document.Node.Name): Document.Snapshot = | 
| 
c654103e9c9d
more robust Document.Pending_Edits: cover all nodes simulataneously, and thus support proper Snapshot.switch;
 wenzelm parents: 
76715diff
changeset | 79 |     GUI_Thread.require { Document_Model.get_snapshot(name) getOrElse session.snapshot(name) }
 | 
| 52974 | 80 | |
| 75393 | 81 |   override def current_command(view: View, snapshot: Document.Snapshot): Option[Command] = {
 | 
| 57612 
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
 wenzelm parents: 
57611diff
changeset | 82 |     GUI_Thread.require {}
 | 
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 83 | |
| 54325 
2c4155003352
clarified Editor.current_command: allow outdated snapshot;
 wenzelm parents: 
53845diff
changeset | 84 | val text_area = view.getTextArea | 
| 54528 | 85 | val buffer = view.getBuffer | 
| 86 | ||
| 64882 | 87 |     Document_View.get(text_area) match {
 | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
54706diff
changeset | 88 | case Some(doc_view) if doc_view.model.is_theory => | 
| 65199 
6bd7081f8319
clarified current_command: index refers to node content, negative index means first command;
 wenzelm parents: 
65196diff
changeset | 89 | snapshot.current_command(doc_view.model.node_name, text_area.getCaretPosition) | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
54706diff
changeset | 90 | case _ => | 
| 76768 
40c8275f0131
tuned signature: follow terminology of VSCode_Resources;
 wenzelm parents: 
76765diff
changeset | 91 |         Document_Model.get_model(buffer) match {
 | 
| 54531 
8330faaeebd5
restrict node_required status and Theories panel to actual theories;
 wenzelm parents: 
54528diff
changeset | 92 | case Some(model) if !model.is_theory => | 
| 65187 | 93 | snapshot.version.nodes.commands_loading(model.node_name).headOption | 
| 54528 | 94 | case _ => None | 
| 95 | } | |
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 96 | } | 
| 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 97 | } | 
| 52977 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 98 | |
| 
15254e32d299
central management of Document.Overlays, independent of Document_Model;
 wenzelm parents: 
52974diff
changeset | 99 | |
| 66101 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 100 | /* overlays */ | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 101 | |
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 102 | override def node_overlays(name: Document.Node.Name): Document.Node.Overlays = | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 103 | Document_Model.node_overlays(name) | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 104 | |
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 105 | override def insert_overlay(command: Command, fn: String, args: List[String]): Unit = | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 106 | Document_Model.insert_overlay(command, fn, args) | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 107 | |
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 108 | override def remove_overlay(command: Command, fn: String, args: List[String]): Unit = | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 109 | Document_Model.remove_overlay(command, fn, args) | 
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 110 | |
| 
0f0f294e314f
maintain overlays within main state of document models;
 wenzelm parents: 
66094diff
changeset | 111 | |
| 55877 | 112 | /* navigation */ | 
| 52980 | 113 | |
| 82418 | 114 | def goto_file( | 
| 115 | focus: Boolean, | |
| 116 | view: View, | |
| 117 | name: String, | |
| 82431 | 118 | line: Int = -1, | 
| 82437 | 119 | offset: Text.Offset = -1, | 
| 120 | at_target: (Buffer, Text.Offset) => Unit = (_, _) => () | |
| 82418 | 121 |   ): Unit = {
 | 
| 57612 
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
 wenzelm parents: 
57611diff
changeset | 122 |     GUI_Thread.require {}
 | 
| 52980 | 123 | |
| 82419 
955c5d6c1acf
remove goto_buffer in favour of uniform goto_file;
 wenzelm parents: 
82418diff
changeset | 124 | PIDE.plugin.navigator.record(view) | 
| 56413 | 125 | |
| 82429 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 126 | def buffer_offset(buffer: Buffer): Text.Offset = | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 127 | ((if (line < 0) 0 else buffer.getLineStartOffset(line min buffer.getLineCount)) + | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 128 | (if (offset < 0) 0 else offset)) min buffer.getLength | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 129 | |
| 54706 | 130 |     JEdit_Lib.jedit_buffer(name) match {
 | 
| 52980 | 131 | case Some(buffer) => | 
| 60893 | 132 | if (focus) view.goToBuffer(buffer) else view.showBuffer(buffer) | 
| 82437 | 133 | val target = buffer_offset(buffer) | 
| 134 | view.getTextArea.setCaretPosition(target) | |
| 135 | at_target(buffer, target) | |
| 52980 | 136 | |
| 70016 | 137 | case None => | 
| 70167 
b33f28c81ba9
clarified goto_file (again): treat bad entry as plain file to open empty buffer instead of error (amending a8142ac5e4b6);
 wenzelm parents: 
70016diff
changeset | 138 | val is_dir = | 
| 70016 | 139 |           try {
 | 
| 140 | val vfs = VFSManager.getVFSForPath(name) | |
| 141 | val vfs_file = vfs._getFile((), name, view) | |
| 70167 
b33f28c81ba9
clarified goto_file (again): treat bad entry as plain file to open empty buffer instead of error (amending a8142ac5e4b6);
 wenzelm parents: 
70016diff
changeset | 142 | vfs_file != null && vfs_file.getType == VFSFile.DIRECTORY | 
| 70016 | 143 | } | 
| 144 |           catch { case ERROR(_) => false }
 | |
| 54706 | 145 | |
| 70167 
b33f28c81ba9
clarified goto_file (again): treat bad entry as plain file to open empty buffer instead of error (amending a8142ac5e4b6);
 wenzelm parents: 
70016diff
changeset | 146 | if (is_dir) VFSBrowser.browseDirectory(view, name) | 
| 73224 
49686e3b1909
clarified links to external files, e.g. .pdf within .thy source document;
 wenzelm parents: 
72823diff
changeset | 147 |         else if (!Isabelle_System.open_external_file(name)) {
 | 
| 82426 | 148 | val buffer = jEdit.openFile(view, name) | 
| 82429 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 149 |           if (buffer != null && (line >= 0 || offset >= 0)) {
 | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 150 |             AwtRunnableQueue.INSTANCE.runAfterIoTasks({ () =>
 | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 151 | val target = buffer_offset(buffer) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 152 |               if (view.getBuffer == buffer) {
 | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 153 | view.getTextArea.setCaretPosition(target) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 154 | buffer.setIntegerProperty(Buffer.CARET, target) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 155 | buffer.setBooleanProperty(Buffer.CARET_POSITIONED, true) | 
| 82437 | 156 | at_target(buffer, target) | 
| 82429 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 157 | } | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 158 |               else {
 | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 159 | buffer.setIntegerProperty(Buffer.CARET, target) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 160 | buffer.setBooleanProperty(Buffer.CARET_POSITIONED, true) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 161 | buffer.unsetProperty(Buffer.SCROLL_VERT) | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 162 | } | 
| 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 163 | }) | 
| 82427 
1c646ad68bd8
eliminated patch: imitate jEdit.gotoMarker more directly;
 wenzelm parents: 
82426diff
changeset | 164 | } | 
| 70016 | 165 | } | 
| 52980 | 166 | } | 
| 167 | } | |
| 168 | ||
| 75393 | 169 |   def goto_doc(view: View, path: Path): Unit = {
 | 
| 75120 | 170 | if (path.is_pdf) Doc.view(path) | 
| 171 | else goto_file(true, view, File.platform_path(path)) | |
| 61660 
78b371644654
added antiquotation @{doc}, e.g. useful for demonstration purposes;
 wenzelm parents: 
61557diff
changeset | 172 | } | 
| 
78b371644654
added antiquotation @{doc}, e.g. useful for demonstration purposes;
 wenzelm parents: 
61557diff
changeset | 173 | |
| 55877 | 174 | |
| 175 | /* hyperlinks */ | |
| 176 | ||
| 61660 
78b371644654
added antiquotation @{doc}, e.g. useful for demonstration purposes;
 wenzelm parents: 
61557diff
changeset | 177 | def hyperlink_doc(name: String): Option[Hyperlink] = | 
| 81350 
1818358373e2
misc tuning and clarification: Doc.Entry supports both plain files and pdf documents;
 wenzelm parents: 
80225diff
changeset | 178 | Doc.contents().entries(name = _ == name).headOption.map(entry => | 
| 
1818358373e2
misc tuning and clarification: Doc.Entry supports both plain files and pdf documents;
 wenzelm parents: 
80225diff
changeset | 179 |       new Hyperlink {
 | 
| 
1818358373e2
misc tuning and clarification: Doc.Entry supports both plain files and pdf documents;
 wenzelm parents: 
80225diff
changeset | 180 | override val external: Boolean = !entry.path.is_file | 
| 
1818358373e2
misc tuning and clarification: Doc.Entry supports both plain files and pdf documents;
 wenzelm parents: 
80225diff
changeset | 181 | def follow(view: View): Unit = goto_doc(view, entry.path) | 
| 
1818358373e2
misc tuning and clarification: Doc.Entry supports both plain files and pdf documents;
 wenzelm parents: 
80225diff
changeset | 182 | override def toString: String = "doc " + quote(name) | 
| 75118 | 183 | }) | 
| 61660 
78b371644654
added antiquotation @{doc}, e.g. useful for demonstration purposes;
 wenzelm parents: 
61557diff
changeset | 184 | |
| 56461 | 185 | def hyperlink_url(name: String): Hyperlink = | 
| 186 |     new Hyperlink {
 | |
| 64663 | 187 | override val external = true | 
| 56729 | 188 | def follow(view: View): Unit = | 
| 71692 | 189 |         Isabelle_Thread.fork(name = "hyperlink_url") {
 | 
| 69901 | 190 |           try { Isabelle_System.open(Url.escape_name(name)) }
 | 
| 56461 | 191 |           catch {
 | 
| 192 | case exn: Throwable => | |
| 62062 
ee610059b0e9
fewer use of GUI_Thread.now to reduce danger of deadlock on shutdown;
 wenzelm parents: 
61728diff
changeset | 193 |               GUI_Thread.later {
 | 
| 
ee610059b0e9
fewer use of GUI_Thread.now to reduce danger of deadlock on shutdown;
 wenzelm parents: 
61728diff
changeset | 194 | GUI.error_dialog(view, "System error", GUI.scrollable_text(Exn.message(exn))) | 
| 
ee610059b0e9
fewer use of GUI_Thread.now to reduce danger of deadlock on shutdown;
 wenzelm parents: 
61728diff
changeset | 195 | } | 
| 56729 | 196 | } | 
| 197 | } | |
| 56461 | 198 | override def toString: String = "URL " + quote(name) | 
| 52980 | 199 | } | 
| 55876 | 200 | |
| 82418 | 201 | def hyperlink_file( | 
| 202 | focus: Boolean, | |
| 203 | name: String, | |
| 204 | line: Int = -1, | |
| 82429 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 205 | offset: Text.Offset = -1 | 
| 82418 | 206 | ): Hyperlink = | 
| 56461 | 207 |     new Hyperlink {
 | 
| 82437 | 208 |       def follow(view: View): Unit = {
 | 
| 209 | import Isabelle_Navigator.Pos | |
| 210 | PIDE.plugin.navigator.record(Pos(view)) | |
| 211 | goto_file(focus, view, name, line = line, offset = offset, | |
| 212 | at_target = (buffer, target) => Pos.make(JEdit_Lib.buffer_name(buffer), target)) | |
| 213 | } | |
| 82418 | 214 | override def toString: String = "file " + quote(name) | 
| 56461 | 215 | } | 
| 55876 | 216 | |
| 75393 | 217 | def hyperlink_source_file( | 
| 218 | focus: Boolean, | |
| 219 | source_name: String, | |
| 220 | line1: Int, | |
| 221 | offset: Symbol.Offset | |
| 222 |   ) : Option[Hyperlink] = {
 | |
| 82720 
956ecf2c07a0
more flexible ML_Settings in Isabelle/Scala, depending on system options and some default settings;
 wenzelm parents: 
82437diff
changeset | 223 |     for (platform_path <- PIDE.resources.source_file(PIDE.ml_settings, source_name)) yield {
 | 
| 64841 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 224 | def hyperlink(pos: Line.Position) = | 
| 82429 
d37f279ae3bf
clarified target position: line start + offset (or column);
 wenzelm parents: 
82427diff
changeset | 225 | hyperlink_file(focus, platform_path, line = pos.line, offset = pos.column) | 
| 64841 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 226 | |
| 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 227 |       if (offset > 0) {
 | 
| 82193 | 228 |         PIDE.resources.get_file_content(PIDE.resources.node_name(platform_path)) match {
 | 
| 64841 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 229 | case Some(text) => | 
| 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 230 | hyperlink( | 
| 73358 | 231 | Symbol.iterator(text).zipWithIndex.takeWhile(p => p._2 < offset - 1).map(_._1). | 
| 232 | foldLeft(Line.Position.zero)(_.advance(_))) | |
| 64841 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 233 | case None => | 
| 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 234 | hyperlink(Line.Position((line1 - 1) max 0)) | 
| 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 235 | } | 
| 55878 | 236 | } | 
| 64841 
d53696aed874
added node_name(String): imitate jEdit buffer operations;
 wenzelm parents: 
64840diff
changeset | 237 | else hyperlink(Line.Position((line1 - 1) max 0)) | 
| 55878 | 238 | } | 
| 239 | } | |
| 55876 | 240 | |
| 56461 | 241 | override def hyperlink_command( | 
| 75393 | 242 | focus: Boolean, | 
| 243 | snapshot: Document.Snapshot, | |
| 244 | id: Document_ID.Generic, | |
| 245 | offset: Symbol.Offset = 0 | |
| 246 |   ) : Option[Hyperlink] = {
 | |
| 56461 | 247 | if (snapshot.is_outdated) None | 
| 82418 | 248 |     else {
 | 
| 249 | snapshot.find_command_position(id, offset) | |
| 82433 | 250 | .map(pos => hyperlink_file(focus, pos.name, line = pos.line, offset = pos.column)) | 
| 82418 | 251 | } | 
| 56461 | 252 | } | 
| 253 | ||
| 75393 | 254 | def is_hyperlink_position( | 
| 255 | snapshot: Document.Snapshot, | |
| 256 | text_offset: Text.Offset, | |
| 257 | pos: Position.T | |
| 258 |   ): Boolean = {
 | |
| 61011 | 259 |     pos match {
 | 
| 64667 | 260 | case Position.Item_Id(id, range) if range.start > 0 => | 
| 64665 | 261 |         snapshot.find_command(id) match {
 | 
| 72823 | 262 | case Some((node, command)) if snapshot.get_node(command.node_name) eq node => | 
| 61011 | 263 |             node.command_start(command) match {
 | 
| 64667 | 264 | case Some(start) => text_offset == start + command.chunk.decode(range.start) | 
| 61011 | 265 | case None => false | 
| 266 | } | |
| 267 | case _ => false | |
| 268 | } | |
| 269 | case _ => false | |
| 270 | } | |
| 271 | } | |
| 272 | ||
| 60893 | 273 | def hyperlink_position(focus: Boolean, snapshot: Document.Snapshot, pos: Position.T) | 
| 274 | : Option[Hyperlink] = | |
| 60874 | 275 |     pos match {
 | 
| 64667 | 276 | case Position.Item_File(name, line, range) => | 
| 277 | hyperlink_source_file(focus, name, line, range.start) | |
| 278 | case Position.Item_Id(id, range) => | |
| 279 | hyperlink_command(focus, snapshot, id, range.start) | |
| 60874 | 280 | case _ => None | 
| 281 | } | |
| 282 | ||
| 60893 | 283 | def hyperlink_def_position(focus: Boolean, snapshot: Document.Snapshot, pos: Position.T) | 
| 284 | : Option[Hyperlink] = | |
| 60874 | 285 |     pos match {
 | 
| 64667 | 286 | case Position.Item_Def_File(name, line, range) => | 
| 287 | hyperlink_source_file(focus, name, line, range.start) | |
| 288 | case Position.Item_Def_Id(id, range) => | |
| 289 | hyperlink_command(focus, snapshot, id, range.start) | |
| 60874 | 290 | case _ => None | 
| 291 | } | |
| 66094 | 292 | |
| 293 | ||
| 294 | /* dispatcher thread */ | |
| 295 | ||
| 296 | override def assert_dispatcher[A](body: => A): A = GUI_Thread.assert(body) | |
| 297 | override def require_dispatcher[A](body: => A): A = GUI_Thread.require(body) | |
| 298 | override def send_dispatcher(body: => Unit): Unit = GUI_Thread.later(body) | |
| 299 | override def send_wait_dispatcher(body: => Unit): Unit = GUI_Thread.now(body) | |
| 52971 
31926d2c04ee
tuned signature -- more abstract PIDE editor operations;
 wenzelm parents: diff
changeset | 300 | } |