scala.reflect.internal.util.TableDef.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-reflect Show documentation
Show all versions of scala-reflect Show documentation
Reflection Library for the Scala Programming Language
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala
package reflect.internal.util
import TableDef._
import scala.language.postfixOps
/** A class for representing tabular data in a way that preserves
* its inner beauty.
* One creates an instance of TableDef by defining the columns of
* the table, then uses that to create an instance of Table by
* passing in a sequence of rows.
*/
class TableDef[T](_cols: Column[T]*) {
// These operators are about all there is to it.
/** Appends a column to the table. */
def ~(next: Column[T]) = retThis(cols :+= next)
// Below this point should all be considered private/internal.
private var cols: List[Column[T]] = _cols.toList
def defaultSep(index: Int) = if (index > (cols.size - 2)) "" else " "
def sepAfter(i: Int): String = defaultSep(i)
def sepWidths = cols.indices map (i => sepAfter(i).length)
def colNames = cols map (_.name)
def colFunctions = cols map (_.f)
def colApply(el: T) = colFunctions map (f => f(el))
def retThis(body: => Unit): this.type = { body ; this }
class Table(val rows: Seq[T]) extends Seq[T] {
def iterator = rows.iterator
def apply(index: Int) = rows(index)
def length = rows.length
def maxColWidth(col: Column[T]) = col.name +: (rows map col.f) map (_.toString.length) max
def specs = cols map (_ formatSpec rows)
val colWidths = cols map maxColWidth
val rowFormat = mkFormatString(sepAfter)
val headFormat = mkFormatString(i => " " * sepWidths(i))
val argLists = rows map colApply
val headers = List(
headFormat.format(colNames: _*),
(colWidths, sepWidths).zipped map ((w1, w2) => "-" * w1 + " " * w2) mkString
)
def mkFormatString(sepf: Int => String): String =
specs.zipWithIndex map { case (c, i) => c + sepf(i) } mkString
def toFormattedSeq = argLists map (xs => rowFormat.format(xs: _*))
def allToSeq = headers ++ toFormattedSeq
override def toString = allToSeq mkString "\n"
}
def table(rows: Seq[T]) = new Table(rows)
override def toString = cols.mkString("TableDef(", ", ", ")")
}
object TableDef {
case class Column[-T](name: String, f: T => Any, left: Boolean) {
def maxWidth(elems: Seq[T]): Int = name +: (elems map f) map (_.toString.length) max
def formatSpec(elems: Seq[T]): String = {
val justify = if (left) "-" else ""
"%" + justify + maxWidth(elems) + "s"
}
override def toString = {
val justify = if (left) "<<" else ">>"
justify + "(" + name + ")"
}
}
def apply[T](cols: Column[T]*) = new TableDef[T](cols: _*)
}