File Coverage

blib/lib/Data/Printer/Filter/HASH.pm
Criterion Covered Total %
statement 72 74 97.3
branch 30 34 88.2
condition 22 30 73.3
subroutine 7 7 100.0
pod 0 1 0.0
total 131 146 89.7


line stmt bran cond sub pod time code
1             package Data::Printer::Filter::HASH;
2 32     32   189 use strict;
  32         59  
  32         808  
3 32     32   135 use warnings;
  32         54  
  32         753  
4 32     32   168 use Data::Printer::Filter;
  32         65  
  32         183  
5 32     32   149 use Data::Printer::Common;
  32         60  
  32         752  
6 32     32   150 use Scalar::Util ();
  32         57  
  32         22148  
7              
8             filter 'HASH' => \&parse;
9              
10              
11             sub parse {
12 80     80 0 152 my ($hash_ref, $ddp) = @_;
13 80         118 my $tied = '';
14 80 100 100     198 if ($ddp->show_tied and my $tie = ref tied %$hash_ref) {
15 1         3 $tied = " (tied to $tie)";
16             }
17 80 50 33     213 return $ddp->maybe_colorize('{', 'brackets')
18             . ' ' . $ddp->maybe_colorize('...', 'hash')
19             . ' ' . $ddp->maybe_colorize('}', 'brackets')
20             . $tied
21             if $ddp->max_depth && $ddp->current_depth >= $ddp->max_depth;
22              
23 80         254 my @src_keys = keys %$hash_ref;
24 80 100       232 return $ddp->maybe_colorize('{}', 'brackets') . $tied unless @src_keys;
25 68 100       187 @src_keys = Data::Printer::Common::_nsort(@src_keys) if $ddp->sort_keys;
26              
27 68         131 my $len = 0;
28 68   100     211 my $align_keys = $ddp->multiline && $ddp->align_hash;
29              
30 68         244 my @i = Data::Printer::Common::_fetch_indexes_for(\@src_keys, 'hash', $ddp);
31              
32 68         128 my %processed_keys;
33             # first pass, preparing keys and getting largest key size:
34 68         124 foreach my $idx (@i) {
35 153 100       302 next if ref $idx;
36 146         279 my $raw_key = $src_keys[$idx];
37 146         313 my $colored_key = Data::Printer::Common::_process_string($ddp, $raw_key, 'hash');
38 146         287 my $new_key = Data::Printer::Common::_colorstrip($colored_key);
39              
40 146 100       269 if (_needs_quote($ddp, $raw_key, $new_key)) {
41 2         5 my $quote_char = $ddp->scalar_quotes;
42             # foo'bar ==> 'foo\'bar'
43 2 50       8 if (index($new_key, $quote_char) >= 0) {
44 0         0 $new_key =~ s{$quote_char}{\\$quote_char}g;
45 0         0 $colored_key =~ s{$quote_char}{\\$quote_char}g;
46             }
47 2         5 $new_key = $quote_char . $new_key . $quote_char;
48 2         6 $colored_key = $ddp->maybe_colorize($quote_char, 'quotes')
49             . $colored_key
50             . $ddp->maybe_colorize($quote_char, 'quotes')
51             ;
52             }
53 146         609 $processed_keys{$idx} = {
54             raw => $raw_key,
55             colored => $colored_key,
56             nocolor => $new_key,
57             };
58 146 100       326 if ($align_keys) {
59 92         122 my $l = length $new_key;
60 92 100       224 $len = $l if $l > $len;
61             }
62             }
63             # second pass, traversing and rendering:
64 68         210 $ddp->indent;
65 68         137 my $total_keys = scalar @i; # yes, counting messages so ',' appear in between.
66             #keys %processed_keys;
67 68         170 my $string = $ddp->maybe_colorize('{', 'brackets');
68 68         130 foreach my $idx (@i) {
69 153         202 $total_keys--;
70             # $idx is a message to display, not a real index
71 153 100       276 if (ref $idx) {
72 7         14 $string .= $ddp->newline . $$idx;
73 7         16 next;
74             }
75 146         213 my $key = $processed_keys{$idx};
76              
77 146         314 my $original_varname = $ddp->current_name;
78             # update 'var' to 'var{key}':
79             $ddp->current_name(
80             $original_varname
81             . ($ddp->arrows eq 'all' || ($ddp->arrows eq 'first' && $ddp->current_depth == 1) ? '->' : '')
82 146 100 66     312 . '{' . $key->{nocolor} . '}'
83             );
84              
85 146         285 my $padding = $len - length($key->{nocolor});
86 146 100       280 $padding = 0 if $padding < 0;
87             $string .= $ddp->newline
88             . $key->{colored}
89 146         305 . (' ' x $padding)
90             . $ddp->maybe_colorize($ddp->hash_separator, 'separator')
91             ;
92              
93             # scalar references should be re-referenced to gain
94             # a '\' in front of them.
95 146         332 my $ref = ref $hash_ref->{$key->{raw}};
96 146 100 100     541 if ( $ref && $ref eq 'SCALAR' ) {
    100 100        
97 2         8 $string .= $ddp->parse(\$hash_ref->{ $key->{raw} });
98             }
99             elsif ( $ref && $ref ne 'REF' ) {
100 45         127 $string .= $ddp->parse( $hash_ref->{ $key->{raw} });
101             } else {
102 99         323 $string .= $ddp->parse(\$hash_ref->{ $key->{raw} });
103             }
104              
105 146 100 66     511 $string .= $ddp->maybe_colorize($ddp->separator, 'separator')
106             if $total_keys > 0 || $ddp->end_separator;
107              
108             # restore var name back to "var"
109 146         313 $ddp->current_name($original_varname);
110             }
111 68         191 $ddp->outdent;
112 68         168 $string .= $ddp->newline . $ddp->maybe_colorize('}', 'brackets');
113 68         406 return $string . $tied;
114             };
115              
116             #######################################
117             ### Private auxiliary helpers below ###
118             #######################################
119              
120             sub _needs_quote {
121 146     146   253 my ($ddp, $raw_key, $new_key) = @_;
122 146         311 my $quote_keys = $ddp->quote_keys;
123 146         289 my $scalar_quotes = $ddp->scalar_quotes;
124 146 50 33     782 return 0 unless defined $quote_keys && defined $scalar_quotes;;
125 146 50 66     925 if ($quote_keys eq 'auto'
      66        
126             && $raw_key eq $new_key
127             && $new_key !~ /\s|\r|\n|\t|\f/) {
128 144         346 return 0;
129             }
130 2         13 return 1;
131             }
132              
133             1;