File Coverage

lib/LEOCHARRE/DEBUG.pm
Criterion Covered Total %
statement 98 147 66.6
branch 21 50 42.0
condition 9 22 40.9
subroutine 17 21 80.9
pod n/a
total 145 240 60.4


line stmt bran cond sub pod time code
1             package LEOCHARRE::DEBUG;
2 4     4   105977 use strict;
  4         12  
  4         142  
3 4     4   24 use vars qw($VERSION);
  4         6  
  4         705  
4             $VERSION = sprintf "%d.%02d", q$Revision: 1.14 $ =~ /(\d+)/g;
5              
6             $LEOCHARRE::DEBUG::_DEBUG = 0;
7             $LEOCHARRE::DEBUG::USE_COLOR = 0;
8              
9 0     0   0 sub _DEBUG { return $LEOCHARRE::DEBUG::_DEBUG; }
10              
11             sub __DEBUG {
12 4     4   8 my $pkg = shift;
13             return sub {
14 12 50   12   92 my $val = ref $_[0] ? $_[1] : $_[0];
15 4     4   24 no strict 'refs';
  4         11  
  4         502  
16 12 100       35 ${"$pkg\::DEBUG"} = $val if defined $val;
  2         8  
17 12         16 return ${"$pkg\::DEBUG"};
  12         72  
18 4         26 };
19             }
20              
21              
22             sub __debug {
23 0     0   0 my $pkg = shift;
24              
25             return sub {
26 4     4   21 no strict 'refs';
  4         7  
  4         305  
27 0     0   0 my $DEBUG = ${"$pkg\::DEBUG"}; #TODO there is a way to do this at compile time
  0         0  
28             # instead of run time
29            
30 0 0       0 $DEBUG or return 1;
31            
32 0         0 my $_prepend = ' # ';
33            
34            
35            
36             # are we being used as method?
37             # so that $self->debug() works like debug()
38 0         0 my $val = shift;
39 0 0       0 if (ref $val){ # then likely used as method
40 0         0 $val = shift; # use the next value.
41             }
42 4     4   21 no strict 'refs';
  4         8  
  4         406  
43            
44 0         0 my $debug_label = shift;
45 0   0     0 $debug_label ||= 1;
46            
47             # if they specify a label starting with a letter, show ONLY those debug messages
48 0 0       0 if ($debug_label=~/^[a-z]/i){
49 0 0       0 $debug_label eq $DEBUG or return 1;
50             }
51            
52             # if they specify a number, show ONLY if DEBUG is at LEAST that
53             else {
54 4     4   20 no warnings;
  4         8  
  4         1915  
55 0 0       0 ( $DEBUG >= $debug_label ) or return 1;
56             }
57            
58            
59            
60             # SET CALLER NAMESPACE
61 0         0 my $sub = (caller(1))[3];
62             # if used in a script, caller wont be there
63 0   0     0 $sub ||= 'main';
64            
65            
66 0         0 my $caller_changed = 0;
67 0 0       0 if (${"$pkg\::_DEBUG_LAST_CALLER"} ne $sub ){
  0         0  
68 0         0 $caller_changed = 1;
69            
70             # if last had no new line.. then put a newline
71 0 0       0 ${"$pkg\::_DEBUG_SHOW_NAMESPACE"} or print STDERR "\n";
  0         0  
72 0         0 ${"$pkg\::_DEBUG_SHOW_NAMESPACE"} = 1;
  0         0  
73            
74             }
75 0         0 ${"$pkg\::_DEBUG_LAST_CALLER"} = $sub;
  0         0  
76            
77 0 0       0 unless (${"$pkg\::_DEBUG_SHOW_WHOLE_NAMESPACE"}){
  0         0  
78 0         0 $sub=~s/^.*:://; # print sub() instead of MyPackage::sub()
79             }
80            
81 0 0 0     0 if( ${"$pkg\::_DEBUG_SHOW_NAMESPACE"} or $caller_changed){
  0         0  
82 0         0 print STDERR " $_prepend$sub(),";
83             }
84            
85 0 0       0 defined $val or $val ='';
86              
87             # if ref.. use dumper
88 0 0       0 if ( ref $val ){
89 0         0 require Data::Dumper;
90 0         0 $val = Data::Dumper::Dumper($val);
91             }
92            
93 0         0 print STDERR " $val\n";
94            
95            
96 0 0       0 if ($val=~/\n$/ ) {
97 0         0 ${"$pkg\::_DEBUG_SHOW_NAMESPACE"} = 1;
  0         0  
98             }
99             else {
100 0         0 ${"$pkg\::_DEBUG_SHOW_NAMESPACE"} = 0;
  0         0  
101             }
102            
103 0         0 return 1;
104 0         0 };
105             }
106              
107              
108             sub __debug_smaller {
109 4     4   9 my $pkg = shift;
110              
111             return sub {
112 4     4   25 no strict 'refs';
  4         11  
  4         2286  
113 36     36   11651 my $DEBUG = ${"$pkg\::DEBUG"}; #TODO there is a way to do this at compile time, not run time
  36         97  
114 36 100       92 $DEBUG or return 1;
115             # are we being used as method?
116             # so that $self->debug() works like debug()
117              
118            
119 34         56 my @msgs = grep { length $_ } map { __resolve_one_message($_) } @_;
  44         98  
  45         92  
120              
121              
122              
123             # what's the debug level
124 34         75 my $debug_level = __resolve_debug_level($pkg);
125              
126 34 100       69 if ( $debug_level > 1 ){
127            
128            
129             # SET CALLER NAMESPACE
130 9         17 my $sub = (caller(1))[3];
131             # if used in a script, caller wont be there
132 9   33     44 $sub ||= $pkg;
133 9 50       31 $sub = ($sub eq 'main') ? $0 : "$sub()";
134              
135 9         17 @msgs = map { " $_" } @msgs;
  15         47  
136 9         24 unshift @msgs, "\n# $sub";
137              
138             }
139              
140            
141 34         94 __cleanup_message(\$_) for @msgs;
142              
143              
144              
145 34 100 66     142 if ( $LEOCHARRE::DEBUG::USE_COLOR or ($debug_level > 2) ){
146 4         2207 require Term::ANSIColor;
147 4         8127 $Term::ANSIColor::AUTORESET = 1;
148             #$LEOCHARRE::DEBUG::USE_COLOR ||= 'green';
149 4 100       46 print STDERR Term::ANSIColor::colored ("@msgs",
150             ($LEOCHARRE::DEBUG::USE_COLOR=~/[a-z]/ ? $LEOCHARRE::DEBUG::USE_COLOR : 'green'));
151             }
152             else {
153 30         467 print STDERR "@msgs";
154             }
155 34         963 return 1;
156 4         23 };
157             }
158              
159             # new stuff
160             sub __cleanup_message {
161 53     53   71 my $mref = shift;
162 53         116 $$mref=~s/\.$/\.\n/;
163             #$$mref=~s/^([A-Z])/\n$1/;
164 53         124 1;
165             }
166              
167             sub __resolve_debug_level { # show whole namespace or none
168 34     34   47 my $pkg = shift;
169             # return 0, 1, 2
170            
171              
172 4     4   27 no strict 'refs';
  4         16  
  4         1169  
173              
174 34 50       53 ${"$pkg\::DEBUG"} or return 0;
  34         109  
175              
176              
177 34         156 ( $LEOCHARRE::DEBUG::DEBUG_SHOW_WHOLE_NAMESPACE
178 34 100 66     86 or ( ${"$pkg\::DEBUG"} > 1 ))
179             and return 2;
180              
181              
182             #${"$pkg\::DEBUG"} == 1 and return 1;
183 25         44 1;
184              
185              
186             }
187              
188             sub __resolve_one_message {
189 45     45   62 my $msg = shift;
190            
191 45 100 66     174 if( ( ref $msg ) and (( ref $msg eq 'ARRAY' ) or (ref $msg eq 'HASH')) ){
    100 66        
192 1         1078 require Data::Dumper;
193 1         6930 my $msg2 = Data::Dumper::Dumper($msg);
194 1         130 return $msg2;
195             }
196             elsif ( ref $msg ){ # method of package .. ?
197 1         3 return;
198             }
199 43         112 return $msg;
200             }
201              
202              
203              
204             # end new stuff
205              
206             sub import {
207             ## find out who is calling us
208 4     4   33 my $pkg = caller;
209              
210 4         13 for (@_){
211 5 100       30 if ($_=~/use_color/){
212 1         3 $LEOCHARRE::DEBUG::USE_COLOR = 'dark';
213             }
214             }
215              
216             ## while strict doesn't deal with globs, it still
217             ## catches symbolic de/referencing
218 4     4   23 no strict 'refs';
  4         8  
  4         1686  
219              
220              
221             #print STDERR " [$pkg]\n";
222              
223             ## iterate through all the globs in the symbol table
224             # foreach my $glob (keys %LEOCHARRE::DEBUG::) {
225             ## skip anything without a subroutine and 'import'
226             # next if not defined *{$LEOCHARRE::DEBUG::{$glob}}{CODE}
227             # or $glob eq 'import';
228              
229             ## assign subroutine into caller's package
230             # *{$pkg . "::$glob"} = \&{"LEOCHARRE::DEBUG::$glob"};
231             # }
232              
233 4         11 my ($D1,$D2,$D3,$D4) =(0,1,0,0);
234            
235 4         15 *{"$pkg\::DEBUG"} = __DEBUG($pkg);
  4         46  
236             #*{"$pkg\::debug"} = __debug($pkg);
237 4         22 *{"$pkg\::debug"} = __debug_smaller($pkg);
  4         123  
238            
239 4         11 *{"$pkg\::DEBUG"} = \$D1; #0;
  4         14  
240 4         10 *{"$pkg\::_DEBUG_SHOW_NAMESPACE"} = \$D2; #1;
  4         23  
241 4         8 *{"$pkg\::_DEBUG_LAST_CALLER"} = \$D3;#$0;
  4         20  
242 4         8 *{"$pkg\::_DEBUG_SHOW_WHOLE_NAMESPACE"} = \$D4 ;# 0;
  4         50  
243 4         11 *{"$pkg\::__resolve_one_message"} = \&__resolve_one_message;
  4         20  
244 4         10 *{"$pkg\::__resolve_debug_level"} = \&__resolve_debug_level;
  4         18  
245 4         8 *{"$pkg\::__cleanup_message"} = \&__cleanup_message;
  4         18  
246              
247              
248 4         12892 *{"$pkg\::debug_detect_cliopt"} =
249             sub {
250 0     0     for (@ARGV){
251 0 0         if ($_ eq '-d'){
252 0           ${"$pkg\::DEBUG"} = 1;
  0            
253 0           last;
254             }
255             }
256 4         15 };
257              
258              
259              
260             # if we are being imported by a script (main) and there is and -d @ARGV, then turn debug on
261              
262              
263             #if ($pkg eq 'main'){
264             # if ( "@ARGV"=~/[\s|]-d[\s|]/ ){
265             # ${"$pkg\::DEBUG"} = 1;
266             # }
267             #}
268              
269             # ABUSE CALLING PACKAGE, these are scalars we want
270             # for (qw(DEBUG _DEBUG_SHOW_NAMESPACE _DEBUG_SHOW_WHOLE_NAMESPACE _DEBUG_LAST_CALLER)){
271             # my $glob = $_;
272             # *{$pkg . "::$glob"} = \${"LEOCHARRE::DEBUG::$glob"};
273             # }
274             }
275              
276              
277              
278              
279              
280              
281              
282              
283              
284              
285              
286             1;
287              
288             =pod
289              
290             =head1 NAME
291              
292             LEOCHARRE::DEBUG - deprecated
293              
294             =head1 SYNOPSIS
295              
296             In A.pm
297              
298             package A;
299             use LEOCHARRE::DEBUG;
300             use strict;
301              
302              
303             sub new {
304             my $class = shift;
305             my $self ={};
306             bless $self, $class;
307             return $self;
308             }
309              
310             sub test {
311             my $self = shift;
312             DEBUG or return 0;
313             debug('ok .. i ran.');
314            
315             debug('ok .. i am more verbose.',2); # shows only if DEBUG level is 2 or more
316            
317             return 1;
318             }
319              
320             In script.t
321              
322             use Test::Simple 'no_plan';
323             use strict;
324             use A;
325              
326             my $o = new A;
327              
328             $A::DEBUG = 1;
329             ok( $o->test );
330              
331             $A::DEBUG = 0;
332             ok( !($o->test) );
333              
334             =pod
335              
336             =head1 DESCRIPTION
337              
338             Deprecated. Use L instead.
339              
340             =head1 USING COLOR
341              
342             requires Term::ANSIColor
343             use color..
344              
345             use LEOCHARRE::DEBUG 'use_color';
346             DEBUG 1;
347             debug('i am gray');
348              
349             by default we use 'dark'
350             if you want to change..
351              
352             $LEOCHARRE::DEBUG::USE_COLOR = 'red';
353              
354             Also..
355              
356             use LEOCHARRE::DEBUG;
357             $LEOCHARRE::DEBUG::USE_COLOR = 'red';
358             debug('i am red');
359              
360              
361             =head1 DEBUG()
362              
363             set and get accessor
364             returns number
365             this is also the debug level.
366             if set to 0, no debug messages are shown.
367              
368             print STDERR "oops" if DEBUG;
369              
370             =head1 debug_detect_cliopt()
371              
372             inspects the @ARGV and if there's a '-d' opt, sets debug to 1
373              
374             =head1 debug()
375              
376             argument is message, will only print to STDERR if DEBUG is on.
377             optional argument is debug level that must be on for this to print, it is assumed
378             level 1 (DEBUG on) if none passed.
379              
380             package My:Mod;
381             use LEOCHARRE::DEBUG;
382            
383             My::Mod::DEBUG = 1;
384            
385             debug('only show this if DEBUG is on');
386             # same as:
387             debug('only show this if DEBUG is on',1);
388            
389             debug('only show this if DEBUG is on',2); # will not show, debug level is 1
390              
391             My::Mod::DEBUG = 2;
392             debug('only show this if DEBUG is on',2); # will show, debug level is 2
393             debug('only show this if DEBUG is on'); # will also show, debug level is at least 1
394            
395             debug('only show this if DEBUG is on',3); # will not show, debug level is not 3 or more.
396            
397             My::Mod::DEBUG = 0;
398             debug('only show this if DEBUG is on'); # will not show, debug is off
399             debug('only show this if DEBUG is on',3); # will not show, debug is off
400              
401            
402              
403            
404            
405              
406            
407              
408             If your message argument does not end in a newline, next message will not be prepended with
409             the subroutine name.
410              
411             sub dostuff {
412             debug("This is..");
413              
414             # ...
415              
416             debug("done.\n");
417              
418             debug("ok?");
419             }
420              
421             Would print
422              
423             dostuff(), This is.. done.
424             dostuff(), ok?
425              
426              
427              
428             =head1 DESCRIPTION
429              
430             I want to be able in my code to do this
431              
432              
433             package My::Module;
434            
435             sub run {
436             print STDERR "ok\n" if DEBUG;
437             }
438            
439            
440             package main;
441            
442             $My::Module::DEBUG = 1;
443            
444             My::Module::run();
445              
446             And I am tired of coding this
447              
448             $My::ModuleName::DEBUG = 0;
449             sub DEBUG : lvalue { $My::ModuleName::DEBUG }
450              
451             Using this module the subroutine DEBUG will return true or false, and it can be set via the
452             namespace of the package using it.
453              
454             =head1 NOTES
455              
456             This package, alike LEOCHARRE::CLI, are under the author's name because the code herein comprises
457             his particular mode of work. These modules are used throughout his works, and in no way interfere
458             with usage of those more general modules.
459              
460             =head1 DEBUG level
461              
462             If DEBUG is set to at least "1", messages are shown as long as they are debug level 1.
463             If you do not specify a debug level to debug(), 1 is assumed.
464              
465             $MYMOD::DEBUG = 0;
466              
467             Show at least debug() calls with argument 2
468              
469             $MYMOD::DEBUG = 2;
470            
471              
472             Show at least debug() with argument 3
473              
474             $MYMOD::DEBUG = 3;
475              
476              
477             =head2 DEBUG tags
478              
479             What if you want to show only messages that match a tag?
480             If you pass a tag label starting in a letter and specify in DEBUG..
481            
482             $MYMOD::DEBUG = 'a';
483              
484             debug('hi'); # will not show
485              
486             debug('hi','a'); # WILL show
487              
488             debug('hi','b'); # will not show
489             debug('hi',2); # will not show
490              
491              
492             =head1 SEE ALSO
493              
494             L
495             L
496              
497             =head1 AUTHOR
498              
499             Leo Charre leocharre at cpan dot org
500              
501             =head1 COPYRIGHT
502              
503             Copyright (c) 2009 Leo Charre. All rights reserved.
504              
505             =head1 LICENSE
506              
507             This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License".
508              
509             =head1 DISCLAIMER
510              
511             This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
512              
513             See the "GNU General Public License" for more details.
514            
515             =cut