NAME
Data::TreeDraw - Graphical representation of nested data structures.
VERSION
This document describes Data::TreeDraw version 0.0.1
DESCRIPTION
While there are a number of great programs out there for Dumping and visualising heavily nested data structures these can often be over-whelming and hard to read. Additionally, often in order to access a particular data entry you often have to back-trace over a Dumped structure to find the specific code appropriate to dereference that particular value. This module aims to address these issues and several others by providing number of different features with a very simple interface that is particularly aimed at helping to visualise data-rich heavily-nested structures - see OVERVIEW.
This module exports a single sub-routine call draw
. Simply call this routine with the data structure you wish to print along with a HASH reference of any options you wish to pass - see OPTIONS and OVERVIEW.
This module was written by me, for me and so internally may be a bit esoteric. If there is significant interest I will improve and expand it.
SYNOPSIS
Create suitable structure.
# Create a Code Reference.
my $c_ref = sub { print q{blah}; $_->[0] };
# Create a heavily nested set of references.
my $r_ref = \\\\\[q{pink},321];
# Create an object of type HASH;
my $pca->{g} = 4;
bless $pca, q{Some::Class};
# Create a GLOB.
*f = *g;
# Create a nested data structure with various typed of nested data e.g. defined and undefined SCALAR, ARRAY, HASH and REFs
my $a = [ q{hi}, q{there}, [ q{i}, q{am} ], 1, { r => \\q{} }, { r => { y => 3 }, t => [ { r => *g } ] }, $c_ref, *f, $r_ref, q{nine}, [ [ 3,q{----3-----}, 3 ],
[3, 3, 3, 3, ], [ 3, 3, 3, ] ], 1, \\\{ r => \[] }, \\\q{foo}, { g => 2, t => 2, y => q{------2-------}, r => [3], step => { the => q{blah} }, o => [ [4]
] }, [ [ [q{--4--}]] , [ [ 4, 4, q{-4-}, q{--4--} ] ], 2, [3] ], \\\q{}, 1, [ [3 , 3], 2, $pca] , 1, { g => [ 3, 3, q{blah}, 3, 3, 3 ] } ,[ [ 3 ] ], $a, undef ];
# Create cyclic references.
my $b = [$a];
my $c = [$b];
$a->[2][3] = $c;
$a->[2][2] = $a;
# Make our nested data structure an object
bless $a, q{Other::Class};
Use module and call draw
routine on structure.
use Data::TreeDraw;
draw($a);
Prints:
Method called from Package 'main' on Blessed Object of type 'ARRAY' and Class 'Other::Class'.
ARRAY REFERENCE (0)
|
|__SCALAR = 'hi' (1) [ '->[0]' ]
|
|__SCALAR = 'there' (1) [ '->[1]' ]
|
|__ARRAY REFERENCE (1) [ '->[2]' ]
| |
| |__SCALAR = 'i' (2) [ '->[2][0]' ]
| |
| |__SCALAR = 'am' (2) [ '->[2][1]' ]
| |
| |__CYCLIC REFERENCE (2) [ '->[2][2]' ]
| |
| |__ARRAY REFERENCE (2) [ '->[2][3]' ]
| |
| |__ARRAY REFERENCE (3) [ '->[2][3][0]' ]
| |
| |__CYCLIC REFERENCE (4) [ '->[2][3][0][0]' ]
|
|__SCALAR = '1' (1) [ '->[3]' ]
|
|__HASH REFERENCE (1) [ '->[4]' ]
| |
| |__'r'=>REFERENCE-TO-REFERENCE (2)
| |
| |__SCALAR REFERENCE (3)
| |
| |__SCALAR = '' [EMPTY STRING] (4)
|
|__HASH REFERENCE (1) [ '->[5]' ]
| |
| |__'r'=>HASH REFERENCE (2) [ '->[5]{r}' ]
| | |
| | |__'y'=>SCALAR = '3' (3) [ '->[5]{r}{y}' ]
| |
| |__'t'=>ARRAY REFERENCE (2) [ '->[5]{t}' ]
| |
| |__HASH REFERENCE (3) [ '->[5]{t}[0]' ]
| |
| |__'r'=>GLOB = '*main::g' (4) [ '->[5]{t}[0]{r}' ]
|
etc.
OVERVIEW
Tree Structure
All structures are displayed as a "clear" Tree-structure branching from a single root.
ARRAY REFERENCE (0)
|
|__SCALAR = 'hi' (1) [ '->[0]' ]
|
|__SCALAR = 'there' (1) [ '->[1]' ]
|
|__ARRAY REFERENCE (1) [ '->[2]' ]
| |
| |__SCALAR = 'i' (2) [ '->[2][0]' ]
| |
| |__SCALAR = 'am' (2) [ '->[2][1]' ]
| |
| |__CYCLIC REFERENCE (2) [ '->[2][2]' ]
| |
| |__ARRAY REFERENCE (2) [ '->[2][3]' ]
| |
| |__ARRAY REFERENCE (3) [ '->[2][3][0]' ]
etc.
Notation
The notation
option (defaults to on - with "1") results in the printing along side (in square-brackets) the specific REFERENCE or SCALAR value of the particular arrow-notation required to access/dereference that REFERENCE or SCALAR value e.g. "[ '->[4]{hash_key}[12]' ]" next to an ARRAY reference means that to dereference that particular value within the passed structure simply append "->[4]{hash_key}[12] " to the originally passed reference.
e.g. To access the above ARRAY reference printed as: "ARRAY REFERENCE (2) [ '->[2][3][0]' ]"
Simply use: $original_data_passed->[2][3][0];
Spacing
For a more compressed version of the print disable the spaces
options by setting it to "0" (this option is enabled by default). The above Tree is printed as:
ARRAY REFERENCE (0)
|__SCALAR = 'hi' (1) [ '->[0]' ]
|__SCALAR = 'there' (1) [ '->[1]' ]
|__ARRAY REFERENCE (1) [ '->[2]' ]
| |__SCALAR = 'i' (2) [ '->[2][0]' ]
| |__SCALAR = 'am' (2) [ '->[2][1]' ]
| |__CYCLIC REFERENCE (2) [ '->[2][2]' ]
| |__ARRAY REFERENCE (2) [ '->[2][3]' ]
| |__ARRAY REFERENCE (3) [ '->[2][3][0]' ]
| |__CYCLIC REFERENCE (4) [ '->[2][3][0][0]' ]
etc.
Indentation Level
The nesting/indentation level of ALL structures is printed along-side of the REFERENCE/SCALAR value in parenthesis:
e.g. SCALAR = 'some_value' (nesting_level/e.g.4)
EMPTY STRINGS
Any SCALAR value containing an empty string is printed as that e.g. '', but to ease distinguishing it from ' ' it additionally prints [EMPTY STRING] along-side.
e.g. SCALAR = '' [EMPTY STRING]
Long Arrays
With data-rich structures arrays may often have many elements. In such cases printing each SCALAR value within the array on a separate line makes reading the structure difficult:
ARRAY REFERENCE (2) [ '->[20]{g}' ]
|
|__SCALAR = 'val1' (3) [ '->[20]{g}[0]' ]
|
|__SCALAR = 'val2' (3) [ '->[20]{g}[1]' ]
|
|__SCALAR = 'val3' (3) [ '->[20]{g}[2]' ]
|
|__SCALAR = 'val4' (3) [ '->[20]{g}[3]' ]
etc.
The long_array
option (defaults to off - "0") over-rides this behaviour and instead arrays consisting of "just" SCALAR values are printed on a single-line. With this setting relatively short arrays are printed in full on a single line along with their length:
ARRAY REFERENCE (3) ---LONG_LIST_OF_SCALARS--- [ length = 4 ]: val1, val2, val3, val4 [ '->[20]{g}'
Longer arrays are printed in a similar fashion except that only the length and first 3 elements are printed (just to indicate the nature of the values stored by the array).
ARRAY REFERENCE (2) ---LONG_LIST_OF_SCALARS--- [ length = 4 ] e.g. 0..2: val1, val2, val3 [ '->[20]{g}' ]
You can switch the length of array that triggers these two behaviours using the array_length
option (defaults to 3). See OPTIONS for further info.
Lists-of-Lists.
In cases of Lists-of-lists the readability may suffer further - especially as these structures often correspond to 2-dim tables. Thus in cases of ARRAYS consisting uniquely of ARRAYS of SCALARS:
|__ARRAY REFERENCE (2) [ '->[10][0]' ]
| |
| |__SCALAR = '2' (3) [ '->[10][0][0]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][0][1]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][0][2]' ]
|
|__ARRAY REFERENCE (2) [ '->[10][1]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][1][0]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][1][1]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][1][2]' ]
| |
| |__SCALAR = '3' (3) [ '->[10][1][3]' ]
|
|__ARRAY REFERENCE (2) [ '->[10][2]' ]
|
|__SCALAR = '3' (3) [ '->[10][2][0]' ]
|
|__SCALAR = '3' (3) [ '->[10][2][1]' ]
|
|__SCALAR = '3' (3) [ '->[10][2][2]' ]
The lol
option when set to "1" will replace these structures with (this option defaults to "0"):
ARRAY REFERENCE (1) ---LIST OF LISTS--- [ rows = 3 and longest nested list length = 4 ] [ '->[10]' ]
You may be interested in the particular values within these structures. In this case lol
set to "2" creates a temporary break in the tree-structure with a table of the values and their access values and an extension of their root:
ARRAY REFERENCE (1) ---LIST OF LISTS--- [ rows = 3 and longest nested list length = 4 ] [ '->[10]' ]
|
---
.----------+-------+-------+-------+-------.
| | ..[0] | ..[1] | ..[2] | ..[3] |
+----------+-------+-------+-------+-------+
| ..[0].. | '3' | '3' | '3' | --- |
| ..[1].. | '3' | '3' | '3' | '3' |
| ..[2].. | '3' | '3' | '3' | --- |
'----------+-------+-------+-------+-------'
---
|
This option may be used with the long_arrays
option in which case the lol
option takes precedence and above structure would be printed as above instead of:
|__ARRAY REFERENCE (1) [ '->[10]' ]
|
|__ARRAY REFERENCE (2) ---LONG_LIST_OF_SCALARS--- [ length = 3 ]: 3, 3, 3 [ '->[10][0]' ]
|
|__ARRAY REFERENCE (2) ---LONG_LIST_OF_SCALARS--- [ length = 4 ]: 3, 3, 3, 3 [ '->[10][1]' ]
|
|__ARRAY REFERENCE (2) ---LONG_LIST_OF_SCALARS--- [ length = 3 ]: 3, 3, 3 [ '->[10][2]' ]
HASH keys.
As HASHES are simply unordered LISTs using a look up key HASH references are displayed just ARRAY references only with the hash key appended e.g.
|__HASH REFERENCE (1) [ '->[20]' ]
|
|__'hash_key'=>ARRAY REFERENCE (2) [ '->[20]{g}' ]
|
|__SCALAR = '3' (3) [ '->[20]{g}[0]' ]
HASH key lookup
You may be interested in just the values of a particular HASH entry. In this case using the hash_key
option you can start Tree printing from that particular HASH key. See OPTIONS for usage.
HASH key 'given_key' found and indentation level '5':
|__'given_key'=>REFERENCE-TO-REFERENCE (5)
| |
|__UNDEFINED ARRAY REFERENCE (6)
etc.
HASH key 'given_key' found 2 times in nested data structure.
Minimum printing depth
You may not be interested in values near the root of the structure. In which case you can set the min_depth
option (defaults to 0).
Starting print at depth 2.
| |__SCALAR = 'i' (2) [ '->[2][0]' ]
| |
| |__SCALAR = 'am' (2) [ '->[2][1]' ]
| |
| |__CYCLIC REFERENCE (2) [ '->[2][2]' ]
| |
| |__ARRAY REFERENCE (2) [ '->[2][3]' ]
| |
| |__ARRAY REFERENCE (3) [ '->[2][3][0]' ]
| |
| |__CYCLIC REFERENCE (4) [ '->[2][3][0][0]' ]
|
Indent decrementing to '1' below min_depth level of '2'
| |__'r'=>REFERENCE-TO-REFERENCE (2)
| |
| |__SCALAR REFERENCE (3)
| |
| |__SCALAR = '' [EMPTY STRING] (4)
|
Maximum printing depth
If you do not wish to view deeply nested structures you can set the max_depth
option (defaults to 10):
ARRAY REFERENCE (0)
|
|__SCALAR = 'hi' (1) [ '->[0]' ]
|
|__SCALAR = 'there' (1) [ '->[1]' ]
|
|__ARRAY REFERENCE (1) [ '->[2]' ]
| |
| |__SCALAR EXCEEDS MAX NESTING DEPTH (2)
| |
| |__SCALAR EXCEEDS MAX NESTING DEPTH (2)
| |
etc.
Object recursion.
In cases where an object reference is pointed within the structure its class will be printed:
|__BLESSED OBJECT BELONGING TO CLASS: Statistics::PCA (2) [ '->[18][2]' ]
However, you may be wish to continue the recursion into the object. This can be done by setting the unwrap_object
option to "1" (defaults to "0"):
|
|__BLESSED OBJECT BELONGING TO CLASS: Statistics::PCA (3) ---RECURSING-INTO-OBJECT---
|
|
|__HASH REFERENCE (3)
|
etc.
Note: while the structure is indented further - the actual indentation level in parenthesis does not change - this is just aids the identification of the type of data-type of the object within the structure. Also as yet, the notation
option is not supported with the object_unwrap
option.
Method introspection for objects
You may additionally wish to introspect either the root structure or lower-level objects for their methods. This module can use the introspection facility of Class::MOP and print a formated table by setting the object_methods
option to "1" (as with lol
this temporarily breaks the tree structure):
|__BLESSED OBJECT BELONGING TO CLASS: Statistics::PCA (3) ---RECURSING-INTO-OBJECT---
|
---
.-----------------------------------------------------.
| Methods |
+-----------------------------------------------------+
| Statistics::PCA::_deep_copy_references |
| Statistics::PCA::print_eigenvectors |
| Statistics::PCA::_calculate_eigens_cephes |
| ... |
'-----------------------------------------------------'
---
|
|__HASH REFERENCE (3)
|
etc.
OPTIONS
All options are passed by hash reference:
draw($data, {max_depth => 3, unwrap_objects => 1, object_methods => 1} );
array_limit
Name: array_limit
Description: Used in conjunction with long_array option. Specifies the cutoff point for printing an entire array of SCALARS and just first few example elements.
Usage: draw($data, {array_limit => 6});
Values: 3-10.
Default: 5.
hash_key
Name: hash_key
Description: Allows printing of just those elements within a HASH of interest within a structure.
Usage: draw($data, {hash_key => q{a_key_name});
Values: String.
Default: undef.
lol
Name: lol
Description: This option suppresses long-outputs given from Lists-of-Lists - see OVERVIEW.
Usage: draw($data, {lol => 2});
Values: 0, 1, 2.
Default: 0.
long_array
Name: long_array
Description: This option suppresses long-output from long arrays of SCALARS - see OVERVIEW.
Usage: draw($data, {long_array => 2});
Values: 0, 1.
Default: 0.
max_depth
Name: max_depth
Description: Specifies the maximum indentation/nesting depth to proceed to - see OVERVIEW.
Usage: draw($data, {max_depth => 6});
Values: 0-10.
Default: 10.
max_methods
Name: max_methods
Description: Used in conjunction with the object_methods option. Specifies the maximum number of object methods to print.
Usage: draw($data, {max_methods => 6});
Values: 1-100.
Default: 50.
min_depth
Name: min_depth
Description: Specifies the minimum indentation depth to start printing at - see OVERVIEW.
Usage: draw($data, {array_limit => 6});
Values: 0-9.
Default: 0.
notation
Name: notation
Description: This option enables or disables the automatic arrow "->" notation printing specifying how to dereference a particular entity within the structure.
Usage: draw($data, {notation => 0});
Values: 0, 1.
Default: 1.
object_methods
Name: object_methods
Description: Turns on object method introspection using the Class::MOP module.
Usage: draw($data, {object_methods => 1});
Values: 0, 1.
Default: 0.
spaces
Name: spaces
Description: This option enables and disables the printing of extra "branch" lines in the Tree structure for easier visualisation.
Usage: draw($data, {spaces => 0});
Values: 0, 1.
Default: 1.
unwrap_objects
Name: unwrap_objects
Description: This option causes the program to recurse into objects that fall within a data structure.
Usage: draw($data, {unwrap_objects => 1});
Values: 0, 1.
Default: 1.
borders
Name: borders - This option is not yet fully implemented.
Description:
Usage: Disabled atm as not yet fully implemented.
Values: "0", "1".
Default: "0" (off).
DEPENDENCIES
Scalar::Util => "1.22", Class::MOP => "0.95", Text::SimpleTable => "2.0", Carp => "1.08",
AUTHOR
Daniel S. T. Hughes <dsth@cantab.net>
SEE ASLO
Data::Dumper, Data::TreeDumper.
LICENCE AND COPYRIGHT
Copyright (c) 2009, Daniel S. T. Hughes <dsth@cantab.net>
. All rights reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.
DISCLAIMER OF WARRANTY
because this software is licensed free of charge, there is no warranty for the software, to the extent permitted by applicable law. Except when otherwise stated in writing the copyright holders and/or other parties provide the software "as is" without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the software is with you. Should the software prove defective, you assume the cost of all necessary servicing, repair, or correction.
In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party who may modify and/or redistribute the software as permitted by the above licence, be liable to you for damages, including any general, special, incidental, or consequential damages arising out of the use or inability to use the software (including but not limited to loss of data or data being rendered inaccurate or losses sustained by you or third parties or a failure of the software to operate with any other software), even if such holder or other party has been advised of the possibility of such damages.