From 8c85744d67e0b5da328b8c9c031df0f96e0a3a6c Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 7 Mar 2019 16:39:47 -0500 Subject: [PATCH 1/3] Use IO.Newline for stack trace --- .../scala/sbt/internal/util/StackTrace.scala | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala index 58888e8be..37cc42400 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/StackTrace.scala @@ -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) } From 8215026bc3c45ff70d4d9c0be7c98bf5d2b85dc2 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 7 Mar 2019 16:42:10 -0500 Subject: [PATCH 2/3] Account for log line longer than the terminal width widthHolder will hold on to the terminal width if supplied by sbt. This avoids adding dependencies to JLine. --- .../sbt/internal/util/ConsoleAppender.scala | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala index e18add319..50f6fb507 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala @@ -97,8 +97,14 @@ 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) /** Hide stack trace altogether. */ val noSuppressedMessage = (_: SuppressedTraceContext) => None @@ -463,7 +469,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) From d496a5dff559a14d689a7138069164e764cec1ea Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 7 Mar 2019 16:49:54 -0500 Subject: [PATCH 3/3] Make showProgress configurable --- .../sbt/internal/util/ConsoleAppender.scala | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala index 50f6fb507..741bafc4f 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/ConsoleAppender.scala @@ -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 } @@ -105,6 +105,9 @@ object ConsoleAppender { 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 @@ -141,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