src/Pure/Tools/ml_console.scala
author wenzelm
Tue, 08 Mar 2016 18:15:16 +0100
changeset 62559 83e815849a91
child 62561 4bf00f54e4bc
permissions -rw-r--r--
isabelle console is based on Isabelle/Scala;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Tools/ml_console.scala
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     3
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     4
Run Isabelle process with raw ML console and line editor.
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     5
*/
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     6
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     7
package isabelle
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     8
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     9
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    10
import scala.annotation.tailrec
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    11
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    12
import jline.console.ConsoleReader
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    13
import jline.console.history.FileHistory
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    14
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    15
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    16
object ML_Console
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    17
{
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    18
  /* command line entry point */
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    19
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    20
  def main(args: Array[String])
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    21
  {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    22
    Command_Line.tool {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    23
      var dirs: List[Path] = Nil
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    24
      var logic = Isabelle_System.getenv("ISABELLE_LOGIC")
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    25
      var modes: List[String] = Nil
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    26
      var no_build = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    27
      var options = Options.init()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    28
      var system_mode = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    29
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    30
      val getopts = Getopts("""
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    31
Usage: isabelle console [OPTIONS]
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    32
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    33
  Options are:
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    34
    -d DIR       include session directory
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    35
    -l NAME      logic session name (default ISABELLE_LOGIC=""" + quote(logic) + """)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    36
    -m MODE      add print mode for output
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    37
    -n           no build of session image on startup
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    38
    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    39
    -r           logic session is RAW_ML_SYSTEM
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    40
    -s           system build mode for session image
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    41
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    42
  Run Isabelle process with raw ML console and line editor.
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    43
""",
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    44
        "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    45
        "l:" -> (arg => logic = arg),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    46
        "m:" -> (arg => modes = arg :: modes),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    47
        "n" -> (arg => no_build = true),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    48
        "o:" -> (arg => options = options + arg),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    49
        "r" -> (_ => logic = "RAW_ML_SYSTEM"),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    50
        "s" -> (_ => system_mode = true))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    51
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    52
      val more_args = getopts(args)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    53
      if (!more_args.isEmpty) getopts.usage()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    54
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    55
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    56
      // build
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    57
      if (!no_build && logic != "RAW_ML_SYSTEM" &&
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    58
          Build.build(options = options, build_heap = true, no_build = true,
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    59
            dirs = dirs, system_mode = system_mode, sessions = List(logic)) != 0)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    60
      {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    61
        val progress = new Console_Progress
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    62
        progress.echo("Build started for Isabelle/" + logic + " ...")
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    63
        progress.interrupt_handler {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    64
          val rc =
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    65
            Build.build(options = options, progress = progress, build_heap = true,
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    66
              dirs = dirs, system_mode = system_mode, sessions = List(logic))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    67
          if (rc != 0) sys.exit(rc)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    68
        }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    69
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    70
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    71
      // reader with history
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    72
      val history = new FileHistory(Path.explode("$ISABELLE_HOME_USER/console_history").file)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    73
      val reader = new ConsoleReader
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    74
      reader.setHistory(history)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    75
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    76
      // process loop
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    77
      val process =
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    78
        ML_Process(options, heap = logic,
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    79
          modes = if (logic == "RAW_ML_SYSTEM") Nil else modes ::: List("ASCII"))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    80
      val process_output = Future.thread[Unit]("process_output") {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    81
        var result = new StringBuilder(100)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    82
        var finished = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    83
        while (!finished) {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    84
          var c = -1
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    85
          var done = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    86
          while (!done && (result.length == 0 || process.stdout.ready)) {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    87
            c = process.stdout.read
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    88
            if (c >= 0) result.append(c.asInstanceOf[Char])
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    89
            else done = true
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    90
          }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    91
          if (result.length > 0) {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    92
            System.out.print(result.toString)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    93
            System.out.flush()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    94
            result.length = 0
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    95
          }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    96
          else {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    97
            process.stdout.close()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    98
            finished = true
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    99
          }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   100
        }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   101
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   102
      val process_input = Future.thread[Unit]("process_input") {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   103
        POSIX_Interrupt.handler { process.interrupt } {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   104
          var finished = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   105
          while (!finished) {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   106
            reader.readLine() match {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   107
              case null =>
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   108
                process.stdin.close()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   109
                finished = true
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   110
              case line =>
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   111
                process.stdin.write(line)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   112
                process.stdin.write("\n")
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   113
                process.stdin.flush()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   114
            }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   115
          }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   116
        }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   117
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   118
      val process_result = Future.thread[Int]("process_result") {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   119
        val rc = process.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   120
        process_input.cancel
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   121
        rc
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   122
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   123
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   124
      process_output.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   125
      process_input.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   126
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   127
      val rc = process_result.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   128
      history.flush()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   129
      rc
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   130
    }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   131
  }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   132
}