[ANN] Asciicast.jl

Asciicast.jl makes it easy to include and maintain animated gifs of Julia REPL sessions in documents (like package READMEs) and in documentation.

Screenshot 2023-12-12 at 23.09.12

With Asciicast, in Documenter docs, you can use @cast blocks similar to @repl ones. For example

using Pkg
1 + 1

generates and embeds an animation of the code executing. The Documenter Usage section of the docs shows all of the options, as well as some examples.

Likewise, in documents like READMEs, you can include blocks like

```julia {cast="true"}
using Pkg

Then run Asciicast.cast_document. It will parse the document using pandoc, identify these blocks, execute the Julia code, generate a gif, save it to disk, then add an image link to the gif into the document, writing it back out. This makes it easy to update and maintain these gifs. The Markdown Usage section of the docs goes into all the details there. Also, as an aside from the animations, I think this same technique could be used to ensure README examples stay fresh, e.g. by calling something similar in the tests to execute the code.

One caveat is that we lack a precise markdown parser that maintains syntax trivia like whitespace etc, so when pandoc writes the document back out, it will effectively re-format it (in ways that should not change the rendered output, but can change the markdown file itself quite a bit).

Additionally, Asciicast.jl provides macros and other functionality to generate animations directly. They also support VSCode, to show animations in the plot pane (using the js asciinema-player, not gifs, meaning they are high resolution always).

I developed the first version of this code a few years ago to add animations to my toy package TravelingSalesmanExact, but recently expanded and updated it quite a bit, and registered it in General (it can be useful as a test dependency at least). I also tested it out on ProgressMeter.jl, and documented some limitations of my approach.

Asciicast.jl also builds on Documenter, and relies heavily on some of its internals (reusing some of it’s functionality for code parsing and execution). But perhaps it can be stable with the help of some integration tests in Documenter.

I hope it can be useful!


Wow this is awesome. Thank you!

1 Like

Very cool!

1 Like

Very nice! It would be cool to also emulate keystroke delay when typing input via some sort of stochastic delay.

Nice! But from the name I thought it would be a package that converted unicode to ascii, or something, such as α to a, ü to u, etc.

I guess it works for unicode characters as well?

1 Like

Yeah, the name comes from the asciicast file format. This package mostly just generates asciicast files, then hands then off to compatible software in the show method or to make the gifs. Unicode should be fine.

1 Like

I have a delay per line but not while typing each line. I think Replay.jl does something like that though. Would be cool to add!

As an aside because you mention readmes, is there any way to actually keep those up to date in CI without making things really messy? That the readme is part of the repo and not a CI artifact complicates things

1 Like

I haven’t setup anything for that currently; in Asciicast.jl itself, I check in the tests that calling Asciicast.cast_readme does not change the current readme; if it does, sometimes that means I’ve changed the example, but often it means the formatting changed, so it’s not super satisfying. A better option would be to save the .cast files next to the gifs, then in the tests regenerate them, then compare the .cast files loosely (e.g. timings may be different), and fail if it seems they are stale. I started thinking about this but haven’t implemented much yet.

In terms of autogenerating the gifs in CI, one thing I can think of there is storing them on a different branch, like documenter does with github-pages, and then having the image links reference them from github on that branch, rather than a local reference. However that doesn’t help if the image links in the readme itself are out of date. (E.g. this can work if you always have 3 examples in the same order and just want the gifs to be up-to-date).

Another option is a periodic github workflow that just PRs the readme / assets directory with the contents of Asciicast.cast_readme(MyPackage). That would be easy to implement at least.

Personally I don’t really mind regenerating them manually, as long as the CI only fails when they are actually stale as opposed to unrelated formatting changes in the readme.

1 Like