book: add enum documentation

This commit is contained in:
René Kijewski 2025-01-25 20:55:01 +01:00
parent 5944ab9bef
commit 1066c884f3
2 changed files with 172 additions and 0 deletions

View File

@ -118,6 +118,85 @@ recognized:
struct HelloTemplate<'a> { ... } struct HelloTemplate<'a> { ... }
``` ```
## Templating `enum`s
You can add derive `Template`s for `struct`s and `enum`s.
If you add `#[template()]` only to the item itself, both item kinds work exactly the same.
But with `enum`s you also have the option to add a specialized implementation to one, some,
or all variants:
```rust
#[derive(Debug, Template)]
#[template(path = "area.txt")]
enum Area {
Square(f32),
Rectangle { a: f32, b: f32 },
Circle { radius: f32 },
}
```
```jinja2
{%- match self -%}
{%- when Self::Square(side) -%}
{{side}}^2
{%- when Self::Rectangle { a, b} -%}
{{a}} * {{b}}
{%- when Self::Circle { radius } -%}
pi * {{radius}}^2
{%- endmatch -%}
```
will give you the same results as:
```rust
#[derive(Template, Debug)]
#[template(ext = "txt")]
enum AreaPerVariant {
#[template(source = "{{self.0}}^2")]
Square(f32),
#[template(source = "{{a}} * {{b}}")]
Rectangle { a: f32, b: f32 },
#[template(source = "pi * {{radius}}^2")]
Circle { radius: f32 },
}
```
As you can see with the `ext` attribute, `enum` variants inherit most settings of the `enum`:
`config`, `escape`, `ext`, `syntax`, and `whitespace`.
Not inherited are: `block`, and `print`.
If there is no `#[template]` annotation for an `enum` variant,
then the `enum` needs a default implementation, which will be used if `self` is this variant.
A good compromise between annotating only the template, or all its variants,
might be using the `block` argument on the members:
```rust
#[derive(Template, Debug)]
#[template(path = "area.txt")]
enum AreaWithBlocks {
#[template(block = "square")]
Square(f32),
#[template(block = "rectangle")]
Rectangle { a: f32, b: f32 },
#[template(block = "circle")]
Circle { radius: f32 },
}
```
```jinja2
{%- block square -%}
{{self.0}}^2
{%- endblock -%}
{%- block rectangle -%}
{{a}} * {{b}}
{%- endblock -%}
{%- block circle -%}
pi * {{radius}}^2
{%- endblock -%}
```
## Documentation as template code ## Documentation as template code
[#documentation-as-template-code]: #documentation-as-template-code [#documentation-as-template-code]: #documentation-as-template-code

View File

@ -3,6 +3,99 @@ use std::fmt::{Debug, Display};
use rinja::Template; use rinja::Template;
#[test]
fn test_book_example() {
#[derive(Template, Debug)]
#[template(
source = "
{%- match self -%}
{%- when Self::Square(side) -%} {{side}}^2
{%- when Self::Rectangle { a, b} -%} {{a}} * {{b}}
{%- when Self::Circle { radius } -%} pi * {{radius}}^2
{%- endmatch -%}
",
ext = "txt"
)]
enum AreaWithMatch {
#[template(source = "{{self.0}}^2", ext = "txt")]
Square(f32),
#[template(source = "{{a}} * {{b}}", ext = "txt")]
Rectangle { a: f32, b: f32 },
#[template(source = "pi * {{radius}}^2", ext = "txt")]
Circle { radius: f32 },
}
assert_eq!(AreaWithMatch::Square(2.0).render().unwrap(), "2^2");
assert_eq!(
AreaWithMatch::Rectangle { a: 1.0, b: 2.0 }
.render()
.unwrap(),
"1 * 2",
);
assert_eq!(
AreaWithMatch::Circle { radius: 3.0 }.render().unwrap(),
"pi * 3^2"
);
#[derive(Template, Debug)]
enum AreaPerVariant {
#[template(source = "{{self.0}}^2", ext = "txt")]
Square(f32),
#[template(source = "{{a}} * {{b}}", ext = "txt")]
Rectangle { a: f32, b: f32 },
#[template(source = "pi * {{radius}}^2", ext = "txt")]
Circle { radius: f32 },
}
assert_eq!(AreaPerVariant::Square(2.0).render().unwrap(), "2^2");
assert_eq!(
AreaPerVariant::Rectangle { a: 1.0, b: 2.0 }
.render()
.unwrap(),
"1 * 2",
);
assert_eq!(
AreaPerVariant::Circle { radius: 3.0 }.render().unwrap(),
"pi * 3^2"
);
#[derive(Template, Debug)]
#[template(
source = "
{%- block square -%}
{{self.0}}^2
{%- endblock -%}
{%- block rectangle -%}
{{a}} * {{b}}
{%- endblock -%}
{%- block circle -%}
pi * {{radius}}^2
{%- endblock -%}
",
ext = "txt"
)]
enum AreaWithBlocks {
#[template(block = "square")]
Square(f32),
#[template(block = "rectangle")]
Rectangle { a: f32, b: f32 },
#[template(block = "circle")]
Circle { radius: f32 },
}
assert_eq!(AreaWithBlocks::Square(2.0).render().unwrap(), "2^2");
assert_eq!(
AreaWithBlocks::Rectangle { a: 1.0, b: 2.0 }
.render()
.unwrap(),
"1 * 2",
);
assert_eq!(
AreaWithBlocks::Circle { radius: 3.0 }.render().unwrap(),
"pi * 3^2"
);
}
#[test] #[test]
fn test_simple_enum() { fn test_simple_enum() {
#[derive(Template, Debug)] #[derive(Template, Debug)]