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 34     34   265 use strict;
  34         72  
  34         1056  
3 34     34   170 use warnings;
  34         71  
  34         1065  
4 34     34   231 use Data::Printer::Filter;
  34         79  
  34         193  
5 34     34   190 use Data::Printer::Common;
  34         90  
  34         876  
6 34     34   212 use Scalar::Util ();
  34         83  
  34         27530  
7              
8             filter 'HASH' => \&parse;
9              
10              
11             sub parse {
12 80     80 0 175 my ($hash_ref, $ddp) = @_;
13 80         144 my $tied = '';
14 80 100 100     230 if ($ddp->show_tied and my $tie = ref tied %$hash_ref) {
15 1         5 $tied = " (tied to $tie)";
16             }
17 80 50 33     281 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         308 my @src_keys = keys %$hash_ref;
24 80 100       257 return $ddp->maybe_colorize('{}', 'brackets') . $tied unless @src_keys;
25 68 100       220 @src_keys = Data::Printer::Common::_nsort(@src_keys) if $ddp->sort_keys;
26              
27 68         145 my $len = 0;
28 68   100     205 my $align_keys = $ddp->multiline && $ddp->align_hash;
29              
30 68         239 my @i = Data::Printer::Common::_fetch_indexes_for(\@src_keys, 'hash', $ddp);
31              
32 68         125 my %processed_keys;
33             # first pass, preparing keys and getting largest key size:
34 68         151 foreach my $idx (@i) {
35 153 100       343 next if ref $idx;
36 146         261 my $raw_key = $src_keys[$idx];
37 146         360 my $colored_key = Data::Printer::Common::_process_string($ddp, $raw_key, 'hash');
38 146         333 my $new_key = Data::Printer::Common::_colorstrip($colored_key);
39              
40 146 100       294 if (_needs_quote($ddp, $raw_key, $new_key)) {
41 2         7 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         13 $new_key = $quote_char . $new_key . $quote_char;
48 2         9 $colored_key = $ddp->maybe_colorize($quote_char, 'quotes')
49             . $colored_key
50             . $ddp->maybe_colorize($quote_char, 'quotes')
51             ;
52             }
53 146         636 $processed_keys{$idx} = {
54             raw => $raw_key,
55             colored => $colored_key,
56             nocolor => $new_key,
57             };
58 146 100       384 if ($align_keys) {
59 92         155 my $l = length $new_key;
60 92 100       250 $len = $l if $l > $len;
61             }
62             }
63             # second pass, traversing and rendering:
64 68         234 $ddp->indent;
65 68         142 my $total_keys = scalar @i; # yes, counting messages so ',' appear in between.
66             #keys %processed_keys;
67 68         165 my $string = $ddp->maybe_colorize('{', 'brackets');
68 68         137 foreach my $idx (@i) {
69 153         227 $total_keys--;
70             # $idx is a message to display, not a real index
71 153 100       329 if (ref $idx) {
72 7         15 $string .= $ddp->newline . $$idx;
73 7         23 next;
74             }
75 146         280 my $key = $processed_keys{$idx};
76              
77 146         325 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     354 . '{' . $key->{nocolor} . '}'
83             );
84              
85 146         305 my $padding = $len - length($key->{nocolor});
86 146 100       359 $padding = 0 if $padding < 0;
87             $string .= $ddp->newline
88             . $key->{colored}
89 146         338 . (' ' 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         409 my $ref = ref $hash_ref->{$key->{raw}};
96 146 100 100     604 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         129 $string .= $ddp->parse( $hash_ref->{ $key->{raw} });
101             } else {
102 99         346 $string .= $ddp->parse(\$hash_ref->{ $key->{raw} });
103             }
104              
105 146 100 66     597 $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         383 $ddp->current_name($original_varname);
110             }
111 68         232 $ddp->outdent;
112 68         149 $string .= $ddp->newline . $ddp->maybe_colorize('}', 'brackets');
113 68         478 return $string . $tied;
114             };
115              
116             #######################################
117             ### Private auxiliary helpers below ###
118             #######################################
119              
120             sub _needs_quote {
121 146     146   302 my ($ddp, $raw_key, $new_key) = @_;
122 146         320 my $quote_keys = $ddp->quote_keys;
123 146         334 my $scalar_quotes = $ddp->scalar_quotes;
124 146 50 33     581 return 0 unless defined $quote_keys && defined $scalar_quotes;;
125 146 50 66     1016 if ($quote_keys eq 'auto'
      66        
126             && $raw_key eq $new_key
127             && $new_key !~ /\s|\r|\n|\t|\f/) {
128 144         457 return 0;
129             }
130 2         5 return 1;
131             }
132              
133             1;