File Coverage

blib/lib/JIP/Debug.pm
Criterion Covered Total %
statement 68 68 100.0
branch 15 18 83.3
condition 10 11 90.9
subroutine 16 16 100.0
pod 2 7 28.5
total 111 120 92.5


line stmt bran cond sub pod time code
1             package JIP::Debug;
2              
3 1     1   3808 use base qw(Exporter);
  1         3  
  1         90  
4              
5 1     1   23 use 5.006;
  1         4  
6 1     1   7 use strict;
  1         3  
  1         39  
7 1     1   7 use warnings;
  1         10  
  1         51  
8 1     1   614 use Devel::StackTrace;
  1         3337  
  1         33  
9 1     1   7 use Carp qw(croak);
  1         2  
  1         65  
10 1     1   783 use Data::Dumper qw(Dumper);
  1         7022  
  1         81  
11 1     1   8 use Fcntl qw(LOCK_EX LOCK_UN);
  1         2  
  1         54  
12 1     1   6 use English qw(-no_match_vars);
  1         3  
  1         10  
13              
14             our $VERSION = '0.999_003';
15              
16             our @EXPORT_OK = qw(
17             to_debug
18             to_debug_raw
19             to_debug_empty
20             to_debug_count
21             to_debug_trace
22             );
23              
24             our $HANDLE = \*STDERR;
25              
26             our $MSG_FORMAT = qq{%s\n%s\n\n};
27             our $MSG_DELIMITER = q{-} x 80;
28             our $MSG_EMPTY_LINES = qq{\n} x 18;
29              
30             our $DUMPER_INDENT = 1;
31             our $DUMPER_DEEPCOPY = 1;
32             our $DUMPER_SORTKEYS = 1;
33              
34             our %TRACE_PARAMS = (
35             skip_frames => 1, # skip to_debug_trace
36             );
37             our %TRACE_AS_STRING_PARAMS;
38              
39             our $COLOR = 'bright_green';
40              
41             our $MAYBE_COLORED = sub { return $ARG[0] };
42             eval {
43             require Term::ANSIColor;
44             $MAYBE_COLORED = sub { return Term::ANSIColor::colored($ARG[0], $COLOR); };
45             };
46              
47             our $MAKE_MSG_HEADER = sub {
48             # $MAKE_MSG_HEADER=0, to_debug=1
49             my ($package, undef, $line) = caller 1;
50              
51             # $MAKE_MSG_HEADER=0, to_debug=1, subroutine=2
52             my $subroutine = (caller 2)[3];
53              
54             $subroutine = resolve_subroutine_name($subroutine);
55              
56             my $text = join q{, }, (
57             sprintf('package=%s', $package),
58             (defined $subroutine ? sprintf('subroutine=%s', $subroutine) : ()),
59             sprintf('line=%d', $line, ),
60             );
61             $text = qq{[$text]:};
62              
63             {
64             my $msg_delimiter = defined $MSG_DELIMITER ? $MSG_DELIMITER : q{};
65             $text = sprintf qq{%s\n%s\n%s}, $msg_delimiter, $text, $msg_delimiter;
66             }
67              
68             return $MAYBE_COLORED->($text);
69             };
70              
71             our $NO_LABEL_KEY = '';
72             our %COUNT_OF_LABEL = ($NO_LABEL_KEY => 0);
73              
74             # Supported on Perl 5.22+
75             eval {
76             require Sub::Util;
77              
78             if (my $set_subname = Sub::Util->can('set_subname')) {
79             $set_subname->('MAYBE_COLORED', $MAYBE_COLORED);
80             $set_subname->('MAKE_MSG_HEADER', $MAKE_MSG_HEADER);
81             }
82             };
83              
84             sub to_debug {
85 1     1 0 5876 my $msg_body = do {
86 1         4 local $Data::Dumper::Indent = $DUMPER_INDENT;
87 1         4 local $Data::Dumper::Deepcopy = $DUMPER_DEEPCOPY;
88 1         3 local $Data::Dumper::Sortkeys = $DUMPER_SORTKEYS;
89              
90 1         8 Dumper(\@ARG);
91             };
92              
93 1         108 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
94              
95 1         10 return send_to_output($msg);
96             }
97              
98             sub to_debug_raw {
99 1     1 0 4822 my $msg_text = shift;
100              
101 1         5 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_text;
102              
103 1         9 return send_to_output($msg);
104             }
105              
106             sub to_debug_empty {
107 1     1 0 4953 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $MSG_EMPTY_LINES;
108              
109 1         11 return send_to_output($msg);
110             }
111              
112             sub to_debug_count {
113 16     16 1 44112 my ($label, $cb);
114 16 100 66     144 if (@ARG == 2 && ref $ARG[1] eq 'CODE') {
    100 100        
    100          
115 2         9 ($label, $cb) = @ARG;
116             }
117             elsif (@ARG == 1 && ref $ARG[0] eq 'CODE') {
118 2         7 $cb = $ARG[0];
119             }
120             elsif (@ARG == 1) {
121 8         20 $label = $ARG[0];
122             }
123              
124 16 100 100     74 $label = defined $label && length $label ? $label : $NO_LABEL_KEY;
125              
126 16   100     75 my $count = $COUNT_OF_LABEL{$label} || 0;
127 16         45 $count++;
128 16         35 $COUNT_OF_LABEL{$label} = $count;
129              
130 16         83 my $msg_body = sprintf '%s: %d', $label, $count;
131              
132 16         51 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
133              
134 16 100       485 $cb->($label, $count) if defined $cb;
135              
136 16         75 return send_to_output($msg);
137             }
138              
139             sub to_debug_trace {
140 1     1 1 6726 my $cb = shift;
141              
142 1         12 my $trace = Devel::StackTrace->new(%TRACE_PARAMS);
143              
144 1         547 my $msg_body = $trace->as_string(%TRACE_AS_STRING_PARAMS);
145 1         1280 $msg_body =~ s{\n+$}{}x;
146              
147 1         7 my $msg = sprintf $MSG_FORMAT, $MAKE_MSG_HEADER->(), $msg_body;
148              
149 1 50       25 $cb->($trace) if defined $cb;
150              
151 1         5 return send_to_output($msg);
152             }
153              
154             sub send_to_output {
155 22     22 0 9132 my $msg = shift;
156              
157 22 50       69 return unless $HANDLE;
158              
159 22         185 flock $HANDLE, LOCK_EX;
160 22 50       112 $HANDLE->print($msg) or croak(sprintf q{Can't write to output: %s}, $OS_ERROR);
161 22         1024 flock $HANDLE, LOCK_UN;
162              
163 22         176 return 1;
164             }
165              
166             sub resolve_subroutine_name {
167 14     14 0 18566 my $subroutine = shift;
168              
169 14 100       53 return unless defined $subroutine;
170              
171 12         75 my ($subroutine_name) = $subroutine =~ m{::(\w+)$}x;
172              
173 12         45 return $subroutine_name;
174             }
175              
176             1;
177              
178             __END__