File Coverage

blib/lib/Data/Dx.pm
Criterion Covered Total %
statement 88 146 60.2
branch 15 32 46.8
condition 12 26 46.1
subroutine 18 22 81.8
pod n/a
total 133 226 58.8


line stmt bran cond sub pod time code
1             package Data::Dx;
2              
3             =encoding utf8
4              
5             =cut
6              
7 5     5   511694 use 5.012;
  5         22  
8 5     5   3275 use utf8;
  5         1734  
  5         60  
9 5     5   235 use warnings;
  5         16  
  5         387  
10              
11             our $VERSION = '0.000011';
12              
13 5     5   5272 use Keyword::Declare;
  5         820606  
  5         61  
14              
15             my %COLOUR = (
16             key => 'bold ansi136', # Soft orange
17             value => 'cyan',
18             punct => 'bold ansi245', # Mid-grey
19             comment => 'blue',
20             );
21              
22             my @OUTPUT;
23 5     5   2049 BEGIN { @OUTPUT = \*STDERR }
24              
25             sub _dx {
26 42     42   129 my ($expr) = @_;
27 5     5   55 use List::Util 'max';
  5         11  
  5         2380  
28              
29             # Flatten the expression to a single line...
30 42         302 $expr =~ s{\s+}{ }g;
31              
32             # Simple arrays and hashes need to be dumped by reference...
33 42 100       429 my $ref = $expr =~ /^[\@%][\w:]++$/ ? q{\\} : q{};
34              
35             # How much to indent...
36 42         349 my $indent = ' ' x (length($expr) + 3);
37              
38             # Handle unbalanced {...} in the expression...
39 42         199 my $str_expr = $expr;
40 42         126 $str_expr =~ s{ ( [\\\{\}] ) }{\\$1}xmsg;
41              
42             # Generate the source...
43 42         445 return qq{Data::Dx::_format_data(__LINE__, __FILE__, q{$str_expr}, q{$indent}, $ref $expr);};
44             }
45              
46              
47             sub import {
48 4     4   71 my (undef, $opt_ref) = @_;
49 4   100     38 my %opt = ( colour => -t *STDERR, %{$opt_ref//{}} );
  4         40  
50              
51             # Lexical colour control...
52             $^H{'Data::Dx no_colour'} = 1
53 4 50       44 if !$opt{colour};
54              
55             # Lexical output redirect...
56 4 100       17 if ($opt{to}) {
57 3         13 $^H{'Data::Dx output'} = @OUTPUT;
58 3         10 push @OUTPUT, $opt{to};
59             }
60 4         54  
61 0 50 50 28   0 keyword Dx (Expr $expr) { _dx($expr) }
  0         0  
  0         0  
  4         79  
  28         3503160  
  28         56  
  28         73  
  4         147  
62 0 50 50 14   0 keyword Dₓ (Expr $expr) { _dx($expr) }
  0         0  
  0         0  
  0         0  
  4         22  
  28         6724  
  4         56  
  14         1629767  
  14         37  
  14         33  
63 0         0  
  0         0  
  28         1324  
  4         21  
  14         3443  
64 0         0 utf8->import();
  14         673  
  4         176  
65 5         41 }
  0         0  
  0         0  
  4         63  
  28         1157  
  28         154  
66 5         56  
  0         0  
  0         0  
  4         224  
  4         28  
  14         605  
  14         63  
67 5     5   364285 sub unimport {
  4     0   201  
  0         0  
  0         0  
68 5 0 0 5   368979 keyword Dx (Expr $expr) { }
  0     0   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
69 0 0 0 0   0 keyword Dₓ (Expr $expr) { }
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
70 0         0 }
  0         0  
  0         0  
  0         0  
  0         0  
71 0         0  
  0         0  
72 5         53 sub _color {
  0         0  
  0         0  
  0         0  
73 5         51 state $colorer = eval {
  0         0  
  0         0  
  0         0  
  0         0  
74 5 50   5   271859 require Win32::Console::ANSI if $^O eq 'MSWin32';
  0         0  
  3         19  
75 5     5   288655 require Term::ANSIColor;
  3         4464  
76             sub { return shift if ((caller 1)[10]//{})->{'Data::Dx no_colour'}
77 135 50 50 135   1647 || ((caller 2)[10]//{})->{'Data::Dx no_colour'};
      50        
      33        
78 0         0 goto &Term::ANSIColor::colored;
79             }
80 0   33 0   0 } // sub { shift };
  135     135   193  
  3         33680  
81 135         225 $colorer->(@_);
82             }
83              
84             sub _format_data {
85             # Unpack leadings args...
86 42     42   582905 my $linenum = shift;
87 42         82 my $filename = shift;
88 42         79 my $expr = shift;
89 42         76 my $indent = shift;
90              
91             # Serialize any Contextual::Return::Value objects (which break dump())...
92 42         89 for my $arg (@_) {
93 51 50 100     246 if ((ref($arg)||q{}) =~ m{\A Contextual::Return}xms) {
94 0         0 require Contextual::Return;
95 0         0 Contextual::Return::FREEZE($arg);
96             }
97             }
98              
99             # Then repack data...
100 42 100       126 my $data = @_ > 1 ? [@_] : shift;
101              
102             # Lexical configurations...
103 42   50     192 my $hint = ((caller 0)[10] // {});
104              
105             # Dump the data...
106 42         79 my $dump;
107 42 100       86 if (!defined $data) {
108 9         56 $dump = _color('undef', $COLOUR{value});
109             }
110             else {
111 5     5   6021 use Data::Dump 'dump';
  5         32782  
  5         3200  
112 33         113 $dump = dump($data);
113              
114 33 50       9472 if (!$hint->{'Data::Dx no_colour'}) {
115 0         0 my $bw_dump = $dump;
116 0         0 $dump = q{};
117 0         0 $bw_dump
118             =~ s{ $PPR::GRAMMAR
119             (?: (? (?: (?&PerlString) | (?&PerlBareword) ) (?= \s*+ => ) )
120             | (? (?&PerlLiteral) | sub \s*+ { \s*+ ... \s*+ } )
121             | (? \S )
122             | (? . )
123             )
124             }{
125             $dump .= exists $+{key} ? _color( "$+{key}", $COLOUR{key} )
126             : exists $+{punct} ? _color( "$+{punct}", $COLOUR{punct} )
127             : exists $+{literal} ? _color( "$+{literal}", $COLOUR{value} )
128 0 0       0 : "$+{space}";
    0          
    0          
129 0         0 "";
130             }gxmseo;
131             }
132              
133 33         174 $dump =~ s{ (?! \A ) ^ }{$indent}gxms;
134             }
135              
136 42   50     132 my $output = $OUTPUT[$hint->{'Data::Dx output'} // 0];
137              
138 42         159 print {$output}
139             _color("#line $linenum $filename\n", $COLOUR{comment}),
140             _color($expr, $COLOUR{key}),
141 42         63 _color(' = ', $COLOUR{punct}),
142             "$dump\n\n";
143             }
144              
145              
146              
147              
148             1; # Magic true value required at end of module
149             __END__