File Coverage

blib/lib/true.pm
Criterion Covered Total %
statement 42 43 97.6
branch 10 14 71.4
condition 5 6 83.3
subroutine 11 11 100.0
pod 0 1 0.0
total 68 75 90.6


line stmt bran cond sub pod time code
1             package true;
2              
3 11     11   105574 use strict;
  11         24  
  11         298  
4 11     11   50 use warnings;
  11         22  
  11         255  
5              
6 11     11   5195 use B::Hooks::OP::Annotation;
  11         8060  
  11         320  
7 11     11   4711 use B::Hooks::OP::Check;
  11         12942  
  11         382  
8 11     11   5167 use Devel::StackTrace;
  11         38044  
  11         384  
9 11     11   79 use XSLoader;
  11         20  
  11         296  
10              
11             # XXX this declaration must be on a single line
12             # https://metacpan.org/pod/version#How-to-declare()-a-dotted-decimal-version
13 11     11   4505 use version 0.77; our $VERSION = version->declare('v1.0.2');
  11         19586  
  11         145  
14              
15             our %TRUE;
16              
17             # set the logger from the first rule which matches the $TRUE_PM_DEBUG
18             # environment variable:
19             #
20             # - warn with a backtrace (cluck) if it's an integer > 1
21             # - warn (without a backtrace) if it's truthy
22             # - otherwise (default), do nothing
23             #
24             our $DEBUG = do {
25             my $debug = $ENV{TRUE_PM_DEBUG} || '0';
26             $debug = $debug =~ /^\d+$/ ? int($debug) : 1;
27             $debug && ($debug > 1 ? do { require Carp; \&Carp::cluck } : sub { warn(@_) });
28             };
29              
30             XSLoader::load(__PACKAGE__, $VERSION);
31              
32             sub _debug($) {
33 45 50   45   112 $DEBUG->(@_, $/) if ($DEBUG);
34             }
35              
36             # return the full path of the file that's currently being compiled.
37             # XXX CopFILE(&PL_compiling) gives the wrong result here (it works in the
38             # OP-checker in the XS).
39             sub ccfile() {
40 64     64 0 109 my ($file, $source, $line);
41 64         243 my $trace = Devel::StackTrace->new;
42              
43             # find the innermost require frame
44             #
45             # for "use Foo::Bar" or "require Foo::Bar", the evaltext contains
46             # "Foo/Bar.pm", and the filename/line refer to the file where the
47             # use/require statement appeared.
48              
49             # work from the innermost frame out
50 64         18203 while (my $frame = $trace->next_frame) {
51 470 100       42035 next unless ($frame->is_require);
52              
53 61         368 my $required = $frame->evaltext;
54              
55 61 50       353 if (defined($file = $INC{$required})) {
56 61         131 $source = $frame->filename;
57 61         473 $line = $frame->line;
58             } else { # shouldn't happen
59 0         0 warn "true: can't find required file ($required) in \%INC";
60             }
61              
62 61         280 last;
63             }
64              
65 64 50       1260 return wantarray ? ($file, $source, $line) : $file;
66             }
67              
68             sub import {
69 56     56   88116 my ($file, $source, $line) = ccfile();
70              
71 56 100 100     989 if (defined($file) && not($TRUE{$file})) {
72 41         89 $TRUE{$file} = 1;
73 41         188 _debug "true: enabling true for $file at $source line $line";
74 41         3085 xs_enter();
75             }
76             }
77              
78             sub unimport {
79 8     8   112 my ($file, $source, $line) = ccfile();
80              
81 8 100 66     256 if (defined($file) && $TRUE{$file}) {
82 4         21 _debug "true: disabling true for $file at $source line $line";
83 4         9 delete $TRUE{$file};
84 4 50       160 xs_leave() unless (%TRUE);
85             }
86             }
87              
88             1;
89              
90             __END__
91              
92             =head1 NAME
93              
94             true - automatically return a true value when a file is required
95              
96             =head1 SYNOPSIS
97              
98             package Contemporary::Perl;
99              
100             use strict;
101             use warnings;
102             use true;
103              
104             sub import {
105             strict->import();
106             warnings->import();
107             true->import();
108             }
109              
110             =head1 DESCRIPTION
111              
112             Perl's C<require> builtin (and its C<use> wrapper) requires the files it loads
113             to return a true value. This is usually accomplished by placing a single
114              
115             1;
116              
117             statement at the end of included scripts or modules. It's not onerous to add
118             but it's a speed bump on the Perl novice's road to enlightenment. In addition,
119             it appears to be a I<non-sequitur> to the uninitiated, leading some to attempt
120             to mitigate its appearance with a comment:
121              
122             1; # keep require happy
123              
124             or:
125              
126             1; # Do not remove this line
127              
128             or even:
129              
130             1; # Must end with this, because Perl is bogus.
131              
132             This module packages this "return true" behaviour so that it doesn't need to be
133             written explicitly. It can be used directly, but it is intended to be invoked
134             from the C<import> method of a L<Modern::Perl|Modern::Perl>-style module that
135             enables modern Perl features and conveniences and cleans up legacy Perl warts.
136              
137             =head2 METHODS
138              
139             C<true> is file-scoped rather than lexically-scoped. Importing it anywhere in a
140             file (e.g. at the top-level or in a nested scope) causes that file to return true,
141             and unimporting it anywhere in a file restores the default behaviour. Redundant
142             imports/unimports are ignored.
143              
144             =head3 import
145              
146             Enable the "automatically return true" behaviour for the currently-compiling
147             file. This should typically be invoked from the C<import> method of a module
148             that loads C<true>. Code that uses this module solely on behalf of its callers
149             can load C<true> without importing it e.g.
150              
151             use true (); # don't import
152              
153             sub import {
154             true->import();
155             }
156              
157             1;
158              
159             But there's nothing stopping a wrapper module also importing C<true> to obviate
160             its own need to explicitly return a true value:
161              
162             use true; # both load and import it
163              
164             sub import {
165             true->import();
166             }
167              
168             # no need to return true
169              
170             =head3 unimport
171              
172             Disable the "automatically return true" behaviour for the currently-compiling file.
173              
174             =head2 EXPORTS
175              
176             None by default.
177              
178             =head1 NOTES
179              
180             Because the unquoted name C<true> represents the boolean value C<true> in YAML,
181             the module name must be quoted when written as a dependency in META.yml. In cases
182             where this can't easily be done, a dependency can be declared on the package
183             L<true::VERSION>, which has the same version as C<true.pm>.
184              
185             =head1 VERSION
186              
187             1.0.2
188              
189             =head1 SEE ALSO
190              
191             =over
192              
193             =item * L<latest>
194              
195             =item * L<Modern::Perl>
196              
197             =item * L<nonsense>
198              
199             =item * L<perl5i>
200              
201             =item * L<Toolkit>
202              
203             =back
204              
205             =head1 AUTHOR
206              
207             chocolateboy <chocolate@cpan.org>
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             Copyright (c) 2010-2020 by chocolateboy.
212              
213             This library is free software; you can redistribute it and/or modify it under the
214             terms of the L<Artistic License 2.0|https://www.opensource.org/licenses/artistic-license-2.0.php>.
215              
216             =cut