1 /* Title: lib/jedit/plugin/isabelle_plugin.scala
5 Isabelle/jEdit plugin -- main setup.
10 import org.gjt.sp.jedit.jEdit
11 import org.gjt.sp.jedit.EditPlugin
12 import org.gjt.sp.util.Log
14 import errorlist.DefaultErrorSource
15 import errorlist.ErrorSource
17 import java.util.Properties
18 import java.lang.NumberFormatException
20 import scala.collection.mutable.ListBuffer
21 import scala.io.Source
27 object IsabellePlugin {
29 /* Isabelle process */
31 var isabelle: IsabelleProcess = null
33 def result_content(result: IsabelleProcess.Result) =
34 XML.content(isabelle.decode_result(result)).mkString("")
39 private var id_count: BigInt = 0
41 def id() : String = synchronized { id_count += 1; "jedit:" + id_count }
43 def id_properties(value: String) : Properties = {
44 val props = new Properties
45 props.setProperty(Markup.ID, value)
49 def id_properties() : Properties = { id_properties(id()) }
52 /* result consumers */
54 type Consumer = IsabelleProcess.Result => Boolean
55 private var consumers = new ListBuffer[Consumer]
57 def add_consumer(consumer: Consumer) = synchronized { consumers += consumer }
59 def add_permanent_consumer(consumer: IsabelleProcess.Result => Unit) = {
60 add_consumer(result => { consumer(result); false })
63 def del_consumer(consumer: Consumer) = synchronized { consumers -= consumer }
65 private def consume(result: IsabelleProcess.Result) = {
66 synchronized { consumers.elements.toList } foreach (consumer =>
68 if (result != null && result.is_control) Log.log(Log.DEBUG, result, null)
70 try { consumer(result) }
71 catch { case e: Throwable => Log.log(Log.ERROR, result, e); true }
72 if (finished || result == null) del_consumer(consumer)
76 class ConsumerThread extends Thread {
81 try { IsabellePlugin.isabelle.get_result() }
82 catch { case _: NullPointerException => null }
86 if (result.kind == IsabelleProcess.Kind.EXIT) {
99 /* Main plugin setup */
101 class IsabellePlugin extends EditPlugin {
103 import IsabellePlugin._
105 val errors = new DefaultErrorSource("isabelle")
106 val consumer_thread = new ConsumerThread
109 override def start = {
113 ErrorSource.registerErrorSource(errors)
115 add_permanent_consumer (result =>
116 if (result != null &&
117 (result.kind == IsabelleProcess.Kind.WARNING ||
118 result.kind == IsabelleProcess.Kind.ERROR)) {
119 (Position.line_of(result.props), Position.file_of(result.props)) match {
120 case (Some(line), Some(file)) =>
122 if (result.kind == IsabelleProcess.Kind.WARNING) ErrorSource.WARNING
123 else ErrorSource.ERROR
124 val content = result_content(result)
125 if (content.length > 0) {
126 val lines = Source.fromString(content).getLines
127 val err = new DefaultErrorSource.DefaultError(errors,
128 typ, file, line - 1, 0, 0, lines.next)
129 for (msg <- lines) err.addExtraMessage(msg)
137 /* Isabelle process */
140 (for (mode <- jEdit.getProperty("isabelle.print-modes").split("\\s+") if mode != "")
143 val logic = jEdit.getProperty("isabelle.logic")
144 if (logic != "") List(logic) else Nil
146 isabelle = new IsabelleProcess((options ++ args): _*)
148 consumer_thread.start
153 override def stop = {
156 ErrorSource.unregisterErrorSource(errors)