render_tree/lib.rs
1//! This module defines a tree structure that you can use to build documents
2//! to render with color.
3//!
4//! There are three kinds of nodes in the Render Tree:
5//!
6//! - Lines, which represent content followed by a newline
7//! - Sections, which represent named content that can be targeted by
8//! style rules.
9//! - Components, which are parameterized chunks of the Render Tree
10//!
11//! The easiest way to build a render tree is using the `tree!` macro:
12//!
13//! ```
14//! #[macro_use]
15//! extern crate render_tree;
16//! extern crate termcolor;
17//! use render_tree::{Document, Line, RenderComponent};
18//! use termcolor::StandardStream;
19//!
20//! fn main() -> std::io::Result<()> {
21//! let world = "world";
22//!
23//! let document = tree! {
24//! <Line as {
25//! "Hello" {world}
26//! }>
27//!
28//! <Line as {
29//! "Goodbye" {world}
30//! }>
31//! };
32//!
33//! document.write()
34//! }
35//! ```
36//!
37//! This will print out:
38//!
39//! ```text
40//! Hello world
41//! Goodbye world
42//!
43//! ```
44//!
45//! You can use sections and stylesheets to colorize the output:
46//!
47//! ```
48//! #[macro_use]
49//! extern crate render_tree;
50//! extern crate termcolor;
51//! use render_tree::{Document, Line, RenderComponent, Section, Stylesheet};
52//! use render_tree::prelude::*;
53//! use termcolor::StandardStream;
54//!
55//! fn main() -> std::io::Result<()> {
56//! let world = "world";
57//!
58//! let document = tree! {
59//! <Line as {
60//! <Section name="hello" as { "Hello" }>
61//! {world}
62//! }>
63//!
64//! <Line as {
65//! <Section name="goodbye" as { "Goodbye"}>
66//! {world}
67//! }>
68//! };
69//!
70//! let stylesheet = Stylesheet::new()
71//! .add("hello", "fg: blue")
72//! .add("goodbye", "fg: red");
73//!
74//! document.write_styled(&stylesheet)
75//! }
76//! ```
77//!
78//! This will print out:
79//!
80//! ```text
81//! Hello world
82//! Goodbye world
83//!
84//! ```
85//!
86//! with the word "Hello" colored blue and "Goodbye" colored red.
87//!
88//! You can nest sections, which can be targeted by style paths:
89//!
90//!
91//! ```
92//! #[macro_use]
93//! extern crate render_tree;
94//! extern crate termcolor;
95//! use render_tree::{Document, Line, RenderComponent, Section, Stylesheet};
96//! use render_tree::prelude::*;
97//! use termcolor::StandardStream;
98//!
99//! fn main() -> std::io::Result<()> {
100//! let world = "world";
101//!
102//! let document = tree! {
103//! <Line as {
104//! <Section name="hello-world" as {
105//! <Section name="greeting" as { "Hello" }>
106//! {world}
107//! }>
108//! }>
109//!
110//! <Line as {
111//! "Some content in the middle here"
112//! }>
113//!
114//! <Line as {
115//! <Section name="goodbye-world" as {
116//! <Section name="greeting" as { "Goodbye" }>
117//! {world}
118//! }>
119//! }>
120//! };
121//!
122//! let stylesheet = Stylesheet::new()
123//! .add("** greeting", "weight: bold")
124//! .add("hello-world greeting", "fg: red")
125//! .add("goodbye-world greeting", "fg: blue");
126//!
127//! document.write_styled(&stylesheet)
128//! }
129//! ```
130//!
131//! This will print out:
132//!
133//! ```text
134//! Hello world
135//! Some content in the middle here
136//! Goodbye world
137//!
138//! ```
139//!
140//! with the "Hello world" and "Goodbye world" bolded, the word "Hello" colored
141//! red (and bolded, of course), and the word "Goodbye" colored red (and
142//! bolded).
143//!
144//! Globs (`**`) in a rule are superseded by stars (`*`), which are supersede by
145//! literal names. Globs match zero or more section names and stars match exactly
146//! one section name.
147//!
148//! # Using without the `tree!` macro
149//!
150//! It's also easy to build a Render Tree without the macro. Repeating the previous
151//! example without the macro and without the string DSL for the stylesheet:
152//!
153//! ```
154//! #[macro_use]
155//! extern crate render_tree;
156//! extern crate termcolor;
157//! use render_tree::{
158//! Color,
159//! Document,
160//! Line,
161//! Render,
162//! RenderComponent,
163//! Section,
164//! Selector,
165//! Segment,
166//! Style,
167//! Stylesheet
168//! };
169//! use termcolor::StandardStream;
170//!
171//! fn main() -> std::io::Result<()> {
172//! let world = "world";
173//!
174//! let document = Document::with(
175//! Line(
176//! Section("hello-world", |doc|
177//! doc.add(
178//! Section("greeting", |doc| doc.add("Hello").add(world))
179//! )
180//! )
181//! )
182//! ).add(
183//! Line(
184//! "Some content in the middle here"
185//! )
186//! ).add(
187//! Line(
188//! Section("goodbye-world", |doc|
189//! doc.add(
190//! Section("greeting", |doc| doc.add("Goodbye").add(world))
191//! )
192//! )
193//! )
194//! );
195//!
196//! let stylesheet = Stylesheet::new()
197//! .add(Selector::glob().add("greeting"), Style::new().bold())
198//! .add(Selector::name("hello-world").add("greeting"), Style::new().fg(Color::Red))
199//! .add(Selector::name("goodbye-world").add("greeting"), Style::new().fg(Color::Blue));
200//!
201//! document.write_styled(&stylesheet)
202//! }
203//! ```
204
205#[macro_use]
206pub mod macros;
207mod component;
208mod debug;
209pub mod document;
210mod helpers;
211pub mod prelude;
212mod render;
213pub mod stylesheet;
214pub(crate) mod utils;
215
216pub use self::component::*;
217pub use self::document::*;
218pub use self::helpers::*;
219pub use self::render::*;
220pub use self::stylesheet::{Color, Segment, Selector, Style, Stylesheet};