File Coverage

blib/lib/Path/This.pm
Criterion Covered Total %
statement 80 83 96.3
branch 21 26 80.7
condition n/a
subroutine 19 21 90.4
pod 2 2 100.0
total 122 132 92.4


line stmt bran cond sub pod time code
1             package Path::This;
2              
3 1     1   69070 use strict;
  1         11  
  1         30  
4 1     1   4 use warnings;
  1         2  
  1         23  
5 1     1   5 use Carp ();
  1         2  
  1         12  
6 1     1   5 use Cwd ();
  1         2  
  1         27  
7 1     1   6 use File::Basename ();
  1         1  
  1         20  
8 1     1   476 use Sub::Util ();
  1         313  
  1         181  
9              
10             our $VERSION = '0.005';
11              
12 3     3 1 2638 sub THISFILE () { Cwd::abs_path((caller)[1]) }
13             sub THISDIR () {
14 3     3 1 13 my $file = (caller)[1];
15 3 100       124 return -e $file ? File::Basename::dirname(Cwd::abs_path $file) : Cwd::getcwd;
16             }
17              
18             sub import {
19 6     6   942 my $class = shift;
20 6         21 my ($package, $file) = caller;
21              
22 6         12 my ($abs_file, $abs_dir);
23 6         12 foreach my $item (@_) {
24 12 100       75 if ($item =~ m/\A([&\$])?THISFILE\z/) {
    50          
25 6         13 my $symbol = $1;
26 6 100       15 unless (defined $abs_file) {
27 3         47 $abs_file = Cwd::abs_path $file;
28             }
29 6 100       22 if (!$symbol) {
    100          
    50          
30 2         3 my $const_file = $abs_file;
31 1     1   7 no strict 'refs';
  1         2  
  1         41  
32 1     1   6 no warnings 'redefine';
  1         2  
  1         95  
33 2         3 *{"${package}::THISFILE"} = \&{Sub::Util::set_subname
  2         1458  
34 2     0   20 "${package}::THISFILE", sub () { $const_file }};
  0         0  
35             } elsif ($symbol eq '&') {
36 1     1   6 no strict 'refs';
  1         2  
  1         39  
37 1     1   6 no warnings 'redefine';
  1         2  
  1         86  
38 2         5 *{"${package}::THISFILE"} = \&THISFILE;
  2         239  
39             } elsif ($symbol eq '$') {
40 1     1   7 no strict 'refs';
  1         1  
  1         142  
41 2         3 *{"${package}::THISFILE"} = \$abs_file;
  2         58  
42             }
43             } elsif ($item =~ m/\A([&\$])?THISDIR\z/) {
44 6         16 my $symbol = $1;
45 6 50       17 unless (defined $abs_dir) {
46 6 100       326 $abs_dir = defined $abs_file ? File::Basename::dirname($abs_file)
    50          
47             : -e $file ? File::Basename::dirname($abs_file = Cwd::abs_path $file)
48             : Cwd::getcwd;
49             }
50 6 100       28 if (!$symbol) {
    100          
    50          
51 2         5 my $const_dir = $abs_dir;
52 1     1   8 no strict 'refs';
  1         2  
  1         26  
53 1     1   4 no warnings 'redefine';
  1         13  
  1         114  
54 2         3 *{"${package}::THISDIR"} = \&{Sub::Util::set_subname
  2         16  
55 2     0   35 "${package}::THISDIR", sub () { $const_dir }};
  0         0  
56             } elsif ($symbol eq '&') {
57 1     1   6 no strict 'refs';
  1         2  
  1         38  
58 1     1   5 no warnings 'redefine';
  1         2  
  1         60  
59 2         7 *{"${package}::THISDIR"} = \&THISDIR;
  2         12  
60             } elsif ($symbol eq '$') {
61 1     1   6 no strict 'refs';
  1         2  
  1         142  
62 2         4 *{"${package}::THISDIR"} = \$abs_dir;
  2         11  
63             }
64             } else {
65 0           Carp::croak qq{"$item" is not exported by the $class module};
66             }
67             }
68             }
69              
70             1;
71              
72             =head1 NAME
73              
74             Path::This - Path to this source file or directory
75              
76             =head1 SYNOPSIS
77              
78             use Path::This '$THISFILE';
79             print "This file is $THISFILE\n";
80              
81             use Path::This '$THISDIR';
82             use lib "$THISDIR/../lib";
83              
84             # constant subs can be constant-folded by the parser
85              
86             use Path::This 'THISDIR';
87             my $bar_path = THISDIR . '/bar'; # string formed at parse time
88              
89             # equivalent values resolved with only core modules
90             # use constant or BEGIN to resolve __FILE__ as early as possible
91              
92             use Cwd 'abs_path';
93             use File::Basename 'dirname';
94              
95             use constant THISFILE => abs_path __FILE__;
96             # or
97             my $THISFILE;
98             BEGIN { $THISFILE = abs_path __FILE__ }
99              
100             use constant THISDIR => dirname abs_path __FILE__;
101             # or
102             my $THISDIR;
103             BEGIN { $THISDIR = dirname abs_path __FILE__ }
104              
105             =head1 DESCRIPTION
106              
107             Exports package variables by request that represent the current source file or
108             directory containing that file. Dynamic or constant sub versions can also be
109             requested. Paths will be absolute with symlinks resolved.
110              
111             Note that the package variable or constant sub will be exported to the current
112             package globally. If the same package will be defined across multiple files,
113             use the dynamic sub export so the file path will be calculated when the sub is
114             called.
115              
116             For cases where this module cannot be loaded beforehand, the last section of
117             the L shows how to perform the same task with core modules.
118              
119             See L for the specific case of adding paths to C<@INC> relative
120             to the current source file.
121              
122             =head1 EXPORTS
123              
124             =head2 $THISFILE
125              
126             =head2 &THISFILE
127              
128             =head2 THISFILE
129              
130             print "$THISFILE\n";
131             my $file = THISFILE;
132              
133             Absolute path to the current source file. Behavior is undefined when called
134             without a source file (e.g. from the command line or STDIN). C<$THISFILE> will
135             export a package variable, C<&THISFILE> will export a dynamic subroutine (C<&>
136             not needed to call it), and C will export an inlinable constant.
137              
138             =head2 $THISDIR
139              
140             =head2 &THISDIR
141              
142             =head2 THISDIR
143              
144             print "$THISDIR\n";
145             my $dir = THISDIR;
146              
147             Absolute path to the directory containing the current source file, or the
148             current working directory when called without a source file (e.g. from the
149             command line or STDIN). C<$THISDIR> will export a package variable, C<&THISDIR>
150             will export a dynamic subroutine (C<&> not needed to call it), and C
151             will export an inlinable constant.
152              
153             =head1 BUGS
154              
155             Report any issues on the public bugtracker.
156              
157             =head1 AUTHOR
158              
159             Dan Book
160              
161             =head1 COPYRIGHT AND LICENSE
162              
163             This software is Copyright (c) 2019 by Dan Book.
164              
165             This is free software, licensed under:
166              
167             The Artistic License 2.0 (GPL Compatible)
168              
169             =head1 SEE ALSO
170              
171             L, L, L