derive-deftly 1.11.0

An ergonomic way to write derive() macros
Documentation
<!-- @dd-navbar -->
<!-- this line automatically maintained by update-navbars --><nav style="text-align: right; margin-bottom: 12px;">[ <em>docs: <a href="https://docs.rs/derive-deftly/latest/derive_deftly/index.html">crate top-level</a> | <a href="https://docs.rs/derive-deftly/latest/derive_deftly/index.html#overall-toc">overall toc, macros</a> | <a href="https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html">template etc. reference</a> | <a href="https://diziet.pages.torproject.net/rust-derive-deftly/latest/guide/"><strong>guide/tutorial</strong></a></em> ]</nav>

# Transforming names and strings

Often, it's useful to define new identifiers
based on existing ones,
or to convert identifiers into strings.

You _could_ use the existing [`paste`] crate for this,
or you can use a native facility provided by derive-deftly.

For example, suppose that you want
to define a template that makes a "discriminant" type
for your enumerations.
You want the new type to be named `FooDiscriminant`,
where `Foo` is the name of your existing type.
While you're at it, you want to add an `is_` function
to detect each variant.

You can do that like this:
```rust
# use derive_deftly::define_derive_deftly;
define_derive_deftly! {
    Discriminant:

    #[derive(Copy,Clone,Eq,PartialEq,Debug)]
    enum ${paste $tname Discriminant} {
        $(
            $vname,
        )
    }

    impl<$tgens> $ttype where $twheres {
       fn discriminant(&self) -> ${paste $tname Discriminant} {
          match self {
              $(
                  $vpat => ${paste $tname Discriminant}::$vname,
              )
          }
        }

        $(
            fn ${paste is_ ${snake_case $vname}} (&self) -> bool {
                self.discriminant() ==
                    ${paste $tname Discriminant} ::$vname
            }
        )
    }
}
```

Here we see a couple of new constructs.

First, we're using
[`${paste}`][x:paste]
to glue several identifiers together into one.
When we say `${paste $tname Discriminant}`,
we are generating a new identifier from `$tname`
(the type name)
and the word Discriminant.
So if the type name is `Foo`,
the new type will be called `FooDiscriminant`.

Second, we're using
[`${snake_case}`][case-changing]
to transform an identifier into `snake_case`
(that is, lowercase words separated by underscores).
We use this to turn the name of each variant (`$vname`)
into a name suitable for use in a function name.
So if a variant is called `ExampleVariant`,
`${snake_case $vname}`  will be `example_variant`,
and `${paste is_ ${snake_case $vname}}` will be
`is_example_variant`.

There are [other case-changers][case-changing]:
  * `${pascal_case my_ident}` becomes `MyIdent`.
    You can also write this as
    `${upper_camel_case ..}`.
  * `${lower_camel_case my_ident}` becomes `myIdent`.
  * `${shouty_snake_case MyIdent}` becomes `MY_IDENT`.
  * `${snake_case MyIdent}` becomes `my_ident`, as you've already seen.

You can abbreviate `${paste ...}` as `$<...>`.

<!--
  TODO: Should we show `$<...>` instead of `${paste ...}`?
  Maybe we should principally advertise `$<...>`, everywhere,
  and de-emphasise `${paste ...}`.
 -->

#### Pasting onto types

Here's a side-note:
You can use `${paste}` to append identifiers to a type
(like `$ttype` or `$ftype`),
not just an identifier.
When you do this, `${paste}` will
[do the right thing][identifier-pasting]
even if the type is generic.

For example, if `$ftype` is `Vec<u8>`,
then `${paste $ftype Builder}` will expand to
`VecBuilder<u8>`, not `Vec<u8>Builder`.

#### A note on syntax

In this last section,
you've seen a new syntax for the first time.
Both `${paste ident ident..}` and `${snake_case ident}`
are special cases of the following meta-syntax,
which derive-deftly uses everywhere:

[`${KEYWORD ARGS.. }`][arg-syntax]

In fact, if you want,
you can use this format
for all of the expansion macros you have already seen:
`$ttype` is just a shortened form for `${ttype}`,
`$fname` is just `${fname}`,
and so on.

Some keywords,
including some of those we've already seen,
can take named arguments.
The syntax for this is:

`${KEYWORD ARGNAME=VALUE ARGNAME=VALUE...}`

> For example, we can use this syntax to give optional arguments to `$vpat`;
> see the template syntax reference for more information.

If you ever need to write a literal `$`
(say, if you want to confuse yourself
by making derive-deftly-generated pattern macros)
you can write [`$$`][dollar-dollar].


[`paste`]: https://docs.rs/paste/latest/paste/
[dollar-dollar]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#dollar-dollar
[x:paste]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#x:paste
[case-changing]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#case-changing
[identifier-pasting]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#x:paste
[arg-syntax]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#named-and-positional-template-arguments-to-expansions-and-conditions