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>

# Getting started with if/then/else conditionals

In the example above,
we made it possible to rename the "new" function
generated by our template.
But our approach is flawed:
if the user _doesn't_ provide
the `#[deftly(newfn)]` attribute,
the expansion of `${tmeta(constructor(newfn)) ...}` 
will fail with an error!

Let's show how to fix that:
```rust
# use derive_deftly::define_derive_deftly;
define_derive_deftly! {
   Constructor for struct:

   impl<$tgens> $ttype where $twheres {
   $tvis fn
        // (1) This "if" defines the function name:
        ${if tmeta(constructor(newfn)) {
            ${tmeta(constructor(newfn)) as ident}
          } else {
            new
          }
        }
        // The rest is as before:
     ( $( $fname: $ftype , ) ) -> Self {
          Self {
              $( $fname , )
          }
      }
   }
}
#
# use derive_deftly::Deftly;
# #[derive(Deftly)]
# #[derive_deftly(Constructor)]
# #[deftly(constructor(newfn="construct_example"))]
# struct Example {
#    a: f64,
#    b: String
# }
# #[derive(Deftly)]
# #[derive_deftly(Constructor)]
# struct Example2 {
#    a: f64,
#    b: String
# }
```

Have a look at the part of the template marked with `// (1)`.
It introduces a new concept: _conditional expansion_.
The
[`${if cond {expansion}}`][x:if]
keyword checks whether a given _condition_ is true.
If it is, then the `$if` keyword expands to the expansion second argument.
Otherwise, it expands to an "else" argument (if any).

> Also, you can chain `$if`s, as in
> `${if COND1 { ... } else if COND2 { ... } else { ... }`
> and so on!

Here, the condition is
[`tmeta(constructor(newfn))`][c:tmeta] ("toplevel metavalue").
That condition is true if the current type
has an `#[deftly(newfn)]` attribute,
and false otherwise.
There are also `vmeta` and `fmeta` conditions
to detect `#[deftly(..)]` attributes
on variants and fields respectively.

> Note: Don't confuse conditions with expansions!
> As we use it here, `tmeta(x)` is a condition (true or false),
> whereas `${tmeta(x) as ident}` is an expansion.
>
> They are similar
> (for memorability and consistency), but
> conditions and expansions have separate namespaces;
> you cannot (in general) use them interchangeably.

There is a
[complete list of recognized conditions][ref:conditions]
in the reference.

## Multiple exclusive options with `$select1` {#select1}

Sometimes you want to make sure _exactly one_
condition matches.

This is a good choice when you have multiple options
for controlling some feature, and you want to make sure
that the user has specified exactly one
(or maybe, no more than one).

You can do this using the `${select1}` keyword:

`${select1 COND1 { ... } else if COND2 { ... } ... else { ... }`

Its syntax is identical to `${if}`.
But the behaviour is different: _all_ conditions are checked.
If more than one condition is true,
then derive-deftly rejects `${select1}`:
it fails to expand, and
emits an error.
If no conditions are true,
and there is no `else` clause,
then `${select1}` is also rejected
(it fails to expand,
and emits an error).

Here's an example of how we could use `${select1}`
if we wanted to allow `constructor(default_name)`,
as a synonym for our default behavior.
In this case, we enforce that the user has specified
`constructor(newfn(X))` _or_ `constructor(default_name)` _or_ neither,
but not both:

```rust
# use derive_deftly::define_derive_deftly;
# define_derive_deftly! {
#   Constructor for struct:
#
#   impl<$tgens> $ttype where $twheres {
# pub fn
   ${select1
       tmeta(constructor(newfn)) { ${tmeta(constructor(newfn))} }
       else if tmeta(constructor(default_name)) { new }
       else { new }
    }
# () {}
#   }
# }
```


[x:if]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#x:if
[c:tmeta]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#c:tmeta
[ref:conditions]: https://docs.rs/derive-deftly/latest/derive_deftly/doc_reference/index.html#conditions