diff --git a/README.md b/README.md index c1746ac..26226cd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PPrint for Kotlin -This is a port of Li Haoyi's excellent Scala pretty-printing library into Kotlin. +This is a port of Li Haoyi's excellent Scala pretty-printing library into Kotlin (pprint)[https://github.com/com-lihaoyi/PPrint]. (As well as Li Haoyi's excellent Ansi-Formatting library Fansi!) ## Usage @@ -21,4 +21,92 @@ val p = Person(Name("Joe", "Bloggs"), 42) println(pprint(p)) ``` +It will print the following beautiful output: + + +PPrint-Kotlin supports most of the same features and options as the Scala version. +I will document them here over time however for now please refer to the Scala documentation +* For PPrint here - https://github.com/com-lihaoyi/PPrint +* For Fansi here - https://github.com/com-lihaoyi/fansi + +## Nested Data and Complex Collections + +PPrint excells at printing nested data structures and complex collections. + +For example lists embedded in objects: +```kotlin +data class Address(val street: String, val zip: Int) +data class Customer(val name: Name, val addresses: List
) + +val p = Customer(Name("Joe", "Bloggs"), listOf(Address("foo", 123), Address("bar", 456), Address("baz", 789))) +println(pprint(p)) +``` + +Maps embedded in objects: +```kotlin +data class Alias(val value: String) +data class ComplexCustomer(val name: Name, val addressAliases: Map) + +val p = + ComplexCustomer( + Name("Joe", "Bloggs"), + mapOf(Alias("Primary") to Address("foo", 123), Alias("Secondary") to Address("bar", 456), Alias("Tertiary") to Address("baz", 789)) + ) +println(pprint(p)) +``` + +Lists embedded in maps imbedded in objects: +```kotlin +val p = + VeryComplexCustomer( + Name("Joe", "Bloggs"), + mapOf( + Alias("Primary") to + listOf(Address("foo", 123), Address("foo1", 123), Address("foo2", 123)), + Alias("Secondary") to + listOf(Address("bar", 456), Address("bar1", 456), Address("bar2", 456)), + Alias("Tertiary") to + listOf(Address("baz", 789), Address("baz1", 789), Address("baz2", 789)) + ) + ) +println(pprint(p)) +``` + +## Infinite Sequences + +Another very impressive ability of PPrint is that it can print infinite sequences, even if they are embedded +other objects for example: +```kotlin +data class SequenceHolder(val seq: Sequence) + +var i = 0 +val p = SequenceHolder(generateSequence { "foo-${i++}" }) +println(pprint(p, defaultHeight = 10)) +``` + +PPrint is able to print this infinite sequence without stack-overflowing or running out of memory +because it is highly lazy. It only evaluates the sequence as it is printing it, +and the printing is always constrained by the height and width of the output. You can +control these with the `defaultHeight` and `defaultWidth` parameters to the `pprint` function. + +## Black & White Printing + +The output of the pprint function is not actually a java.lang.String, but a fansi.Str. This +means you can control how it is printed. For example, to print it in black and white simple do: +```kotlin +import io.exoquery.pprint.PPrinter + +val p = Person(Name("Joe", "Bloggs"), 42) + +// Use Black & White Printing +println(pprint(p).plainText) +``` + +## Extending PPrint + +TODO + +## Fansi + +TODO diff --git a/src/test/kotlin/io/exoquery/pprint/Examples.kt b/src/test/kotlin/io/exoquery/pprint/Examples.kt index d47b8cd..cf726d5 100644 --- a/src/test/kotlin/io/exoquery/pprint/Examples.kt +++ b/src/test/kotlin/io/exoquery/pprint/Examples.kt @@ -6,11 +6,56 @@ import io.exoquery.pprint data class Name(val first: String, val last: String) data class Person(val name: Name, val age: Int) +data class Address(val street: String, val zip: Int) +data class Customer(val name: Name, val addresses: List
) + +data class Alias(val value: String) +data class ComplexCustomer(val name: Name, val addressAliases: Map) + +data class VeryComplexCustomer(val name: Name, val addressAliases: Map>) + +data class SequenceHolder(val seq: Sequence) fun main() { + // run { + // val p = Person(Name("Joe", "Bloggs"), 42) + // println(pprint(p)) + // } + + // run { + // val p = Customer(Name("Joe", "Bloggs"), listOf(Address("foo", 123), Address("bar", 456), Address("baz", 789))) + // println(pprint(p)) + // } + + // run { + // val p = + // ComplexCustomer( + // Name("Joe", "Bloggs"), + // mapOf(Alias("Primary") to Address("foo", 123), Alias("Secondary") to Address("bar", 456), Alias("Tertiary") to Address("baz", 789)) + // ) + // println(pprint(p)) + // } + + // run { + // val p = + // VeryComplexCustomer( + // Name("Joe", "Bloggs"), + // mapOf( + // Alias("Primary") to + // listOf(Address("foo", 123), Address("foo1", 123), Address("foo2", 123)), + // Alias("Secondary") to + // listOf(Address("bar", 456), Address("bar1", 456), Address("bar2", 456)), + // Alias("Tertiary") to + // listOf(Address("baz", 789), Address("baz1", 789), Address("baz2", 789)) + // ) + // ) + // println(pprint(p)) + // } + run { - val p = Person(Name("Joe", "Bloggs"), 42) - println(pprint(p)) + var i = 0 + val p = SequenceHolder(generateSequence { "foo-${i++}" }) + println(pprint(p, defaultHeight = 10).plainText) } //val seq = generateSequence { "foo" }