File Coverage

blib/lib/Data/Show.pm
Criterion Covered Total %
statement 48 50 96.0
branch 7 10 70.0
condition 4 7 57.1
subroutine 8 8 100.0
pod 1 1 100.0
total 68 76 89.4


line stmt bran cond sub pod time code
1             package Data::Show;
2              
3 2     2   24791 use warnings;
  2         4  
  2         60  
4 2     2   9 use strict;
  2         5  
  2         109  
5 2     2   1833 use Data::Dump 'dump';
  2         19241  
  2         164  
6 2     2   66 use 5.010;
  2         7  
  2         117  
7              
8             our $VERSION = '0.002002';
9              
10             # Unconditionally export show()...
11             sub import {
12 2     2   10 no strict 'refs';
  2         5  
  2         3860  
13 2     2   26 *{caller().'::show'} = \&show;
  2         76  
14             }
15              
16              
17             # Useful patterns...
18              
19             my $IDENT = qr{
20             [^\W\d]\w* (?: :: [^\W\d]\w* )* | [_\W]
21             }xms;
22              
23 2     2   17 use re 'eval';
  2         4  
  2         1403  
24             my $CODE = qr{
25             (?&CODE_FRAGMENT)
26              
27             (?(DEFINE)
28             (?
29             (?: (?"ED)
30             | \b (?: q[qxr]?+ | [msy] | tr ) \s* (?&DELIMITED)
31             | (?&NESTED)
32             | [%\$\@] (?: (?&BRACE_DELIMS) | $IDENT) (?&NESTED)?
33             | [^][{}()"'`;]
34             )++
35             )
36              
37             (?
38             (?: (?"ED)
39             | \b (?: q[qxr]?+ | [msy] | tr ) \s* (?&DELIMITED)
40             | (?&NESTED)
41             | [^][{}()"'`]
42             )++
43             )
44              
45             (?
46             " [^\\"]++ (?: \\. [^\\"]++ )* "
47             | ' [^\\']++ (?: \\. [^\\']++ )* '
48             | ` [^\\`]++ (?: \\. [^\\`]++ )* `
49             | / [^\\/]++ (?: \\. [^\\/]++ )* /
50             | \? [^\\?]++ (?: \\. [^\\?]++ )* \?
51             )
52              
53             (?
54             (?&BRACE_DELIMS)
55             | (?&PAREN_DELIMS)
56             | (?&ANGLE_DELIMS)
57             | (?&SQUARE_DELIMS)
58             | \s++ (?\w) (?:\\.|(?!\g{DELIM_W}).)*+ \g{DELIM_W}
59             | (?[^\w\s]) (?:\\.|(?!\g{DELIM_S}).)*+ \g{DELIM_S}
60             )
61              
62             (?
63             \( (?&NESTED_CODE_FRAGMENT) \)
64             | \[ (?&NESTED_CODE_FRAGMENT) \]
65             | \{ (?&NESTED_CODE_FRAGMENT) \}
66             | \< (?&NESTED_CODE_FRAGMENT) \>
67             )
68              
69             (? \{ (?: [^{}] | \\. | (?&BRACE_DELIMS) )*+ \} )
70             (? \( (?: [^()] | \\. | (?&PAREN_DELIMS) )*+ \) )
71             (? \< (?: [^<>] | \\. | (?&ANGLE_DELIMS) )*+ \> )
72             (? \[ (?: [^][] | \\. | (?&SQUARE_DELIMS) )*+ \] )
73             )
74             }xms;
75              
76              
77             # Configuration for layout of representation...
78             my $DEFAULT_INDENT = 4;
79             my $MAX_WIDTH = 72;
80             my $TITLE_POS = 6;
81              
82             # Be a ninja...
83             our @CARP_NOT;
84              
85             # The whole point of the module...
86             sub show {
87              
88             # Determine context...
89 13     13 1 1500 my (undef, $file, $line) = caller();
90              
91             # Extract description of arglist from context...
92 13         20 my $desc;
93 13 50       445 if (open my $fh, '<', $file) {
94 13   50     33 for (1..$line-1) { readline($fh) // last }
  264         630  
95 13         19 $desc = do { local $/; readline $fh; };
  13         35  
  13         183  
96             }
97              
98             # Trim filename and format context info and description...
99 13         52 $file =~ s{.*[/\\]}{}xms;
100 13         30 my $context = "'$file', line $line";
101 13   33     31 $desc //= $context;
102              
103             # Isolate arg list and compress internal whitespace...
104 13         1387 $desc =~ s{ \A (?: (?!\bshow) . )*? \b show \b \s* ($CODE) \s* (?: [;\}] .* | \Z ) }{$1}xms;
105 13         63 $desc =~ s{\A \( | \) \Z}{}gxms;
106 13         33 $desc =~ s{\s+}{ }gxms;
107              
108             # Serialize Contextual::Return::Value objects (which break dump())...
109 13         26 for my $arg (@_) {
110 28 50 100     143 if ((ref($arg)||q{}) =~ m{\A Contextual::Return}xms) {
111 0         0 require Contextual::Return;
112 0         0 Contextual::Return::FREEZE($arg);
113             }
114             }
115              
116             # Serialize argument (restoring it, if it was inappropriately flattened)...
117 13 100       360 my $representation = $desc =~ m{ \A \@ $IDENT \s* \Z }xms ? dump(\@_ )
    100          
118             : $desc =~ m{ \A \% $IDENT \s* \Z }xms ? dump({@_})
119             : dump( @_ );
120              
121             # Indent representation wrt heading...
122 13         2380 $representation =~ s{^}{ q{ } x $DEFAULT_INDENT }gxmse;
  13         81  
123              
124             # Clean up parens around title...
125 13         94 $desc =~ s{ \A \s* (?| \( \s* (.*?) \s* \) | \s* (.*?) \s* ) \Z }
126             {( $1 )}xms;
127              
128             # Insert title into header...
129 13         25 my $header = '=' x $MAX_WIDTH;
130 13         22 substr($header, $TITLE_POS, length($desc), $desc);
131              
132             # Add context if it isn't just context...
133 13 50       33 if ($desc ne "( $context )") {
134 13         21 $context = "[ $context ]";
135 13         22 substr($header, -length($context)-$TITLE_POS, -$TITLE_POS, $context);
136             }
137              
138             # Display data...
139 13         15 print {*STDERR} "$header\n\n$representation\n\n\n";
  13         59  
140              
141 13         201 return;
142             }
143              
144              
145             1; # Magic true value required at end of module
146             __END__