File Coverage

blib/lib/Log/Report/Minimal.pm
Criterion Covered Total %
statement 74 101 73.2
branch 22 52 42.3
condition 11 32 34.3
subroutine 19 34 55.8
pod 18 19 94.7
total 144 238 60.5


line stmt bran cond sub pod time code
1             # This code is part of Perl distribution Log-Report-Optional version 1.08.
2             # The POD got stripped from this file by OODoc version 3.04.
3             # For contributors see file ChangeLog.
4              
5             # This software is copyright (c) 2013-2025 by Mark Overmeer.
6              
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
10              
11             #oodist: *** DO NOT USE THIS VERSION FOR PRODUCTION ***
12             #oodist: This file contains OODoc-style documentation which will get stripped
13             #oodist: during its release in the distribution. You can use this file for
14             #oodist: testing, however the code of this development version may be broken!
15              
16             package Log::Report::Minimal;{
17             our $VERSION = '1.08';
18             }
19              
20 4     4   196493 use base 'Exporter';
  4         6  
  4         531  
21              
22 4     4   22 use warnings;
  4         4  
  4         204  
23 4     4   14 use strict;
  4         9  
  4         94  
24              
25 4     4   1484 use Log::Report::Util;
  4         18  
  4         736  
26 4     4   34 use List::Util qw/first/;
  4         18  
  4         322  
27 4     4   24 use Scalar::Util qw/blessed/;
  4         6  
  4         176  
28              
29 4     4   2225 use Log::Report::Minimal::Domain ();
  4         10  
  4         7801  
30              
31             ### if you change anything here, you also have to change Log::Report::Minimal
32             my @make_msg = qw/__ __x __n __nx __xn N__ N__n N__w/;
33             my @functions = qw/report dispatcher try textdomain/;
34             my @reason_functions = qw/trace assert info notice warning mistake error fault alert failure panic/;
35              
36             our @EXPORT_OK = (@make_msg, @functions, @reason_functions);
37              
38             sub trace(@); sub assert(@); sub info(@); sub notice(@); sub warning(@);
39             sub mistake(@); sub error(@); sub fault(@); sub alert(@); sub failure(@);
40             sub panic(@); sub report(@); sub textdomain($@);
41             sub __($); sub __x($@); sub __n($$$@); sub __nx($$$@); sub __xn($$$@);
42             sub N__($); sub N__n($$); sub N__w(@);
43              
44             my ($mode, %need);
45             sub need($)
46 4     4 0 7 { $mode = shift;
47 4         36 %need = map +($_ => 1), expand_reasons mode_accepts $mode;
48             }
49             need 'NORMAL';
50              
51             my %textdomains;
52             textdomain 'default';
53              
54             sub _interpolate(@)
55 3     3   26 { my ($msgid, %args) = @_;
56              
57 3         6 my $textdomain = $args{_domain};
58 3 50       8 unless($textdomain)
59 3         12 { my ($pkg) = caller 1;
60 3         13 $textdomain = pkg2domain $pkg;
61             }
62              
63 3         7 (textdomain $textdomain)->interpolate($msgid, \%args);
64             }
65              
66             #--------------------
67              
68             sub textdomain($@)
69 12 50 33 12 1 62 { if(@_==1 && blessed $_[0])
70 0         0 { my $domain = shift;
71 0         0 return $textdomains{$domain->name} = $domain;
72             }
73              
74 12 50       27 if(@_==2)
75             { # used for 'maintenance' and testing
76 0 0       0 return delete $textdomains{$_[0]} if $_[1] eq 'DELETE';
77 0 0       0 return $textdomains{$_[0]} if $_[1] eq 'EXISTS';
78             }
79              
80 12         16 my $name = shift;
81 12   66     73 my $domain = $textdomains{$name} ||= Log::Report::Minimal::Domain->new(name => $name);
82              
83 12 50       43 @_ ? $domain->configure(@_, where => [caller]) : $domain;
84             }
85              
86             #--------------------
87              
88             # $^S = $EXCEPTIONS_BEING_CAUGHT; parse: undef, eval: 1, else 0
89              
90             sub _report($$@)
91 2     2   7 { my ($opts, $reason) = (shift, shift);
92              
93             # return when no-one needs it: skip unused trace() fast!
94 2 50       14 my $stop = exists $opts->{is_fatal} ? $opts->{is_fatal} : is_fatal $reason;
95 2 50 33     10 $need{$reason} || $stop or return;
96              
97 2 50       8 is_reason $reason
98             or error __x"token '{token}' not recognized as reason", token=>$reason;
99              
100             $opts->{errno} ||= $!+0 || $? || 1
101 2 50 0     24 if use_errno($reason) && !defined $opts->{errno};
      0        
      33        
102              
103 2         6 my $message = shift;
104 2 50       7 @_%2 and error __x"odd length parameter list with '{msg}'", msg => $message;
105              
106 2         7 my $show = lc($reason).': '.$message;
107              
108 2 100       6 if($stop)
109             { # ^S = EXCEPTIONS_BEING_CAUGHT, within eval or try
110 1   50     8 $! = $opts->{errno} || 0;
111 1         15 die "$show\n"; # call the die handler
112             }
113             else
114 1         15 { warn "$show\n"; # call the warn handler
115             }
116              
117 1         13 1;
118             }
119              
120              
121 0     0 1 0 sub dispatcher($@) { panic "no dispatchers available in ".__PACKAGE__ }
122              
123              
124             sub try(&@)
125 0     0 1 0 { my $code = shift;
126              
127 0 0       0 @_ % 2 and report {}, PANIC => __x"odd length parameter list for try(): forgot the terminating ';'?";
128              
129             #XXX MO: only needs the fatal subset, exclude the warns/prints
130 0         0 eval { $code->() };
  0         0  
131             }
132              
133             #--------------------
134              
135             sub report(@)
136 0 0 0 0 1 0 { my %opt = @_ && ref $_[0] eq 'HASH' ? %{ (shift) } : ();
  0         0  
137 0         0 _report \%opt, @_;
138             }
139              
140 0     0 1 0 sub trace(@) {_report {}, TRACE => @_}
141 0     0 1 0 sub assert(@) {_report {}, ASSERT => @_}
142 0     0 1 0 sub info(@) {_report {}, INFO => @_}
143 0     0 1 0 sub notice(@) {_report {}, NOTICE => @_}
144 1     1 1 1333 sub warning(@) {_report {}, WARNING => @_}
145 0     0 1 0 sub mistake(@) {_report {}, MISTAKE => @_}
146 1     1 1 162740 sub error(@) {_report {}, ERROR => @_}
147 0     0 1 0 sub fault(@) {_report {}, FAULT => @_}
148 0     0 1 0 sub alert(@) {_report {}, ALERT => @_}
149 0     0 1 0 sub failure(@) {_report {}, FAILURE => @_}
150 0     0 1 0 sub panic(@) {_report {}, PANIC => @_}
151              
152             #--------------------
153              
154 3     3   422842 sub __($) { $_[0] }
155              
156              
157              
158             sub __x($@)
159 1 50   1   5 { @_%2 or error __x"even length parameter list for __x at {where}", where => join(' line ', (caller)[1,2]);
160 1         4 _interpolate @_, _expand => 1;
161             }
162              
163              
164             sub __n($$$@)
165 0     0   0 { my ($single, $plural, $count) = (shift, shift, shift);
166 0 0       0 _interpolate +($count==1 ? $single : $plural), _count => $count, @_;
167             }
168              
169              
170             sub __nx($$$@)
171 1     1   655 { my ($single, $plural, $count) = (shift, shift, shift);
172 1 50       5 _interpolate +($count==1 ? $single : $plural), _count => $count, _expand => 1, @_;
173             }
174              
175              
176             sub __xn($$$@) # repeated for prototype
177 1     1   1117 { my ($single, $plural, $count) = (shift, shift, shift);
178 1 50       5 _interpolate +($count==1 ? $single : $plural), _count => $count , _expand => 1, @_;
179             }
180              
181              
182 0     0 1 0 sub N__($) { $_[0] }
183 0     0 1 0 sub N__n($$) {@_}
184 1     1 1 696 sub N__w(@) {split " ", $_[0]}
185              
186             #--------------------
187              
188             sub import(@)
189 5     5   48 { my $class = shift;
190              
191 5 100 100     31 my $to_level = @_ && $_[0] =~ m/^\+\d+$/ ? shift : 0;
192 5 100       16 my $textdomain = @_%2 ? shift : 'default';
193 5         8 my %opts = @_;
194 5   50     28 my $syntax = delete $opts{syntax} || 'SHORT';
195              
196 5         28 my ($pkg, $fn, $linenr) = caller $to_level;
197 5         24 pkg2domain $pkg, $textdomain, $fn, $linenr;
198 5         15 my $domain = textdomain $textdomain;
199              
200             need delete $opts{mode}
201 5 50       18 if defined $opts{mode};
202              
203 5         10 my @export;
204 5 50       17 if(my $in = $opts{import})
205 0 0       0 { push @export, ref $in eq 'ARRAY' ? @$in : $in;
206             }
207             else
208 5         22 { push @export, @functions, @make_msg;
209              
210 5   50     49 my $syntax = delete $opts{syntax} || 'SHORT';
211 5 50 0     14 if($syntax eq 'SHORT')
    0          
212 5         22 { push @export, @reason_functions
213             }
214             elsif($syntax ne 'REPORT' && $syntax ne 'LONG')
215 0         0 { error __x"syntax flag must be either SHORT or REPORT, not `{flag}'", flag => $syntax;
216             }
217             }
218              
219 5         940 $class->export_to_level(1+$to_level, undef, @export);
220              
221 5 50       3257 $domain->configure(%opts, where => [$pkg, $fn, $linenr ])
222             if %opts;
223             }
224              
225             1;