Skip to content

Commit

Permalink
Add default args. Add example. Add docs. Set version
Browse files Browse the repository at this point in the history
  • Loading branch information
deusaquilus committed Dec 31, 2024
1 parent 5a65a0b commit fb50ddb
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 10 deletions.
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ println(CustomPPrinter5(PPrinterConfig()).invoke(p))
//> PersonBorn(name = "Joe")
```
## Using `elementName` metadata - Kotlin Multiplatform
## Using `elementName` metadata in Kotlin Multiplatform
If you want to filter out fields based on `elementName` in Kotlin Multiplatform inside of the PPrinter you need to override
the `treeifyComposite` method.
Expand Down Expand Up @@ -430,7 +430,7 @@ println(CustomPPrinter6<PersonBorn>(PersonBorn.serializer(), PPrinterConfig()).i
//> PersonBorn(name = "Joe")
```
#### Sealed Hierarchies in KMP
#### Sealed Hierarchies in Kotlin Multiplatform
According to the `kotlinx-serialization` documentation, every member of a sealed hierarchy must be annotated with `@Serializable`.
For example, in the following hierarchy:
Expand All @@ -448,7 +448,57 @@ Every member is annotated with `@Serializable`.
This requirement extends to PPrint-Multiplatform as well since it relies on `kotlinx-serialization`
to traverse the hierarchy.
#### How do deal with Custom Fields in KMP
## Manual Printing in Kotlin Multiplatform
If you want to print values with a simple and well-defined structure in Kotlin Multiplatform, you can use the the PPrinterManual class.
For example:
```kotlin
data class Person(val name: String, val age: Int)
class CustomPPrinter7 : PPrinterManual<Person>() {
override fun treeify(x: Any?, elementName: String?, escapeUnicode: Boolean, showFieldNames: Boolean): Tree =
when (x) {
is Person -> Tree.Apply("Person", listOf(Tree.KeyValue("name", Tree.Literal(x.name)), Tree.KeyValue("age", Tree.Literal(x.age))).iterator())
else -> super.treeify(x, elementName, escapeUnicode, showFieldNames) // will just use Tree.Literal(x.toString())
}
}
val p = Person("Joe", 42)
println(CustomPPrinter7().invoke(p))
//> Person(name = "Joe", age = 42)
```
Frequently, it will be useful to combine manual printers and automatic printers. For example:
```kotlin
data class PersonFavorite(val name: String, val age: Int, val favoriteColor: Colors) /// See the Sealed Hierarchies section above
class ColorsPrinter(config: PPrinterConfig): PPrinter<Colors>(Colors.serializer(), config)
class CustomPPrinter7(config: PPrinterConfig): PPrinterManual<Any?>(config) {
fun treeifyThis(x: Any?, elementName: String?) =
treeify(x, elementName, config.defaultEscapeUnicode, config.defaultShowFieldNames)
override fun treeify(x: Any?, elementName: String?, escapeUnicode: Boolean, showFieldNames: Boolean): Tree =
when (x) {
is PersonFavorite ->
Tree.Apply(
"PersonFavorite",
iteratorOf(treeifyThis(x.name, "name"), treeifyThis(x.age, "age"), treeifyThis(x.favoriteColor, "favoriteColor")),
elementName
)
is Colors -> ColorsPrinter(config).treeify(x, elementName, escapeUnicode, showFieldNames)
else -> super.treeify(x, elementName, escapeUnicode, showFieldNames)
}
}
val joe = PersonFavorite("Joe", 123, Colors.Custom("FF0000"))
val printer = CustomPPrinter7(PPrinterConfig())
val p = printer(joe)
println(p)
//> PersonFavorite("Joe", 123, Custom(value = "FF0000"))
```
#### How do deal with Custom Fields in Kotlin Multiplatform
In general whenever you have a atom-property i.e. something not generic you can just mark the field as @Contextual
so long as there is a specific case defined for it in `treeifyWith`. However if you are using a type such as
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ allprojects {

allprojects {
group = "io.exoquery"
version = "3.0.0.E"
version = "3.0.0"
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,29 @@ sealed interface Tree {
/**
* Foo(aa, bbb, cccc)
*/
data class Apply(val prefix: String, val body: Iterator<Tree>, override val elementName: String?): Tree
data class Apply(val prefix: String, val body: Iterator<Tree>, override val elementName: String? = null): Tree

/**
* LHS op RHS
*/
data class Infix(val lhs: Tree, val op: String, val rhs: Tree, override val elementName: String?): Tree
data class Infix(val lhs: Tree, val op: String, val rhs: Tree, override val elementName: String? = null): Tree

/**
* "xyz"
*/
data class Literal(val body: String, override val elementName: String?): Tree{
data class Literal(val body: String, override val elementName: String? = null): Tree{
val hasNewLine = body.any { c -> c == '\n' || c == '\r' }
}

/**
* x = y
*/
data class KeyValue(val key: String, val value: Tree, override val elementName: String?): Tree
data class KeyValue(val key: String, val value: Tree, override val elementName: String? = null): Tree

/**
* xyz
*/
data class Lazy(val body0: (Ctx) -> Iterator<String>, override val elementName: String?): Tree
data class Lazy(val body0: (Ctx) -> Iterator<String>, override val elementName: String? = null): Tree

data class Ctx(
val width: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.exoquery.pprint
import io.exoquery.kmp.pprint.PPrintSequenceSerializer
import io.exoquery.kmp.pprint.PPrinter
import io.exoquery.kmp.pprint
import io.exoquery.kmp.pprint.PPrinterManual
import kotlinx.serialization.*
import java.time.LocalDate
import java.time.format.DateTimeFormatter
Expand Down Expand Up @@ -168,6 +169,42 @@ fun customPrinter6() {
println(p)
}

@Serializable
sealed interface Colors {
@Serializable object Red : Colors
@Serializable object Green : Colors
@Serializable object Blue : Colors
@Serializable data class Custom(val value: String) : Colors
}

data class PersonFavorite(val name: String, val age: Int, val favoriteColor: Colors) /// See the Sealed Hierarchies section above

class ColorsPrinter(config: PPrinterConfig): PPrinter<Colors>(Colors.serializer(), config)

class CustomPPrinter7(config: PPrinterConfig): PPrinterManual<Any?>(config) {
fun treeifyThis(x: Any?, elementName: String?) =
treeify(x, elementName, config.defaultEscapeUnicode, config.defaultShowFieldNames)

override fun treeify(x: Any?, elementName: String?, escapeUnicode: Boolean, showFieldNames: Boolean): Tree =
when (x) {
is PersonFavorite ->
Tree.Apply(
"PersonFavorite",
iteratorOf(treeifyThis(x.name, "name"), treeifyThis(x.age, "age"), treeifyThis(x.favoriteColor, "favoriteColor")),
elementName
)
is Colors -> ColorsPrinter(config).treeify(x, elementName, escapeUnicode, showFieldNames)
else -> super.treeify(x, elementName, escapeUnicode, showFieldNames)
}
}

fun customPrinter7() {
val joe = PersonFavorite("Joe", 123, Colors.Custom("FF0000"))
val printer = CustomPPrinter7(PPrinterConfig(showGenericForCollections = true))
val p = printer(joe)
println(p)
}

@OptIn(ExperimentalSerializationApi::class)
fun main() {
// showMap()
Expand All @@ -180,5 +217,6 @@ fun main() {

// GADT1.gadt()
//GADT2.gadt()
customPrinter6()
//customPrinter6()
customPrinter7()
}

0 comments on commit fb50ddb

Please sign in to comment.