Split ConsoleOut into its own file, track the global ConsoleOut and use it instead of StandardMain.console

This commit is contained in:
Mark Harrah 2013-02-25 09:24:04 -05:00
parent 0280216e02
commit 67010fa0b2
4 changed files with 109 additions and 61 deletions

View File

@ -7,55 +7,27 @@ package sbt
object ConsoleLogger
{
def systemOut: ConsoleOut = printStreamOut(System.out)
def overwriteContaining(s: String): (String,String) => Boolean = (cur, prev) =>
cur.contains(s) && prev.contains(s)
@deprecated("Moved to ConsoleOut", "0.13.0")
def systemOut: ConsoleOut = ConsoleOut.systemOut
/** ConsoleOut instance that is backed by System.out. It overwrites the previously printed line
* if the function `f(lineToWrite, previousLine)` returns true.
*
* The ConsoleOut returned by this method assumes that the only newlines are from println calls
* and not in the String arguments. */
def systemOutOverwrite(f: (String,String) => Boolean): ConsoleOut = new ConsoleOut {
val lockObject = System.out
private[this] var last: Option[String] = None
private[this] var current = new java.lang.StringBuffer
def print(s: String): Unit = synchronized { current.append(s) }
def println(s: String): Unit = synchronized { current.append(s); println() }
def println(): Unit = synchronized {
val s = current.toString
if(formatEnabled && last.exists(lmsg => f(s, lmsg)))
System.out.print(OverwriteLine)
System.out.println(s)
last = Some(s)
current = new java.lang.StringBuffer
}
}
def printStreamOut(out: PrintStream): ConsoleOut = new ConsoleOut {
val lockObject = out
def print(s: String) = out.print(s)
def println(s: String) = out.println(s)
def println() = out.println()
}
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 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() }
}
@deprecated("Moved to ConsoleOut", "0.13.0")
def overwriteContaining(s: String): (String,String) => Boolean = ConsoleOut.overwriteContaining(s)
@deprecated("Moved to ConsoleOut", "0.13.0")
def systemOutOverwrite(f: (String,String) => Boolean): ConsoleOut = ConsoleOut.systemOutOverwrite(f)
@deprecated("Moved to ConsoleOut", "0.13.0")
def printStreamOut(out: PrintStream): ConsoleOut = ConsoleOut.printStreamOut(out)
@deprecated("Moved to ConsoleOut", "0.13.0")
def printWriterOut(out: PrintWriter): ConsoleOut = ConsoleOut.printWriterOut(out)
@deprecated("Moved to ConsoleOut", "0.13.0")
def bufferedWriterOut(out: BufferedWriter): ConsoleOut = bufferedWriterOut(out)
/** Escape character, used to introduce an escape sequence. */
final val ESC = '\u001B'
/** Move to beginning of previous line and clear the line. */
private[sbt] final val OverwriteLine = "\r\u001BM\u001B[2K"
/** An escape terminator is a character in the range `@` (decimal value 64) to `~` (decimal value 126).
* It is the final character in an escape sequence. */
def isEscapeTerminator(c: Char): Boolean =
@ -120,9 +92,9 @@ object ConsoleLogger
private[this] def os = System.getProperty("os.name")
private[this] def isWindows = os.toLowerCase.indexOf("windows") >= 0
def apply(out: PrintStream): ConsoleLogger = apply(printStreamOut(out))
def apply(out: PrintWriter): ConsoleLogger = apply(printWriterOut(out))
def apply(out: ConsoleOut = systemOut, ansiCodesSupported: Boolean = formatEnabled,
def apply(out: PrintStream): ConsoleLogger = apply(ConsoleOut.printStreamOut(out))
def apply(out: PrintWriter): ConsoleLogger = apply(ConsoleOut.printWriterOut(out))
def apply(out: ConsoleOut = ConsoleOut.systemOut, ansiCodesSupported: Boolean = formatEnabled,
useColor: Boolean = formatEnabled, suppressedMessage: SuppressedTraceContext => Option[String] = noSuppressedMessage): ConsoleLogger =
new ConsoleLogger(out, ansiCodesSupported, useColor, suppressedMessage)
@ -200,10 +172,3 @@ class ConsoleLogger private[ConsoleLogger](val out: ConsoleOut, override val ans
{ log(labelColor(Level.Info), Level.Info.toString, BLUE, message) }
}
final class SuppressedTraceContext(val traceLevel: Int, val useColor: Boolean)
sealed trait ConsoleOut
{
val lockObject: AnyRef
def print(s: String): Unit
def println(s: String): Unit
def println(): Unit
}

View File

@ -0,0 +1,62 @@
package sbt
import java.io.{BufferedWriter, PrintStream, PrintWriter}
sealed trait ConsoleOut
{
val lockObject: AnyRef
def print(s: String): Unit
def println(s: String): Unit
def println(): Unit
}
object ConsoleOut
{
def systemOut: ConsoleOut = printStreamOut(System.out)
def overwriteContaining(s: String): (String,String) => Boolean = (cur, prev) =>
cur.contains(s) && prev.contains(s)
/** Move to beginning of previous line and clear the line. */
private[this] final val OverwriteLine = "\r\u001BM\u001B[2K"
/** ConsoleOut instance that is backed by System.out. It overwrites the previously printed line
* if the function `f(lineToWrite, previousLine)` returns true.
*
* The ConsoleOut returned by this method assumes that the only newlines are from println calls
* and not in the String arguments. */
def systemOutOverwrite(f: (String,String) => Boolean): ConsoleOut = new ConsoleOut {
val lockObject = System.out
private[this] var last: Option[String] = None
private[this] var current = new java.lang.StringBuffer
def print(s: String): Unit = synchronized { current.append(s) }
def println(s: String): Unit = synchronized { current.append(s); println() }
def println(): Unit = synchronized {
val s = current.toString
if(ConsoleLogger.formatEnabled && last.exists(lmsg => f(s, lmsg)))
System.out.print(OverwriteLine)
System.out.println(s)
last = Some(s)
current = new java.lang.StringBuffer
}
}
def printStreamOut(out: PrintStream): ConsoleOut = new ConsoleOut {
val lockObject = out
def print(s: String) = out.print(s)
def println(s: String) = out.println(s)
def println() = out.println()
}
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 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() }
}
}

View File

@ -5,11 +5,28 @@ package sbt
import java.io.{File, PrintWriter}
final case class GlobalLogging(full: Logger, backed: ConsoleLogger, backing: GlobalLogBacking)
/** Provides the current global logging configuration.
*
* `full` is the current global logger. It should not be set directly because it is generated as needed from `backing.newLogger`.
* `console` is where all logging from all ConsoleLoggers should go.
* `backed` is the ConsoleLogger that other loggers should feed into.
* `backing` tracks the files that persist the global logging. */
final case class GlobalLogging(full: Logger, console: ConsoleOut, backed: ConsoleLogger, backing: GlobalLogBacking)
/** Tracks the files that persist the global logging.
* `file` is the current backing file. `last` is the previous backing file, if there is one.
* `newLogger` creates a new global logging configuration from a sink and backing configuration.
* `newBackingFile` creates a new temporary location for the next backing file. */
final case class GlobalLogBacking(file: File, last: Option[File], newLogger: (PrintWriter, GlobalLogBacking) => GlobalLogging, newBackingFile: () => File)
{
/** Shifts the current backing file to `last` and sets the current backing to `newFile`. */
def shift(newFile: File) = GlobalLogBacking(newFile, Some(file), newLogger, newBackingFile)
/** Shifts the current backing file to `last` and sets the current backing to a new temporary file generated by `newBackingFile`. */
def shiftNew() = shift(newBackingFile())
/** If there is a previous backing file in `last`, that becomes the current backing file and the previous backing is cleared.
* Otherwise, no changes are made. */
def unshift = GlobalLogBacking(last getOrElse file, None, newLogger, newBackingFile)
}
object GlobalLogBacking
@ -21,10 +38,11 @@ object GlobalLogging
{
@deprecated("Explicitly specify standard out.", "0.13.0")
def initial(newLogger: (PrintWriter, GlobalLogBacking) => GlobalLogging, newBackingFile: => File): GlobalLogging =
initial(newLogger, newBackingFile, ConsoleLogger.systemOut)
initial(newLogger, newBackingFile, ConsoleOut.systemOut)
def initial(newLogger: (PrintWriter, GlobalLogBacking) => GlobalLogging, newBackingFile: => File, console: ConsoleOut): GlobalLogging =
{
val log = ConsoleLogger(console)
GlobalLogging(log, log, GlobalLogBacking(newLogger, newBackingFile))
GlobalLogging(log, console, log, GlobalLogBacking(newLogger, newBackingFile))
}
}

View File

@ -17,18 +17,21 @@ object MainLogging
backed setTrace backingTrace
multi: Logger
}
@deprecated("Explicitly specify the console output.", "0.13.0")
def globalDefault(writer: PrintWriter, backing: GlobalLogBacking): GlobalLogging =
globalDefault(writer, backing, ConsoleLogger.systemOut)
globalDefault(writer, backing, ConsoleOut.systemOut)
def globalDefault(writer: PrintWriter, backing: GlobalLogBacking, console: ConsoleOut): GlobalLogging =
{
val backed = defaultBacked()(writer)
val full = multiLogger(defaultMultiConfig(console, backed ) )
GlobalLogging(full, backed, backing)
GlobalLogging(full, console, backed, backing)
}
@deprecated("Explicitly specify the console output.", "0.13.0")
def defaultMultiConfig(backing: AbstractLogger): MultiLoggerConfig =
defaultMultiConfig(ConsoleLogger.systemOut, backing)
defaultMultiConfig(ConsoleOut.systemOut, backing)
def defaultMultiConfig(console: ConsoleOut, backing: AbstractLogger): MultiLoggerConfig =
new MultiLoggerConfig(defaultScreen(console, ConsoleLogger.noSuppressedMessage), backing, Nil, Level.Info, Level.Debug, -1, Int.MaxValue)
@ -43,7 +46,7 @@ object MainLogging
ConsoleLogger(console, suppressedMessage = suppressedMessage)
def defaultBacked(useColor: Boolean = ConsoleLogger.formatEnabled): PrintWriter => ConsoleLogger =
to => ConsoleLogger(ConsoleLogger.printWriterOut(to), useColor = useColor)
to => ConsoleLogger(ConsoleOut.printWriterOut(to), useColor = useColor)
}
final case class MultiLoggerConfig(console: AbstractLogger, backed: AbstractLogger, extra: List[AbstractLogger],