An experimental Debug + diff + pretty-printer library for MoonBit. We plan
to add this to the standard library when it is more mature.
It provides:
- A
Debugtrait that turns values into a structuralRepr - A tree-based
diff(ReprDelta) with configurable float tolerance - A pretty printer for both
ReprandReprDelta(optionally with ANSI marks) - A binary to auto-generate
Debugimplementations for your types
Goals:
-
A way to debug values and show the diff, with pretty-printing
-
Replacing Some Roles of
ShowandToJsonThe current
Showtrait produces output that is not suitable for debugging, as it lacks indentation and line breaks.
TheToJsontrait produces JSON, which is more readable with@json.inspectbut not ideal for MoonBit-specific types (e.g., enums).
It can also confuse users who expectToJsonto produce structured data rather than a debug representation.With the introduction of
Debug, theShowtrait can focus on producing specialized output (such asJson::stringify,String::to_string, etc.), andderive(Show)will be deprecated.
Non-goals:
- Deserializing from
Reprback to original values - Output a valid moonbit code representation
The current pre-build command design forces us to separate the build script (written in MoonBit) into its own module and use a local binary dependency to invoke it. Therefore, the project is structured as follows:
debug/: the main library moduleauto_derive/: the build script module that generatesDebugimplementationsauto_derive_example/: an example module that uses thedebuglibrary and build script to generate code
Run the small demo:
moon run cmd/mainIn another package, import this module in moon.pkg.json :
{
"import": [{ "path": "moonbit-community/debug", "alias": "dbg" }]
}Then call:
///|
fn show_examples {
println(@dbg.pretty_print([1, 2, 3]))
println(@dbg.pretty_print_diff(Some(1), Some(2)))
}Use record , ctor , array , and friends to build a Repr :
///|
struct Person {
name : String
age : Int
}
///|
pub impl @dbg.Debug for Person with debug(self) {
@dbg.record([("name", @dbg.debug(self.name)), ("age", @dbg.debug(self.age))])
}To automatically generate Debug implementations for your types:
-
add
moonbit-community/debug_derivingas a binary dependency in yourmoon.mod.json -
add a
pre-buildcommand that runs thedebug_derivingbinary, for example:
{
"pre-build": [
{
"command": "$mod_dir/.mooncakes/moonbit-community/debug_deriving/debug_deriving $input $output",
"input": "input.mbt",
"output": "output.mbt"
}
]
}- in your
input.mbt, add#debug.deriveattribute to your types:
///|
#debug.derive
struct Pos(Int, Int)All options are passed directly as optional parameters to functions:
max_depth?: optional depth limit; omit for default (4), or passmax_depth=nto prunethreshold?: controls single-line vs multi-line rendering (default: 8)use_ansi?: enables+/-with ANSI colors in diffs (default: true)
max_relative_error?: float tolerance for comparingDoublevalues
See docs_test.mbt and examples_test.mbt for runnable, snapshot-based
examples.
///|
test {
inspect(pretty_print([1, 2, 3]), content="[1, 2, 3]")
inspect(
pretty_print_diff(1, 2, compact_threshold=100, use_ansi=false),
content="-1 +2",
)
}