The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Data::RenderAsTree - Render any data structure as an object of type Tree::DAG_Node

Synopsis

This is scripts/synopsis.pl:

        #!/usr/bin/env perl

        use strict;
        use warnings;

        use Data::RenderAsTree;

        use Tree::DAG_Node;

        # ------------------------------------------------

        my($sub) = sub {};
        my($s)   =
        {
                A =>
                {
                        a      => {},
                        bbbbbb => $sub,
                        c123   => $sub,
                        d      => \$sub,
                },
                B => [qw(element_1 element_2 element_3)],
                C =>
                {
                        b =>
                        {
                                a =>
                                {
                                        a => {},
                                        b => sub {},
                                        c => '429999999999999999999999999999999999999999999999',
                                }
                        }
                },
                DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD => 'd',
                Object     => Tree::DAG_Node -> new({name => 'A tree', attributes => {one => 1} }),
                Ref2Scalar => \'A shortish string', # Use ' in comment for UltraEdit hiliting.
        };
        my($result) = Data::RenderAsTree -> new
                (
                        attributes       => 0,
                        max_key_length   => 25,
                        max_value_length => 20,
                        title            => 'Synopsis',
                        verbose          => 0,
                ) -> render($s);

        print join("\n", @$result), "\n";

See the "FAQ" for a discussion as to whether you should call "render($s)" or "run($s)".

This is the output of scripts/synopsis.pl:

        Synopsis
            |--- {} [HASH 1]
                 |--- A = {} [HASH 2]
                 |    |--- {} [HASH 3]
                 |         |--- a = {} [HASH 4]
                 |         |    |--- {} [HASH 5]
                 |         |--- bbbbbb = CODE(0x1c93e30) [CODE 6]
                 |         |--- c123 [CODE 7 -> CODE 6]
                 |         |--- d [REF 8 -> CODE 6]
                 |--- B [ARRAY 9]
                 |    |--- 1 = [] [ARRAY 10]
                 |         |--- 0 = element_1 [SCALAR 11]
                 |         |--- 1 = element_2 [SCALAR 12]
                 |         |--- 2 = element_3 [SCALAR 13]
                 |--- C = {} [HASH 14]
                 |    |--- {} [HASH 15]
                 |         |--- b = {} [HASH 16]
                 |              |--- {} [HASH 17]
                 |                   |--- a = {} [HASH 18]
                 |                        |--- {} [HASH 19]
                 |                             |--- a = {} [HASH 20]
                 |                             |    |--- {} [HASH 21]
                 |                             |--- b = CODE(0x2475c68) [CODE 22]
                 |                             |--- c = 42999999999999999... [VALUE 23]
                 |--- DDDDDDDDDDDDDDDDDDDDDD... = d [VALUE 24]
                 |--- Object = {} [HASH 25]
                 |    |--- Class = Tree::DAG_Node [BLESS 26]
                 |         |--- {} [HASH 27]
                 |              |--- attributes = {} [HASH 28]
                 |              |    |--- {} [HASH 29]
                 |              |         |--- one = 1 [VALUE 30]
                 |              |--- daughters [ARRAY 31]
                 |              |    |--- 1 = [] [ARRAY 32]
                 |              |--- mother = undef [VALUE 33]
                 |              |--- name = A tree [VALUE 34]
                 |--- Ref2Scalar = SCALAR(0x230a230) [SCALAR 35]
                      |--- SCALAR(0x230a230) = A shortish string [SCALAR 36]

Description

Data::RenderAsTree provides a mechanism to display a Perl data structure.

The data supplied to "render($s)" is stored in an object of type Tree::DAG_Node.

render() returns an arrayref by calling Tree::DAG_Node's tree2string() method, so you can just print the return value as a string by using code as in synopsis.pl above.

It also means you can display as much or as little of the result as you wish, by printing a range of array elements.

Hash key lengths can be limited by "max_key_length($int)", and hash value lengths can be limited by "max_value_length($int)".

For sub-classing, see "process_tree()".

The module serves as a simple replacement for Data::TreeDumper, but without the huge set of features.

For sample code, see these programs in the scripts/ directory of the distro:

o array.pl
o bless.pl
o hash.pl
o mixup.pl
o ref.pl
o synopsis.pl

See also the test files t/*.t, which are basically copies of the above. And that means, like the *.pl above, all expected output is given in the source code.

Lastly, see the "FAQ" for details such as how to process the output tree yourself.

Distributions

This module is available as a Unix-style distro (*.tgz).

See http://savage.net.au/Perl-modules/html/installing-a-module.html for help on unpacking and installing distros.

Installation

Install Data::RenderAsTree as you would for any Perl module:

Run:

        cpanm Data::RenderAsTree

or run:

        sudo cpan Data::RenderAsTree

or unpack the distro, and then either:

        perl Build.PL
        ./Build
        ./Build test
        sudo ./Build install

or:

        perl Makefile.PL
        make (or dmake or nmake)
        make test
        make install

Constructor and Initialization

new() is called as my($g2m) = Data::RenderAsTree -> new(k1 => v1, k2 => v2, ...).

It returns a new object of type Data::RenderAsTree.

Key-value pairs accepted in the parameter list (see corresponding methods for details [e.g. "max_key_length([$int])"]):

o attributes => $Boolean

This is a debugging aid. When set to 1, metadata attached to each tree node is included in the output.

Default: 0.

o clean_nodes => $Boolean

Clean up nodes before printing, by changing the node's name to '' (the empty string) if it's undef, and by changing to '' any node attribute value which is undef.

Set to 1 to activate option.

Default: 0.

o max_key_length => $int

Use this to limit the lengths of hash keys.

Default: 10_000.

o max_value_length => $int

Use this to limit the lengths of hash values.

Default: 10_000.

o title => $s

Use this to set the name of the root node in the tree.

Default: 'Root'.

Methods

attributes([$Boolean])

Here, the [] indicate an optional parameter.

Gets or sets the attributes option.

Note: The value passed to Tree::DAG_Node's tree2string() method is (1 - $Boolean).

attributes is a parameter to "new()".

clean_nodes([$Boolean])

Gets or sets the value of the clean_nodes option.

This stops undef warnings when printing (i.e. when calling the tree's tree2string() method).

Values:

o 0

Do not clean up nodes.

o 1

Clean up nodes by doing both these:

o The node's name

Change the node's name to '' (the empty string) if it's undef.

o The node's attribute values

Change to '' any node attribute value which is undef.

max_key_length([$int])

Here, the [] indicate an optional parameter.

Gets or sets the maximum string length displayed for hash keys.

max_key_length is a parameter to "new()".

max_key_length([$int])

Here, the [] indicate an optional parameter.

Gets or sets the maximum string length displayed for hash values.

max_key_length is a parameter to "new()".

new()

See "Constructor and Initialization" for details on the parameters accepted by "new()".

process_tree()

Just before "render($s)" returns, it calls process_tree(), while walks the tree and adjusts various bits of data attached to each node in the tree.

If sub-classing this module, e.g. to change the precise text displayed, I recommend concentrating your efforts on this method.

Also, see the answer to the first question in the "FAQ".

render($s)

Renders $s into an object of type Tree::DAG_Node.

Returns an arrayref after calling the tree2string() method for Tree::DAG_Node.

See "Synopsis" for a typical usage.

See also "run($s)", which returns the root of the tree.

The choice of calling render() or run() is discussed in the "FAQ".

root()

Returns the root node in the tree, which is an object of type Tree::DAG_Node.

run($s)

Renders $s into an object of type Tree::DAG_Node.

Returns the root of the tree.

See also "render($s)", which returns an arrayref of the tree's data.

The choice of calling render() or run() is discussed in the "FAQ".

title([$s])

Here, the [] indicate an optional parameter.

Gets or sets the title, which is the name of the root node in the tree.

title is a parameter to "new()".

verbose([$Boolean])

Here, the [] indicate an optional parameter.

Gets or sets the verbose option, which prints a message upon entry to each method, with parameters, and prints the tree at the start of "process_tree()".

verbose is a parameter to "new()".

FAQ

Can I process the tree myself?

Sure. Just call "render($s)" and then "root($s)" to get the root of the tree, and process it any way you wish.

Otherwise, call "root($s)", which returns the root directly.

See the next question for help in choosing between render() and root().

See "process_tree()" for sample code. More information is in the docs for Tree::DAG_Node especially under the discussion of walk_down().

How do I choose between calling render() and root()?

"render($s)" automatically calls Tree::DAG_Node's tree2string() method, which you may not want.

For instance, the tree might have undef as the name of node, or the value of an attribute, so that calling tree2string() triggers undefined variable warnings when converting the node's attributes to a string.

With "run($s)", since tree2string() is not called, you have time to process the tree yourself, cleaning up the nodes, before converting it to an arrayref of strings by calling tree2string() directly. Indeed, with run() you may never call tree2string() at all.

Users of Marpa::R2 would normally call "run($s)". See MarpaX::Languages::Lua::Parser for sample code, where node names of undef are the reason for this choice.

What are the attributes of the tree nodes?

Firslty, each node has a name, which you can set or get with the name([$new_name]) method. Here, [] refer to an optional parameter.

Secondly, the attributes of each node are held in a hashref, getable and setable with the attributes([$hashref]) method. The returned hashref has these (key => value) pairs:

o name => $string

This is a copy of the name of the node. It's here because "process_tree()" changes the name of some nodes as it walks the tree.

o type => $string

This is the reftype() (from the module "Scalar::Util") of the value (see the value key, below), or one of various strings I use, and hence has values like:

o ARRAY

The value is an arrayref.

o BLESS

The value is blessed into a class, who name is in the value.

o CODE

The value is a coderef.

o HASH

The value is a hashref.

o REF

The value is presumably a generic reference. I could not see an explanation which I skimmed the output of 'perldoc perlref'.

o SCALAR

The value is a scalarref.

o VALUE

The value is just a literal value.

I did not use LITERAL because the 1-letter abbreviation 'L' clashes with the 1-letter abbreviation of 'LVALUE', which reftype() can return.

Other values returned by reftype() are not used by this module.

o uid => $integer

Each node in the tree has a unique integer identifier, counting from 1 up.

o use_value => $Boolean

Node values (see next point) can be undef, and this flag serves the following purpose:

o Zero

Do not use the value. It's undef, and set by the code, and thus not a real node's value.

o One

The node's value really is undef, or any other value. Use it in the output.

o value => $string

Finally, the actual value of the node.

Why are there so many levels in the output?

Or: Couldn't you cut some cases showing '{}' and '[]'?

Cutting them introduces other problems, especially when the input is a set of nested arrayrefs.

See scripts/array.pl, example 4 (hash key 4), for such a case.

Why do you decorate the output with e.g. [HASH 1] and not [H1]?

I feel the style [H1] used by Data::TreeDumper is unnecessarily cryptic.

I found a problem with the output of synopsis.pl!

It says:

        |--- B [ARRAY 9]
        |    |--- 1 = [] [ARRAY 10]

Why is there a '1 = []' in there?

Firstly, note that hash keys are returned in sorted order.

And, for hash keys, that integer counts them, so A would have gotten a 0, and C would get a 2, if they pointed to arrayrefs.

Why did you use Text::Truncate?

The major alternatives are String::Truncate and Text::Elide, or re-inventing the wheel.

The first module seems too complex, and the second truncates to whole words, which makes sense in some applications, but not for dumping raw data.

How would I go about sub-classing this module?

This matter is discussed in the notes for method "process_tree()".

See Also

Data::TreeDumper.

Machine-Readable Change Log

The file Changes was converted into Changelog.ini by Module::Metadata::Changes.

Version Numbers

Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions.

Repository

https://github.com/ronsavage/Data-RenderAsTree

Support

Email the author, or log a bug on RT:

https://rt.cpan.org/Public/Dist/Display.html?Name=Data::RenderAsTree.

Author

Data::RenderAsTree was written by Ron Savage <ron@savage.net.au> in 2015.

My homepage: http://savage.net.au/.

Copyright

Australian copyright (c) 2015, Ron Savage.

        All Programs of mine are 'OSI Certified Open Source Software';
        you can redistribute them and/or modify them under the terms of
        The Artistic License 2.0, a copy of which is available at:
        http://opensource.org/licenses/alphabetical.