File Coverage

blib/lib/Devel/PrettyTrace.pm
Criterion Covered Total %
statement 58 61 95.0
branch 15 18 83.3
condition 7 9 77.7
subroutine 12 12 100.0
pod 0 6 0.0
total 92 106 86.7


line stmt bran cond sub pod time code
1             package Devel::PrettyTrace;
2              
3 4     4   84993 use 5.005;
  4         15  
  4         156  
4 4     4   21 use strict;
  4         7  
  4         150  
5              
6 4     4   3470 use parent qw(Exporter);
  4         1435  
  4         21  
7 4     4   4428 use Data::Printer;
  4         181109  
  4         32  
8 4     4   4871 use List::MoreUtils qw(all any);
  4         7441  
  4         3608  
9              
10             our $VERSION = '0.04';
11             our @EXPORT = qw(bt);
12              
13             our $Indent = ' ';
14             our $Evalen = 40;
15             our $Deeplimit = 0;
16             our $Skiplevels = 0;
17              
18             our %IgnorePkg;
19             our %Opts = (
20             colored => 1,
21             class => {
22             internals => 1,
23             show_methods => 'none',
24             parents => 0,
25             linear_isa => 0,
26             expand => 1,
27             },
28             max_depth => 2,
29             indent => 2,
30             );
31              
32             sub bt() {
33             #local @DB::args;
34 6     6 0 1893 my $ret = '';
35 6         15 my $i = $Skiplevels + 1; #skip own call
36 6         20 my $filter = get_ignore_filter();
37            
38 6   100     50 while (
      100        
39             ($Deeplimit <= 0 || $i < $Deeplimit + 1)
40             &&
41             (my @info = get_caller_info($i + 1)) #+1 as we introduce another call frame
42             ){
43 19         28 $i++;
44 19 100       40 next if $filter->($info[3]);
45            
46 18         134 $ret .= format_call(\@info);
47             }
48            
49 6 50       20 if (defined wantarray){
50 6         65 return $ret;
51             }else{
52 0         0 print STDERR $ret;
53             }
54             }
55              
56             sub get_ignore_filter{
57 6     6 0 21 my @filters = map { qr/^\Q$_\E/ } keys %IgnorePkg;
  1         17  
58            
59             return sub {
60 19     19   25 my $test_pkg = shift;
61            
62 19 100       137 return 1 if any { $test_pkg =~ $_ } @filters;
  4         104  
63 18         82 return 0;
64             }
65 6         35 }
66              
67             sub format_call{
68 18     18 0 23 my $info = shift;
69              
70 18         24 my $result = $Indent;
71            
72 18 100       63 if (defined $info->[6]){
    100          
73 1 50       4 if ($info->[7]){
74 0         0 $result .= "require $info->[6]";
75            
76             }else{
77 1         33 $info->[6] =~ s/\n;$/;/;
78 1         6 $result .= "eval '".trim_to_length($info->[6], $Evalen)."'";
79             }
80            
81             }elsif ($info->[3] eq '(eval)'){
82 1         3 $result .= 'eval {...}';
83            
84             }else{
85 16         36 $result .= $info->[3];
86             }
87            
88 18 100       42 if ($info->[4]){
89 16         21 $result .= "(";
90            
91 16 100       40 if (scalar @DB::args){
92 5         18 $result .= format_args();
93             }
94            
95 16         27 $result .= ')';
96             }
97            
98 18         56 $result .= " called at $info->[1] line $info->[2]\n";
99              
100 18         217 return $result;
101             }
102              
103             sub format_args{
104 5     5 0 41 my $result = p(@DB::args, %Opts);
105            
106             #result is always non-empty array, so transform [\n a\n b\n] => \n\t\t a \n\t\t b \n\t
107 5         9023 $result =~ s/^.*?\n/\n/;
108 5         23 $result =~ s/\]$//;
109 5         42 $result =~ s/\n/\n$Indent/go;
110            
111 5         17 return $result;
112             }
113              
114             sub trim_to_length{
115 1     1 0 2 my ($str, $len) = @_;
116            
117 1 50 33     9 if ($len > 2 && length($str) > $len){
118 0         0 substr($str, $len - 3) = '...';
119             }
120            
121 1         4 return $str;
122             }
123              
124             sub get_caller_info{
125 24     24 0 32 my $level = shift;
126              
127 24         35 do {
128             package DB;
129 24         49 @DB::args = ();
130 24         235 return caller($level);
131             };
132             }
133              
134             1;