Skip to content

Instantly share code, notes, and snippets.

@metasim
Created October 8, 2016 15:52
Show Gist options
  • Select an option

  • Save metasim/57b1b44e135ce1b97970e82aaa89bfd9 to your computer and use it in GitHub Desktop.

Select an option

Save metasim/57b1b44e135ce1b97970e82aaa89bfd9 to your computer and use it in GitHub Desktop.
import pprint.PPrinter._
/**
* Pretty printer support for products where field names are rendered.
* @author sfitch
* @since 9/14/16
*/
object ProductPPrinter {
/** Pretty Printer adding 'key = value' field rendering. */
implicit def ProductWithFieldsPPrinter[P <: Product] = new pprint.PPrinter[P] {
import Internals._
override def render0(t: P, c: pprint.Config): Iterator[String] = {
val values = asFields(t)
pprint.Internals.handleChunks(t.productPrefix, c, { conf ⇒
values.iterator.map { case (name, value) ⇒
Iterator(s"$name = ") ++ implicitly[pprint.PPrint[Any]].pprinter.render(value, c)
}
})
}
}
implicit class HasPPString(val p: Product) extends AnyVal {
def toPPString(implicit c: pprint.Config = pprint.Config.Defaults.PPrintConfig): String = pprint.tokenize(p).mkString
}
object Internals {
/** This allows for recursive invocation of the ProductWithFieldsPPrinter based on dynamic type introspection. */
implicit object AnyReifiedRepr extends pprint.PPrinter[Any] {
override def render0(t: Any, c: pprint.Config): Iterator[String] = {
implicit val anyPrinter = this
t match {
case Some(stuff) ⇒ anyPrinter.render(stuff, c)
case p: Product ⇒ ProductWithFieldsPPrinter.render(p, c)
case a: Array[Any @unchecked] ⇒ ArrayRepr[Any].render(a, c)
case s: Seq[_] ⇒ SeqRepr[Any, Seq].render(s, c)
case m: Map[Any @unchecked, _] ⇒ MapRepr[Any, Any].render(m, c)
case f: Float ⇒ FloatRepr.render(f, c)
case d: Double ⇒ DoubleRepr.render(d, c)
case i: Int ⇒ IntRepr.render(i, c)
case l: Long ⇒ LongRepr.render(l, c)
case b: Boolean ⇒ BooleanRepr.render(b, c)
case o ⇒ StringRepr.render(o.toString, c) // cop-out
}
}
}
// NB: This is brittle. Presumes field order and productIterator are the same.
private[ProductPPrinter] def asFields[P <: Product](p: P) = {
p.getClass.getDeclaredFields.map(_.getName).zip(p.productIterator.to)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment