src/Tools/jEdit/src/scala_console.scala
author wenzelm
Fri, 20 Jul 2012 22:29:25 +0200
changeset 49424 0d2114eb412a
parent 49007 7700f0e9618c
child 49427 dbd75cbb84ba
permissions -rw-r--r--
more explicit java.io.{File => JFile};
wenzelm@44162
     1
/*  Title:      Tools/jEdit/src/scala_console.scala
wenzelm@36760
     2
    Author:     Makarius
wenzelm@36760
     3
wenzelm@36760
     4
Scala instance of Console plugin.
wenzelm@36760
     5
*/
wenzelm@34844
     6
wenzelm@34844
     7
package isabelle.jedit
wenzelm@34844
     8
wenzelm@34844
     9
wenzelm@36039
    10
import isabelle._
wenzelm@36039
    11
wenzelm@34847
    12
import console.{Console, ConsolePane, Shell, Output}
wenzelm@34844
    13
wenzelm@34848
    14
import org.gjt.sp.jedit.{jEdit, JARClassLoader}
wenzelm@34844
    15
import org.gjt.sp.jedit.MiscUtilities
wenzelm@34844
    16
wenzelm@44400
    17
import java.lang.System
wenzelm@49424
    18
import java.io.{File => JFile, OutputStream, Writer, PrintWriter}
wenzelm@34844
    19
wenzelm@49007
    20
import scala.tools.nsc.{GenericRunnerSettings, NewLinePrintWriter, ConsoleWriter}
wenzelm@49007
    21
import scala.tools.nsc.interpreter.IMain
wenzelm@34849
    22
import scala.collection.mutable
wenzelm@34844
    23
wenzelm@34844
    24
wenzelm@34844
    25
class Scala_Console extends Shell("Scala")
wenzelm@34844
    26
{
wenzelm@34853
    27
  /* reconstructed jEdit/plugin classpath */
wenzelm@34853
    28
wenzelm@34853
    29
  private def reconstruct_classpath(): String =
wenzelm@34853
    30
  {
wenzelm@34853
    31
    def find_jars(start: String): List[String] =
wenzelm@34853
    32
      if (start != null)
wenzelm@49424
    33
        Standard_System.find_files(new JFile(start),
wenzelm@34853
    34
          entry => entry.isFile && entry.getName.endsWith(".jar")).map(_.getAbsolutePath)
wenzelm@34853
    35
      else Nil
wenzelm@34853
    36
    val path = find_jars(jEdit.getSettingsDirectory) ::: find_jars(jEdit.getJEditHome)
wenzelm@49424
    37
    path.mkString(JFile.pathSeparator)
wenzelm@34853
    38
  }
wenzelm@34853
    39
wenzelm@34853
    40
wenzelm@34852
    41
  /* global state -- owned by Swing thread */
wenzelm@34852
    42
wenzelm@49007
    43
  private var interpreters = Map[Console, IMain]()
wenzelm@34844
    44
wenzelm@34844
    45
  private var global_console: Console = null
wenzelm@34844
    46
  private var global_out: Output = null
wenzelm@34844
    47
  private var global_err: Output = null
wenzelm@34844
    48
wenzelm@34853
    49
  private val console_stream = new OutputStream
wenzelm@34853
    50
  {
wenzelm@34853
    51
    val buf = new StringBuilder
wenzelm@34853
    52
    override def flush()
wenzelm@34853
    53
    {
wenzelm@34853
    54
      val str = Standard_System.decode_permissive_utf8(buf.toString)
wenzelm@34853
    55
      buf.clear
wenzelm@34853
    56
      if (global_out == null) System.out.print(str)
wenzelm@34853
    57
      else Swing_Thread.now { global_out.writeAttrs(null, str) }
wenzelm@34853
    58
    }
wenzelm@34853
    59
    override def close() { flush () }
wenzelm@34853
    60
    def write(byte: Int) { buf.append(byte.toChar) }
wenzelm@34853
    61
  }
wenzelm@34853
    62
wenzelm@34853
    63
  private val console_writer = new Writer
wenzelm@34853
    64
  {
wenzelm@34853
    65
    def flush() {}
wenzelm@34853
    66
    def close() {}
wenzelm@34853
    67
wenzelm@34853
    68
    def write(cbuf: Array[Char], off: Int, len: Int)
wenzelm@34853
    69
    {
wenzelm@36039
    70
      if (len > 0) write(new String(cbuf.slice(off, off + len)))
wenzelm@34853
    71
    }
wenzelm@34853
    72
wenzelm@34853
    73
    override def write(str: String)
wenzelm@34853
    74
    {
wenzelm@34853
    75
      if (global_out == null) System.out.println(str)
wenzelm@34853
    76
      else global_out.print(null, str)
wenzelm@34853
    77
    }
wenzelm@34853
    78
  }
wenzelm@34853
    79
wenzelm@34847
    80
  private def with_console[A](console: Console, out: Output, err: Output)(e: => A): A =
wenzelm@34847
    81
  {
wenzelm@34847
    82
    global_console = console
wenzelm@34847
    83
    global_out = out
wenzelm@34847
    84
    global_err = if (err == null) out else err
wenzelm@34853
    85
    val res = Exn.capture { scala.Console.withOut(console_stream)(e) }
wenzelm@34853
    86
    console_stream.flush
wenzelm@34847
    87
    global_console = null
wenzelm@34847
    88
    global_out = null
wenzelm@34847
    89
    global_err = null
wenzelm@34847
    90
    Exn.release(res)
wenzelm@34847
    91
  }
wenzelm@34847
    92
wenzelm@34844
    93
  private def report_error(str: String)
wenzelm@34844
    94
  {
wenzelm@34844
    95
    if (global_console == null || global_err == null) System.err.println(str)
wenzelm@34853
    96
    else Swing_Thread.now { global_err.print(global_console.getErrorColor, str) }
wenzelm@34844
    97
  }
wenzelm@34844
    98
wenzelm@34849
    99
wenzelm@34853
   100
  /* jEdit console methods */
wenzelm@34844
   101
wenzelm@34844
   102
  override def openConsole(console: Console)
wenzelm@34844
   103
  {
wenzelm@34844
   104
    val settings = new GenericRunnerSettings(report_error)
wenzelm@34853
   105
    settings.classpath.value = reconstruct_classpath()
wenzelm@34852
   106
wenzelm@49007
   107
    val interp = new IMain(settings, new PrintWriter(console_writer, true))
wenzelm@34848
   108
    {
wenzelm@34848
   109
      override def parentClassLoader = new JARClassLoader
wenzelm@34848
   110
    }
wenzelm@34848
   111
    interp.setContextClassLoader
wenzelm@34849
   112
    interp.bind("view", "org.gjt.sp.jedit.View", console.getView)
wenzelm@34855
   113
    interp.bind("console", "console.Console", console)
wenzelm@34854
   114
    interp.interpret("import isabelle.jedit.Isabelle")
wenzelm@34853
   115
wenzelm@34848
   116
    interpreters += (console -> interp)
wenzelm@34844
   117
  }
wenzelm@34844
   118
wenzelm@34844
   119
  override def closeConsole(console: Console)
wenzelm@34844
   120
  {
wenzelm@34844
   121
    interpreters -= console
wenzelm@34844
   122
  }
wenzelm@34844
   123
wenzelm@34852
   124
  override def printInfoMessage(out: Output)
wenzelm@34852
   125
  {
wenzelm@34852
   126
    out.print(null,
wenzelm@34852
   127
     "This shell evaluates Isabelle/Scala expressions.\n\n" +
wenzelm@34852
   128
     "The following special toplevel bindings are provided:\n" +
wenzelm@34854
   129
     "  view      -- current jEdit/Swing view (e.g. view.getBuffer, view.getTextArea)\n" +
wenzelm@46451
   130
     "  console   -- jEdit Console plugin\n" +
wenzelm@46451
   131
     "  Isabelle  -- Isabelle plugin (e.g. Isabelle.session, Isabelle.document_model)\n")
wenzelm@34852
   132
  }
wenzelm@34852
   133
wenzelm@34844
   134
  override def printPrompt(console: Console, out: Output)
wenzelm@37176
   135
  {
wenzelm@34847
   136
    out.writeAttrs(ConsolePane.colorAttributes(console.getInfoColor), "scala>")
wenzelm@37176
   137
    out.writeAttrs(ConsolePane.colorAttributes(console.getPlainColor), " ")
wenzelm@37176
   138
  }
wenzelm@34844
   139
wenzelm@34844
   140
  override def execute(console: Console, input: String, out: Output, err: Output, command: String)
wenzelm@34844
   141
  {
wenzelm@34849
   142
    val interp = interpreters(console)
wenzelm@34849
   143
    with_console(console, out, err) { interp.interpret(command) }
wenzelm@34847
   144
    if (err != null) err.commandDone()
wenzelm@37176
   145
    out.commandDone()
wenzelm@34844
   146
  }
wenzelm@34852
   147
wenzelm@34852
   148
  override def stop(console: Console)
wenzelm@34852
   149
  {
wenzelm@34852
   150
    closeConsole(console)
wenzelm@34852
   151
    console.clear
wenzelm@34852
   152
    openConsole(console)
wenzelm@34852
   153
    val out = console.getOutput
wenzelm@34852
   154
    out.commandDone
wenzelm@34852
   155
    printPrompt(console, out)
wenzelm@34852
   156
  }
wenzelm@34844
   157
}