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