[−][src]Macro render_tree::tree
This macro builds a Document
using nested syntax.
Inline values using {...}
syntax
You can insert any Render
value into a document using {...}
syntax.
use render_tree::prelude::*; let hello = "hello"; let world = format!("world"); let title = ". The answer is "; let answer = 42; let document = tree! { {hello} {" "} {world} {". The answer is "} {answer} }; assert_eq!(document.to_string()?, "hello world. The answer is 42");
Built-in types that implement render include:
- Anything that implements
Display
(including String, &str, the number types, etc.). The text value is inserted into the document. - Other
Document
s, which are concatenated onto the document. - A
SomeValue
adapter that takes anOption<impl Renderable>
and inserts its inner value if present. - An
Empty
value that adds nothing to the document.
Inline Components
You can create components to encapsulate some logic:
use render_tree::prelude::*; struct Header { code: usize, message: &'static str, } impl Render for Header { fn render(self, document: Document) -> Document { document.add(tree! { {self.code} {": "} {self.message} }) } } let code = 1; let message = "Something went wrong"; let document = tree! { <Header code={code} message={message}> }; assert_eq!(document.to_string()?, "1: Something went wrong");
Block Components
You can also build components that take a block that runs exactly
once (an FnOnce
).
#[macro_use] extern crate render_tree; use render_tree::prelude::*; struct Message { code: usize, message: &'static str, trailing: &'static str, } impl BlockComponent for Message { fn append( self, block: impl FnOnce(Document) -> Document, mut document: Document, ) -> Document { document = document.add(tree! { {self.code} {": "} {self.message} {" "} }); document = block(document); document = document.add(tree! { {self.trailing} }); document } } let code = 1; let message = "Something went wrong"; let document = tree! { <Message code={code} message={message} trailing={" -- yikes!"} as { {"!!! It's really quite bad !!!"} }> }; assert_eq!(document.to_string()?, "1: Something went wrong !!! It's really quite bad !!! -- yikes!");
Iterators
Finally, you can create components that take a block and call the block multiple times (an iterator).
use render_tree::prelude::*; use std::io; pub struct UpcaseAll<Iterator: IntoIterator<Item = String>> { pub items: Iterator, } impl<Iterator: IntoIterator<Item = String>> IterBlockComponent for UpcaseAll<Iterator> { type Item = String; fn append( self, mut block: impl FnMut(String, Document) -> Document, mut document: Document, ) -> Document { for item in self.items { document = block(item.to_uppercase(), document); } document } } let list = vec![format!("Hello"), format!("World")]; let document = tree! { <UpcaseAll items={list} as |item| { {"upcase:"} {item} }> }; assert_eq!(document.to_string()?, "upcase:HELLOupcase:WORLD");