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

util.Text.scala Maven / Gradle / Ivy

// Copyright (c) 2018-2021 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package skunk.util

import cats.Monoid
import cats.implicits._

// display combinators for styled text
final class Text private (private val content: List[Text.Segment]) {
  def ++(other: Text): Text = new Text(content ++ other.content)
  def length: Int = content.foldMap(_.body.length)
  def render: String = content.foldMap(_.render)
  def padTo(n: Int): Text =
    content match {
      case Nil => Text.padding(n)
      case _   =>
        val extra = n - length
        if (extra <= 0) this else this ++ Text.padding(extra)
    }
  override def toString: String = s"""Text("$render")"""
}

object Text {

  // Constructors

  def apply(body: String): Text = plain(body)

  lazy val plain:   String => Text = styled("", _)
  lazy val red:     String => Text = styled(Console.RED, _)
  lazy val blue:    String => Text = styled(Console.BLUE, _)
  lazy val green:   String => Text = styled(Console.GREEN, _)
  lazy val yellow:  String => Text = styled(Console.YELLOW, _)
  lazy val cyan:    String => Text = styled(Console.CYAN, _)
  lazy val magenta: String => Text = styled(Console.MAGENTA, _)

  val empty: Text = plain("")

  def padding(n: Int): Text = Text(" " * n)

  def styled(style: String, body: String): Text = new Text(List(Segment(style, body)))

  case class Segment(style: String, body: String) {
    def render: String = style + body + Console.RESET
  }
  object Segment {
    val Empty = Segment("", "")
  }

  implicit val MonoidText: Monoid[Text] =
    new Monoid[Text] {
      val empty = new Text(Nil)
      def combine(a: Text, b: Text): Text = a ++ b
    }

  def grid(rows: List[List[Text]]): List[Text] = {
    val lengths  = rows.map(_.map(_.length))
    val paddings = LazyList.from(0).map(i => lengths.map(_.lift(i).orEmpty).max)
    rows.map(_.zipWithIndex.map { case (s, n) => s.padTo(paddings(n)) }.intercalate(Text("  ")))
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy