Created
October 8, 2016 15:52
-
-
Save metasim/57b1b44e135ce1b97970e82aaa89bfd9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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