| author | wenzelm | 
| Fri, 01 Sep 2023 21:23:55 +0200 | |
| changeset 78629 | 569135d7352a | 
| parent 75702 | 97e8f4c938bf | 
| child 80492 | 43323d886ea3 | 
| permissions | -rw-r--r-- | 
| 73987 
fc363a3b690a
build.props for isabelle.jar, including isabelle.jedit;
 wenzelm parents: 
73702diff
changeset | 1 | /* Title: Tools/jEdit/jedit_main/scala_console.scala | 
| 36760 | 2 | Author: Makarius | 
| 3 | ||
| 4 | Scala instance of Console plugin. | |
| 5 | */ | |
| 34841 | 6 | |
| 73987 
fc363a3b690a
build.props for isabelle.jar, including isabelle.jedit;
 wenzelm parents: 
73702diff
changeset | 7 | package isabelle.jedit_main | 
| 34841 | 8 | |
| 9 | ||
| 36015 | 10 | import isabelle._ | 
| 73987 
fc363a3b690a
build.props for isabelle.jar, including isabelle.jedit;
 wenzelm parents: 
73702diff
changeset | 11 | import isabelle.jedit._ | 
| 36015 | 12 | |
| 34844 | 13 | import console.{Console, ConsolePane, Shell, Output}
 | 
| 71863 | 14 | import org.gjt.sp.jedit.JARClassLoader | 
| 75654 | 15 | import java.io.OutputStream | 
| 34841 | 16 | |
| 17 | ||
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 18 | object Scala_Console {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 19 | class Interpreter(context: Scala.Compiler.Context, val console: Console) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 20 | extends Scala.Interpreter(context) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 21 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 22 | def console_interpreter(console: Console): Option[Interpreter] = | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 23 |     Scala.Interpreter.get { case int: Interpreter if int.console == console => int }
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 24 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 25 |   def running_interpreter(): Interpreter = {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 26 | val self = Thread.currentThread() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 27 |     Scala.Interpreter.get { case int: Interpreter if int.running_thread(self) => int }
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 28 |       .getOrElse(error("Bad Scala interpreter thread"))
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 29 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 30 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 31 | def running_console(): Console = running_interpreter().console | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 32 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 33 | val init = """ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 34 | import isabelle._ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 35 | import isabelle.jedit._ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 36 | val console = isabelle.jedit_main.Scala_Console.running_console() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 37 | val view = console.getView() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 38 | """ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 39 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 40 | |
| 75393 | 41 | class Scala_Console extends Shell("Scala") {
 | 
| 57612 
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
 wenzelm parents: 
57609diff
changeset | 42 | /* global state -- owned by GUI thread */ | 
| 34849 | 43 | |
| 57609 | 44 | @volatile private var global_console: Console = null | 
| 45 | @volatile private var global_out: Output = null | |
| 46 | @volatile private var global_err: Output = null | |
| 34841 | 47 | |
| 75393 | 48 |   private val console_stream = new OutputStream {
 | 
| 65876 | 49 | val buf = new StringBuilder(100) | 
| 50 | ||
| 75393 | 51 |     override def flush(): Unit = {
 | 
| 73367 | 52 |       val s = buf.synchronized { val s = buf.toString; buf.clear(); s }
 | 
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 53 | val str = UTF8.decode_permissive(s) | 
| 57612 
990ffb84489b
clarified module name: facilitate alternative GUI frameworks;
 wenzelm parents: 
57609diff
changeset | 54 |       GUI_Thread.later {
 | 
| 74023 
fd4b4385ad3c
more robust: for the sake of Isabelle.app on macOS;
 wenzelm parents: 
73987diff
changeset | 55 | if (global_out == null) java.lang.System.out.print(str) | 
| 56834 
a752f065f3d3
fork Scala interpreter thread, independently of Swing_Thread;
 wenzelm parents: 
56833diff
changeset | 56 | else global_out.writeAttrs(null, str) | 
| 
a752f065f3d3
fork Scala interpreter thread, independently of Swing_Thread;
 wenzelm parents: 
56833diff
changeset | 57 | } | 
| 73702 
7202e12cb324
tuned signature --- following hints by IntelliJ IDEA;
 wenzelm parents: 
73367diff
changeset | 58 | Time.seconds(0.01).sleep() // FIXME adhoc delay to avoid loosing output | 
| 34850 
fdd560e80264
redirect scala.Console output during interpretation;
 wenzelm parents: 
34849diff
changeset | 59 | } | 
| 65876 | 60 | |
| 73340 | 61 | override def close(): Unit = flush() | 
| 65876 | 62 | |
| 75393 | 63 |     def write(byte: Int): Unit = {
 | 
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 64 | val c = byte.toChar | 
| 57609 | 65 |       buf.synchronized { buf.append(c) }
 | 
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 66 | if (c == '\n') flush() | 
| 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 67 | } | 
| 34850 
fdd560e80264
redirect scala.Console output during interpretation;
 wenzelm parents: 
34849diff
changeset | 68 | } | 
| 
fdd560e80264
redirect scala.Console output during interpretation;
 wenzelm parents: 
34849diff
changeset | 69 | |
| 75393 | 70 |   private def with_console[A](console: Console, out: Output, err: Output)(e: => A): A = {
 | 
| 34844 | 71 | global_console = console | 
| 72 | global_out = out | |
| 73 | global_err = if (err == null) out else err | |
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 74 |     try {
 | 
| 56832 | 75 |       scala.Console.withErr(console_stream) {
 | 
| 76 |         scala.Console.withOut(console_stream) { e }
 | |
| 77 | } | |
| 78 | } | |
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 79 |     finally {
 | 
| 74037 | 80 | console_stream.flush() | 
| 56833 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 81 | global_console = null | 
| 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 82 | global_out = null | 
| 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 83 | global_err = null | 
| 
d0a57abc71f8
clarified synchronization and exception handling;
 wenzelm parents: 
56832diff
changeset | 84 | } | 
| 34844 | 85 | } | 
| 86 | ||
| 34841 | 87 | |
| 56834 
a752f065f3d3
fork Scala interpreter thread, independently of Swing_Thread;
 wenzelm parents: 
56833diff
changeset | 88 | /* jEdit console methods */ | 
| 
a752f065f3d3
fork Scala interpreter thread, independently of Swing_Thread;
 wenzelm parents: 
56833diff
changeset | 89 | |
| 75393 | 90 |   override def openConsole(console: Console): Unit = {
 | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 91 | val context = | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 92 | Scala.Compiler.context( | 
| 75702 | 93 | jar_files = JEdit_Lib.directories, | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 94 | class_loader = Some(new JARClassLoader)) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 95 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 96 | val interpreter = new Scala_Console.Interpreter(context, console) | 
| 75654 | 97 | interpreter.execute((context, state) => | 
| 98 | context.compile(Scala_Console.init, state = state).state) | |
| 34841 | 99 | } | 
| 100 | ||
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 101 | override def closeConsole(console: Console): Unit = | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 102 | Scala_Console.console_interpreter(console).foreach(_.shutdown()) | 
| 34841 | 103 | |
| 75393 | 104 |   override def printInfoMessage(out: Output): Unit = {
 | 
| 34849 | 105 | out.print(null, | 
| 106 | "This shell evaluates Isabelle/Scala expressions.\n\n" + | |
| 57848 | 107 | "The contents of package isabelle and isabelle.jedit are imported.\n" + | 
| 34849 | 108 | "The following special toplevel bindings are provided:\n" + | 
| 50205 | 109 | " view -- current jEdit/Swing view (e.g. view.getBuffer, view.getTextArea)\n" + | 
| 110 | " console -- jEdit Console plugin\n" + | |
| 55621 
8d69c15b6fb9
added PIDE.snapshot, PIDE.rendering for convenience;
 wenzelm parents: 
55618diff
changeset | 111 | " PIDE -- Isabelle/PIDE plugin (e.g. PIDE.session, PIDE.snapshot, PIDE.rendering)\n") | 
| 34849 | 112 | } | 
| 113 | ||
| 75393 | 114 |   override def printPrompt(console: Console, out: Output): Unit = {
 | 
| 34844 | 115 | out.writeAttrs(ConsolePane.colorAttributes(console.getInfoColor), "scala>") | 
| 37175 | 116 | out.writeAttrs(ConsolePane.colorAttributes(console.getPlainColor), " ") | 
| 117 | } | |
| 34841 | 118 | |
| 73340 | 119 | override def execute( | 
| 75393 | 120 | console: Console, | 
| 121 | input: String, | |
| 122 | out: Output, | |
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 123 | err: Output, | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 124 | command: String | 
| 75393 | 125 |   ): Unit = {
 | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 126 | Scala_Console.console_interpreter(console).foreach(interpreter => | 
| 75654 | 127 |       interpreter.execute { (context, state) =>
 | 
| 128 |         val result = with_console(console, out, err) { context.compile(command, state) }
 | |
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 129 |         GUI_Thread.later {
 | 
| 75654 | 130 | val diag = if (err == null) out else err | 
| 131 |           for (message <- result.messages) {
 | |
| 132 | val color = if (message.is_error) console.getErrorColor else null | |
| 133 | diag.print(color, message.text + "\n") | |
| 134 | } | |
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 135 | Option(err).foreach(_.commandDone()) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 136 | out.commandDone() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 137 | } | 
| 75654 | 138 | result.state | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 139 | }) | 
| 34841 | 140 | } | 
| 34849 | 141 | |
| 73340 | 142 | override def stop(console: Console): Unit = | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 143 | Scala_Console.console_interpreter(console).foreach(_.shutdown()) | 
| 34841 | 144 | } |