Skip to content

Commit

Permalink
docs: Update the READMEs
Browse files Browse the repository at this point in the history
  • Loading branch information
mcy committed Jan 25, 2025
1 parent c456960 commit 6a207ce
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ depend on each other.
- ⛩️ [`ilex`](https://github.com/mcy/strings/tree/main/ilex) - The last lexer I
ever want to write.

- 🗒️ [`allman`](https://github.com/mcy/strings/tree/main/allman) - A DOM for
code formatters.

- 👑 [`gilded`](https://github.com/mcy/strings/tree/main/gilded) - How I learned
to stop worrying and love golden testing.

- 💢 [`proc2decl`](https://github.com/mcy/strings/tree/main/proc2decl) - Proc
macros suck!

---

All libraries are Apache-2.0 licensed.
42 changes: 42 additions & 0 deletions allman/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# allman

`allman` - A code formatting and line reflowing toolkit. 🗒️🖋️

`allman::Doc` is a DOM-like structure that specifies how indentation,
like breaking, and reflowing should be handled. It is a tree of `Tag`s
that dictate layout information for the source code to format.

For example, the Allman brace style (for which this crate is named) can
be implemented as follows:

```rust
// flat: fn foo() { ... }
//
// broken:
// fn foo()
// {
// // ...
// }
Doc::new()
.tag("fn")
.tag(Tag::Space)
.tag("foo")
.tag("(").tag(")")
.tag_with(Tag::Group(40), |doc| {
doc
.tag_if(Tag::Space, If::Flat)
.tag_if(Tag::Break(1), If::Broken)
.tag("{")
.tag_if(Tag::Space, If::Flat)
.tag_if(Tag::Break(1), If::Broken)
.tag_with(Tag::Indent(2), |doc| {
// Brace contents here...
})
.tag_if(Tag::Space, If::Flat)
.tag_if(Tag::Break(1), If::Broken)
.tag("}");
});
```

When calling `Doc::render()`, the layout algorithm will determine whether
`Tag::Group`s should be "broken", i.e., laid out with newlines inside.
2 changes: 1 addition & 1 deletion allman/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! `allman` 🗒️🖋️ - A code formatting and line reflowing toolkit.
//! `allman` - A code formatting and line reflowing toolkit. 🗒️🖋️
//!
//! [`allman::Doc`][Doc] is a DOM-like structure that specifies how indentation,
//! like breaking, and reflowing should be handled. It is a tree of [`Tag`]s
Expand Down
64 changes: 64 additions & 0 deletions gilded/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# gilded

`gilded` - Easy-peesy golden testing. 👑

## Why Golden Testing?

A "golden test" is a test that transforms data in some way, and validates it
by diffing it against an expected result: the "golden".

This is especially useful for testing scenarios that consume an input file
(say, a source code file, for testing a compiler) and generate structured,
diffable textual output (such as JSON or CSV data, or even a `Debug`).

Golden tests are best for cases where the output must be deterministic, and
where capturing fine-grained detail is valuable.

Because they simply compare the result to an expected value byte-for-byte,
changes can quickly regenerate the test output by using the output of the
test itself. Diffs can be examined in code review directly.

This crate also provides the `doc::Doc` type, enabling quick-and-dirty
construction of highly readable structured tree data for golden outputs.

## Defining a Test

A `gilded` test is defined like so:

```rust
#[gilded::test("testdata/**/*.txt")]
fn my_test(test: &gilded::Test) {
// ...
}
```

`my_test` will be run as a separate unit test for every file (relative to
the crate root) which matches the glob passed to the attribute. The input
file's path and contents can be accessed through the `Test` accessors.

To specify golden outputs, use `Test::outputs()`. This specifies the
file extension for the golden, and its computed contents. The extension is
used to construct the path of the result. If the input is `foo/bar.txt`, and
the extension for this output is `csv`, the output will be read/written to
`foo/bar.csv`.

Panicking within the test body will fail the test as normal, tests should
not contain output assertions; those are handled by the framework.

## Generating Goldens

Once the test is created, simply set the `GILDED_REGENERATE` environment
variable: `GILDED_REGENERATE=1 cargo test`.

To regenerate a specific test, simply pass its name as a filter to the test.
See `cargo test -- --help` for available flags.`

Regenerating goldens will cause a `GILDED_CHANGED` file to be crated at the
crate root, which will cause all `gilded` tests in the crate to fail until
it is deleted. Deleting it forces the user to acknowledge that goldens have
been regenerated, to avoid blindly committing them.

## Known Issues

Golden tests can run under MIRI but have extremely large overhead. For the
time being, they are `#[cfg]`'d out in MIRI mode.
2 changes: 2 additions & 0 deletions proc2decl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[package]
name = "proc2decl"
version = "0.1.0"
description = "Write less frickin' proc macro code"

edition.workspace = true
authors.workspace = true
homepage.workspace = true
Expand Down
28 changes: 28 additions & 0 deletions proc2decl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# proc2decl

`proc2decl` exists for one reason only: because proc macros are a toxic
ecosystem.

Sometimes, you want to use an attribute to define a macro. Unfortunately,
Rust does not support declarative macros (also called macros-by-example)
for attributes, for reasons that essentially boil down to cookie-licking.

This crate exists for one purpose only, and that is ot facilitate writing
declarative macros that an attribute converts into.

## How Uo Use

1. Define the macro-by-example you wish to use as the main implementation of
your attribute or derive.

2. Crate a proc-macro crate. This is where the documentation for your
attribute will need to live. Your actual crate should depend on this
crate.

3. Use `bridge!()` to define your bridge proc macros. These
macro calls should be documented, since their doc comments are the ones
that will appear in rustdoc for your macros.

4. `pub use` the macros in your actual crate.

Proc macros suck!

0 comments on commit 6a207ce

Please sign in to comment.