mirror of https://github.com/sbt/sbt.git
Merge pull request #5688 from eatkins/client-jline-ui-fixes
Miscellaneous ui/jline fixes
This commit is contained in:
commit
3908949d73
|
|
@ -80,8 +80,8 @@ private[sbt] final class ProgressState(
|
||||||
private[util] def printPrompt(terminal: Terminal, printStream: PrintStream): Unit =
|
private[util] def printPrompt(terminal: Terminal, printStream: PrintStream): Unit =
|
||||||
if (terminal.prompt != Prompt.Running && terminal.prompt != Prompt.Batch) {
|
if (terminal.prompt != Prompt.Running && terminal.prompt != Prompt.Batch) {
|
||||||
val prefix = if (terminal.isAnsiSupported) s"$DeleteLine$CursorLeft1000" else ""
|
val prefix = if (terminal.isAnsiSupported) s"$DeleteLine$CursorLeft1000" else ""
|
||||||
val pmpt = prefix.getBytes ++ terminal.prompt.render().getBytes
|
printStream.write(prefix.getBytes ++ terminal.prompt.render().getBytes)
|
||||||
pmpt.foreach(b => printStream.write(b & 0xFF))
|
printStream.flush()
|
||||||
}
|
}
|
||||||
private[util] def write(
|
private[util] def write(
|
||||||
terminal: Terminal,
|
terminal: Terminal,
|
||||||
|
|
@ -90,10 +90,10 @@ private[sbt] final class ProgressState(
|
||||||
hasProgress: Boolean
|
hasProgress: Boolean
|
||||||
): Unit = {
|
): Unit = {
|
||||||
addBytes(terminal, bytes)
|
addBytes(terminal, bytes)
|
||||||
if (hasProgress && terminal.prompt != Prompt.Loading) {
|
if (hasProgress) {
|
||||||
terminal.prompt match {
|
terminal.prompt match {
|
||||||
case a: Prompt.AskUser if a.render.nonEmpty =>
|
case a: Prompt.AskUser if a.render.nonEmpty =>
|
||||||
printStream.print(System.lineSeparator + ClearScreenAfterCursor + CursorLeft1000)
|
printStream.print(DeleteLine + ClearScreenAfterCursor + CursorLeft1000)
|
||||||
printStream.flush()
|
printStream.flush()
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,5 @@ private[sbt] object Prompt {
|
||||||
private[sbt] case object Running extends NoPrompt
|
private[sbt] case object Running extends NoPrompt
|
||||||
private[sbt] case object Batch extends NoPrompt
|
private[sbt] case object Batch extends NoPrompt
|
||||||
private[sbt] case object Watch extends NoPrompt
|
private[sbt] case object Watch extends NoPrompt
|
||||||
private[sbt] case object Loading extends NoPrompt
|
|
||||||
private[sbt] case object NoPrompt extends NoPrompt
|
private[sbt] case object NoPrompt extends NoPrompt
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import java.util.concurrent.Executors
|
||||||
|
|
||||||
import sbt.State
|
import sbt.State
|
||||||
import sbt.internal.util.{ ConsoleAppender, ProgressEvent, ProgressState, Util }
|
import sbt.internal.util.{ ConsoleAppender, ProgressEvent, ProgressState, Util }
|
||||||
import sbt.internal.util.Prompt.{ AskUser, Loading, Running }
|
import sbt.internal.util.Prompt.{ AskUser, Running }
|
||||||
|
|
||||||
private[sbt] class UserThread(val channel: CommandChannel) extends AutoCloseable {
|
private[sbt] class UserThread(val channel: CommandChannel) extends AutoCloseable {
|
||||||
private[this] val uiThread = new AtomicReference[(UITask, Thread)]
|
private[this] val uiThread = new AtomicReference[(UITask, Thread)]
|
||||||
|
|
@ -70,8 +70,7 @@ private[sbt] class UserThread(val channel: CommandChannel) extends AutoCloseable
|
||||||
}
|
}
|
||||||
val state = consolePromptEvent.state
|
val state = consolePromptEvent.state
|
||||||
terminal.prompt match {
|
terminal.prompt match {
|
||||||
case Loading | Running =>
|
case Running => terminal.setPrompt(AskUser(() => UITask.shellPrompt(terminal, state)))
|
||||||
terminal.setPrompt(AskUser(() => UITask.shellPrompt(terminal, state)))
|
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
onProgressEvent(ProgressEvent("Info", Vector(), None, None, None))
|
onProgressEvent(ProgressEvent("Info", Vector(), None, None, None))
|
||||||
|
|
|
||||||
|
|
@ -454,7 +454,12 @@ object Defaults extends BuildCommon {
|
||||||
def paths: Seq[Setting[_]] = Seq(
|
def paths: Seq[Setting[_]] = Seq(
|
||||||
baseDirectory := thisProject.value.base,
|
baseDirectory := thisProject.value.base,
|
||||||
target := baseDirectory.value / "target",
|
target := baseDirectory.value / "target",
|
||||||
historyPath := (historyPath or target(t => Option(t / ".history"))).value,
|
// Use a different history path for jline3 because the jline2 format is
|
||||||
|
// incompatible. By sbt 1.4.0, we should consider revering this to t / ".history"
|
||||||
|
// and possibly rewriting the jline2 history in a jline3 compatible format if the
|
||||||
|
// history file is incompatible. For now, just use a different file to facilitate
|
||||||
|
// going back and forth between 1.3.x and 1.4.x.
|
||||||
|
historyPath := (historyPath or target(t => Option(t / ".history3"))).value,
|
||||||
sourceDirectory := baseDirectory.value / "src",
|
sourceDirectory := baseDirectory.value / "src",
|
||||||
sourceManaged := crossTarget.value / "src_managed",
|
sourceManaged := crossTarget.value / "src_managed",
|
||||||
resourceManaged := crossTarget.value / "resource_managed",
|
resourceManaged := crossTarget.value / "resource_managed",
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,10 @@ private[sbt] object xMain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
// Clear any stray progress lines
|
||||||
ShutdownHooks.close()
|
ShutdownHooks.close()
|
||||||
|
System.out.print(ConsoleAppender.ClearScreenAfterCursor)
|
||||||
|
System.out.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -913,8 +916,6 @@ object BuiltinCommands {
|
||||||
}
|
}
|
||||||
|
|
||||||
def doLoadProject(s0: State, action: LoadAction.Value): State = {
|
def doLoadProject(s0: State, action: LoadAction.Value): State = {
|
||||||
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(None), force = true)
|
|
||||||
StandardMain.exchange.channels.foreach(_.terminal.setPrompt(Prompt.Loading))
|
|
||||||
welcomeBanner(s0)
|
welcomeBanner(s0)
|
||||||
checkSBTVersionChanged(s0)
|
checkSBTVersionChanged(s0)
|
||||||
val (s1, base) = Project.loadAction(SessionVar.clear(s0), action)
|
val (s1, base) = Project.loadAction(SessionVar.clear(s0), action)
|
||||||
|
|
@ -935,9 +936,7 @@ object BuiltinCommands {
|
||||||
SessionSettings.checkSession(session, s2)
|
SessionSettings.checkSession(session, s2)
|
||||||
val s3 = addCacheStoreFactoryFactory(Project.setProject(session, structure, s2))
|
val s3 = addCacheStoreFactoryFactory(Project.setProject(session, structure, s2))
|
||||||
val s4 = setupGlobalFileTreeRepository(s3)
|
val s4 = setupGlobalFileTreeRepository(s3)
|
||||||
val s5 = CheckBuildSources.init(LintUnused.lintUnusedFunc(s4))
|
CheckBuildSources.init(LintUnused.lintUnusedFunc(s4))
|
||||||
StandardMain.exchange.prompt(ConsolePromptEvent(s5))
|
|
||||||
s5
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val setupGlobalFileTreeRepository: State => State = { state =>
|
private val setupGlobalFileTreeRepository: State => State = { state =>
|
||||||
|
|
@ -981,11 +980,9 @@ object BuiltinCommands {
|
||||||
val exchange = StandardMain.exchange
|
val exchange = StandardMain.exchange
|
||||||
if (exchange.channels.exists(ContinuousCommands.isInWatch)) {
|
if (exchange.channels.exists(ContinuousCommands.isInWatch)) {
|
||||||
val s1 = exchange.run(s0)
|
val s1 = exchange.run(s0)
|
||||||
def needPrompt(c: CommandChannel) =
|
|
||||||
ContinuousCommands.isInWatch(c) && !ContinuousCommands.isPending(c)
|
|
||||||
exchange.channels.foreach {
|
exchange.channels.foreach {
|
||||||
case c if needPrompt(c) => c.prompt(ConsolePromptEvent(s1))
|
case c if ContinuousCommands.isPending(c) =>
|
||||||
case _ =>
|
case c => c.prompt(ConsolePromptEvent(s1))
|
||||||
}
|
}
|
||||||
val exec: Exec = getExec(s1, Duration.Inf)
|
val exec: Exec = getExec(s1, Duration.Inf)
|
||||||
val remaining: List[Exec] =
|
val remaining: List[Exec] =
|
||||||
|
|
|
||||||
|
|
@ -198,9 +198,9 @@ object MainLoop {
|
||||||
state.put(sbt.Keys.currentTaskProgress, new Keys.TaskProgress(progress))
|
state.put(sbt.Keys.currentTaskProgress, new Keys.TaskProgress(progress))
|
||||||
} else state
|
} else state
|
||||||
}
|
}
|
||||||
exchange.setState(progressState)
|
StandardMain.exchange.setState(progressState)
|
||||||
exchange.setExec(Some(exec))
|
StandardMain.exchange.setExec(Some(exec))
|
||||||
exchange.unprompt(ConsoleUnpromptEvent(exec.source), force = false)
|
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(exec.source))
|
||||||
val newState = Command.process(exec.commandLine, progressState)
|
val newState = Command.process(exec.commandLine, progressState)
|
||||||
if (exec.execId.fold(true)(!_.startsWith(networkExecPrefix)) &&
|
if (exec.execId.fold(true)(!_.startsWith(networkExecPrefix)) &&
|
||||||
!exec.commandLine.startsWith(networkExecPrefix)) {
|
!exec.commandLine.startsWith(networkExecPrefix)) {
|
||||||
|
|
|
||||||
|
|
@ -357,11 +357,7 @@ private[sbt] final class CommandExchange {
|
||||||
case c => c.prompt(event)
|
case c => c.prompt(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def unprompt(event: ConsoleUnpromptEvent, force: Boolean): Unit = {
|
def unprompt(event: ConsoleUnpromptEvent): Unit = channels.foreach(_.unprompt(event))
|
||||||
if (force)
|
|
||||||
channels.foreach(c => c.unprompt(event.copy(lastSource = Some(CommandSource(c.name)))))
|
|
||||||
else channels.foreach(_.unprompt(event))
|
|
||||||
}
|
|
||||||
|
|
||||||
def logMessage(event: LogEvent): Unit = {
|
def logMessage(event: LogEvent): Unit = {
|
||||||
channels.foreach {
|
channels.foreach {
|
||||||
|
|
|
||||||
|
|
@ -1254,11 +1254,11 @@ private[sbt] object ContinuousCommands {
|
||||||
}
|
}
|
||||||
|
|
||||||
private[this] val preWatchCommand = watchCommand(preWatch) { (channel, state) =>
|
private[this] val preWatchCommand = watchCommand(preWatch) { (channel, state) =>
|
||||||
StandardMain.exchange.channelForName(channel).foreach(_.terminal.setPrompt(Prompt.Running))
|
StandardMain.exchange.channelForName(channel).foreach(_.terminal.setPrompt(Prompt.Watch))
|
||||||
watchState(channel).beforeCommand(state)
|
watchState(channel).beforeCommand(state)
|
||||||
}
|
}
|
||||||
private[this] val postWatchCommand = watchCommand(postWatch) { (channel, state) =>
|
private[this] val postWatchCommand = watchCommand(postWatch) { (channel, state) =>
|
||||||
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))), false)
|
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))
|
||||||
val ws = watchState(channel)
|
val ws = watchState(channel)
|
||||||
watchStates.put(channel, ws.withPending(false))
|
watchStates.put(channel, ws.withPending(false))
|
||||||
ws.afterCommand(state)
|
ws.afterCommand(state)
|
||||||
|
|
@ -1268,7 +1268,7 @@ private[sbt] object ContinuousCommands {
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
private[sbt] def stopWatchImpl(channelName: String): Unit = {
|
private[sbt] def stopWatchImpl(channelName: String): Unit = {
|
||||||
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channelName))), false)
|
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channelName))))
|
||||||
Option(watchStates.get(channelName)).foreach { ws =>
|
Option(watchStates.get(channelName)).foreach { ws =>
|
||||||
ws.afterWatch()
|
ws.afterWatch()
|
||||||
ws.callbacks.onExit()
|
ws.callbacks.onExit()
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,8 @@ private[sbt] final class TaskTraceEvent
|
||||||
()
|
()
|
||||||
} finally {
|
} finally {
|
||||||
trace.close()
|
trace.close()
|
||||||
console.println(s"wrote $outFile")
|
try console.println(s"wrote $outFile")
|
||||||
|
catch { case _: java.nio.channels.ClosedChannelException => }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue