mirror of https://github.com/sbt/sbt.git
Merge pull request #184 from eed3si9n/wip/progress
Adds sbt.color flag and sbt.progress flag
This commit is contained in:
commit
f16997d3a9
|
|
@ -126,6 +126,9 @@ lazy val utilLogging = (project in internalPath / "util-logging")
|
|||
// Private final class constructors changed
|
||||
exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcretePosition.this"),
|
||||
exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcreteProblem.this"),
|
||||
exclude[ReversedMissingMethodProblem]("sbt.internal.util.ConsoleOut.flush"),
|
||||
// This affects Scala 2.11 only it seems, so it's ok?
|
||||
exclude[InheritedNewAbstractMethodProblem]("sbt.internal.util.codec.JsonProtocol.LogOptionFormat"),
|
||||
),
|
||||
)
|
||||
.configure(addSbtIO)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.util
|
||||
/** value for logging options like color */
|
||||
sealed abstract class LogOption extends Serializable
|
||||
object LogOption {
|
||||
|
||||
|
||||
case object Always extends LogOption
|
||||
case object Never extends LogOption
|
||||
case object Auto extends LogOption
|
||||
}
|
||||
|
|
@ -9,4 +9,5 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
|||
with sbt.internal.util.codec.TraceEventFormats
|
||||
with sbt.internal.util.codec.AbstractEntryFormats
|
||||
with sbt.internal.util.codec.SuccessEventFormats
|
||||
with sbt.internal.util.codec.LogOptionFormats
|
||||
object JsonProtocol extends JsonProtocol
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.util.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait LogOptionFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val LogOptionFormat: JsonFormat[sbt.internal.util.LogOption] = new JsonFormat[sbt.internal.util.LogOption] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.util.LogOption = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.readString(js) match {
|
||||
case "Always" => sbt.internal.util.LogOption.Always
|
||||
case "Never" => sbt.internal.util.LogOption.Never
|
||||
case "Auto" => sbt.internal.util.LogOption.Auto
|
||||
}
|
||||
case None =>
|
||||
deserializationError("Expected JsString but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.util.LogOption, builder: Builder[J]): Unit = {
|
||||
val str = obj match {
|
||||
case sbt.internal.util.LogOption.Always => "Always"
|
||||
case sbt.internal.util.LogOption.Never => "Never"
|
||||
case sbt.internal.util.LogOption.Auto => "Auto"
|
||||
}
|
||||
builder.writeString(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,3 +25,10 @@ type TraceEvent implements sbt.internal.util.AbstractEntry {
|
|||
type SuccessEvent {
|
||||
message: String!
|
||||
}
|
||||
|
||||
## value for logging options like color
|
||||
enum LogOption {
|
||||
Always
|
||||
Never
|
||||
Auto
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,13 +100,63 @@ object ConsoleAppender {
|
|||
/** Hide stack trace altogether. */
|
||||
val noSuppressedMessage = (_: SuppressedTraceContext) => None
|
||||
|
||||
/** Indicates whether formatting has been disabled in environment variables. */
|
||||
/**
|
||||
* Indicates whether formatting has been disabled in environment variables.
|
||||
* 1. -Dsbt.log.noformat=true means no formatting.
|
||||
* 2. -Dsbt.color=always/auto/never/true/false
|
||||
* 3. -Dsbt.colour=always/auto/never/true/false
|
||||
* 4. -Dsbt.log.format=always/auto/never/true/false
|
||||
*/
|
||||
val formatEnabledInEnv: Boolean = {
|
||||
import java.lang.Boolean.{ getBoolean, parseBoolean }
|
||||
val value = System.getProperty("sbt.log.format")
|
||||
if (value eq null) (ansiSupported && !getBoolean("sbt.log.noformat")) else parseBoolean(value)
|
||||
def useColorDefault: Boolean = {
|
||||
// This approximates that both stdin and stdio are connected,
|
||||
// so by default color will be turned off for pipes and redirects.
|
||||
val hasConsole = Option(java.lang.System.console).isDefined
|
||||
ansiSupported && hasConsole
|
||||
}
|
||||
sys.props.get("sbt.log.noformat") match {
|
||||
case Some(_) => !java.lang.Boolean.getBoolean("sbt.log.noformat")
|
||||
case _ =>
|
||||
sys.props
|
||||
.get("sbt.color")
|
||||
.orElse(sys.props.get("sbt.colour"))
|
||||
.orElse(sys.props.get("sbt.log.format"))
|
||||
.flatMap({ s =>
|
||||
parseLogOption(s) match {
|
||||
case LogOption.Always => Some(true)
|
||||
case LogOption.Never => Some(false)
|
||||
case _ => None
|
||||
}
|
||||
})
|
||||
.getOrElse(useColorDefault)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the super shell is enabled.
|
||||
*/
|
||||
lazy val showProgress: Boolean =
|
||||
formatEnabledInEnv && sys.props
|
||||
.get("sbt.progress")
|
||||
.flatMap({ s =>
|
||||
parseLogOption(s) match {
|
||||
case LogOption.Always => Some(true)
|
||||
case LogOption.Never => Some(false)
|
||||
case _ => None
|
||||
}
|
||||
})
|
||||
.getOrElse(true)
|
||||
|
||||
private[sbt] def parseLogOption(s: String): LogOption =
|
||||
s.toLowerCase match {
|
||||
case "always" => LogOption.Always
|
||||
case "auto" => LogOption.Auto
|
||||
case "never" => LogOption.Never
|
||||
case "true" => LogOption.Always
|
||||
case "false" => LogOption.Never
|
||||
case _ => LogOption.Auto
|
||||
}
|
||||
|
||||
private[this] val generateId: AtomicInteger = new AtomicInteger
|
||||
|
||||
/**
|
||||
|
|
@ -406,11 +456,18 @@ class ConsoleAppender private[ConsoleAppender] (
|
|||
appendLog(SUCCESS_LABEL_COLOR, Level.SuccessLabel, SUCCESS_MESSAGE_COLOR, message)
|
||||
}
|
||||
|
||||
private final val ScrollUp = "\u001B[S"
|
||||
private final val DeleteLine = "\u001B[2K"
|
||||
private final val CursorLeft1000 = "\u001B[1000D"
|
||||
private def write(msg: String): Unit = {
|
||||
val cleanedMsg =
|
||||
if (!useFormat || !ansiCodesSupported) EscHelpers.removeEscapeSequences(msg)
|
||||
else msg
|
||||
out.println(cleanedMsg)
|
||||
if (!useFormat || !ansiCodesSupported) {
|
||||
out.println(EscHelpers.removeEscapeSequences(msg))
|
||||
} else if (ConsoleAppender.showProgress) {
|
||||
out.print(s"$ScrollUp$DeleteLine$msg${CursorLeft1000}")
|
||||
out.flush()
|
||||
} else {
|
||||
out.println(msg)
|
||||
}
|
||||
}
|
||||
|
||||
private def appendMessage(level: Level.Value, msg: Message): Unit =
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ sealed trait ConsoleOut {
|
|||
def print(s: String): Unit
|
||||
def println(s: String): Unit
|
||||
def println(): Unit
|
||||
def flush(): Unit
|
||||
}
|
||||
|
||||
object ConsoleOut {
|
||||
|
|
@ -39,6 +40,14 @@ object ConsoleOut {
|
|||
last = Some(s)
|
||||
current.setLength(0)
|
||||
}
|
||||
def flush(): Unit = synchronized {
|
||||
val s = current.toString
|
||||
if (ConsoleAppender.formatEnabledInEnv && last.exists(lmsg => f(s, lmsg)))
|
||||
lockObject.print(OverwriteLine)
|
||||
lockObject.print(s)
|
||||
last = Some(s)
|
||||
current.setLength(0)
|
||||
}
|
||||
}
|
||||
|
||||
def printStreamOut(out: PrintStream): ConsoleOut = new ConsoleOut {
|
||||
|
|
@ -46,17 +55,20 @@ object ConsoleOut {
|
|||
def print(s: String) = out.print(s)
|
||||
def println(s: String) = out.println(s)
|
||||
def println() = out.println()
|
||||
def flush() = out.flush()
|
||||
}
|
||||
def printWriterOut(out: PrintWriter): ConsoleOut = new ConsoleOut {
|
||||
val lockObject = out
|
||||
def print(s: String) = out.print(s)
|
||||
def println(s: String) = { out.println(s); out.flush() }
|
||||
def println() = { out.println(); out.flush() }
|
||||
def println(s: String) = { out.println(s); flush() }
|
||||
def println() = { out.println(); flush() }
|
||||
def flush() = { out.flush() }
|
||||
}
|
||||
def bufferedWriterOut(out: BufferedWriter): ConsoleOut = new ConsoleOut {
|
||||
val lockObject = out
|
||||
def print(s: String) = out.write(s)
|
||||
def println(s: String) = { out.write(s); println() }
|
||||
def println() = { out.newLine(); out.flush() }
|
||||
def println() = { out.newLine(); flush() }
|
||||
def flush() = { out.flush() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue