File Coverage

blib/lib/Util/Underscore.pm
Criterion Covered Total %
statement 98 99 98.9
branch 10 12 83.3
condition 1 3 33.3
subroutine 32 32 100.0
pod n/a
total 141 146 96.5


line stmt bran cond sub pod time code
1             package Util::Underscore;
2              
3             #ABSTRACT: Common helper functions without having to import them
4              
5 13     13   124014 use strict;
  13         20  
  13         317  
6 13     13   46 use warnings;
  13         15  
  13         351  
7              
8 13     13   4983 use version 0.77; our $VERSION = qv('v1.4.0');
  13         17249  
  13         61  
9 13     13   8863 use overload ();
  13         6262  
  13         216  
10              
11 13     13   49 use Carp ();
  13         14  
  13         193  
12 13     13   5037 use Const::Fast 0.011 ();
  13         24140  
  13         275  
13 13     13   5751 use Data::Dump 1.10 ();
  13         48169  
  13         357  
14 13     13   6251 use List::MoreUtils 0.07 ();
  13         91400  
  13         338  
15 13     13   69 use List::Util 1.35 ();
  13         188  
  13         178  
16 13     13   5904 use POSIX ();
  13         60949  
  13         344  
17 13     13   70 use Scalar::Util 1.36 ();
  13         266  
  13         243  
18 13     13   6043 use Try::Tiny 0.03 ();
  13         13576  
  13         293  
19 13     13   10310 use IPC::Run 0.92 ();
  13         367671  
  13         627  
20              
21              
22             BEGIN {
23             # check if a competing "_" exists
24 13 100   13   417 if (keys %{_::}) {
25 1         23 Carp::confess qq(The package "_" has already been defined);
26             }
27             }
28              
29             BEGIN {
30             # Load the dummy "_.pm" module.
31             # This will set up various booby traps so that "_" isn't used directly.
32             # In order to prevent the traps from triggering when *we* go there, we have
33             # to declare our peaceful intentions:
34 12     12   35 local our $_WE_COME_IN_PEACE = 'pinky swear';
35 12         3987 require _;
36             }
37              
38             our $_ASSIGN_ALIASES;
39              
40             BEGIN {
41             $_ASSIGN_ALIASES = sub {
42 108         396 my ($pkg, %aliases) = @_;
43 12     12   41 no strict 'refs'; ## no critic (ProhibitNoStrict)
  12         13  
  12         1051  
44 108         264 while (my ($this, $that) = each %aliases) {
45 432         402 my $target = "_::${this}";
46 432         341 my $source = "${pkg}::${that}";
47 432         5621 *{$target} = *{$source}{CODE}
  432         1049  
48 432   33     276 // Carp::croak "Unknown subroutine $source in _ASSIGN_ALIASES";
49             }
50 12     12   493 };
51             }
52              
53              
54             # From now, every function is in the "_" package
55             ## no critic (ProhibitMultiplePackages)
56             package # Hide from PAUSE
57             _;
58              
59             ## no critic (RequireArgUnpacking, RequireFinalReturn, ProhibitSubroutinePrototypes)
60             # Why this "no critic"? In an util module, efficiency is crucial because we
61             # have no idea about the context where these function are being used. Therefore,
62             # no arg unpacking, and no explicit return. Most functions are so trivial anyway
63             # that this isn't much of a legibility concern.
64             # Subroutine prototypes are used to offer a convenient and natural interface.
65             # I fully understand why they shouldn't be used in ordinary code, but this
66             # module puts them to mostly good use.
67              
68             # Predeclare a few things so that we can use them in the sub definitions below.
69             sub blessed(_);
70             sub ref_type(_);
71              
72             # load the actual function collections
73 12     12   4633 use Util::Underscore::Scalars ();
  12         20  
  12         218  
74 12     12   4172 use Util::Underscore::Numbers ();
  12         16  
  12         166  
75 12     12   3915 use Util::Underscore::References ();
  12         17  
  12         198  
76 12     12   4011 use Util::Underscore::Objects ();
  12         15  
  12         182  
77 12     12   4138 use Util::Underscore::ListUtils ();
  12         20  
  12         381  
78              
79              
80             BEGIN {
81 12     12   27 $_ASSIGN_ALIASES->(
82             'Carp',
83             carp => 'carp',
84             cluck => 'cluck',
85             croak => 'croak',
86             confess => 'confess',
87             );
88             }
89              
90             $_ASSIGN_ALIASES->(
91             'Try::Tiny',
92             try => 'try',
93             catch => 'catch',
94             finally => 'finally',
95             );
96              
97             sub carpf($@) {
98 1     1   1929 my $pattern = shift;
99 1         6 @_ = sprintf $pattern, @_;
100 1         19 goto &carp;
101             }
102              
103             sub cluckf($@) {
104 1     1   621 my $pattern = shift;
105 1         5 @_ = sprintf $pattern, @_;
106 1         13 goto &cluck;
107             }
108              
109             sub croakf($@) {
110 1     1   1013 my $pattern = shift;
111 1         6 @_ = sprintf $pattern, @_;
112 1         10 goto &croak;
113             }
114              
115             sub confessf($@) {
116 1     1   524 my $pattern = shift;
117 1         6 @_ = sprintf $pattern, @_;
118 1         10 goto &confess;
119             }
120              
121              
122             $_ASSIGN_ALIASES->('Scalar::Util', is_open => 'openhandle');
123              
124             sub _::prototype ($;$) {
125 10 100   10   3346 if (@_ == 2) {
126 4 50       17 goto &Scalar::Util::set_prototype if @_ == 2;
127             }
128 6 50       11 if (@_ == 1) {
129 6         6 my ($coderef) = @_;
130 6         21 return prototype $coderef; # Calls CORE::prototype
131             }
132             else {
133             ## no critic (RequireInterpolationOfMetachars)
134 0         0 Carp::confess '_::prototype($;$) takes exactly one or two arguments';
135             }
136             }
137              
138             # This sub uses CamelCase because it's a factory function
139             sub Dir(@) { ## no critic (NamingConventions::Capitalization)
140 1     1   1448 require Path::Class;
141 1         20045 Path::Class::Dir->new(@_);
142             }
143              
144             # This sub uses CamelCase because it's a factory function
145             sub File(@) { ## no critic (NamingConventions::Capitalization)
146 1     1   1372 require Path::Class;
147 1         4 Path::Class::File->new(@_);
148             }
149              
150              
151             $_ASSIGN_ALIASES->(
152             'Data::Dump',
153             pp => 'pp',
154             dd => 'dd',
155             );
156              
157              
158             ## no critic (ProhibitBuiltinHomonyms)
159             sub caller(;$) {
160 3     3   1568 require Util::Underscore::CallStackFrame;
161 3 100       15 Util::Underscore::CallStackFrame->of(@_ ? shift() + 1 : 1);
162             }
163              
164             sub callstack(;$) {
165 2 100   2   2702 my $level = @_ ? shift() + 1 : 1;
166 2         2 my @callers;
167 2         7 while (my $caller = Util::Underscore::CallStackFrame->of($level + @callers))
168             {
169 23         39 push @callers, $caller;
170             }
171 2         12 return @callers;
172             }
173              
174              
175             $_ASSIGN_ALIASES->(
176             'IPC::Run',
177             process_run => 'run',
178             process_start => 'start',
179             );
180              
181              
182              
183             1;
184              
185             __END__