All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.arainko.ducktape.internal.Logger.scala Maven / Gradle / Ivy

The newest version!
package io.github.arainko.ducktape.internal

import scala.Ordering.Implicits.*
import scala.quoted.*

private[ducktape] object Logger {

  // Logger Config
  private[ducktape] transparent inline given level: Level = Level.Off
  private val output = Output.StdOut
  private def filter(msg: String, loc: String) = true
  enum Level {
    case Off, Debug, Info
  }

  object Level {
    given Ordering[Level] = Ordering.by(_.ordinal)
  }

  enum Output {
    case StdOut, Report

    final def print(msg: String, level: Level)(using Quotes) = {
      import quotes.reflect.*

      def colored(color: String & scala.Singleton)(msg: String) = s"$color$msg${Console.RESET}"
      def green(msg: String) = colored(Console.GREEN)(msg)

      val location =
        Symbol.spliceOwner.pos
          .map(pos => s"${pos.sourceFile.name}:${pos.startLine}:${pos.startColumn}")
          .map(formatted => green(" [" + formatted + "]"))
          .getOrElse("")
      val formatted = s"${green(s"[${level.toString().toUpperCase()}]")}$location $msg"
      this match {
        case StdOut => if filter(msg, location) then println(formatted)
        case Report => if filter(msg, location) then quotes.reflect.report.info(formatted)
      }
    }
  }

  inline def loggedInfo[A](using Quotes)(
    inline msg: String
  )(value: A)(using Debug[A]) = {
    info(msg, value)
    value
  }

  inline def info(inline msg: String)(using quotes: Quotes): Unit =
    inline level match {
      case Level.Debug => if level <= Level.Info then output.print(msg, Level.Info)
      case Level.Info  => if level <= Level.Info then output.print(msg, Level.Info)
      case Level.Off   => ()
    }

  inline def info[A](
    inline msg: String,
    value: A
  )(using Debug[A], Quotes): Unit =
    info(s"$msg: ${Debug.show(value)}")

  inline def loggedDebug[A](using Quotes)(
    inline msg: String
  )(value: A)(using Debug[A]) = {
    debug(msg, value)
    value
  }

  inline def debug(inline msg: String)(using quotes: Quotes): Unit =
    inline level match {
      case Level.Debug => if level <= Level.Debug then output.print(msg, Level.Debug)
      case Level.Info  => if level <= Level.Debug then output.print(msg, Level.Debug)
      case Level.Off   => ()
    }

  inline def debug[A](inline msg: String, value: A)(using
    _debug: Debug[A],
    quotes: Quotes
  ): Unit =
    debug(s"$msg: ${Debug.show(value)}")
}

extension (ctx: StringContext) {
  private[ducktape] def ds(args: Any*): String = {
    val pi = ctx.parts.iterator
    val ai = args.iterator
    val bldr = new StringBuilder(pi.next())
    while ai.hasNext do {
      bldr.append(ai.next().getClass().getSimpleName())
      bldr.append(pi.next())
    }
    bldr.toString
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy