diff --git a/compiler/src/dotty/tools/dotc/config/CliCommand.scala b/compiler/src/dotty/tools/dotc/config/CliCommand.scala index 7f6ea0cece5f..5e8b159aa8af 100644 --- a/compiler/src/dotty/tools/dotc/config/CliCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CliCommand.scala @@ -3,7 +3,7 @@ package config import Settings.* import core.Contexts.* -import printing.Highlighting +import dotty.shaded.fansi import dotty.tools.dotc.util.chaining.* import scala.PartialFunction.cond @@ -154,10 +154,9 @@ trait CliCommand: def apply(texts: List[List[(String, String)]])(using Context): String = StringBuilder().tap(columnate(_, texts)).toString private def columnate(sb: StringBuilder, texts: List[List[(String, String)]])(using Context): Unit = - import Highlighting.* - val colors = Seq(Green(_), Yellow(_), Magenta(_), Cyan(_), Red(_)) + val colors: Seq[String => fansi.Str] = Seq(fansi.Color.Green(_), fansi.Color.Yellow(_), fansi.Color.Magenta(_), fansi.Color.Cyan(_), fansi.Color.Red(_)) val nocolor = texts.length == 1 - def color(index: Int): String => Highlight = if nocolor then NoColor(_) else colors(index % colors.length) + def color(index: Int): String => fansi.Str = if nocolor then fansi.Str(_) else colors(index % colors.length) val maxCol = ctx.settings.pageWidth.value val field1 = maxField.min(texts.flatten.map(_._1.length).filter(_ < maxField).max) // widest field under maxField val field2 = if field1 + separation + maxField < maxCol then maxCol - field1 - separation else 0 // skinny window -> terminal wrap @@ -173,13 +172,13 @@ trait CliCommand: case i => val (prefix, rest) = fld.splitAt(i) ; prefix :: loopOverField2(rest.trim) text.split("\n").toList.flatMap(loopOverField2).filter(_.nonEmpty).mkString(EOL + "".padLeft(field1) + separator) end formatField2 - def format(first: String, second: String, index: Int, colorPicker: Int => String => Highlight) = - sb.append(colorPicker(index)(formatField1(first)).show) + def format(first: String, second: String, index: Int, colorPicker: Int => String => fansi.Str) = + sb.append(colorPicker(index)(formatField1(first)).render) .append(separator) .append(formatField2(second)) .append(EOL): Unit def fancy(first: String, second: String, index: Int) = format(first, second, index, color) - def plain(first: String, second: String) = format(first, second, 0, _ => NoColor(_)) + def plain(first: String, second: String) = format(first, second, 0, _ => fansi.Str(_)) if heading1.nonEmpty then plain(heading1, heading2) diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index daf4e70ad25a..ff9efda1b9ec 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -9,7 +9,6 @@ import Texts.*, Types.*, Flags.*, Symbols.*, Contexts.* import Decorators.* import reporting.Message import util.{DiffUtil, SimpleIdentitySet} -import Highlighting.* object Formatting { @@ -156,6 +155,8 @@ object Formatting { given Show[util.Spans.Span] = ShowAny given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny given Show[typer.ForceDegree.Value] = ShowAny + given Show[dotty.shaded.fansi.Str] with + def show(x: dotty.shaded.fansi.Str) = x.render end Show end ShownDef export ShownDef.{ Show, Shown } diff --git a/compiler/src/dotty/tools/dotc/printing/Highlighting.scala b/compiler/src/dotty/tools/dotc/printing/Highlighting.scala deleted file mode 100644 index c9b3e2a5aa83..000000000000 --- a/compiler/src/dotty/tools/dotc/printing/Highlighting.scala +++ /dev/null @@ -1,72 +0,0 @@ -package dotty.tools -package dotc -package printing - -import scala.collection.mutable -import core.Contexts.* - -object Highlighting { - - abstract class Highlight(private val highlight: String) { - def text: String - - def show(using Context): String = if ctx.useColors then highlight + text + Console.RESET else text - - override def toString: String = - highlight + text + Console.RESET - - def +(other: Highlight)(using Context): HighlightBuffer = - new HighlightBuffer(this) + other - - def +(other: String)(using Context): HighlightBuffer = - new HighlightBuffer(this) + other - } - - abstract class Modifier(private val mod: String, text: String) extends Highlight(Console.RESET) { - override def show(using Context): String = - if (ctx.settings.color.value == "never") "" - else mod + super.show - } - - case class HighlightBuffer(hl: Highlight)(using Context) { - private val buffer = new mutable.ListBuffer[String] - - buffer += hl.show - - def +(other: Highlight): HighlightBuffer = { - buffer += other.show - this - } - - def +(other: String): HighlightBuffer = { - buffer += other - this - } - - override def toString: String = - buffer.mkString - } - - case class NoColor(text: String) extends Highlight(Console.RESET) - - case class Red(text: String) extends Highlight(Console.RED) - case class Blue(text: String) extends Highlight(Console.BLUE) - case class Cyan(text: String) extends Highlight(Console.CYAN) - case class Black(text: String) extends Highlight(Console.BLACK) - case class Green(text: String) extends Highlight(Console.GREEN) - case class White(text: String) extends Highlight(Console.WHITE) - case class Yellow(text: String) extends Highlight(Console.YELLOW) - case class Magenta(text: String) extends Highlight(Console.MAGENTA) - - case class RedB(text: String) extends Highlight(Console.RED_B) - case class BlueB(text: String) extends Highlight(Console.BLUE_B) - case class CyanB(text: String) extends Highlight(Console.CYAN_B) - case class BlackB(text: String) extends Highlight(Console.BLACK_B) - case class GreenB(text: String) extends Highlight(Console.GREEN_B) - case class WhiteB(text: String) extends Highlight(Console.WHITE_B) - case class YellowB(text: String) extends Highlight(Console.YELLOW_B) - case class MagentaB(text: String) extends Highlight(Console.MAGENTA_B) - - case class Bold(text: String) extends Modifier(Console.BOLD, text) - case class Underlined(text: String) extends Modifier(Console.UNDERLINED, text) -} diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 90dfb72ef010..ffd853725fa3 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -14,6 +14,7 @@ import Variances.varianceSign import util.{Chars, SourcePosition} import scala.util.control.NonFatal import scala.annotation.switch +import dotty.shaded.fansi import config.{Config, Feature} import ast.{tpd, untpd} import cc.* @@ -846,9 +847,10 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def literalText(text: Text): Text = coloredText(text, SyntaxHighlighting.LiteralColor) protected def stringText(text: Text): Text = coloredText(text, SyntaxHighlighting.StringColor) - protected def coloredStr(text: String, color: String): String = - if (ctx.useColors) color + text + SyntaxHighlighting.NoColor else text - protected def coloredText(text: Text, color: String): Text = - if (ctx.useColors) color ~ text ~ SyntaxHighlighting.NoColor else text + protected def coloredStr(text: String, color: dotty.shaded.fansi.Attrs): String = + if (ctx.useColors) color(text).render else text + protected def coloredText(text: Text, color: dotty.shaded.fansi.Attrs): Text = + if (ctx.useColors) fansi.Attrs.emitAnsiCodes(0, color.applyMask) ~ text ~ fansi.Attrs.emitAnsiCodes(color.applyMask, 0) + else text } diff --git a/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala b/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala index f02cbf159224..56e78ff722ed 100644 --- a/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/ReplPrinter.scala @@ -56,6 +56,6 @@ class ReplPrinter(_ctx: Context) extends RefinedPrinter(_ctx) { // We don't want the colors coming from RefinedPrinter as the REPL uses its // own syntax coloring mechanism. - override def coloredStr(text: String, color: String): String = text - override def coloredText(text: Text, color: String): Text = text + override def coloredStr(text: String, color: dotty.shaded.fansi.Attrs): String = text + override def coloredText(text: Text, color: dotty.shaded.fansi.Attrs): Text = text } diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 6c0ff2ffffbe..cd323cc8d871 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -11,7 +11,8 @@ import dotty.tools.dotc.reporting.Reporter import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SourceFile -import java.util.Arrays +import dotty.shaded.fansi +import scala.collection.mutable.ArrayBuffer /** This object provides functions for syntax highlighting in the REPL */ object SyntaxHighlighting { @@ -23,14 +24,14 @@ object SyntaxHighlighting { private inline val debug = true // Keep in sync with SyntaxHighlightingTests - val NoColor: String = Console.RESET - val CommentColor: String = Console.BLUE - val KeywordColor: String = Console.YELLOW - val ValDefColor: String = Console.CYAN - val LiteralColor: String = Console.GREEN - val StringColor: String = Console.GREEN - val TypeColor: String = Console.MAGENTA - val AnnotationColor: String = Console.MAGENTA + val NoColor: fansi.Attrs = fansi.Attrs.Empty + val CommentColor: fansi.Attrs = fansi.Color.Blue + val KeywordColor: fansi.Attrs = fansi.Color.Yellow + val ValDefColor: fansi.Attrs = fansi.Color.Cyan + val LiteralColor: fansi.Attrs = fansi.Color.Green + val StringColor: fansi.Attrs = fansi.Color.Green + val TypeColor: fansi.Attrs = fansi.Color.Magenta + val AnnotationColor: fansi.Attrs = fansi.Color.Magenta def highlight(in: String)(using Context): String = { def freshCtx = ctx.fresh.setReporter(Reporter.NoReporter) @@ -41,18 +42,20 @@ object SyntaxHighlighting { given Context = freshCtx .setCompilationUnit(CompilationUnit(source, mustExist = false)(using freshCtx)) - val colorAt = Array.fill(in.length)(NoColor) + // Buffer to collect all highlight ranges for fansi.Str.overlayAll + val ranges = ArrayBuffer[(fansi.Attrs, Int, Int)]() - def highlightRange(from: Int, to: Int, color: String) = - Arrays.fill(colorAt.asInstanceOf[Array[AnyRef]], from, to, color) + def highlightRange(from: Int, to: Int, attrs: fansi.Attrs) = + if (attrs != fansi.Attrs.Empty) + ranges += ((attrs, from, to)) - def highlightPosition(span: Span, color: String) = if (span.exists) + def highlightPosition(span: Span, attrs: fansi.Attrs) = if (span.exists) if (span.start < 0 || span.end > in.length) { if (debug) println(s"Trying to highlight erroneous position $span. Input size: ${in.length}") } else - highlightRange(span.start, span.end, color) + highlightRange(span.start, span.end, attrs) val scanner = new Scanner(source) while (scanner.token != EOF) { @@ -78,7 +81,7 @@ object SyntaxHighlighting { highlightRange(start, end, KeywordColor) case IDENTIFIER if name == nme.??? => - highlightRange(start, end, Console.RED_B) + highlightRange(start, end, fansi.Back.Red) case IDENTIFIER if name.head.isUpper && name.exists(!_.isUpper) => highlightRange(start, end, KeywordColor) @@ -133,21 +136,8 @@ object SyntaxHighlighting { val trees = parser.blockStatSeq() TreeHighlighter.highlight(trees) - - val highlighted = new StringBuilder() - - for (idx <- colorAt.indices) { - val prev = if (idx == 0) NoColor else colorAt(idx - 1) - val curr = colorAt(idx) - if (curr != prev) - highlighted.append(curr) - highlighted.append(in(idx)) - } - - if (colorAt.last != NoColor) - highlighted.append(NoColor) - - highlighted.toString + // Apply all color ranges at once using fansi.Str.overlayAll + fansi.Str(in).overlayAll(ranges.toSeq).render catch case e: StackOverflowError => in diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index 32c9bf91f919..922b84eb429d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -10,6 +10,7 @@ import printing.Formatting.hl import config.SourceVersion import cc.CaptureSet import cc.Capabilities.* +import dotty.shaded.fansi import scala.annotation.threadUnsafe @@ -386,6 +387,10 @@ abstract class Message(val errorId: ErrorMessageID)(using Context) { self => def withoutDisambiguation(): this.type = withDisambiguation(Disambiguation.None) + private def stripFansiColorsIfNecessary(str: String)(using Context): String = + if ctx.useColors then str + else fansi.Str(str).plainText + private def inMessageContext(disambiguate: Disambiguation)(op: Context ?=> String): String = if ctx eq NoContext then op else @@ -397,7 +402,7 @@ abstract class Message(val errorId: ErrorMessageID)(using Context) { self => if !ctx1.property(MessageLimiter).isDefined then ctx1.setProperty(MessageLimiter, ErrorMessageLimiter()) ctx1 - op(using msgContext) + stripFansiColorsIfNecessary(op(using msgContext)) /** The message to report. tags are filtered out */ @threadUnsafe lazy val message: String = diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index a306f74858d4..9e9be4811657 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -9,8 +9,8 @@ import java.lang.System.{lineSeparator => EOL} import core.Contexts.* import core.Decorators.* import io.AbstractFile -import printing.Highlighting.{Blue, Red, Yellow} import printing.SyntaxHighlighting +import dotty.shaded.fansi import Diagnostic.* import util.{SourcePosition, NoSourcePosition} import util.Chars.{ LF, CR, FF, SU } @@ -205,8 +205,8 @@ trait MessageRendering { def explanation(m: Message)(using Context): String = { val sb = new StringBuilder( s"""| - |${Blue("Explanation").show} - |${Blue("===========").show}""".stripMargin + |${if ctx.useColors then fansi.Color.Blue("Explanation").render else "Explanation"} + |${if ctx.useColors then fansi.Color.Blue("===========").render else "==========="}""".stripMargin ) sb.append(EOL).append(m.explanation) if (!m.explanation.endsWith(EOL)) sb.append(EOL) @@ -305,10 +305,12 @@ trait MessageRendering { } private def hl(str: String)(using Context, Level): String = - summon[Level].value match - case interfaces.Diagnostic.ERROR => Red(str).show - case interfaces.Diagnostic.WARNING => Yellow(str).show - case interfaces.Diagnostic.INFO => Blue(str).show + if ctx.useColors then + summon[Level].value match + case interfaces.Diagnostic.ERROR => fansi.Color.Red(str).render + case interfaces.Diagnostic.WARNING => fansi.Color.Yellow(str).render + case interfaces.Diagnostic.INFO => fansi.Color.Blue(str).render + else str private def diagnosticLevel(dia: Diagnostic): String = dia match { diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index e86538eb8110..315573da151d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -10,7 +10,7 @@ import SymDenotations.SymDenotation import NameKinds.{WildcardParamName, ContextFunctionParamName} import parsing.Scanners.Token import parsing.Tokens -import printing.Highlighting.* +import dotty.shaded.fansi import printing.Formatting import ErrorMessageID.* import ast.Trees @@ -643,9 +643,9 @@ extends SyntaxMsg(UnboundPlaceholderParameterID) { class IllegalStartSimpleExpr(illegalToken: String)(using Context) extends SyntaxMsg(IllegalStartSimpleExprID) { - def msg(using Context) = i"expression expected but ${Red(illegalToken)} found" + def msg(using Context) = i"expression expected but ${fansi.Color.Red(illegalToken)} found" def explain(using Context) = { - i"""|An expression cannot start with ${Red(illegalToken)}.""" + i"""|An expression cannot start with ${fansi.Color.Red(illegalToken)}.""" } } @@ -1583,7 +1583,7 @@ class TypeDoesNotTakeParameters(tpe: Type, params: List[untpd.Tree])(using Conte val ps = if (params.size == 1) s"a type parameter ${params.head}" else s"type parameters ${params.map(_.show).mkString(", ")}" - i"""You specified ${NoColor(ps)} for $tpe, which is not + i"""You specified $ps for $tpe, which is not |declared to take any. |""" } @@ -1745,7 +1745,7 @@ class CannotExtendAnyVal(sym: Symbol)(using Context) def explain(using Context) = if sym.is(Trait) then i"""Only classes (not traits) are allowed to extend ${hl("AnyVal")}, but traits may extend - |${hl("Any")} to become ${Green("\"universal traits\"")} which may only have ${hl("def")} members. + |${hl("Any")} to become ${fansi.Color.Green("\"universal traits\"")} which may only have ${hl("def")} members. |Universal traits can be mixed into classes that extend ${hl("AnyVal")}. |""" else if sym.is(Module) then @@ -2192,13 +2192,13 @@ class UnapplyInvalidReturnType(unapplyResult: Type, unapplyName: Name)(using Con if Feature.migrateTo3 && unapplyName == nme.unapplySeq then "\nYou might want to try to rewrite the extractor to use `unapply` instead." else "" - i"""| ${Red(i"$unapplyResult")} is not a valid result type of an $unapplyName method of an ${Magenta("extractor")}.$addendum""" + i"""| ${fansi.Color.Red(i"$unapplyResult")} is not a valid result type of an $unapplyName method of an ${fansi.Color.Magenta("extractor")}.$addendum""" def explain(using Context) = if (unapplyName.show == "unapply") i""" |To be used as an extractor, an unapply method has to return a type that either: - | - has members ${Magenta("isEmpty: Boolean")} and ${Magenta("get: S")} (usually an ${Green("Option[S]")}) - | - is a ${Green("Boolean")} - | - is a ${Green("Product")} (like a ${Magenta("Tuple2[T1, T2]")}) of arity i with i >= 1, and has members _1 to _i + | - has members ${fansi.Color.Magenta("isEmpty: Boolean")} and ${fansi.Color.Magenta("get: S")} (usually an ${fansi.Color.Green("Option[S]")}) + | - is a ${fansi.Color.Green("Boolean")} + | - is a ${fansi.Color.Green("Product")} (like a ${fansi.Color.Magenta("Tuple2[T1, T2]")}) of arity i with i >= 1, and has members _1 to _i | |See: https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html#fixed-arity-extractors | @@ -2207,35 +2207,35 @@ class UnapplyInvalidReturnType(unapplyResult: Type, unapplyName: Name)(using Con |class A(val i: Int) | |object B { - | def unapply(a: A): ${Green("Option[Int]")} = Some(a.i) + | def unapply(a: A): ${fansi.Color.Green("Option[Int]")} = Some(a.i) |} | |object C { - | def unapply(a: A): ${Green("Boolean")} = a.i == 2 + | def unapply(a: A): ${fansi.Color.Green("Boolean")} = a.i == 2 |} | |object D { - | def unapply(a: A): ${Green("(Int, Int)")} = (a.i, a.i) + | def unapply(a: A): ${fansi.Color.Green("(Int, Int)")} = (a.i, a.i) |} | |object Test { | def test(a: A) = a match { - | ${Magenta("case B(1)")} => 1 - | ${Magenta("case a @ C()")} => 2 - | ${Magenta("case D(3, 3)")} => 3 + | ${fansi.Color.Magenta("case B(1)")} => 1 + | ${fansi.Color.Magenta("case a @ C()")} => 2 + | ${fansi.Color.Magenta("case D(3, 3)")} => 3 | } |} """ else i""" |To be used as an extractor, an unapplySeq method has to return a type which has members - |${Magenta("isEmpty: Boolean")} and ${Magenta("get: S")} where ${Magenta("S <: Seq[V]")} (usually an ${Green("Option[Seq[V]]")}): + |${fansi.Color.Magenta("isEmpty: Boolean")} and ${fansi.Color.Magenta("get: S")} where ${fansi.Color.Magenta("S <: Seq[V]")} (usually an ${fansi.Color.Green("Option[Seq[V]]")}): | |object CharList { - | def unapplySeq(s: String): ${Green("Option[Seq[Char]")} = Some(s.toList) + | def unapplySeq(s: String): ${fansi.Color.Green("Option[Seq[Char]")} = Some(s.toList) | | "example" match { - | ${Magenta("case CharList(c1, c2, c3, c4, _, _, _)")} => + | ${fansi.Color.Magenta("case CharList(c1, c2, c3, c4, _, _, _)")} => | println(s"$$c1,$$c2,$$c3,$$c4") | case _ => | println("Expected *exactly* 7 characters!") diff --git a/compiler/src/dotty/tools/repl/JLineTerminal.scala b/compiler/src/dotty/tools/repl/JLineTerminal.scala index fc193667154d..6f5c10011fb5 100644 --- a/compiler/src/dotty/tools/repl/JLineTerminal.scala +++ b/compiler/src/dotty/tools/repl/JLineTerminal.scala @@ -2,6 +2,7 @@ package dotty.tools.repl import scala.language.unsafeNulls +import dotty.shaded.fansi import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.parsing.Scanners.Scanner import dotty.tools.dotc.parsing.Tokens.* @@ -33,7 +34,7 @@ class JLineTerminal extends java.io.Closeable { private val history = new DefaultHistory private def blue(str: String)(using Context) = - if (ctx.settings.color.value != "never") Console.BLUE + str + Console.RESET + if (ctx.settings.color.value != "never") fansi.Color.Blue(str).render else str protected def promptStr = "scala" private def prompt(using Context) = blue(s"\n$promptStr> ") diff --git a/compiler/src/scala/quoted/runtime/impl/printers/SyntaxHighlight.scala b/compiler/src/scala/quoted/runtime/impl/printers/SyntaxHighlight.scala index cc3ecc2b153a..5fe8ed4cde92 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/SyntaxHighlight.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/SyntaxHighlight.scala @@ -1,6 +1,8 @@ package scala.quoted package runtime.impl.printers +import dotty.shaded.fansi + trait SyntaxHighlight { def highlightKeyword(str: String): String def highlightTypeDef(str: String): String @@ -16,23 +18,14 @@ object SyntaxHighlight { def ANSI: SyntaxHighlight = new SyntaxHighlight { // Keep in sync with SyntaxHighlighting - private val NoColor = Console.RESET - private val CommentColor = Console.BLUE - private val KeywordColor = Console.YELLOW - private val ValDefColor = Console.CYAN - private val LiteralColor = Console.RED - private val StringColor = Console.GREEN - private val TypeColor = Console.MAGENTA - private val AnnotationColor = Console.MAGENTA - - def highlightKeyword(str: String): String = KeywordColor + str + NoColor - def highlightTypeDef(str: String): String = TypeColor + str + NoColor - def highlightLiteral(str: String): String = LiteralColor + str + NoColor - def highlightValDef(str: String): String = ValDefColor + str + NoColor - def highlightOperator(str: String): String = TypeColor + str + NoColor - def highlightAnnotation(str: String): String = AnnotationColor + str + NoColor - def highlightString(str: String): String = StringColor + str + NoColor - def highlightTripleQs: String = Console.RED_B + "???" + NoColor + def highlightKeyword(str: String): String = fansi.Color.Yellow(str).render + def highlightTypeDef(str: String): String = fansi.Color.Magenta(str).render + def highlightLiteral(str: String): String = fansi.Color.Red(str).render + def highlightValDef(str: String): String = fansi.Color.Cyan(str).render + def highlightOperator(str: String): String = fansi.Color.Magenta(str).render + def highlightAnnotation(str: String): String = fansi.Color.Magenta(str).render + def highlightString(str: String): String = fansi.Color.Green(str).render + def highlightTripleQs: String = fansi.Back.Red("???").render } def plain: SyntaxHighlight = new SyntaxHighlight { diff --git a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala index 2a2510a95394..133f8d5aee80 100644 --- a/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala +++ b/compiler/test/dotty/tools/dotc/printing/SyntaxHighlightingTests.scala @@ -2,6 +2,7 @@ package dotty.tools.dotc.printing import scala.language.unsafeNulls +import dotty.shaded.fansi import dotty.tools.DottyTest import org.junit.Assert._ import org.junit.{Ignore, Test} @@ -12,14 +13,15 @@ class SyntaxHighlightingTests extends DottyTest { import SyntaxHighlighting._ private def test(source: String, expected: String): Unit = { + val highlighted = SyntaxHighlighting.highlight(source)(using ctx.withColors) - .replace(NoColor, ">") - .replace(CommentColor, "") + .replace(fansi.Attrs.emitAnsiCodes(NoColor.applyMask, CommentColor.applyMask), "