Skip to content

Instantly share code, notes, and snippets.

@keynmol
Created April 17, 2024 19:54
Show Gist options
  • Save keynmol/de109e14367f98419074681a9958aa0f to your computer and use it in GitHub Desktop.
Save keynmol/de109e14367f98419074681a9958aa0f to your computer and use it in GitHub Desktop.
Logging interpolator for Scala 3
import scala.quoted.*
extension (inline ctx: StringContext)
transparent inline def log(inline args: Any*): Any =
${ impl('ctx, 'args) }
inline private def col(inline f: Console.type => String, inline msg: Any) =
f(Console) + msg.toString() + Console.RESET
private def impl(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(
using Quotes
): Expr[Any] =
val args: List[Expr[Any]] =
val Varargs(args) = argsExpr: @unchecked
args.toList
end args
val codecsBuilder = List.newBuilder[Expr[Any]]
val segmentBuilders = List.newBuilder[Expr[Either[Int, String]]]
args.foreach { expr =>
expr match
case '{ $other: String } =>
segmentBuilders.addOne('{
Right($other)
})
case '{ type t; $s: t } =>
val e = Expr(expr.show)
codecsBuilder.addOne('{
val rend =
if $s != null
then $s.toString
else col(_.RED, "null")
col(_.GREEN, "[" + $e + " = ") +
col(_.BLUE, col(_.BOLD, rend)) +
col(_.GREEN, "]")
})
}
val insertions =
Expr.ofList(codecsBuilder.result() ++ segmentBuilders.result())
'{
val parts = $strCtxExpr.parts.map(Option.apply)
val ins = $insertions.map(Option.apply)
val sb = new StringBuilder
parts.zipAll(ins, None, None).foreach { case (str, insertion) =>
str.foreach(sb.append(_))
insertion.foreach(sb.append(_))
}
println(sb.result)
}
end impl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment