diff --git a/bundledevtool/pom.xml b/bundledevtool/pom.xml
index 4262a649b..4a6b09ce3 100644
--- a/bundledevtool/pom.xml
+++ b/bundledevtool/pom.xml
@@ -36,11 +36,6 @@
org.apache.clerezza.scala
script-engine
-
- jline
- jline
- 0.9.94
-
org.scala-lang
scala-compiler
diff --git a/parent/pom.xml b/parent/pom.xml
index 776e3bef3..613a3f7c1 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -25,7 +25,6 @@
org.apache
apache
10
- ../parent
org.apache.clerezza
clerezza
@@ -35,7 +34,7 @@
0.3-incubating-SNAPSHOT
The direct or indirect parent of all Clerezza Artifacts
- 2.8.1
+ 2.9.2
multimodule-source-release
diff --git a/platform.launcher.storageless.parent/pom.xml b/platform.launcher.storageless.parent/pom.xml
index 40f66d808..de5cae4a8 100644
--- a/platform.launcher.storageless.parent/pom.xml
+++ b/platform.launcher.storageless.parent/pom.xml
@@ -30,7 +30,7 @@
0.9-incubating-SNAPSHOT
pom
Clerezza - Platform Launcher Storageless Parent POM
- A parent for Platform launchers, containing the platform bundles as runtime dependencies.
+ A parent for Platform launchers, containing the platform bundlessca as runtime dependencies.
platform.launcher.storageless
@@ -83,19 +83,13 @@
org.apache.servicemix.bundles
org.apache.servicemix.bundles.scala-library
- 2.8.1_1
+ 2.9.2_1
runtime
org.apache.servicemix.bundles
org.apache.servicemix.bundles.scala-compiler
- 2.8.1_1
- runtime
-
-
- org.apache.servicemix.bundles
- org.apache.servicemix.bundles.jline
- 0.9.94_1
+ 2.9.2_1
runtime
diff --git a/scala-scripting/pom.xml b/scala-scripting/pom.xml
index 8fa8dcc33..463dbc5ab 100644
--- a/scala-scripting/pom.xml
+++ b/scala-scripting/pom.xml
@@ -43,12 +43,12 @@
org.scala-lang
scala-library
- 2.8.1
+ 2.9.2
org.scala-lang
scala-compiler
- 2.8.1
+ 2.9.2
org.apache.felix
diff --git a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/BundleContextScalaInterpreter.scala b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/BundleContextScalaInterpreter.scala
index 0fd01167f..f713e3071 100644
--- a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/BundleContextScalaInterpreter.scala
+++ b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/BundleContextScalaInterpreter.scala
@@ -29,7 +29,7 @@ import scala.tools.nsc.reporters.Reporter
class BundleContextScalaInterpreter(bundleContext : BundleContext, out: PrintWriter)
- extends Interpreter(new Settings, out) {
+ extends IMain(new Settings, out) {
def this(bundleContext : BundleContext) = {
this(bundleContext, new PrintWriter(System.out))
diff --git a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/InterpreterFactory.scala b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/InterpreterFactory.scala
index 8ca491fec..dda2595ae 100644
--- a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/InterpreterFactory.scala
+++ b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/InterpreterFactory.scala
@@ -42,7 +42,7 @@ class InterpreterFactory() {
bundleContext = null
}
- def createInterpreter(out: PrintWriter) : Interpreter = {
+ def createInterpreter(out: PrintWriter) : IMain = {
val i = new BundleContextScalaInterpreter(bundleContext, out)
i
}
diff --git a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/ScriptEngineFactory.scala b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/ScriptEngineFactory.scala
index 85b8238d5..00d72773c 100644
--- a/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/ScriptEngineFactory.scala
+++ b/scala-scripting/script-engine/src/main/scala/org/apache/clerezza/scala/scripting/ScriptEngineFactory.scala
@@ -55,7 +55,7 @@ class ScriptEngineFactory() extends JavaxEngineFactory with BundleListener {
private var factory: InterpreterFactory = null
private var compilerService: CompilerService = null
- var _interpreter : Interpreter = null;
+ var _interpreter : IMain = null;
private var bundleContext: BundleContext = null
def interpreter = {
if (_interpreter == null) {
@@ -157,10 +157,7 @@ class ScriptEngineFactory() extends JavaxEngineFactory with BundleListener {
interpreter.bind(entry._1,
getAccessibleClass(entry._2.getClass).getName, entry._2)
}
- val result = interpreter.eval[Object](script) match {
- case Some(x) => x
- case None => null
- }
+ val result = interpreter.interpret(script)
if (interpreter.reporter.hasErrors) {
throw new ScriptException("some error","script-file",1)
}
diff --git a/scala-scripting/tests/pom.xml b/scala-scripting/tests/pom.xml
index 010afa775..ce6364892 100644
--- a/scala-scripting/tests/pom.xml
+++ b/scala-scripting/tests/pom.xml
@@ -76,12 +76,6 @@
2.8.1_1
provided
-
- org.apache.servicemix.bundles
- org.apache.servicemix.bundles.jline
- 0.9.94_1
- provided
-
org.apache.clerezza.scala
script-engine
diff --git a/shell/pom.xml b/shell/pom.xml
index d7b8e08b8..f9f591661 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -24,7 +24,7 @@
org.apache.clerezza
clerezza
- 0.2-incubating
+ 0.3-incubating-SNAPSHOT
shell
0.2-incubating-SNAPSHOT
@@ -39,11 +39,6 @@
org.apache.clerezza
osgi.services
-
- jline
- jline
- 0.9.94
-
org.scala-lang
scala-compiler
@@ -52,6 +47,11 @@
org.scala-lang
scala-library
+
+ org.scala-lang
+ jline
+ 2.9.0-1
+
org.apache.felix
org.apache.felix.scr.annotations
@@ -79,9 +79,14 @@
OSGI-INF/serviceComponents.xml
- org.apache.clerezza.shell
+ org.apache.clerezza.shell,
+ scala.tools.jline,
+ scala.tools.jline.console,
+ scala.tools.jline.console.history,
+ scala.tools.jline.console.completer
org.apache.clerezza.shell
org.apache.clerezza.platform.security;resolution:=optional, *
+ jline
diff --git a/shell/src/main/scala/org/apache/clerezza/shell/ConsoleShell.scala b/shell/src/main/scala/org/apache/clerezza/shell/ConsoleShell.scala
index fa1f0e70f..835d9e112 100644
--- a/shell/src/main/scala/org/apache/clerezza/shell/ConsoleShell.scala
+++ b/shell/src/main/scala/org/apache/clerezza/shell/ConsoleShell.scala
@@ -56,7 +56,7 @@ class ConsoleShell() {
}
//this call sets the console terminal to the right settings
//and it must not be invoked when there is no console input, or the system will stop
- val terminalOption = Some(jline.Terminal.setupTerminal())
+ val terminalOption = Some(scala.tools.jline.TerminalFactory.create())
val in = Channels.newInputStream(
(new FileInputStream(FileDescriptor.in)).getChannel());
interruptibleIn = new InterruptibleInputStream(in)
diff --git a/shell/src/main/scala/org/apache/clerezza/shell/Shell.scala b/shell/src/main/scala/org/apache/clerezza/shell/Shell.scala
index bd7c02c5b..041f83506 100644
--- a/shell/src/main/scala/org/apache/clerezza/shell/Shell.scala
+++ b/shell/src/main/scala/org/apache/clerezza/shell/Shell.scala
@@ -18,99 +18,113 @@
*/
package org.apache.clerezza.shell;
-
-
-import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Component
import org.osgi.framework.BundleContext
import org.osgi.framework.BundleEvent
import org.osgi.framework.BundleListener
-import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentContext
import org.osgi.framework.Bundle
-import java.io.{File, PrintWriter, Reader, StringWriter, BufferedReader, InputStreamReader, InputStream, Writer, OutputStream}
+import java.io.{ File, PrintWriter, Reader, StringWriter, BufferedReader, InputStreamReader, InputStream, Writer, OutputStream }
import java.lang.reflect.InvocationTargetException
import java.net._
import java.security.PrivilegedActionException
import java.security.AccessController
import java.security.PrivilegedAction
-
import javax.script.ScriptContext
-import javax.script.{ScriptEngineFactory => JavaxEngineFactory, Compilable,
- CompiledScript, ScriptEngine, AbstractScriptEngine, Bindings,
- SimpleBindings, ScriptException}
-import jline.CandidateListCompletionHandler
-import jline.{CompletionHandler, Completor, Terminal, ConsoleReader, ArgumentCompletor, History => JHistory}
-import java.util.{ArrayList, Arrays}
-
-//import scala.collection.immutable.Map
+import javax.script.{
+ ScriptEngineFactory => JavaxEngineFactory,
+ Compilable,
+ CompiledScript,
+ ScriptEngine,
+ AbstractScriptEngine,
+ Bindings,
+ SimpleBindings,
+ ScriptException
+}
+import java.util.{ ArrayList, Arrays }
import scala.actors.DaemonActor
import scala.collection.immutable
-import scala.tools.nsc._;
-import scala.tools.nsc.interpreter._;
-import scala.tools.nsc.io.{AbstractFile, PlainFile, VirtualDirectory}
+import scala.tools.nsc._
+import scala.tools.nsc.interpreter._
+import scala.tools.nsc.io.{ AbstractFile, PlainFile, VirtualDirectory }
import scala.tools.nsc.util._
import scala.tools.nsc.symtab.SymbolLoaders
import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.reporters.Reporter
import scala.tools.util.PathResolver
-import scala.tools.nsc.util.{ClassPath, JavaClassPath}
+import scala.tools.nsc.util.{ ClassPath, JavaClassPath }
import scala.actors.Actor
import scala.actors.Actor._
import org.apache.clerezza.scala.scripting._
import java.io.File
import org.slf4j.scala.Logging
-
-class Shell(factory: InterpreterFactory, val inStream: InputStream,
- out: OutputStream, shellCommands: immutable.Set[ShellCommand], terminalOption: Option[Terminal] = None ) extends Logging {
-
-
- private var bundleContext: BundleContext = null
-
- private var bindings = Set[(String, String, Any)]()
- private var imports = Set[String]()
- private var terminationListeners = Set[Shell.TerminationListener]();
-
- val terminal = terminalOption match {
- case Some(x) => x
- case None => new jline.UnixTerminal
- }
-
- val interpreterLoop = new InterpreterLoop(new BufferedReader(new InputStreamReader(inStream)), new PrintWriter(out, true)) {
- override def createInterpreter() {
- interpreter = factory.createInterpreter(out)
- interpreter.beQuietDuring {
- for (binding <- bindings) {
- interpreter.bind(binding._1, binding._2, binding._3)
- }
- for (v <- imports) {
- interpreter.interpret("import "+v)
- }
- }
- }
-
- override val prompt = "zz>"
-
- override val standardCommands: List[Command] = {
- import CommandImplicits._
- (for (shellCommand <- shellCommands) yield {
- LineArg(shellCommand.command, shellCommand.description, (line: String)=> {
- val (continue, linesToRecord) = shellCommand.execute(line, Shell.this.out)
- Result(continue, linesToRecord)
- })
- }).toList :::
- List(
- NoArgs("help", "print this help message", printHelp),
- VarArgs("history", "show the history (optional arg: lines to show)", printHistory),
- LineArg("h?", "search the history", searchHistory),
- OneArg("load", "load and interpret a Scala file", load),
- NoArgs("power", "enable power user mode", power),
- NoArgs("quit", "terminate the console shell (use shutdown to shut down clerezza)", () => Result(false, None)),
- NoArgs("replay", "reset execution and replay all previous commands", replay),
- LineArg("sh", "fork a shell and run a command", runShellCmd),
- NoArgs("silent", "disable/enable automatic printing of results", verbosity)
- )
- }
-
- override def printHelp() = {
+import scala.tools.nsc.interpreter.JLineReader
+import scala.tools.jline.Terminal
+import scala.tools.jline.console.completer.CompletionHandler
+import scala.tools.jline.console.ConsoleReader
+import scala.tools.jline.console.completer.CandidateListCompletionHandler
+import java.lang.CharSequence
+import scala.tools.jline.UnixTerminal
+import scala.tools.jline.console.history.History
+
+class Shell(factory: InterpreterFactory, val inStream: InputStream,
+ outStream: OutputStream, shellCommands: immutable.Set[ShellCommand], terminalOption: Option[Terminal] = None) extends Logging {
+
+ private var bundleContext: BundleContext = null
+
+ private var bindings = Set[(String, String, Any)]()
+ private var imports = Set[String]()
+ private var terminationListeners = Set[Shell.TerminationListener]();
+
+ val terminal = terminalOption match {
+ case Some(x) => x
+ case None => new UnixTerminal
+ }
+
+ val interpreterLoop = new ILoop(new BufferedReader(new InputStreamReader(inStream)), new PrintWriter(outStream, true)) {
+ override def createInterpreter() {
+ intp = factory.createInterpreter(out)
+ intp.beQuietDuring {
+ for (binding <- bindings) {
+ intp.bind(binding._1, binding._2, binding._3)
+ }
+ for (v <- imports) {
+ intp.interpret("import " + v)
+ }
+ }
+ }
+
+ override val prompt = "zz>"
+ override def isAsync = false
+
+ override lazy val standardCommands: List[LoopCommand] = {
+ import LoopCommand._
+ (for (shellCommand <- shellCommands) yield {
+ new LineCmd(shellCommand.command, "", shellCommand.description, (line: String) => {
+ val (continue, linesToRecord) = shellCommand.execute(line, Shell.this.outStream)
+ Result(continue, linesToRecord)
+ })
+ }).toList ::: List(
+ cmd("help", "[command]", "print this summary or command-specific help", helpCommand),
+ historyCommand,
+ cmd("h?", "", "search the history", searchHistory),
+ cmd("load", "", "load and interpret a Scala file", loadCommand),
+ nullary("paste", "enter paste mode: all input up to ctrl-D compiled together", pasteCommand),
+ nullary("power", "enable power user mode", powerCmd),
+ nullary("quit", "terminate the console shell (use shutdown to shut down clerezza)", () => Result(false, None)),
+ nullary("replay", "reset execution and replay all previous commands", replay),
+ shCommand,
+ nullary("silent", "disable/enable automatic printing of results", verbosity))
+ }
+
+ /** print a friendly help message */
+ override def helpCommand(line: String): Result = {
+ if (line == "") printAdditinalHelp();
+
+ super.helpCommand(line);
+ }
+
+ def printAdditinalHelp() = {
out println "This is a scala based console, it supports any Scala expression, as well as the command described below."
out println "To access an OSGi service use $[interface]."
out println ""
@@ -124,158 +138,107 @@ class Shell(factory: InterpreterFactory, val inStream: InputStream,
out println ("import "+v)
}
out println ""
- super.printHelp()
- }
-
-
- override def main(settings: Settings) {
- this.settings = settings
- createInterpreter()
-
- // sets in to some kind of reader depending on environmental cues
- in = new InteractiveReader() {
-
- override lazy val history = Some(History(consoleReader))
- override lazy val completion = Option(interpreter) map (x => new Completion(x))
-
- val consoleReader = {
-
- val r = new jline.ConsoleReader(inStream, out, null, terminal)
- r setHistory (History().jhistory)
- r setBellEnabled false
- completion foreach { c =>
- r addCompletor c.jline
- r setAutoprintThreshhold 250
- }
- import java.util.List
- r setCompletionHandler new CompletionHandler {
- def complete(reader: ConsoleReader, candidates: List[_], pos: Int) = {
- val buffer = reader.getCursorBuffer()
- if (candidates.size == 1) {
- CandidateListCompletionHandler.setBuffer(reader, candidates.get(0).toString, pos)
- } else {
- import collection.JavaConversions._
- def commonHead(a: String,b: String):String = {
- if (a.isEmpty || b.isEmpty) {
- ""
- } else {
- if (a(0) == b(0)) {
- a(0)+commonHead(a.tail, b.tail)
- } else ""
- }
- }
- val canStrings = candidates.map(_.toString)
- val longestCommonPrefix = canStrings.tail.foldRight(canStrings.head)((a,b) => commonHead(a,b))
- CandidateListCompletionHandler.setBuffer(reader, longestCommonPrefix, pos)
- out.println()
- out.println(candidates.mkString("\t"))
- out.print(prompt)
- out.print(reader.getCursorBuffer())
- }
- true
- }
- }
- /* a second completor is ignored, would have to wrapp the above
- r addCompletor new Completor {
- def complete(p1: String, p2: Int, candidates: java.util.List[_]) = {
- logger.warn("JLINE: candidates : "+candidates)
- val canStrings = candidates.asInstanceOf[List[String]]
- canStrings.add("Clerezza")
- canStrings.add("Apache")
- try {
- throw new RuntimeException
- } catch {
- case e => logger.warn("stack ", e)
- }
- 0
- }
- }*/
-
- r
- }
-
- def readOneLine(prompt: String) = consoleReader readLine prompt
- val interactive = false
- }
- //in = new SimpleReader(inStream, out, true)
-
- loadFiles(settings)
- try {
- // it is broken on startup; go ahead and exit
- if (interpreter.reporter.hasErrors) return
-
- printWelcome()
-
- // this is about the illusion of snappiness. We call initialize()
- // which spins off a separate thread, then print the prompt and try
- // our best to look ready. Ideally the user will spend a
- // couple seconds saying "wow, it starts so fast!" and by the time
- // they type a command the compiler is ready to roll.
- interpreter.initialize()
- repl()
- }
- finally closeInterpreter()
}
- override def printWelcome() {
- import Properties._
- val welcomeMsg =
- """|Welcome to the Apache Clerezza Console
+ override def process(settings: Settings): Boolean = {
+ this.settings = settings
+ createInterpreter()
+
+ // sets in to some kind of reader depending on environmental cues
+ //ignore settings.noCompletion.value)
+ {
+ val myIn = new StreamJLineReader(new JLineCompletion(intp), inStream, outStream, terminal)
+ in = myIn
+ //are we postinit already?
+ addThunk(myIn.consoleReader.postInit)
+ }
+ loadFiles(settings)
+ // it is broken on startup; go ahead and exit
+ if (intp.reporter.hasErrors)
+ return false
+
+ // This is about the illusion of snappiness. We call initialize()
+ // which spins off a separate thread, then print the prompt and try
+ // our best to look ready. The interlocking lazy vals tend to
+ // inter-deadlock, so we break the cycle with a single asynchronous
+ // message to an actor.
+ if (isAsync) {
+ intp initialize initializedCallback()
+ createAsyncListener() // listens for signal to run postInitialization
+ }
+ else {
+ intp.initializeSynchronous()
+ postInitialization()
+ }
+ printWelcome()
+
+ try loop()
+ catch AbstractOrMissingHandler()
+ finally closeInterpreter()
+
+ true
+ }
+
+ override def printWelcome() {
+ import Properties._
+ val welcomeMsg =
+ """|Welcome to the Apache Clerezza Console
|Console is based on Scala %s (%s, Java %s).
|Type in expressions to have them evaluated.
- |Type :help for more information.""" .
- stripMargin.format(versionString, javaVmName, javaVersion)
-
- plushln(welcomeMsg)
- }
- }
- val console: Actor = new DaemonActor {
- def act() {
- try {
- interpreterLoop.main(Array[String]())
- } finally {
- for (l <- terminationListeners) {
- l.terminated
- }
- println("console terminated")
- }
- }
- }
-
- def start() {
- console.start
- }
-
- def stop() {
- interpreterLoop.command(":q")
- interpreterLoop.closeInterpreter()
- }
-
- def bind(name: String, boundType: String, value: Any) {
- bindings += ((name, boundType, value))
- }
-
- def addImport(importValue: String) {
- imports += importValue
- }
-
- def addTerminationListener(l: Shell.TerminationListener) {
- terminationListeners += l
- }
-
- def removeTerminationListener(l: Shell.TerminationListener) {
- terminationListeners -= l
- }
+ |Type :help for more information.""".
+ stripMargin.format(versionString, javaVmName, javaVersion)
+
+ echo(welcomeMsg)
+ }
+ }
+ val console: Actor = new DaemonActor {
+ def act() {
+ try {
+ interpreterLoop.process(Array[String]())
+ } finally {
+ for (l <- terminationListeners) {
+ l.terminated
+ }
+ println("console terminated")
+ }
+ }
+ }
+
+ def start() {
+
+ console.start
+ }
+
+ def stop() {
+ interpreterLoop.command(":q")
+ interpreterLoop.closeInterpreter()
+ }
+
+ def bind(name: String, boundType: String, value: Any) {
+ bindings += ((name, boundType, value))
+ }
+
+ def addImport(importValue: String) {
+ imports += importValue
+ }
+
+ def addTerminationListener(l: Shell.TerminationListener) {
+ terminationListeners += l
+ }
+
+ def removeTerminationListener(l: Shell.TerminationListener) {
+ terminationListeners -= l
+ }
}
object Shell {
- trait TerminationListener {
- def terminated: Unit
- }
-
- trait Environment {
- val componentContext: ComponentContext;
- val in: InputStream;
- val out: OutputStream;
- }
+ trait TerminationListener {
+ def terminated: Unit
+ }
+
+ trait Environment {
+ val componentContext: ComponentContext;
+ val in: InputStream;
+ val out: OutputStream;
+ }
}
\ No newline at end of file
diff --git a/shell/src/main/scala/org/apache/clerezza/shell/ShellFactory.scala b/shell/src/main/scala/org/apache/clerezza/shell/ShellFactory.scala
index 2c84ff39e..ecff56c72 100644
--- a/shell/src/main/scala/org/apache/clerezza/shell/ShellFactory.scala
+++ b/shell/src/main/scala/org/apache/clerezza/shell/ShellFactory.scala
@@ -27,7 +27,7 @@ import java.io.OutputStream
import java.security.AccessController
import java.security.PrivilegedAction
import org.apache.clerezza.scala.scripting.InterpreterFactory
-import jline.Terminal
+import scala.tools.jline.Terminal
class ShellFactory() {
diff --git a/shell/src/main/scala/org/apache/clerezza/shell/StreamJLineReader.scala b/shell/src/main/scala/org/apache/clerezza/shell/StreamJLineReader.scala
new file mode 100644
index 000000000..dcbc34a1f
--- /dev/null
+++ b/shell/src/main/scala/org/apache/clerezza/shell/StreamJLineReader.scala
@@ -0,0 +1,91 @@
+package org.apache.clerezza.shell
+
+import scala.tools.jline.Terminal
+import scala.tools.jline.TerminalFactory
+import scala.tools.jline.console.completer.CandidateListCompletionHandler
+import scala.tools.jline.console.completer.Completer
+import scala.tools.jline.console.completer.CompletionHandler
+import scala.tools.jline.console.history.History
+import scala.tools.jline.console.history.MemoryHistory
+import scala.tools.jline.internal.Configuration
+import scala.tools.jline.internal.Log
+import org.fusesource.jansi.AnsiOutputStream
+import java.awt.Toolkit
+import java.awt.datatransfer.Clipboard
+import java.awt.datatransfer.DataFlavor
+import java.awt.datatransfer.Transferable
+import java.awt.datatransfer.UnsupportedFlavorException
+import java.awt.event.ActionListener
+import scala.tools.jline.console.ConsoleReader
+import scala.tools.jline.console.completer._
+import scala.tools.nsc.interpreter.session._
+import scala.collection.JavaConverters._
+import scala.tools.nsc.interpreter.Completion._
+import scala.tools.nsc.io.Streamable.slurp
+import scala.tools.nsc.interpreter._
+import java.io.OutputStream
+
+//a modified version of scala.tools.nsc.interpreter.JLineReader
+/**
+ * Reads from the console using JLine.
+ */
+class StreamJLineReader(_completion: => Completion, in: InputStream, out: OutputStream, terminal: Terminal) extends InteractiveReader {
+ val interactive = false
+ val consoleReader = new StreamJLineConsoleReader()
+
+ lazy val completion = _completion
+ lazy val history: JLineHistory = JLineHistory()
+ lazy val keyBindings =
+ try KeyBinding parse slurp(term.getDefaultBindings)
+ catch { case _: Exception => Nil }
+
+ private def term = consoleReader.getTerminal()
+ def reset() = term.reset()
+ def init() = term.init()
+
+ def scalaToJline(tc: ScalaCompleter): Completer = new Completer {
+ def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
+ val buf = if (_buf == null) "" else _buf
+ val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor)
+ newCandidates foreach (candidates add _)
+ newCursor
+ }
+ }
+
+ class StreamJLineConsoleReader extends ConsoleReader(in, out, null, terminal) with ConsoleReaderHelper {
+ // working around protected/trait/java insufficiencies.
+ def goBack(num: Int): Unit = back(num)
+ def readOneKey(prompt: String) = {
+ this.print(prompt)
+ this.flush()
+ this.readVirtualKey()
+ }
+ def eraseLine() = consoleReader.resetPromptLine("", "", 0)
+ def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() }
+ // override def readLine(prompt: String): String
+
+ // A hook for running code after the repl is done initializing.
+ lazy val postInit: Unit = {
+ this setBellEnabled false
+ if (history ne NoHistory)
+ this setHistory history
+
+ if (completion ne NoCompletion) {
+ val argCompletor: ArgumentCompleter =
+ new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
+ argCompletor setStrict false
+
+ this addCompleter argCompletor
+ this setAutoprintThreshold 400 // max completion candidates without warning
+ }
+ }
+ }
+
+ def currentLine = consoleReader.getCursorBuffer.buffer.toString
+ def redrawLine() = consoleReader.redrawLineAndFlush()
+ def eraseLine() = consoleReader.eraseLine()
+ // Alternate implementation, not sure if/when I need this.
+ // def eraseLine() = while (consoleReader.delete()) { }
+ def readOneLine(prompt: String) = consoleReader readLine prompt
+ def readOneKey(prompt: String) = consoleReader readOneKey prompt
+}