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   148865 use strict;
  13         31  
  13         342  
6 13     13   91 use warnings;
  13         29  
  13         408  
7              
8 13     13   5146 use version 0.77; our $VERSION = qv('v1.4.2');
  13         22009  
  13         111  
9 13     13   8699 use overload ();
  13         6190  
  13         233  
10              
11 13     13   77 use Carp ();
  13         24  
  13         226  
12 13     13   5050 use Const::Fast 0.011 ();
  13         26884  
  13         325  
13 13     13   5368 use Data::Dump 1.10 ();
  13         50570  
  13         419  
14 13     13   6102 use List::MoreUtils 0.07 ();
  13         93988  
  13         392  
15 13     13   108 use List::Util 1.35 ();
  13         222  
  13         244  
16 13     13   6529 use POSIX ();
  13         71338  
  13         356  
17 13     13   104 use Scalar::Util 1.36 ();
  13         270  
  13         266  
18 13     13   5371 use Try::Tiny 0.03 ();
  13         21688  
  13         319  
19 13     13   9554 use IPC::Run 0.92 ();
  13         344299  
  13         661  
20              
21              
22             BEGIN {
23             # check if a competing "_" exists
24 13 100   13   453 if (keys %{_::}) {
25 1         22 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   58 local our $_WE_COME_IN_PEACE = 'pinky swear';
35 12         4422 require _;
36             }
37              
38             our $_ASSIGN_ALIASES;
39              
40             BEGIN {
41             $_ASSIGN_ALIASES = sub {
42 108         544 my ($pkg, %aliases) = @_;
43 12     12   76 no strict 'refs'; ## no critic (ProhibitNoStrict)
  12         25  
  12         1085  
44 108         386 while (my ($this, $that) = each %aliases) {
45 432         864 my $target = "_::${this}";
46 432         727 my $source = "${pkg}::${that}";
47 432         6915 *{$target} = *{$source}{CODE}
  432         1628  
48 432   33     610 // Carp::croak "Unknown subroutine $source in _ASSIGN_ALIASES";
49             }
50 12     12   542 };
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   4724 use Util::Underscore::Scalars ();
  12         29  
  12         240  
74 12     12   4142 use Util::Underscore::Numbers ();
  12         33  
  12         201  
75 12     12   4125 use Util::Underscore::References ();
  12         32  
  12         229  
76 12     12   4106 use Util::Underscore::Objects ();
  12         34  
  12         227  
77 12     12   5291 use Util::Underscore::ListUtils ();
  12         37  
  12         436  
78              
79              
80             BEGIN {
81 12     12   47 $_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   4211 my $pattern = shift;
99 1         7 @_ = sprintf $pattern, @_;
100 1         20 goto &carp;
101             }
102              
103             sub cluckf($@) {
104 1     1   1061 my $pattern = shift;
105 1         7 @_ = sprintf $pattern, @_;
106 1         15 goto &cluck;
107             }
108              
109             sub croakf($@) {
110 1     1   1507 my $pattern = shift;
111 1         7 @_ = sprintf $pattern, @_;
112 1         27 goto &croak;
113             }
114              
115             sub confessf($@) {
116 1     1   922 my $pattern = shift;
117 1         7 @_ = sprintf $pattern, @_;
118 1         11 goto &confess;
119             }
120              
121              
122             $_ASSIGN_ALIASES->('Scalar::Util', is_open => 'openhandle');
123              
124             sub _::prototype ($;$) {
125 10 100   10   4878 if (@_ == 2) {
126 4 50       30 goto &Scalar::Util::set_prototype if @_ == 2;
127             }
128 6 50       16 if (@_ == 1) {
129 6         13 my ($coderef) = @_;
130 6         26 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   2151 require Path::Class;
141 1         21305 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   2380 require Path::Class;
147 1         8 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   2350 require Util::Underscore::CallStackFrame;
161 3 100       18 Util::Underscore::CallStackFrame->of(@_ ? shift() + 1 : 1);
162             }
163              
164             sub callstack(;$) {
165 2 100   2   4139 my $level = @_ ? shift() + 1 : 1;
166 2         4 my @callers;
167 2         10 while (my $caller = Util::Underscore::CallStackFrame->of($level + @callers))
168             {
169 23         87 push @callers, $caller;
170             }
171 2         16 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__