1 /* Title: jedit/plugin/IsabellePlugin.scala
5 Isabelle/jEdit plugin -- main setup.
10 import org.gjt.sp.jedit.EditPlugin
11 import org.gjt.sp.util.Log
13 import errorlist.DefaultErrorSource
14 import errorlist.ErrorSource
16 import java.util.Properties
17 import java.lang.NumberFormatException
19 import scala.collection.mutable.ListBuffer
20 import scala.io.Source
25 object IsabellePlugin {
28 private var idCount = 0
30 def id() : String = synchronized { idCount += 1; "jedit:" + idCount }
32 def idProperties(value: String) : Properties = {
33 val props = new Properties
34 props.setProperty(Markup.ID, value)
38 def idProperties() : Properties = { idProperties(id()) }
43 var errors: DefaultErrorSource = null
45 // the Isabelle process
47 var isabelle: IsabelleProcess = null
51 def result_content(result: IsabelleProcess.Result) =
52 XML.content(isabelle.result_tree(result)).mkString("")
56 type consumer = IsabelleProcess.Result => Boolean
57 private var consumers = new ListBuffer[consumer]
59 def addConsumer(consumer: consumer) = synchronized { consumers += consumer }
61 def addPermanentConsumer(consumer: IsabelleProcess.Result => Unit) = {
62 addConsumer(result => { consumer(result); false })
65 def delConsumer(consumer: consumer) = synchronized { consumers -= consumer }
67 def consume(result: IsabelleProcess.Result) : Unit = {
68 synchronized { consumers.elements.toList } foreach (consumer =>
71 try { consumer(result) }
72 catch { case e: Throwable => Log.log(Log.ERROR, this, e); true }
73 if (finished || result == null)
80 /* Main plugin setup */
82 class IsabellePlugin extends EditPlugin {
83 private var thread: Thread = null
85 override def start = {
87 IsabellePlugin.errors = new DefaultErrorSource("isabelle")
88 ErrorSource.registerErrorSource(IsabellePlugin.errors)
90 IsabellePlugin.addPermanentConsumer (result =>
91 if (result != null && result.props != null &&
92 (result.kind == IsabelleProcess.Kind.WARNING ||
93 result.kind == IsabelleProcess.Kind.ERROR)) {
95 if (result.kind == IsabelleProcess.Kind.WARNING) ErrorSource.WARNING
96 else ErrorSource.ERROR
97 (Position.line_of(result.props), Position.file_of(result.props)) match {
98 case (Some(line), Some(file)) =>
99 val content = IsabellePlugin.result_content(result)
100 if (content.length > 0) {
101 val lines = Source.fromString(content).getLines
102 val err = new DefaultErrorSource.DefaultError(IsabellePlugin.errors,
103 typ, file, line - 1, 0, 0, lines.next)
104 for (msg <- lines) err.addExtraMessage(msg)
105 IsabellePlugin.errors.addError(err)
113 IsabellePlugin.isabelle =
114 new IsabelleProcess("-mno_brackets", "-mno_type_brackets", "-mxsymbols")
115 thread = new Thread (new Runnable {
117 var result: IsabelleProcess.Result = null
120 result = IsabellePlugin.isabelle.results.take
123 case _: NullPointerException => result = null
124 case _: InterruptedException => result = null
126 if (result != null) {
127 System.err.println(result) // FIXME
128 IsabellePlugin.consume(result)
130 if (result.kind == IsabelleProcess.Kind.EXIT) {
132 IsabellePlugin.consume(null)
134 } while (result != null)
140 override def stop = {
141 IsabellePlugin.isabelle.kill
142 thread.interrupt; thread.join; thread = null
143 IsabellePlugin.isabelle = null
145 ErrorSource.unregisterErrorSource(IsabellePlugin.errors)
146 IsabellePlugin.errors = null