wenzelm@44162
|
1 |
/* Title: Tools/jEdit/src/isabelle_hyperlinks.scala
|
wenzelm@36760
|
2 |
Author: Fabian Immler, TU Munich
|
wenzelm@36760
|
3 |
|
wenzelm@36760
|
4 |
Hyperlink setup for Isabelle proof documents.
|
wenzelm@36760
|
5 |
*/
|
immler@34571
|
6 |
|
immler@34571
|
7 |
package isabelle.jedit
|
immler@34572
|
8 |
|
wenzelm@34763
|
9 |
|
wenzelm@36039
|
10 |
import isabelle._
|
wenzelm@36039
|
11 |
|
wenzelm@49424
|
12 |
import java.io.{File => JFile}
|
immler@34572
|
13 |
|
wenzelm@34794
|
14 |
import gatchan.jedit.hyperlinks.{Hyperlink, HyperlinkSource, AbstractHyperlink}
|
immler@34571
|
15 |
|
wenzelm@34794
|
16 |
import org.gjt.sp.jedit.{View, jEdit, Buffer, TextUtilities}
|
immler@34571
|
17 |
|
wenzelm@34591
|
18 |
|
wenzelm@45467
|
19 |
private class Internal_Hyperlink(name: String, start: Int, end: Int, line: Int, offset: Int)
|
immler@34572
|
20 |
extends AbstractHyperlink(start, end, line, "")
|
immler@34571
|
21 |
{
|
wenzelm@45467
|
22 |
override def click(view: View)
|
wenzelm@45467
|
23 |
{
|
wenzelm@45467
|
24 |
val text_area = view.getTextArea
|
wenzelm@45467
|
25 |
if (Isabelle.buffer_name(view.getBuffer) == name)
|
wenzelm@45467
|
26 |
text_area.moveCaretPosition(offset)
|
wenzelm@45467
|
27 |
else
|
wenzelm@45467
|
28 |
Isabelle.jedit_buffer(name) match {
|
wenzelm@45467
|
29 |
case Some(buffer) =>
|
wenzelm@45467
|
30 |
view.setBuffer(buffer)
|
wenzelm@45467
|
31 |
text_area.moveCaretPosition(offset)
|
wenzelm@45467
|
32 |
case None =>
|
wenzelm@45467
|
33 |
}
|
immler@34571
|
34 |
}
|
immler@34571
|
35 |
}
|
immler@34571
|
36 |
|
wenzelm@43198
|
37 |
class External_Hyperlink(start: Int, end: Int, line: Int, def_file: String, def_line: Int)
|
immler@34572
|
38 |
extends AbstractHyperlink(start, end, line, "")
|
immler@34572
|
39 |
{
|
wenzelm@34605
|
40 |
override def click(view: View) = {
|
wenzelm@44532
|
41 |
Isabelle_System.source_file(Path.explode(def_file)) match {
|
wenzelm@39111
|
42 |
case None =>
|
wenzelm@48738
|
43 |
Library.error_dialog(view, "File not found",
|
wenzelm@48738
|
44 |
Library.scrollable_text("Could not find source file " + def_file))
|
wenzelm@34605
|
45 |
case Some(file) =>
|
wenzelm@43198
|
46 |
jEdit.openFiles(view, file.getParent, Array(file.getName, "+line:" + def_line))
|
immler@34576
|
47 |
}
|
wenzelm@34605
|
48 |
}
|
immler@34572
|
49 |
}
|
immler@34572
|
50 |
|
wenzelm@34763
|
51 |
class Isabelle_Hyperlinks extends HyperlinkSource
|
immler@34571
|
52 |
{
|
wenzelm@38869
|
53 |
def getHyperlink(buffer: Buffer, buffer_offset: Int): Hyperlink =
|
wenzelm@37176
|
54 |
{
|
wenzelm@38479
|
55 |
Swing_Thread.assert()
|
wenzelm@39101
|
56 |
Isabelle.buffer_lock(buffer) {
|
wenzelm@39101
|
57 |
Document_Model(buffer) match {
|
wenzelm@39101
|
58 |
case Some(model) =>
|
wenzelm@39101
|
59 |
val snapshot = model.snapshot()
|
wenzelm@39103
|
60 |
val markup =
|
wenzelm@47049
|
61 |
snapshot.select_markup[Hyperlink](
|
wenzelm@47049
|
62 |
Text.Range(buffer_offset, buffer_offset + 1),
|
wenzelm@47049
|
63 |
Some(Set(Isabelle_Markup.ENTITY)),
|
wenzelm@47049
|
64 |
{
|
wenzelm@47082
|
65 |
// FIXME Isabelle_Rendering.hyperlink
|
wenzelm@47049
|
66 |
case Text.Info(info_range,
|
wenzelm@47049
|
67 |
XML.Elem(Markup(Isabelle_Markup.ENTITY, props), _))
|
wenzelm@47049
|
68 |
if (props.find(
|
wenzelm@47049
|
69 |
{ case (Markup.KIND, Isabelle_Markup.ML_OPEN) => true
|
wenzelm@47049
|
70 |
case (Markup.KIND, Isabelle_Markup.ML_STRUCT) => true
|
wenzelm@47049
|
71 |
case _ => false }).isEmpty) =>
|
wenzelm@47049
|
72 |
val Text.Range(begin, end) = info_range
|
wenzelm@47049
|
73 |
val line = buffer.getLineOfOffset(begin)
|
wenzelm@47049
|
74 |
(Position.File.unapply(props), Position.Line.unapply(props)) match {
|
wenzelm@48423
|
75 |
case (Some(def_file), def_line) =>
|
wenzelm@48423
|
76 |
new External_Hyperlink(begin, end, line, def_file, def_line.getOrElse(1))
|
wenzelm@47049
|
77 |
case _ if !snapshot.is_outdated =>
|
wenzelm@47049
|
78 |
(props, props) match {
|
wenzelm@47049
|
79 |
case (Position.Id(def_id), Position.Offset(def_offset)) =>
|
wenzelm@47049
|
80 |
snapshot.state.find_command(snapshot.version, def_id) match {
|
wenzelm@47049
|
81 |
case Some((def_node, def_cmd)) =>
|
wenzelm@47049
|
82 |
def_node.command_start(def_cmd) match {
|
wenzelm@47049
|
83 |
case Some(def_cmd_start) =>
|
wenzelm@47049
|
84 |
new Internal_Hyperlink(def_cmd.node_name.node, begin, end, line,
|
wenzelm@47049
|
85 |
def_cmd_start + def_cmd.decode(def_offset))
|
wenzelm@47049
|
86 |
case None => null
|
wenzelm@47049
|
87 |
}
|
wenzelm@47049
|
88 |
case None => null
|
wenzelm@47049
|
89 |
}
|
wenzelm@47049
|
90 |
case _ => null
|
wenzelm@47049
|
91 |
}
|
wenzelm@47049
|
92 |
case _ => null
|
wenzelm@47049
|
93 |
}
|
wenzelm@47049
|
94 |
})
|
wenzelm@39458
|
95 |
markup match {
|
wenzelm@47069
|
96 |
case Text.Info(_, link) #:: _ => link
|
wenzelm@39458
|
97 |
case _ => null
|
wenzelm@39458
|
98 |
}
|
wenzelm@39101
|
99 |
case None => null
|
wenzelm@39101
|
100 |
}
|
immler@34571
|
101 |
}
|
immler@34571
|
102 |
}
|
immler@34571
|
103 |
}
|