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

zio.internal.macros.RenderedGraph.scala Maven / Gradle / Ivy

There is a newer version: 2.1.11
Show newest version
package zio.internal.macros

import zio.internal.ansi.{AnsiStringOps, Color}

private[macros] sealed trait RenderedGraph { self =>
  def ++(that: RenderedGraph): RenderedGraph
  def >>>(that: RenderedGraph): RenderedGraph
  def render(depth: Int): String
  def render: String = render(0)
}

private[macros] object RenderedGraph {
  def apply(string: String): RenderedGraph = Value(string)

  private val colors = List(Color.Blue, Color.Cyan, Color.Red, Color.Magenta, Color.Green)

  final case class Value(name: String, children: List[RenderedGraph] = List.empty) extends RenderedGraph { self =>
    override def ++(that: RenderedGraph): RenderedGraph = that match {
      case value: Value =>
        Row(List(self, value))
      case Row(values) =>
        Row(self +: values)
    }

    override def >>>(that: RenderedGraph): RenderedGraph =
      that match {
        case Value(string, children) => Value(string, self +: children)
        case Row(_)                  => throw new Error("NOT LIKE THIS")
      }

    override def render(depth: Int): String = {
      val node         = if (depth == 0) "◉" else "◑".faint
      val color        = colors(depth % colors.length)
      val displayTitle = s"$node ".withAnsi(color) + name.bold.withAnsi(color)

      val childCount = children.length
      var idx        = 0

      (displayTitle +:
        children.map { g =>
          idx += 1

          val isNested = idx < childCount
          val symbol   = if (isNested) "├─" else "╰─"
          val lines    = g.render(depth + 1).split("\n")

          val child = (lines.head +: lines.tail.map { line =>
            if (isNested)
              "│ ".faint.withAnsi(color) + line
            else
              "  " + line
          })
            .mkString("\n")

          symbol.faint.withAnsi(color) + child
        })
        .mkString("\n")

    }

  }

  final case class Row(values: List[RenderedGraph]) extends RenderedGraph { self =>
    override def ++(that: RenderedGraph): RenderedGraph =
      that match {
        case value: Value =>
          Row(self.values :+ value)
        case Row(values) =>
          Row(self.values ++ values)
      }

    override def >>>(that: RenderedGraph): RenderedGraph =
      that match {
        case Value(string, children) => Value(string, self.values ++ children)
        case Row(_)                  => throw new Error("NOT LIKE THIS")
      }

    override def render(depth: Int): String =
      values
        .map(_.render(depth))
        .mkString("\n\n")
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy