mirror of https://github.com/sbt/sbt.git
84 lines
2.6 KiB
Scala
84 lines
2.6 KiB
Scala
/*
|
|
* sbt
|
|
* Copyright 2011 - 2018, Lightbend, Inc.
|
|
* Copyright 2008 - 2010, Mark Harrah
|
|
* Licensed under Apache License 2.0 (see LICENSE)
|
|
*/
|
|
|
|
package sbt
|
|
package internal
|
|
|
|
import java.io.File
|
|
import java.nio.channels.ClosedChannelException
|
|
import java.util.concurrent.atomic.AtomicReference
|
|
|
|
import sbt.BasicKeys._
|
|
import sbt.internal.util._
|
|
|
|
private[sbt] final class ConsoleChannel(val name: String) extends CommandChannel {
|
|
private[this] val askUserThread = new AtomicReference[AskUserThread]
|
|
private[this] def getPrompt(s: State): String = s.get(shellPrompt) match {
|
|
case Some(pf) => pf(s)
|
|
case None =>
|
|
def ansi(s: String): String = if (ConsoleAppender.formatEnabledInEnv) s"$s" else ""
|
|
s"${ansi(ConsoleAppender.DeleteLine)}> ${ansi(ConsoleAppender.ClearScreenAfterCursor)}"
|
|
}
|
|
private[this] class AskUserThread(s: State) extends Thread("ask-user-thread") {
|
|
private val history = s.get(historyPath).getOrElse(Some(new File(s.baseDir, ".history")))
|
|
private val prompt = getPrompt(s)
|
|
private val reader =
|
|
new FullReader(
|
|
history,
|
|
s.combinedParser,
|
|
LineReader.HandleCONT,
|
|
Terminal.throwOnClosedSystemIn
|
|
)
|
|
setDaemon(true)
|
|
start()
|
|
override def run(): Unit =
|
|
try {
|
|
reader.readLine(prompt) match {
|
|
case Some(cmd) => append(Exec(cmd, Some(Exec.newExecId), Some(CommandSource(name))))
|
|
case None =>
|
|
println("") // Prevents server shutdown log lines from appearing on the prompt line
|
|
append(Exec("exit", Some(Exec.newExecId), Some(CommandSource(name))))
|
|
}
|
|
()
|
|
} catch {
|
|
case _: ClosedChannelException =>
|
|
} finally askUserThread.synchronized(askUserThread.set(null))
|
|
def redraw(): Unit = {
|
|
System.out.print(ConsoleAppender.clearLine(0))
|
|
reader.redraw()
|
|
System.out.print(ConsoleAppender.ClearScreenAfterCursor)
|
|
System.out.flush()
|
|
}
|
|
}
|
|
private[this] def makeAskUserThread(s: State): AskUserThread = new AskUserThread(s)
|
|
|
|
def run(s: State): State = s
|
|
|
|
def publishBytes(bytes: Array[Byte]): Unit = ()
|
|
|
|
def prompt(event: ConsolePromptEvent): Unit = {
|
|
if (Terminal.systemInIsAttached) {
|
|
askUserThread.synchronized {
|
|
askUserThread.get match {
|
|
case null => askUserThread.set(makeAskUserThread(event.state))
|
|
case t => t.redraw()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def shutdown(): Unit = askUserThread.synchronized {
|
|
askUserThread.get match {
|
|
case null =>
|
|
case t if t.isAlive =>
|
|
t.interrupt()
|
|
askUserThread.set(null)
|
|
case _ => ()
|
|
}
|
|
}
|
|
}
|