com-lihaoyi / pprint Goto Github PK
View Code? Open in Web Editor NEWPretty-printing value, types and type-signatures in Scala
Home Page: https://com-lihaoyi.github.io/PPrint/
License: MIT License
Pretty-printing value, types and type-signatures in Scala
Home Page: https://com-lihaoyi.github.io/PPrint/
License: MIT License
I'd like to use org.apache.commons.lang.StringEscapeUtils.escapeJava
to print string literals.
How can I customise pprint
for doing so?
I constantly get [32m] when I use PPrint (OS == Linux Mint). How to get rid of it?
Does one need some sbt plugin to use this library?
similar ticket, as in the old version of upickle-pprint:
com-lihaoyi/upickle#125
Right here:
PPrint/pprint/src/pprint/Renderer.scala
Line 147 in 3abeed8
fansi.Str(_)
allows one to pass in an ErrorMode controlling whether an exception is thrown. But this call here defaults to throwing an exception. One can also sanitize the input before it is sent to fansi.Str(_)
, but that is not done either. There do not appear to be hooks to allow you to do either of these things if so desired, but I'm virtually ignorant of this codebase so I wouldn't know.
The reason this behavior is bad is that mdoc
processing of scala worksheets explodes if the output of some line of code contains content that would cause fansi.Str(_)
to explode, with no straightforward way to avoid this behavior. I'm seeing this frequently in my current project:
java.lang.IllegalArgumentException: Unknown ansi-escape at index XXX inside string cannot be parsed into an fansi.Str
at fansi.ErrorMode$Throw$.handle(Fansi.scala:419)
at fansi.ErrorMode$Throw$.handle(Fansi.scala:407)
at fansi.Str$.apply(Fansi.scala:272)
at pprint.Renderer.$anonfun$rec$32(Renderer.scala:147)
at scala.collection.Iterator$$anon$9.next(Iterator.scala:575)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:471)
at pprint.Truncated.hasNext(Truncated.scala:80)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:470)
at pprint.Truncated.hasNext(Truncated.scala:80)
at scala.collection.Iterator$$anon$9.hasNext(Iterator.scala:574)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:470)
at scala.collection.Iterator$$anon$10.hasNext(Iterator.scala:592)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:470)
at scala.collection.mutable.StringBuilder.appendAll(StringBuilder.scala:185)
at mdoc.internal.document.Printing$.printOneLine(Printing.scala:28)
at mdoc.internal.worksheets.WorksheetProvider.$anonfun$renderSummary$1(WorksheetProvider.scala:141)
at mdoc.internal.worksheets.WorksheetProvider.$anonfun$renderSummary$1$adapted(WorksheetProvider.scala:124)
at scala.collection.IterableOnceOps.foldLeft(IterableOnce.scala:646)
at scala.collection.IterableOnceOps.foldLeft$(IterableOnce.scala:642)
at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1288)
at mdoc.internal.worksheets.WorksheetProvider.renderSummary(WorksheetProvider.scala:124)
at mdoc.internal.worksheets.WorksheetProvider.renderDecoration(WorksheetProvider.scala:73)
at mdoc.internal.worksheets.WorksheetProvider.$anonfun$evaluateWorksheet$3(WorksheetProvider.scala:42)
at scala.collection.immutable.List.map(List.scala:250)
at mdoc.internal.worksheets.WorksheetProvider.$anonfun$evaluateWorksheet$2(WorksheetProvider.scala:41)
at scala.collection.Iterator$$anon$10.nextCur(Iterator.scala:585)
at scala.collection.Iterator$$anon$10.hasNext(Iterator.scala:599)
at scala.collection.Iterator$$anon$6.hasNext(Iterator.scala:470)
at scala.collection.Iterator$$anon$9.hasNext(Iterator.scala:574)
at scala.collection.immutable.List.prependedAll(List.scala:152)
at scala.collection.IterableOnceOps.toList(IterableOnce.scala:1251)
at scala.collection.IterableOnceOps.toList$(IterableOnce.scala:1251)
at scala.collection.AbstractIterator.toList(Iterator.scala:1288)
at mdoc.internal.worksheets.WorksheetProvider.evaluateWorksheet(WorksheetProvider.scala:48)
at mdoc.internal.worksheets.Mdoc.evaluateWorksheet(Mdoc.scala:55)
at scala.meta.internal.worksheets.WorksheetProvider.scala$meta$internal$worksheets$WorksheetProvider$$evaluateWorksheet(WorksheetProvider.scala:363)
at scala.meta.internal.worksheets.WorksheetProvider$$anon$1.liftedTree1$1(WorksheetProvider.scala:267)
at scala.meta.internal.worksheets.WorksheetProvider$$anon$1.run(WorksheetProvider.scala:267)
I'm sorry that I cannot share the code or data that produces this.
Yes, I'll report an issue to mdoc
too. I understand that throwing exceptions might be a design choice for this library. However, it seems like it should be possible to make pprint.Render
a little safer, given that the underlying fansi
library allows one to control exception throwing behavior.
We are using pprint in property based testing, where we create arbitrary strings. Sadly, pprint fails on some of those characters:
Message: Unknown ansi-escape at index 3 inside string cannot be parsed into an fansi.Str
Example:
import org.scalatest.WordSpec
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class PprintUnitTest extends WordSpec with ScalaCheckPropertyChecks {
"pprint" in {
forAll(minSuccessful(5000000)) { s: String =>
pprint.apply(s)
}
}
}
Hi @lihaoyi !
Scala steward picked up pprint 0.6.1 today but I can't see it in releases or any release notes... is it legit?
Got to be careful with so many supply chain attacks around these days 👀
Welcome to the Ammonite Repl 1.6.9
(Scala 2.12.8 Java 1.8.0_202-ea)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ val x = <?xml-stylesheet href="style.xsl"?>
x: xml.ProcInstr = ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
ProcInstr(
...
It would be useful to have the possibility to print the object all in one line (but still valid Scala code).
Something like:
pprint.pprintln(p, width = None) //or
pprint.pprintln(p, width = 0))
I am using PPrint in a situation where we have to be very careful what we log, how we log, and at which levels. As a result, in most cases I do something like this:
logger.debug("Value is {}", pprint.apply(myCaseClass))
The problem is that in terminals that can't read Fansi, I get stuff output like this because of toString
(which calls render
):
case class Foo(a: Int, b: String)
pprint.apply(Foo(5, "fdf"))
res0: fansi.Str = �[33mFoo�[39m(�[32m5�[39m, �[32m"fdf"�[39m)
And it shows up that way in Splunk.
Is there any guidance or, dare I say it, "best practices" for how best to integrate PPrint with SLF4J so that the output is as rich and clear as possible on both developer environments and logging machinery in higher environments?
Thanks.
I'm seeing a MatchError
thrown during compilation when TPrintImpl
encounters a PolyType
. The full error is:
exception during macro expansion:
scala.MatchError: [+A]Playground.Foo[A] (of class scala.reflect.internal.Types$PolyType)
at pprint.TPrintLowPri$.typePrintImplRec0(TPrintImpl.scala:151)
at pprint.TPrintLowPri$.typePrintImplRec(TPrintImpl.scala:32)
at pprint.TPrintLowPri$.$anonfun$typePrintImplRec0$7(TPrintImpl.scala:103)
at scala.collection.immutable.List.map(List.scala:246)
at pprint.TPrintLowPri$.added$2(TPrintImpl.scala:103)
at pprint.TPrintLowPri$.printArgs$1(TPrintImpl.scala:106)
at pprint.TPrintLowPri$.typePrintImplRec0(TPrintImpl.scala:200)
at pprint.TPrintLowPri$.typePrintImplRec(TPrintImpl.scala:32)
at pprint.TPrintLowPri$.typePrintImpl(TPrintImpl.scala:21)
I was able to put together a minimal reproduction in scastie here that mirrors how this error was triggered in my codebase. For context, this occurs when using PPrint 0.7.1 on scala 2.13.8.
Thank you for all your work on this library!
def apply(x: Any, width: Int = defaultWidth, height: Int = defaultHeight, indent: Int = defaultIndent, initialOffset: Int = 0): fansi.Str =
My usage is that i have case classes with some junk fields (even binary data). When printing them, i'd rather pprint truncate the field so it doesn't use up the vertical space.
I see that output can be shortened by restricting the number of lines, i'd like it to also be shortened by the number of collumns
I can see that there's a 0.5.4
version available:
[info] com.lihaoyi:pprint:test : 0.5.3 -> 0.5.4
but I could not find the release here.
Forgot to push the tag?
➜ amm
Loading...
Welcome to the Ammonite Repl 1.6.2
(Scala 2.12.8 Java 11.0.1)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ import $ivy.`com.comcast::ip4s-core:1.1.1`, com.comcast.ip4s._
import $ivy.$ , com.comcast.ip4s._
@ val home = ipv4"127.0.0.1"
home: Ipv4Address = 127.0.0.1
@ home / 24
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
java.lang.StringLatin1.charAt(StringLatin1.java:47)
java.lang.String.charAt(String.java:693)
scala.collection.immutable.StringOps$.apply$extension(StringOps.scala:41)
pprint.Util$.isOperator(Util.scala:50)
pprint.Walker.$anonfun$treeify$1(Walker.scala:83)
scala.Option.getOrElse(Option.scala:138)
pprint.Walker.treeify(Walker.scala:45)
pprint.PPrinter.treeify(PPrinter.scala:26)
pprint.PPrinter.tokenize(PPrinter.scala:106)
ammonite.repl.FullReplAPI$Internal.print(FullReplAPI.scala:105)
ammonite.repl.FullReplAPI$Internal.print$(FullReplAPI.scala:60)
ammonite.repl.FullReplAPI$$anon$1.print(FullReplAPI.scala:33)
@ (home / 24).toString
res3: String = "127.0.0.1/24"
The type in question is here: https://github.com/Comcast/ip4s/blob/25725c81e7524c885c20e08ac5f57f2456c5e9f3/shared/src/main/scala/com/comcast/ip4s/Cidr.scala#L29
I haven't had a chance to investigate yet. Only notable thing about Cidr
: it's a final class that implements Product
manually.
scala> case class User(id: Int, name: String)
defined class User
scala> val bob: User = User(1, "Bob")
bob: User = User(1,Bob)
scala> pprint.pprintln(bob)
User(1, "Bob")
scala> pprint.pprintln(bob, showFieldNames = true)
User(1, "Bob")
scala> pprint.pprintln(bob, showFieldNames = false)
User(1, "Bob")
With the feature enabled, I expected something like User(id = 1, name = "Bob")
Got a Scala 2.11 Gradle project with this entry:
compile group: 'com.lihaoyi', name: 'pprint_2.11', version: '0.5.3'
But when I run:
exception during macro expansion:
java.lang.ClassNotFoundException: scala.Product$class
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sourcecode.Impls$Chunk$Def.<init>(SourceContext.scala:154)
at sourcecode.Impls$Chunk$Def$.apply(SourceContext.scala:154)
at sourcecode.Impls$Chunk$Def$.apply(SourceContext.scala:154)
at sourcecode.Impls$.enclosing(SourceContext.scala:177)
at sourcecode.Enclosing$.impl(SourceContext.scala:91)
pprint.log(x = input, tag = "My Tag")
I'm sure it is something silly, but any help is appreciated. Thanks.
When trying to use the library I get the following error:
[error] (run-main-0) java.lang.NoClassDefFoundError: scala/reflect/api/TypeCreator
[error] java.lang.NoClassDefFoundError: scala/reflect/api/TypeCreator
[error] at fansi.ColorCategory.$anonfun$Full$1(Fansi.scala:851)
[error] at fansi.ColorCategory.$anonfun$Full$1$adapted(Fansi.scala:850)
[error] at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:237)
[error] at scala.collection.immutable.Range.foreach(Range.scala:158)
[error] at scala.collection.TraversableLike.map(TraversableLike.scala:237)
[error] at scala.collection.TraversableLike.map$(TraversableLike.scala:230)
[error] at scala.collection.AbstractTraversable.map(Traversable.scala:108)
[error] at fansi.ColorCategory.<init>(Fansi.scala:850)
[error] at fansi.Color$.<init>(Fansi.scala:717)
[error] at fansi.Color$.<clinit>(Fansi.scala)
[error] at pprint.PPrinter$.$lessinit$greater$default$4(PPrinter.scala:18)
[error] at pprint.package$.<init>(package.scala:7)
[error] at pprint.package$.<clinit>(package.scala)
[error] at com.ronyhe.minerva.Main$.printParse(Main.scala:17)
[error] at com.ronyhe.minerva.Main$.main(Main.scala:9)
[error] at com.ronyhe.minerva.Main.main(Main.scala)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] Caused by: java.lang.ClassNotFoundException: scala.reflect.api.TypeCreator
[error] at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
[error] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
[error] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
[error] at fansi.ColorCategory.$anonfun$Full$1(Fansi.scala:851)
[error] at fansi.ColorCategory.$anonfun$Full$1$adapted(Fansi.scala:850)
[error] at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:237)
[error] at scala.collection.immutable.Range.foreach(Range.scala:158)
[error] at scala.collection.TraversableLike.map(TraversableLike.scala:237)
[error] at scala.collection.TraversableLike.map$(TraversableLike.scala:230)
[error] at scala.collection.AbstractTraversable.map(Traversable.scala:108)
[error] at fansi.ColorCategory.<init>(Fansi.scala:850)
[error] at fansi.Color$.<init>(Fansi.scala:717)
[error] at fansi.Color$.<clinit>(Fansi.scala)
[error] at pprint.PPrinter$.$lessinit$greater$default$4(PPrinter.scala:18)
[error] at pprint.package$.<init>(package.scala:7)
[error] at pprint.package$.<clinit>(package.scala)
// These are my methods
[error] at com.ronyhe.minerva.Main$.printParse(Main.scala:17)
[error] at com.ronyhe.minerva.Main$.main(Main.scala:9)
[error] at com.ronyhe.minerva.Main.main(Main.scala)
// End of my methods
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[error] Nonzero exit code: 1
Any ideas?
see com-lihaoyi/upickle#209 (comment) for more details
The link to https://www.lihaoyi.com/PPrint/ returns a 404
This is the example code in guide.
pprint.copy(
additionalHandlers = {
case value: Double => pprint.Tree.Literal(f"$value%1.5f") /* 5 digit precision */
}
)
Is it possible to change color in the customized handler?
It is good practice to tag published releases in the source repository. To make it possible for users to find out which source corresponds to which release.
I might have time to work on this at some point...
Just want to make sure there is buy-in before I invest too much time
The documentation at www.lihaoyi.com/PPrint/ currently describes the return type of many methods as String
, when it is actually fansi.Str
. Linking to the fansi library in the documentation would be greatly appreciated.
Initial issue here: com-lihaoyi/Ammonite#1115
The example to reproduce:
println(implicitly[pprint.TPrint[(Int => Option[Int]) => Int]].render)
Gives:
Int => Option[Int] => Int
which should have been:
(Int => Option[Int]) => Int
I used the following function with pprint 0.4.3:
def myLogFunction[T](o: T)(implicit pp: pprint.PPrint[T]): T = {
pprint.pprintln(o, width = 200)(pp)
o
}
The implicit PPrint was used by pprintln (upickle-pprint/pprint/shared/src/main/scala/pprint/package.scala
)
def pprintln[T: PPrint](t: T,
width: Integer = null,
height: Integer = null,
indent: Integer = null,
colors: Colors = null)
(implicit cfg: Config = Config.Defaults.PPrintConfig) = {
tokenize(t, width, height, indent, colors)(implicitly[PPrint[T]], cfg).foreach(print)
println()
}
However, the last version of pprint, 0.5.2, does not use this implicit PPrint.
def pprintln(x: Any,
width: Int = defaultWidth,
height: Int = defaultHeight,
indent: Int = defaultIndent,
initialOffset: Int = 0): Unit = {
tokenize(x, width, height, indent, initialOffset).foreach(print)
println()
}
I can remove the implicit PPrint
from my function, and it compiles, but pprintln
uses the T.toString
instead of pprint.
def myLogFunction[T](o: T): T = {
pprint.pprintln(o, width = 200)
o
}
How do I need to adapt myLogFunction
to the last pprint version?
And how does pprint
work without the previous implicit PPrint
?
I tried revising the git history, but it seems that the git upickle-pprint ends at 0.4.4, and the first version of PPrint starts at 0.4.6, and it seems that it is between these two versions that the implicit PPrint has been removed.
println("SCALA: «values»")
pprint.pprintln("PPRINT: «values»")
prints to my console
SCALA: «values»
"PPRINT: \u00abvalues\u00bb"
is there a way that I could receive
"PPRINT: «values»"
instead?
(using version 0.6 of PPrint)
It'd be awesome if pprint also supported rendering of parameter names.
E.g., an instance of type
case class Color(red: Byte, green: Byte, blue: Byte)
could be rendered as
Color(red = 10, green = 20, blue = 30)
instead of
Color(10, 20, 30)
For some datastructures I’d like to print, I would like to always print the whole thing. As far as I can tell, the only way to do this at the moment is to set an arbitrarily high value for the height, e.g. 1000000000.
I think it would be extremely helpful if we'd have a way to do blacklining on case classes, or collections to see which of the parameters are different. For example
case class Hello(arg: String)
when tokenizing two strings and applying blacklining we'd have something like this:
Hello("World
") > Hello("Everyone
")
This is something that old implementation did, and is great since for the times people use case class
s for convenience but have a better string representation, it would use that instead of just enumerating the fields.
However, the old implementation relied on compile-time type inspection via macros, which is no longer available. We need some way to discover this using Java runtime reflection (we shouldn't depend on Scala-reflection, which is heavy/slow/buggy). As far as I can tell, "did the case class define a custom toString" isn't easily available from the bytecode.
Perhaps we could provide an annotation people can tag their case classes with, or an alternative pprintToString
method they implement, to signal to PPrint that they would prefer to use their custom .toString
instead of our generated default
/home/xyh/play/scala/pprint (master)
./mill -i
Preparing Java 12.0.1 runtime; this may take a minute or two ...
fish: “./mill -i” terminated by signal SIGKILL (Forced quit)
I have a computer with only 8G RAM.
how many RAM is required to run ./mill -i
?
Here is a simple example.
val nodeStr = s"""
|[A]
|[B]
|""".stripMargin.trim
case class Prod(prefix: String)(vs: Any*) extends Product {
override def productPrefix: String = prefix
override def productArity: Int = vs.size
override def productElement(n: Int): Any = vs(n)
}
it("try it another time") {
val v = Prod(nodeStr)(
Prod(nodeStr)(
Prod(nodeStr)(),
Prod(nodeStr)()
)
)
pprint.pprintln(v)
}
Output:
[A]
[B](
[A]
[B](
[A]
[B](),
[A]
[B]()
)
)
Most indentations of [B] are wrong.
Also, I wonder if I can submit a quick patch to customise parenthesis, indentation characters, and comma space? Combining with a fix of the above issue, it will be capable of pprint arbitrary trees (e.g. a Spark SQL LogicalPlan)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.