#!/usr/bin/perl use strict; use warnings; # https://perlmonks.org/?node_id=998803 my $tree = [ [ [[[[["a", "b"], "c"], ["d", "e"]], [[["f", "g"], "h"], [["i", "j"], ["k", ["l", "m"]]]]], ["n", [[["o", "p"], "q"], ["r", "s"]]]], ["t", ["u", "v"]] ], [["w", ["x", "y"]], "z"] ]; $tree = [ [ [[[[["alpha", "bravo"], "charlie"], ["delta", "echo"]], [[["foxtrot", "golf"], "hotel"], [["indigo", "juliet"], ["kilo", ["lima", "mike"]]]]], ["november", [[["oscar", "papa"], "quebec"], ["romeo", "sierra"]]]], ["tango", ["uniform", "victor"]] ], [["whiskey", ["xray", "yankee"]], "zulu"] ]; print tree( $tree ); sub half { ' ' x ( length(shift) >> 1 ) } sub tree { my $tree = shift; ref $tree or return "$tree\n" =~ s/ +/ /gr; # horizontal word ref $tree or return $tree =~ s/./$&\n/gr; # vertical word my ($padl, $padr) = map $_->[0] =~ tr// /cr, # pads my ($left, $right) = map [ tree($_) =~ /.+/g ], @$tree; use List::AllUtils qw( pairwise ); local $_ = join '', pairwise # paste two blocks side by side { "@{[($a // $padl)]} @{[($b // $padr)]}\n" } @$left, @$right; return s{^(?=( *)(\S.*?) {2,}(\S.*?)( *\n))}{ my $span = ' ' x ($+[3] - $-[2] - 2 - length half($2) . half($3)); "$1 " . half($2) . $span =~ tr/ /_/r . half($3) . " $4" . $1 . half($2) . "/$span\\" . half($3) . $4 }er; } #### ___________________________________________________________________ / \ _______________________________________________________________________ ______________ / \ / \ ___________________________________________________________________ ___________ __________ zulu / \ / \ / \ _______________________________________ _______________________ tango _______ whiskey _____ / \ / \ / \ / \ _______________ _______________________ november _______________ uniform victor xray yankee / \ / \ / \ __________ _____ _________ ______________ _________ ______ / \ / \ / \ / \ / \ / \ ______ charlie delta echo ______ hotel ______ _______ _____ quebec romeo sierra / \ / \ / \ / \ / \ alpha bravo foxtrot golf indigo juliet kilo ____ oscar papa / \ lima mike #### _________________________ / \ ____________________________ ______ / \ / \ ___________________________ ___ ___ z / \ / \ / \ u ________________ _________ t __ w __ l / \ / \ a / \ h / \ u _____ _________ n _____ n u v i x y / \ / \ o / \ g n i s r a ___ __ ___ _____ v ___ __ o i c k a n / \ / \ / \ / \ e / \ / \ f t e y k __ c d e __ h __ ___ m __ q r s o o y e / \ h e c / \ o / \ / \ b / \ u o i r r e a b a l h f g t i j k __ e o p e m e m l r r t o o o e n u i / \ r s a b e r p a l a x l l d l l l m c p e o r h v i t f i i o i i a a c a a o e r g e m k r o o t a e t