lib/jedit/plugin/isabelle_plugin.scala
author wenzelm
Sun, 24 Aug 2008 19:02:22 +0200
changeset 27987 c3f7fa72af2a
child 27988 efc6d38d16d2
permissions -rw-r--r--
rearranged source files;
wenzelm@27987
     1
/*  Title:      lib/jedit/plugin/isabelle_plugin.scala
wenzelm@27987
     2
    ID:         $Id$
wenzelm@27987
     3
    Author:     Makarius
wenzelm@27987
     4
wenzelm@27987
     5
Isabelle/jEdit plugin -- main setup.
wenzelm@27987
     6
*/
wenzelm@27987
     7
wenzelm@27987
     8
package isabelle.jedit
wenzelm@27987
     9
wenzelm@27987
    10
import org.gjt.sp.jedit.EditPlugin
wenzelm@27987
    11
import org.gjt.sp.util.Log
wenzelm@27987
    12
wenzelm@27987
    13
import errorlist.DefaultErrorSource
wenzelm@27987
    14
import errorlist.ErrorSource
wenzelm@27987
    15
wenzelm@27987
    16
import java.util.Properties
wenzelm@27987
    17
import java.lang.NumberFormatException
wenzelm@27987
    18
wenzelm@27987
    19
import scala.collection.mutable.ListBuffer
wenzelm@27987
    20
import scala.io.Source
wenzelm@27987
    21
wenzelm@27987
    22
wenzelm@27987
    23
/* Global state */
wenzelm@27987
    24
wenzelm@27987
    25
object IsabellePlugin {
wenzelm@27987
    26
  // unique ids
wenzelm@27987
    27
  @volatile
wenzelm@27987
    28
  private var idCount = 0
wenzelm@27987
    29
wenzelm@27987
    30
  def id() : String = synchronized { idCount += 1; "jedit:" + idCount }
wenzelm@27987
    31
wenzelm@27987
    32
  def idProperties(value: String) : Properties = {
wenzelm@27987
    33
     val props = new Properties
wenzelm@27987
    34
     props.setProperty(Markup.ID, value)
wenzelm@27987
    35
     props
wenzelm@27987
    36
  }
wenzelm@27987
    37
wenzelm@27987
    38
  def idProperties() : Properties = { idProperties(id()) }
wenzelm@27987
    39
wenzelm@27987
    40
wenzelm@27987
    41
  // the error source
wenzelm@27987
    42
  @volatile
wenzelm@27987
    43
  var errors: DefaultErrorSource = null
wenzelm@27987
    44
wenzelm@27987
    45
  // the Isabelle process
wenzelm@27987
    46
  @volatile
wenzelm@27987
    47
  var isabelle: IsabelleProcess = null
wenzelm@27987
    48
wenzelm@27987
    49
wenzelm@27987
    50
  // result content
wenzelm@27987
    51
  def result_content(result: IsabelleProcess.Result) =
wenzelm@27987
    52
    XML.content(isabelle.result_tree(result)).mkString("")
wenzelm@27987
    53
wenzelm@27987
    54
wenzelm@27987
    55
  // result consumers
wenzelm@27987
    56
  type consumer = IsabelleProcess.Result => Boolean
wenzelm@27987
    57
  private var consumers = new ListBuffer[consumer]
wenzelm@27987
    58
wenzelm@27987
    59
  def addConsumer(consumer: consumer) = synchronized { consumers += consumer }
wenzelm@27987
    60
wenzelm@27987
    61
  def addPermanentConsumer(consumer: IsabelleProcess.Result => Unit) = {
wenzelm@27987
    62
    addConsumer(result => { consumer(result); false })
wenzelm@27987
    63
  }
wenzelm@27987
    64
wenzelm@27987
    65
  def delConsumer(consumer: consumer) = synchronized { consumers -= consumer }
wenzelm@27987
    66
wenzelm@27987
    67
  def consume(result: IsabelleProcess.Result) : Unit = {
wenzelm@27987
    68
    synchronized { consumers.elements.toList } foreach (consumer =>
wenzelm@27987
    69
      {
wenzelm@27987
    70
        val finished =
wenzelm@27987
    71
          try { consumer(result) }
wenzelm@27987
    72
          catch { case e: Throwable => Log.log(Log.ERROR, this, e); true }
wenzelm@27987
    73
        if (finished || result == null)
wenzelm@27987
    74
          delConsumer(consumer)
wenzelm@27987
    75
      })
wenzelm@27987
    76
  }
wenzelm@27987
    77
}
wenzelm@27987
    78
wenzelm@27987
    79
wenzelm@27987
    80
/* Main plugin setup */
wenzelm@27987
    81
wenzelm@27987
    82
class IsabellePlugin extends EditPlugin {
wenzelm@27987
    83
  private var thread: Thread = null
wenzelm@27987
    84
wenzelm@27987
    85
  override def start = {
wenzelm@27987
    86
    // error source
wenzelm@27987
    87
    IsabellePlugin.errors = new DefaultErrorSource("isabelle")
wenzelm@27987
    88
    ErrorSource.registerErrorSource(IsabellePlugin.errors)
wenzelm@27987
    89
wenzelm@27987
    90
    IsabellePlugin.addPermanentConsumer (result =>
wenzelm@27987
    91
      if (result != null && result.props != null &&
wenzelm@27987
    92
          (result.kind == IsabelleProcess.Kind.WARNING ||
wenzelm@27987
    93
           result.kind == IsabelleProcess.Kind.ERROR)) {
wenzelm@27987
    94
        val typ =
wenzelm@27987
    95
          if (result.kind == IsabelleProcess.Kind.WARNING) ErrorSource.WARNING
wenzelm@27987
    96
          else ErrorSource.ERROR
wenzelm@27987
    97
        (Position.line_of(result.props), Position.file_of(result.props)) match {
wenzelm@27987
    98
          case (Some(line), Some(file)) =>
wenzelm@27987
    99
            val content = IsabellePlugin.result_content(result)
wenzelm@27987
   100
            if (content.length > 0) {
wenzelm@27987
   101
              val lines = Source.fromString(content).getLines
wenzelm@27987
   102
              val err = new DefaultErrorSource.DefaultError(IsabellePlugin.errors,
wenzelm@27987
   103
                  typ, file, line - 1, 0, 0, lines.next)
wenzelm@27987
   104
              for (msg <- lines) err.addExtraMessage(msg)
wenzelm@27987
   105
              IsabellePlugin.errors.addError(err)
wenzelm@27987
   106
            }
wenzelm@27987
   107
          case _ =>
wenzelm@27987
   108
        }
wenzelm@27987
   109
      })
wenzelm@27987
   110
wenzelm@27987
   111
wenzelm@27987
   112
    // Isabelle process
wenzelm@27987
   113
    IsabellePlugin.isabelle =
wenzelm@27987
   114
      new IsabelleProcess("-mno_brackets", "-mno_type_brackets", "-mxsymbols")
wenzelm@27987
   115
    thread = new Thread (new Runnable {
wenzelm@27987
   116
      def run = {
wenzelm@27987
   117
        var result: IsabelleProcess.Result = null
wenzelm@27987
   118
        do {
wenzelm@27987
   119
          try {
wenzelm@27987
   120
            result = IsabellePlugin.isabelle.results.take
wenzelm@27987
   121
          }
wenzelm@27987
   122
          catch {
wenzelm@27987
   123
            case _: NullPointerException => result = null
wenzelm@27987
   124
            case _: InterruptedException => result = null
wenzelm@27987
   125
          }
wenzelm@27987
   126
          if (result != null) {
wenzelm@27987
   127
            System.err.println(result)   // FIXME
wenzelm@27987
   128
            IsabellePlugin.consume(result)
wenzelm@27987
   129
          }
wenzelm@27987
   130
          if (result.kind == IsabelleProcess.Kind.EXIT) {
wenzelm@27987
   131
            result = null
wenzelm@27987
   132
            IsabellePlugin.consume(null)
wenzelm@27987
   133
          }
wenzelm@27987
   134
        } while (result != null)
wenzelm@27987
   135
      }
wenzelm@27987
   136
    })
wenzelm@27987
   137
    thread.start
wenzelm@27987
   138
  }
wenzelm@27987
   139
wenzelm@27987
   140
  override def stop = {
wenzelm@27987
   141
    IsabellePlugin.isabelle.kill
wenzelm@27987
   142
    thread.interrupt; thread.join; thread = null
wenzelm@27987
   143
    IsabellePlugin.isabelle = null
wenzelm@27987
   144
wenzelm@27987
   145
    ErrorSource.unregisterErrorSource(IsabellePlugin.errors)
wenzelm@27987
   146
    IsabellePlugin.errors = null
wenzelm@27987
   147
  }
wenzelm@27987
   148
}