[][src]Crate render_tree

This module defines a tree structure that you can use to build documents to render with color.

There are three kinds of nodes in the Render Tree:

  • Lines, which represent content followed by a newline
  • Sections, which represent named content that can be targeted by style rules.
  • Components, which are parameterized chunks of the Render Tree

The easiest way to build a render tree is using the tree! macro:

#[macro_use]
extern crate render_tree;
extern crate termcolor;
use render_tree::{Document, Line, RenderComponent};
use termcolor::StandardStream;

fn main() -> std::io::Result<()> {
    let world = "world";

    let document = tree! {
        <Line as {
            "Hello" {world}
        }>

        <Line as {
            "Goodbye" {world}
        }>
    };

    document.write()
}

This will print out:

Hello world
Goodbye world

You can use sections and stylesheets to colorize the output:

#[macro_use]
extern crate render_tree;
extern crate termcolor;
use render_tree::{Document, Line, RenderComponent, Section, Stylesheet};
use render_tree::prelude::*;
use termcolor::StandardStream;

fn main() -> std::io::Result<()> {
    let world = "world";

    let document = tree! {
        <Line as {
            <Section name="hello" as { "Hello" }>
            {world}
        }>

        <Line as {
            <Section name="goodbye" as { "Goodbye"}>
            {world}
        }>
    };

    let stylesheet = Stylesheet::new()
        .add("hello", "fg: blue")
        .add("goodbye", "fg: red");

    document.write_styled(&stylesheet)
}

This will print out:

Hello world
Goodbye world

with the word "Hello" colored blue and "Goodbye" colored red.

You can nest sections, which can be targeted by style paths:

#[macro_use]
extern crate render_tree;
extern crate termcolor;
use render_tree::{Document, Line, RenderComponent, Section, Stylesheet};
use render_tree::prelude::*;
use termcolor::StandardStream;

fn main() -> std::io::Result<()> {
    let world = "world";

    let document = tree! {
        <Line as {
            <Section name="hello-world" as {
                <Section name="greeting" as { "Hello" }>
                {world}
            }>
        }>

        <Line as {
            "Some content in the middle here"
        }>

        <Line as {
            <Section name="goodbye-world" as {
                <Section name="greeting" as { "Goodbye" }>
                {world}
            }>
        }>
    };

    let stylesheet = Stylesheet::new()
        .add("** greeting", "weight: bold")
        .add("hello-world greeting", "fg: red")
        .add("goodbye-world greeting", "fg: blue");

    document.write_styled(&stylesheet)
}

This will print out:

Hello world
Some content in the middle here
Goodbye world

with the "Hello world" and "Goodbye world" bolded, the word "Hello" colored red (and bolded, of course), and the word "Goodbye" colored red (and bolded).

Globs (**) in a rule are superseded by stars (*), which are supersede by literal names. Globs match zero or more section names and stars match exactly one section name.

Using without the tree! macro

It's also easy to build a Render Tree without the macro. Repeating the previous example without the macro and without the string DSL for the stylesheet:

#[macro_use]
extern crate render_tree;
extern crate termcolor;
use render_tree::{
    Color,
    Document,
    Line,
    Render,
    RenderComponent,
    Section,
    Selector,
    Segment,
    Style,
    Stylesheet
};
use termcolor::StandardStream;

fn main() -> std::io::Result<()> {
    let world = "world";
     
    let document = Document::with(
        Line(
            Section("hello-world", |doc|
                doc.add(
                    Section("greeting", |doc| doc.add("Hello").add(world))
                )
            )
        )
    ).add(
        Line(
            "Some content in the middle here"
        )
    ).add(
        Line(
            Section("goodbye-world", |doc|
                doc.add(
                    Section("greeting", |doc| doc.add("Goodbye").add(world))
                )
            )
        )
    );

    let stylesheet = Stylesheet::new()
        .add(Selector::glob().add("greeting"), Style::new().bold())
        .add(Selector::name("hello-world").add("greeting"), Style::new().fg(Color::Red))
        .add(Selector::name("goodbye-world").add("greeting"), Style::new().fg(Color::Blue));

    document.write_styled(&stylesheet)
}

Re-exports

pub use self::document::*;
pub use self::stylesheet::Segment;
pub use self::stylesheet::Selector;
pub use self::stylesheet::Stylesheet;

Modules

document
macros
prelude
stylesheet

Macros

tree

This macro builds a Document using nested syntax.

Structs

Combine
CurriedBlockComponent
CurriedIterBlockComponent
CurriedOnceBlockComponent
Each

A list of items that can be appended into a Document. For each item in items, the callback is invoked, and its return value is appended to the document.

Empty
Join

Equivalent to Each(), but inserts a joiner between two adjacent elements.

OnceBlock
Section

A section that can be appended into a document. Sections are invisible, but can be targeted in stylesheets with selectors using their name.

Style

Enums

Color

Traits

BlockComponent
IterBlockComponent
OnceBlockComponent
Render

The Render trait defines a type that can be added to a Document. It is defined for Node, String, &str, and Document.alloc

RenderComponent

This trait defines a renderable entity with arguments. Types that implement RenderComponent can be packaged up together with their arguments in a Component, and the Component is renderable.

Functions

Component
Each
IfSome
Join
Line

Inserts a line into a Document. The contents are inserted first, followed by a newline.

Section
SomeValue
Style
repeat

Creates a Render that, when appended into a Document, repeats a given string a specified number of times.