A browseable Zig standard library

Created: 2021-07-16 Updated: 2022-08-18 (Re-generated browseable library output)

Though much of it is sparsely commented, the Zig standard library is quite readable. Nevertheless, being told to "go read the source" is intimidating.

How can we make it easier to explore the library source?

"Just turn the source into a website"

So I dreamed up and rejected a huge variety of fanciful ways to present the library. All of them would either require an enormous amount of manual work (and constant care and attention as the Zig language speedily races towards v1.0) or would mean jamming loads of auto-generated data into hundreds of pages.

And it finally dawned on me: since Zig @import()s in the standard library are all relative links, it already is a linked body of documents. All I needed to do was turn the links into clickable hypertext and we’re more than halfway there.

The other idea that went with this was to invert the usual emphasis on the display of the documents from the source to the comments. Now the source is faded and the comments are emphasized. I also highlight pub fn and pub const names so that they’re easier to spot.

Because Zig’s syntax is so minimal and line-based, parsing the library source for a handful of items was almost embarrassingly simple.

I had results almost immediately:

screenshot of stdlib-browseable html output

From the main library import file, std.zig, you can reach every corner of the library.

The output currently weighs in at 25Mb of HTML and generates in under 13 seconds on circa-2019 x86 desktop hardware.

I’m not sure if I’ve achieved the level of readibility I was aiming for yet, but it’s very easy to try out new styles. I’d like to experiment some more with displaying the comments and source in different ways.

Previous attempt: single page reference

My first attempt to create some sort of single-page quick reference for the Zig standard library was hampered by a severe underestimation of exactly how many public functions and data structures it contains!

Trying to get it all to fit ended with a very large, very dense page:

The other problem is that since the page is composed of links to the standard library source on GitHub, I have to keep it up to date or the links quickly become incorrect.


This is a little aside about choosing the right tool for the job.

So my immediate go-to tool for parsing the library source and spitting out HTML documents was AWK. It was built for parsing lines of input, is installed everywhere, and will likely lead to a compact solution.

I had a couple proof-of-concept lines going and I went to use match() to get capture groups like so:

match($0, /(reg)(ex)/, m) { do something with match array m }

…​and suddenly realized I wasn’t using familiar Gawk (always installed on trusty old Slackware). Nay, I was on my "downstairs" computer with a Debian WSL instance. And Debian ships with Mawk. Mawk does not do capture groups in match(). :-(

Argh. Implementation compatibility finally strikes the final nail in the coffin of my decades-long AWK infatuation.

I briefly considered Perl 5, then Raku, then writing a real parser in Zig…​and this whole project was getting dangerously sidetracked in its fragile infancy!

And then it finally hit me: PHP. I know PHP like the back of my hand, it has exactly the tools I need, and, well, it was literally made to generate HTML documents.

I wrote it in PHP and regret nothing. It was almost too easy. Thank you Rasmus. :-)