Trait DisplayTree

Source
pub trait DisplayTree {
    // Required method
    fn fmt(&self, f: &mut Formatter<'_>, style: Style) -> Result;
}
Expand description

A type that can be pretty-printed as a tree with a specified style.

DisplayTree can be derived for structs and enums, and generally the derived implementation should be sufficient, but it can be manually implemented if needed.

§Deriving

Deriving DisplayTree for a type requires that all of its fields not marked #[tree] implement std::fmt::Display. A derived implementation will be formatted as the name of the struct or variant as a node, followed by a branches underneath with a node for each field.

The AsTree type should be used to display a tree implementing DisplayTree. See the AsTree documentation for more information.

use display_tree::{format_tree, AsTree, DisplayTree};

// A tree representing a numerical expression.
#[derive(DisplayTree)]
enum Expr {
    Int(i32),
    BinOp {
        #[node_label]
        op: char,
        #[tree]
        left: Box<Self>,
        #[tree]
        right: Box<Self>,
    },
    UnaryOp {
        #[node_label]
        op: char,
        #[tree]
        arg: Box<Self>,
    },
}

let expr: Expr = get_expr();

assert_eq!(
    format_tree!(expr),
    concat!(
        "+\n",
        "├── -\n",
        "│   └── Int\n",
        "│       └── 2\n",
        "└── Int\n",
        "    └── 7",
    ),
);

§Helper Attributes

[derive(DisplayTree)] provies a few helper attribute that allow the derived implementation to be customized.

§Field Attributes

  • #[tree] marks a field that should be formatted as a tree. By default, a field’s std::fmt::Display implementation will be used to format it in the tree, but fields can be marked with #[tree] to use their DisplayTree implementation instead. #[tree] can be used on any type that conforms to ToDisplayTreeRef, which includes any types that conform to DisplayTree.

  • #[ignore_field] marks a field that should not be included in the tree. When the tree is formatted, the field will not be present.

  • #[node_label] causes a field to be used as the label of the node of the tree that it is under. By default, the name of the struct or variant will be used as the label. For example, for a variant representing a binary operator and its arguments, you might want the operator to be the used as the label of the tree.

  • #[field_label (= "label")] causes the node for a field to have a label in the form label: value when it is formatted. A string literal can be passed to specify the label, otherwise the name of the field will be used.

§Struct/Variant Attributes

  • #[node_label = "label"] specifies the label to use for the node of the tree. By default, the name of the struct or variant will be used.

§Examples

Specifying a field label:

#[derive(display_tree::DisplayTree)]
struct Point {
    #[field_label]
    x: i32,
    #[field_label]
    y: i32,
}

Ignoring a field:

#[derive(display_tree::DisplayTree)]
struct Numbers {
    not_so_secret_number: i32,
    // `super_secret_number` not included when tree is formatted.
    #[ignore_field]
    super_secret_number: i32,
}

Using a field as the node label:

#[derive(display_tree::DisplayTree)]
enum Expr {
    Num(i32),
    BinOp {
        // Show the operator as the node of this variant.
        #[node_label]
        op: char,
        #[tree]
        left: Box<Self>,
        #[tree]
        right: Box<Self>,
    },
}

Using a custom node label:

#[derive(display_tree::DisplayTree)]
// Use "MyStruct" as the node label instead of the name of the `struct`.
#[node_label = "MyStruct"]
struct MyVeryLongComplexDetailedImportantStruct(bool);

Required Methods§

Source

fn fmt(&self, f: &mut Formatter<'_>, style: Style) -> Result

Formats the tree using the given formatter and the given style.

fmt() should not be called directly. It is used by AsTree to format a tree.

§Examples
use display_tree::{AsTree, DisplayTree, Style};

struct Point {
    x: i32,
    y: i32,
}

impl DisplayTree for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>, style: Style) -> std::fmt::Result {
        writeln!(f, "Point")?;
        writeln!(
            f,
            "{}{} x: {}",
            style.char_set.connector,
            std::iter::repeat(style.char_set.horizontal)
                .take(style.indentation as usize)
                .collect::<String>(),
            self.x
        )?;
        write!(
            f,
            "{}{} y: {}",
            style.char_set.end_connector,
            std::iter::repeat(style.char_set.horizontal)
                .take(style.indentation as usize)
                .collect::<String>(),
            self.y
        )
    }
}

assert_eq!(
    format!("{}", AsTree::new(&Point { x: 10, y: 20 })),
    "Point\n\
     ├── x: 10\n\
     └── y: 20",
);

Implementors§