mirror of
https://github.com/JakeWharton/mosaic.git
synced 2025-11-03 05:46:10 +08:00
Enable debug rendering at runtime (#714)
Set MOSAIC_DEBUG_RENDERING=true env var.
This commit is contained in:
@ -57,12 +57,6 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
|
||||||
/**
|
|
||||||
* True for a debug-like output that renders each "frame" on its own with a timestamp delta.
|
|
||||||
* False when using ANSI control sequences to overwrite output.
|
|
||||||
*/
|
|
||||||
private const val debugOutput = false
|
|
||||||
|
|
||||||
public fun renderMosaic(content: @Composable () -> Unit): String {
|
public fun renderMosaic(content: @Composable () -> Unit): String {
|
||||||
val mosaicComposition = MosaicComposition(
|
val mosaicComposition = MosaicComposition(
|
||||||
coroutineContext = BroadcastFrameClock(),
|
coroutineContext = BroadcastFrameClock(),
|
||||||
@ -330,7 +324,7 @@ private fun createRendering(
|
|||||||
ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR,
|
ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR,
|
||||||
synchronizedRendering: Boolean = false,
|
synchronizedRendering: Boolean = false,
|
||||||
): Rendering {
|
): Rendering {
|
||||||
return if (debugOutput) {
|
return if (env("MOSAIC_DEBUG_RENDERING") == "true") {
|
||||||
DebugRendering(ansiLevel = ansiLevel)
|
DebugRendering(ansiLevel = ansiLevel)
|
||||||
} else {
|
} else {
|
||||||
AnsiRendering(ansiLevel, synchronizedRendering)
|
AnsiRendering(ansiLevel, synchronizedRendering)
|
||||||
|
|||||||
@ -21,45 +21,54 @@ internal class DebugRendering(
|
|||||||
) : Rendering {
|
) : Rendering {
|
||||||
private var lastRender: TimeMark? = null
|
private var lastRender: TimeMark? = null
|
||||||
|
|
||||||
|
fun StringBuilder.appendSurface(canvas: TextCanvas) {
|
||||||
|
for (row in 0 until canvas.height) {
|
||||||
|
canvas.appendRowTo(this, row, ansiLevel)
|
||||||
|
append("\r\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun render(mosaic: Mosaic): CharSequence {
|
override fun render(mosaic: Mosaic): CharSequence {
|
||||||
var failed = false
|
var failed = false
|
||||||
val output = buildString {
|
val output = buildString {
|
||||||
lastRender?.let { lastRender ->
|
lastRender?.let { lastRender ->
|
||||||
repeat(50) { append('~') }
|
repeat(50) { append('~') }
|
||||||
append(" +")
|
append(" +")
|
||||||
appendLine(lastRender.elapsedNow())
|
append(lastRender.elapsedNow())
|
||||||
|
append("\r\n")
|
||||||
}
|
}
|
||||||
lastRender = systemClock.markNow()
|
lastRender = systemClock.markNow()
|
||||||
|
|
||||||
appendLine("NODES:")
|
append("NODES:\r\n")
|
||||||
appendLine(mosaic.dump())
|
append(mosaic.dump().replace("\n", "\r\n"))
|
||||||
appendLine()
|
append("\r\n\r\n")
|
||||||
|
|
||||||
val statics = mutableObjectListOf<TextCanvas>()
|
val statics = mutableObjectListOf<TextCanvas>()
|
||||||
try {
|
try {
|
||||||
mosaic.paintStaticsTo(statics)
|
mosaic.paintStaticsTo(statics)
|
||||||
if (statics.isNotEmpty()) {
|
if (statics.isNotEmpty()) {
|
||||||
appendLine("STATIC:")
|
append("STATIC:\r\n")
|
||||||
statics.forEach { static ->
|
statics.forEach { static ->
|
||||||
appendLine(static.render(ansiLevel))
|
appendSurface(static)
|
||||||
}
|
}
|
||||||
appendLine()
|
append("\r\n")
|
||||||
}
|
}
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
failed = true
|
failed = true
|
||||||
appendLine(t.stackTraceToString())
|
append(t.stackTraceToString().replace("\n", "\r\n"))
|
||||||
|
append("\r\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
appendLine("OUTPUT:")
|
append("OUTPUT:\r\n")
|
||||||
try {
|
try {
|
||||||
appendLine(mosaic.paint().render(ansiLevel))
|
appendSurface(mosaic.paint())
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
failed = true
|
failed = true
|
||||||
append(t.stackTraceToString())
|
append(t.stackTraceToString().replace("\n", "\r\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (failed) {
|
if (failed) {
|
||||||
throw RuntimeException("Failed\n\n$output")
|
throw RuntimeException("Failed\r\n\r\n$output")
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,8 +49,8 @@ class DebugRenderingTest {
|
|||||||
| Layout\(\) x=6 y=0 w=5 h=1 DrawBehind
|
| Layout\(\) x=6 y=0 w=5 h=1 DrawBehind
|
||||||
|
|
|
|
||||||
|OUTPUT:
|
|OUTPUT:
|
||||||
|(kotlin\.|java\.lang\.)?UnsupportedOperationException:?
|
|(kotlin\.|java\.lang\.)?UnsupportedOperationException
|
||||||
""".trimMargin().toRegex(),
|
""".trimMargin().replaceLineEndingsWithCRLF().toRegex(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ class DebugRenderingTest {
|
|||||||
|OUTPUT:
|
|OUTPUT:
|
||||||
|Hello
|
|Hello
|
||||||
|
|
|
|
||||||
""".trimMargin(),
|
""".trimMargin().replaceLineEndingsWithCRLF(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ class DebugRenderingTest {
|
|||||||
|OUTPUT:
|
|OUTPUT:
|
||||||
|Hello
|
|Hello
|
||||||
|
|
|
|
||||||
""".trimMargin(),
|
""".trimMargin().replaceLineEndingsWithCRLF(),
|
||||||
)
|
)
|
||||||
|
|
||||||
timeSource += 100.milliseconds
|
timeSource += 100.milliseconds
|
||||||
@ -113,7 +113,7 @@ class DebugRenderingTest {
|
|||||||
|OUTPUT:
|
|OUTPUT:
|
||||||
|Hey!
|
|Hey!
|
||||||
|
|
|
|
||||||
""".trimMargin(),
|
""".trimMargin().replaceLineEndingsWithCRLF(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user