File Coverage

blib/lib/Data/Dx.pm
Criterion Covered Total %
statement 88 146 60.2
branch 15 32 46.8
condition 12 25 48.0
subroutine 18 22 81.8
pod n/a
total 133 225 59.1


line stmt bran cond sub pod time code
1             package Data::Dx;
2              
3 3     3   72071 use 5.012;
  3         24  
4 3     3   1716 use utf8;
  3         43  
  3         14  
5 3     3   93 use warnings;
  3         9  
  3         150  
6              
7             our $VERSION = '0.000010';
8              
9 3     3   2630 use Keyword::Declare;
  3         380646  
  3         34  
10              
11             my %COLOUR = (
12             key => 'bold ansi136', # Soft orange
13             value => 'cyan',
14             punct => 'bold ansi245', # Mid-grey
15             comment => 'blue',
16             );
17              
18             my @OUTPUT;
19 3     3   1084 BEGIN { @OUTPUT = \*STDERR }
20              
21             sub _dx {
22 28     28   81 my ($expr) = @_;
23 3     3   33 use List::Util 'max';
  3         7  
  3         1009  
24              
25             # Flatten the expression to a single line...
26 28         208 $expr =~ s{\s+}{ }g;
27              
28             # Simple arrays and hashes need to be dumped by reference...
29 28 100       280 my $ref = $expr =~ /^[\@%][\w:]++$/ ? q{\\} : q{};
30              
31             # How much to indent...
32 28         618 my $indent = ' ' x (length($expr) + 3);
33              
34             # Handle unbalanced {...} in the expression...
35 28         160 my $str_expr = $expr;
36 28         78 $str_expr =~ s{ ( [\\\{\}] ) }{\\$1}xmsg;
37              
38             # Generate the source...
39 28         317 return qq{Data::Dx::_format_data(__LINE__, __FILE__, q{$str_expr}, q{$indent}, $ref $expr);};
40             }
41              
42              
43             sub import {
44 3     3   45 my (undef, $opt_ref) = @_;
45 3   100     29 my %opt = ( colour => -t *STDERR, %{$opt_ref//{}} );
  3         33  
46              
47             # Lexical colour control...
48             $^H{'Data::Dx no_colour'} = 1
49 3 50       30 if !$opt{colour};
50              
51             # Lexical output redirect...
52 3 100       14 if ($opt{to}) {
53 2         10 $^H{'Data::Dx output'} = @OUTPUT;
54 2         6 push @OUTPUT, $opt{to};
55             }
56 3         6  
57 0 50 50 14   0 keyword Dx (Expr $expr) { _dx($expr) }
  0         0  
  0         0  
  3         76  
  14         1202499  
  14         29  
  14         33  
  3         78  
58 0 50 50 14   0 keyword Dₓ (Expr $expr) { _dx($expr) }
  0         0  
  0         0  
  0         0  
  3         15  
  14         3020  
  3         44  
  14         1187724  
  14         30  
  14         39  
59 0         0  
  0         0  
  14         852  
  3         13  
  14         3041  
60 0         0 utf8->import();
  14         868  
  3         88  
61 3         24 }
  0         0  
  0         0  
  3         26  
  14         609  
  14         64  
62 3         23  
  0         0  
  0         0  
  3         125  
  3         20  
  14         555  
  14         79  
63 3     3   118977 sub unimport {
  3     0   101  
  0         0  
  0         0  
64 3 0 0 3   119349 keyword Dx (Expr $expr) { }
  0     0   0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
65 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  
66 0         0 }
  0         0  
  0         0  
  0         0  
  0         0  
67 0         0  
  0         0  
68 3         27 sub _color {
  0         0  
  0         0  
  0         0  
69 3         23 state $colorer = eval {
  0         0  
  0         0  
  0         0  
  0         0  
70 3 50   3   115130 require Win32::Console::ANSI if $^O eq 'MSWin32';
  0         0  
  2         10  
71 3     3   114971 require Term::ANSIColor;
  2         1263  
72             sub { return shift if ((caller 1)[10]//{})->{'Data::Dx no_colour'}
73 90 50 50 90   990 || ((caller 2)[10]//{})->{'Data::Dx no_colour'};
      50        
      33        
74 0         0 goto &Term::ANSIColor::colored;
75             }
76 0   50 0   0 } // sub { shift };
  90     90   135  
  2         16854  
77 90         142 $colorer->(@_);
78             }
79              
80             sub _format_data {
81             # Unpack leadings args...
82 28     28   2141 my $linenum = shift;
83 28         46 my $filename = shift;
84 28         41 my $expr = shift;
85 28         38 my $indent = shift;
86              
87             # Serialize any Contextual::Return::Value objects (which break dump())...
88 28         77 for my $arg (@_) {
89 34 50 100     133 if ((ref($arg)||q{}) =~ m{\A Contextual::Return}xms) {
90 0         0 require Contextual::Return;
91 0         0 Contextual::Return::FREEZE($arg);
92             }
93             }
94              
95             # Then repack data...
96 28 100       70 my $data = @_ > 1 ? [@_] : shift;
97              
98             # Lexical configurations...
99 28   50     116 my $hint = ((caller 0)[10] // {});
100              
101             # Dump the data...
102 28         54 my $dump;
103 28 100       53 if (!defined $data) {
104 6         13 $dump = _color('undef', $COLOUR{value});
105             }
106             else {
107 3     3   3120 use Data::Dump 'dump';
  3         13657  
  3         1309  
108 22         50 $dump = dump($data);
109              
110 22 50       5135 if (!$hint->{'Data::Dx no_colour'}) {
111 0         0 my $bw_dump = $dump;
112 0         0 $dump = q{};
113 0         0 $bw_dump
114             =~ s{ $PPR::GRAMMAR
115             (?: (? (?: (?&PerlString) | (?&PerlBareword) ) (?= \s*+ => ) )
116             | (? (?&PerlLiteral) | sub \s*+ { \s*+ ... \s*+ } )
117             | (? \S )
118             | (? . )
119             )
120             }{
121             $dump .= exists $+{key} ? _color( "$+{key}", $COLOUR{key} )
122             : exists $+{punct} ? _color( "$+{punct}", $COLOUR{punct} )
123             : exists $+{literal} ? _color( "$+{literal}", $COLOUR{value} )
124 0 0       0 : "$+{space}";
    0          
    0          
125 0         0 "";
126             }gxmseo;
127             }
128              
129 22         82 $dump =~ s{ (?! \A ) ^ }{$indent}gxms;
130             }
131              
132 28   50     70 my $output = $OUTPUT[$hint->{'Data::Dx output'} // 0];
133              
134 28         88 print {$output}
135             _color("#line $linenum $filename\n", $COLOUR{comment}),
136             _color($expr, $COLOUR{key}),
137 28         36 _color(' = ', $COLOUR{punct}),
138             "$dump\n\n";
139             }
140              
141              
142              
143              
144             1; # Magic true value required at end of module
145             __END__