mirror of https://github.com/sbt/sbt.git
Implement ConsoleListener
This commit is contained in:
parent
ff211d08f9
commit
3381f59ae8
|
|
@ -194,30 +194,38 @@ object BasicCommands {
|
|||
}
|
||||
}
|
||||
|
||||
var askingAlready = false
|
||||
val commandListers = Seq(new ConsoleListener(), new NetworkListener())
|
||||
val commandQueue: ConcurrentLinkedQueue[Option[String]] = new ConcurrentLinkedQueue()
|
||||
|
||||
@tailrec def blockUntilNextCommand: Option[String] =
|
||||
private[sbt] var askingAlready = false
|
||||
private[sbt] val commandQueue: ConcurrentLinkedQueue[(String, Option[String])] = new ConcurrentLinkedQueue()
|
||||
private[sbt] val commandListers = Seq(new ConsoleListener(commandQueue), new NetworkListener(commandQueue))
|
||||
@tailrec private[sbt] def blockUntilNextCommand: (String, Option[String]) =
|
||||
Option(commandQueue.poll) match {
|
||||
case Some(x) => x
|
||||
case None =>
|
||||
case _ =>
|
||||
Thread.sleep(50)
|
||||
blockUntilNextCommand
|
||||
}
|
||||
def server = Command.command(Server, Help.more(Server, ServerDetailed)) { s =>
|
||||
if (!askingAlready) {
|
||||
if (askingAlready) {
|
||||
commandListers foreach { x =>
|
||||
x.run(commandQueue, CommandStatus(s, true))
|
||||
x.resume(CommandStatus(s, true))
|
||||
}
|
||||
} else {
|
||||
commandListers foreach { x =>
|
||||
x.run(CommandStatus(s, true))
|
||||
}
|
||||
askingAlready = true
|
||||
}
|
||||
blockUntilNextCommand match {
|
||||
case Some(line) =>
|
||||
// tell listern to be inactive .
|
||||
case (source, Some(line)) =>
|
||||
if (source != "human") {
|
||||
println(line)
|
||||
}
|
||||
commandListers foreach { x =>
|
||||
x.pause()
|
||||
}
|
||||
val newState = s.copy(onFailure = Some(Server), remainingCommands = line +: Server +: s.remainingCommands).setInteractive(true)
|
||||
if (line.trim.isEmpty) newState else newState.clearGlobalLog
|
||||
case None => s.setInteractive(false)
|
||||
case _ => s.setInteractive(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ package sbt
|
|||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
trait CommandListener {
|
||||
abstract class CommandListener(queue: ConcurrentLinkedQueue[(String, Option[String])]) {
|
||||
// represents a loop that keeps asking an IO device for String input
|
||||
def run(queue: ConcurrentLinkedQueue[Option[String]],
|
||||
status: CommandStatus): Unit
|
||||
def run(status: CommandStatus): Unit
|
||||
def shutdown(): Unit
|
||||
def setStatus(status: CommandStatus): Unit
|
||||
def pause(): Unit
|
||||
def resume(status: CommandStatus): Unit
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,66 @@
|
|||
package sbt
|
||||
|
||||
import sbt.internal.util._
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference }
|
||||
import BasicKeys._
|
||||
import java.io.File
|
||||
|
||||
class ConsoleListener extends CommandListener {
|
||||
private[sbt] final class ConsoleListener(queue: ConcurrentLinkedQueue[(String, Option[String])]) extends CommandListener(queue) {
|
||||
private var askUserThread: Option[Thread] = None
|
||||
def makeAskUserThread(status: CommandStatus): Thread = new Thread("ask-user-thread") {
|
||||
val s = status.state
|
||||
val history = (s get historyPath) getOrElse Some(new File(s.baseDir, ".history"))
|
||||
val prompt = (s get shellPrompt) match { case Some(pf) => pf(s); case None => "> " }
|
||||
// val reader = new FullReader(history, s.combinedParser)
|
||||
// val line = reader.readLine(prompt)
|
||||
// line match {
|
||||
// case Some(line) =>
|
||||
// val newState = s.copy(onFailure = Some(Shell), remainingCommands = line +: Shell +: s.remainingCommands).setInteractive(true)
|
||||
// if (line.trim.isEmpty) newState else newState.clearGlobalLog
|
||||
// case None => s.setInteractive(false)
|
||||
// }
|
||||
val reader = JLine.simple(None, false)
|
||||
override def run(): Unit = {
|
||||
try {
|
||||
val line = reader.readLine(prompt)
|
||||
line map { x => queue.add(("human", Some(x))) }
|
||||
} catch {
|
||||
case e: InterruptedException =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// val history = (s get historyPath) getOrElse Some(new File(s.baseDir, ".history"))
|
||||
// val prompt = (s get shellPrompt) match { case Some(pf) => pf(s); case None => "> " }
|
||||
// val reader = new FullReader(history, s.combinedParser)
|
||||
// val line = reader.readLine(prompt)
|
||||
// line match {
|
||||
// case Some(line) =>
|
||||
// val newState = s.copy(onFailure = Some(Shell), remainingCommands = line +: Shell +: s.remainingCommands).setInteractive(true)
|
||||
// if (line.trim.isEmpty) newState else newState.clearGlobalLog
|
||||
// case None => s.setInteractive(false)
|
||||
// }
|
||||
|
||||
def run(queue: ConcurrentLinkedQueue[Option[String]],
|
||||
status: CommandStatus): Unit =
|
||||
{
|
||||
// spawn thread and loop
|
||||
def run(status: CommandStatus): Unit =
|
||||
askUserThread match {
|
||||
case Some(x) if x.isAlive => //
|
||||
case _ =>
|
||||
val x = makeAskUserThread(status)
|
||||
x.start
|
||||
askUserThread = Some(x)
|
||||
}
|
||||
|
||||
def shutdown(): Unit =
|
||||
{
|
||||
// interrupt and kill the thread
|
||||
askUserThread match {
|
||||
case Some(x) if x.isAlive =>
|
||||
x.interrupt
|
||||
askUserThread = None
|
||||
println("shutdown ask user thread")
|
||||
case _ => ()
|
||||
}
|
||||
|
||||
def setStatus(status: CommandStatus): Unit = ???
|
||||
def pause(): Unit = shutdown()
|
||||
|
||||
def resume(status: CommandStatus): Unit =
|
||||
askUserThread match {
|
||||
case Some(x) if x.isAlive => //
|
||||
println("resume??")
|
||||
case _ =>
|
||||
val x = makeAskUserThread(status)
|
||||
println("resume")
|
||||
x.start
|
||||
askUserThread = Some(x)
|
||||
}
|
||||
|
||||
def setStatus(status: CommandStatus): Unit = ()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@ import java.util.concurrent.ConcurrentLinkedQueue
|
|||
|
||||
import sbt.server._
|
||||
|
||||
private[sbt] final class NetworkListener extends CommandListener {
|
||||
private[sbt] final class NetworkListener(queue: ConcurrentLinkedQueue[(String, Option[String])]) extends CommandListener(queue) {
|
||||
|
||||
private var server: Option[ServerInstance] = None
|
||||
|
||||
def run(queue: ConcurrentLinkedQueue[Option[String]],
|
||||
status: CommandStatus): Unit =
|
||||
def run(status: CommandStatus): Unit =
|
||||
{
|
||||
def onCommand(command: sbt.server.Command): Unit = {
|
||||
command match {
|
||||
case Execution(cmd) => queue.add(Some(cmd))
|
||||
case Execution(cmd) => queue.add(("network", Some(cmd)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,6 +25,12 @@ private[sbt] final class NetworkListener extends CommandListener {
|
|||
server.foreach(_.shutdown())
|
||||
}
|
||||
|
||||
// network doesn't pause or resume
|
||||
def pause(): Unit = ()
|
||||
|
||||
// network doesn't pause or resume
|
||||
def resume(status: CommandStatus): Unit = ()
|
||||
|
||||
def setStatus(cmdStatus: CommandStatus): Unit = {
|
||||
server.foreach(server =>
|
||||
server.publish(
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ abstract class ClientConnection(connection: Socket) {
|
|||
if (delimPos > 0) {
|
||||
val chunk = buffer.take(delimPos)
|
||||
buffer = buffer.drop(delimPos + 1)
|
||||
|
||||
|
||||
Serialization.deserialize(chunk).fold(
|
||||
errorDesc => println("Got invalid chunk from client: " + errorDesc),
|
||||
onCommand
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ object BuiltinCommands {
|
|||
def DefaultCommands: Seq[Command] = Seq(ignore, help, completionsCommand, about, tasks, settingsCommand, loadProject,
|
||||
projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion,
|
||||
Cross.crossRestoreSession, setOnFailure, clearOnFailure, stashOnFailure, popOnFailure, setLogLevel, plugin, plugins,
|
||||
ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, early, initialize, act) ++
|
||||
ifLast, multi, shell, BasicCommands.server, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, early, initialize, act) ++
|
||||
compatCommands
|
||||
def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue