Merge pull request #193 from eed3si9n/wip/terminal

Account for log line longer than the terminal width
This commit is contained in:
eugene yokota 2019-03-07 17:35:53 -05:00 committed by GitHub
commit 3572868cac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 27 deletions

View File

@ -3,7 +3,7 @@ package sbt.internal.util
import sbt.util._
import java.io.{ PrintStream, PrintWriter }
import java.util.Locale
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicInteger }
import org.apache.logging.log4j.{ Level => XLevel }
import org.apache.logging.log4j.message.{ Message, ObjectMessage, ReusableObjectMessage }
import org.apache.logging.log4j.core.{ LogEvent => XLogEvent }
@ -97,8 +97,17 @@ class ConsoleLogger private[ConsoleLogger] (
object ConsoleAppender {
private[sbt] final val ScrollUp = "\u001B[S"
private[sbt] def cursorUp(n: Int): String = s"\u001B[${n}A"
private[sbt] def cursorDown(n: Int): String = s"\u001B[${n}B"
private[sbt] def scrollUp(n: Int): String = s"\u001B[${n}S"
private[sbt] final val DeleteLine = "\u001B[2K"
private[sbt] final val CursorLeft1000 = "\u001B[1000D"
private[this] val widthHolder: AtomicInteger = new AtomicInteger
private[sbt] def terminalWidth = widthHolder.get
private[sbt] def setTerminalWidth(n: Int): Unit = widthHolder.set(n)
private[this] val showProgressHolder: AtomicBoolean = new AtomicBoolean(false)
def setShowProgress(b: Boolean): Unit = showProgressHolder.set(b)
def showProgress: Boolean = showProgressHolder.get
/** Hide stack trace altogether. */
val noSuppressedMessage = (_: SuppressedTraceContext) => None
@ -135,21 +144,6 @@ object ConsoleAppender {
}
}
/**
* 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
@ -463,7 +457,18 @@ class ConsoleAppender private[ConsoleAppender] (
if (!useFormat || !ansiCodesSupported) {
out.println(EscHelpers.removeEscapeSequences(msg))
} else if (ConsoleAppender.showProgress) {
out.print(s"$ScrollUp$DeleteLine$msg${CursorLeft1000}")
val textLength = msg.length - 5
val scrollNum =
if (ConsoleAppender.terminalWidth == 0) 1
else (textLength / ConsoleAppender.terminalWidth) + 1
if (scrollNum > 1) {
out.print(s"${cursorDown(1)}$DeleteLine" * (scrollNum - 1) + s"${cursorUp(scrollNum - 1)}")
}
out.print(
s"$ScrollUp$DeleteLine$msg${CursorLeft1000}" + (
if (scrollNum <= 1) ""
else scrollUp(scrollNum - 1)
))
out.flush()
} else {
out.println(msg)

View File

@ -3,6 +3,9 @@
*/
package sbt.internal.util
import sbt.io.IO
import scala.collection.mutable.ListBuffer
object StackTrace {
def isSbtClass(name: String) = name.startsWith("sbt.") || name.startsWith("xsbt.")
@ -18,9 +21,9 @@ object StackTrace {
* where the line for the Throwable is counted plus one line for each stack element.
* Less lines will be included if there are not enough stack elements.
*/
def trimmed(t: Throwable, d: Int): String = {
def trimmedLines(t: Throwable, d: Int): List[String] = {
require(d >= 0)
val b = new StringBuilder()
val b = new ListBuffer[String]()
def appendStackTrace(t: Throwable, first: Boolean): Unit = {
@ -33,16 +36,12 @@ object StackTrace {
}
def appendElement(e: StackTraceElement): Unit = {
b.append("\tat ")
b.append(e)
b.append('\n')
b.append("\tat " + e)
()
}
if (!first)
b.append("Caused by: ")
b.append(t)
b.append('\n')
if (!first) b.append("Caused by: " + t.toString)
else b.append(t.toString)
val els = t.getStackTrace()
var i = 0
@ -59,7 +58,21 @@ object StackTrace {
c = c.getCause()
appendStackTrace(c, false)
}
b.toString()
b.toList
}
/**
* Return a printable representation of the stack trace associated
* with t. Information about t and its Throwable causes is included.
* The number of lines to be included for each Throwable is configured
* via d which should be greater than or equal to 0.
*
* - If d is 0, then all elements are included up to (but not including)
* the first element that comes from sbt.
* - If d is greater than 0, then up to that many lines are included,
* where the line for the Throwable is counted plus one line for each stack element.
* Less lines will be included if there are not enough stack elements.
*/
def trimmed(t: Throwable, d: Int): String =
trimmedLines(t, d).mkString(IO.Newline)
}