Building code inside an mdbook preprocessor

For the imgui-rs project am an playing with an idea:

In the mdbook markdown, you could include example snippets, for example

```imgui-example(200x100)
if ui.button("Example button") {
    println!("Button was clicked");
}
```

Then in the resulting documentation, a snippet is displayed and the code is also wrapped in some supporting code and executed, which using a a software-renderer can generated an "automatic screenshot"

The idea being to show both the code snippet and what the resulting GUI would look like, without the tediousness of manually capturing screenshots (which might become outdated, be inconsistent, or simply not captured)

Half of this is quite easy to do: create an mdbook preprocessor to extract the code blocks. It can output a new code-block and an image.

Part I'm stuck with is how best to take that code snippet and actually compile it - the approaches I've half-thought of are:

  1. Generate a Cargo project in a temp folder, pull each snippet into an examples/... folder, then invoke cargo run --example snippet1 --output .../snippet1.png in the preprocessor
  2. In the mdbook preprocessor, (mis)use the build.rs to pull in the example snippets and build them. In the preprocessor itself, use these preprocessed examples to output the relevant markdown

The former is trickier to get right - generating the cargo project so it links to the current working-copy of the imgui crate, invoking cargo run properly so it picks up any toolchain overrides or whatever. I think the latter idea solves that but I'm not sure if build.rs is flexible enough to reasonably do this, or.. if there is a better approach?

I feel like something like this has most certainly been done, but I'm not sure in which direction to search for ideas!

Thanks!
- Ben

1 Like

Tried this idea and it works nicely. Roughly what I did was:

  1. Have a "common" library which defines some structs with the example snippets and some relevant metadata
  2. build.rs uses mdbook and pulldown_cmark to find fenced code-blocks with ```imgui-example
  3. For each example a function is created in the output.rs something like imgui_example_{identifier}
  4. This output.rs is included in src/lib.rs
  5. Additionally there is a generate_example(identifier: &str, output_path: PathBuf) {...} method generated

Then in the mdbook processor, it does the same thing to find the examples and generate the identifier, then calls run_example(identifier, ...)

The code is in significant need of tidying up, but in case it's of some use to someone my prototype is here: GitHub - dbr/imgui-book-prototype at 04c10cca0d2e1de59a32f934168908fcf68f06b1

I did also find some similar projects:

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.