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 35     35   240 use strict;
  35         93  
  35         1334  
3 35     35   187 use warnings;
  35         59  
  35         1620  
4 35     35   171 use Data::Printer::Filter;
  35         58  
  35         320  
5 35     35   2317 use Data::Printer::Common;
  35         94  
  35         4825  
6 35     35   232 use Scalar::Util ();
  35         2288  
  35         42039  
7              
8             filter 'HASH' => \&parse;
9              
10              
11             sub parse {
12 85     85 0 228 my ($hash_ref, $ddp) = @_;
13 85         168 my $tied = '';
14 85 100 100     280 if ($ddp->show_tied and my $tie = ref tied %$hash_ref) {
15 2         4 $tied = " (tied to $tie)";
16             }
17 85 50 33     302 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 85         356 my @src_keys = keys %$hash_ref;
24 85 100       324 return $ddp->maybe_colorize('{}', 'brackets') . $tied unless @src_keys;
25 71 100       294 @src_keys = Data::Printer::Common::_nsort(@src_keys) if $ddp->sort_keys;
26              
27 71         163 my $len = 0;
28 71   100     275 my $align_keys = $ddp->multiline && $ddp->align_hash;
29              
30 71         337 my @i = Data::Printer::Common::_fetch_indexes_for(\@src_keys, 'hash', $ddp);
31              
32 71         172 my %processed_keys;
33             # first pass, preparing keys and getting largest key size:
34 71         170 foreach my $idx (@i) {
35 160 100       468 next if ref $idx;
36 153         366 my $raw_key = $src_keys[$idx];
37 153         444 my $colored_key = Data::Printer::Common::_process_string($ddp, $raw_key, 'hash');
38 153         387 my $new_key = Data::Printer::Common::_colorstrip($colored_key);
39              
40 153 100       420 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       7 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         7 $new_key = $quote_char . $new_key . $quote_char;
48 2         7 $colored_key = $ddp->maybe_colorize($quote_char, 'quotes')
49             . $colored_key
50             . $ddp->maybe_colorize($quote_char, 'quotes')
51             ;
52             }
53 153         949 $processed_keys{$idx} = {
54             raw => $raw_key,
55             colored => $colored_key,
56             nocolor => $new_key,
57             };
58 153 100       493 if ($align_keys) {
59 99         203 my $l = length $new_key;
60 99 100       320 $len = $l if $l > $len;
61             }
62             }
63             # second pass, traversing and rendering:
64 71         263 $ddp->indent;
65 71         121 my $total_keys = scalar @i; # yes, counting messages so ',' appear in between.
66             #keys %processed_keys;
67 71         250 my $string = $ddp->maybe_colorize('{', 'brackets');
68 71         168 foreach my $idx (@i) {
69 160         271 $total_keys--;
70             # $idx is a message to display, not a real index
71 160 100       444 if (ref $idx) {
72 7         26 $string .= $ddp->newline . $$idx;
73 7         17 next;
74             }
75 153         354 my $key = $processed_keys{$idx};
76              
77 153         413 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 153 100 66     456 . '{' . $key->{nocolor} . '}'
83             );
84              
85 153         397 my $padding = $len - length($key->{nocolor});
86 153 100       386 $padding = 0 if $padding < 0;
87             $string .= $ddp->newline
88             . $key->{colored}
89 153         403 . (' ' 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 153         503 my $ref = ref $hash_ref->{$key->{raw}};
96 153 100 100     808 if ( $ref && $ref eq 'SCALAR' ) {
    100 100        
97 2         12 $string .= $ddp->parse(\$hash_ref->{ $key->{raw} }, tied_parent => !!$tied);
98             }
99             elsif ( $ref && $ref ne 'REF' ) {
100 45         337 $string .= $ddp->parse( $hash_ref->{ $key->{raw} }, tied_parent => !!$tied);
101             } else {
102 106         541 $string .= $ddp->parse(\$hash_ref->{ $key->{raw} }, tied_parent => !!$tied);
103             }
104              
105 153 100 66     1170 $string .= $ddp->maybe_colorize($ddp->separator, 'separator')
106             if $total_keys > 0 || $ddp->end_separator;
107              
108             # restore var name back to "var"
109 153         435 $ddp->current_name($original_varname);
110             }
111 71         307 $ddp->outdent;
112 71         214 $string .= $ddp->newline . $ddp->maybe_colorize('}', 'brackets');
113 71         671 return $string . $tied;
114             };
115              
116             #######################################
117             ### Private auxiliary helpers below ###
118             #######################################
119              
120             sub _needs_quote {
121 153     153   449 my ($ddp, $raw_key, $new_key) = @_;
122 153         434 my $quote_keys = $ddp->quote_keys;
123 153         445 my $scalar_quotes = $ddp->scalar_quotes;
124 153 50 33     728 return 0 unless defined $quote_keys && defined $scalar_quotes;;
125 153 50 66     1420 if ($quote_keys eq 'auto'
      66        
126             && $raw_key eq $new_key
127             && $new_key !~ /\s|\r|\n|\t|\f/) {
128 151         559 return 0;
129             }
130 2         9 return 1;
131             }
132              
133             1;