src/Tools/jEdit/src/isabelle_hyperlinks.scala
author wenzelm
Fri, 20 Jul 2012 22:29:25 +0200
changeset 49424 0d2114eb412a
parent 48738 dd9cbe708e6b
permissions -rw-r--r--
more explicit java.io.{File => JFile};
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
}