RustMe 0.1: a way to manage Rust-y READMEs and other common files

@dAxpeDDa and I have been slowly building towards a vision where our plethora of projects have as much standardization as possible. Part of this is being done using the xtask pattern with our own shared crate that we will grow over time.

Another problem we wanted to solve revolved around managing READMEs, licenses, the CONTRIBUTING.md, the CODE_OF_CONDUCT.md, and more. Today, I’ve released the first version of this tool: rustme.

To explain it, let’s take a look at .rustme/config.ron:

Configuration(
    files: {
        "../README.md":  [
            "header.md",
            "docs.md",
            "generated.md",
            "https://github.com/khonsulabs/.github/raw/main/snippets/readme-footer.md",
        ],
        "../CONTRIBUTING.md":  [
            "https://github.com/khonsulabs/.github/raw/main/docs/CONTRIBUTING.md",
        ],
        "../CODE_OF_CONDUCT.md":  [
            "https://github.com/khonsulabs/.github/raw/main/docs/CODE_OF_CONDUCT.md",
        ],
        ...
    },
    glossaries: [
        External("https://github.com/khonsulabs/.github/raw/main/snippets/glossary.ron")
    ],
)

After installing rustme (cargo install rustme), navigating to that folder and executing rustme will regenerate the README and other files listed using the sources and glossaries provided.

For the files that can be completely shared, such as the code of conduct, we simply store a copy in a central location and each time rustme is executed, it will be updated to the latest version.

Improving #![doc = include_str!(..)]

But that’s only the first benefit. In Rust 1.54, it became possible to use the include_str! macro to include a file as the documentation to your crate. Many people rejoiced, as you could use the same file as your README.md that you could use as the root crate documentation.

This leads to a couple of compatibility issues, however:

Hidden lines in snippets

rustdoc allows you to hide lines of code from snippets by prefixing the line of code with a # character. If you use this feature, your README.md will look weird as it will include these extra lines. It will look great in the docs, however.

rustme solves this problem by preprocessing the markdown files. Any rust-language code blocks that are detected will automatically have the lines that begin with a # removed when generating the output file.

Multiple headings

The generated documentation already includes a top-level heading. If you don’t include a heading in your README, it will look “weird” on GitHub. If you include a heading in your README, it causes the docs to look “weird” due to multiple headings.

rustme allows you to split the markdown that you wish to contain in your documentation into its own file, and concatenate multiple files together into a single file to produce the README.

Additional features

Snippets

If you wish to showcase code, you can annotate the file with extra comments, a la:

// begin rustme snippet: example
fn main() {
  println!("Hello, World!");
}
// end rustme snippet

This snippet can be included in another file by inserting $path/to/file.rs:example$.

Glossaries

Glossaries are simple key-value dictionaries that allow replacing commonly used values. These glossaries can be external or defined inline. These values are injected in the same way as snippets: $key$

Building a community

This project is a small step in many that I’ve been taking towards trying to make the BonsaiDb ecosystem ready for additional contributors. Sure, I could simply copy this new information to each of the 14 repositories that I consider currently active. My thought is that by building this one-day project, I can save myself a lot of future effort when revisions to these files inevitably happen.

As to BonsaiDb, I’m aiming to release 0.1.0-alpha.1 this month. I also want to reveal a high-level roadmap and a list of issues targeting all major features planned for 0.1.0. I’m hoping that one or two more people might be interested in contributing after seeing the vision we have and finding an interesting issue to tackle. Regardless of if anyone else joins, these projects are still very important to us and are part of our road towards building our own apps and games.