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