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   54544 use strict;
  1         7  
  1         32  
4 1     1   6 use warnings;
  1         1  
  1         19  
5 1     1   4 use Carp ();
  1         1  
  1         10  
6 1     1   3 use Cwd ();
  1         1  
  1         19  
7 1     1   10 use File::Basename ();
  1         1  
  1         11  
8 1     1   400 use Sub::Util ();
  1         239  
  1         146  
9              
10             our $VERSION = '0.004';
11              
12 3     3 1 1905 sub THISFILE () { Cwd::abs_path((caller)[1]) }
13             sub THISDIR () {
14 3     3 1 9 my $file = (caller)[1];
15 3 100       92 return -e $file ? File::Basename::dirname(Cwd::abs_path $file) : Cwd::getcwd;
16             }
17              
18             sub import {
19 6     6   737 my $class = shift;
20 6         15 my ($package, $file) = caller;
21              
22 6         10 my ($abs_file, $abs_dir);
23 6         9 foreach my $item (@_) {
24 12 100       55 if ($item =~ m/\A([&\$])?THISFILE\z/) {
    50          
25 6         13 my $symbol = $1;
26 6 100       11 unless (defined $abs_file) {
27 3         36 $abs_file = Cwd::abs_path $file;
28             }
29 6 100       13 if (!$symbol) {
    100          
    50          
30 2         3 my $const_file = $abs_file;
31 1     1   5 no strict 'refs';
  1         1  
  1         34  
32 1     1   6 no warnings 'redefine';
  1         1  
  1         77  
33 2         2 *{"${package}::THISFILE"} = \&{Sub::Util::set_subname
  2         1130  
34 2     0   18 "${package}::THISFILE", sub () { $const_file }};
  0         0  
35             } elsif ($symbol eq '&') {
36 1     1   6 no strict 'refs';
  1         1  
  1         32  
37 1     1   4 no warnings 'redefine';
  1         2  
  1         74  
38 2         4 *{"${package}::THISFILE"} = \&THISFILE;
  2         183  
39             } elsif ($symbol eq '$') {
40 1     1   5 no strict 'refs';
  1         1  
  1         106  
41 2         2 *{"${package}::THISFILE"} = \$abs_file;
  2         45  
42             }
43             } elsif ($item =~ m/\A([&\$])?THISDIR\z/) {
44 6         13 my $symbol = $1;
45 6 50       11 unless (defined $abs_dir) {
46 6 100       257 $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       20 if (!$symbol) {
    100          
    50          
51 2         3 my $const_dir = $abs_dir;
52 1     1   5 no strict 'refs';
  1         1  
  1         22  
53 1     1   4 no warnings 'redefine';
  1         1  
  1         128  
54 2         2 *{"${package}::THISDIR"} = \&{Sub::Util::set_subname
  2         13  
55 2     0   29 "${package}::THISDIR", sub () { $const_dir }};
  0         0  
56             } elsif ($symbol eq '&') {
57 1     1   6 no strict 'refs';
  1         1  
  1         39  
58 1     1   5 no warnings 'redefine';
  1         2  
  1         49  
59 2         4 *{"${package}::THISDIR"} = \&THISDIR;
  2         10  
60             } elsif ($symbol eq '$') {
61 1     1   5 no strict 'refs';
  1         1  
  1         96  
62 2         2 *{"${package}::THISDIR"} = \$abs_dir;
  2         9  
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             # using core modules - use constant or BEGIN to resolve __FILE__ at compile time
85             use Cwd 'abs_path';
86             use File::Basename 'dirname';
87             use constant THISFILE => abs_path __FILE__;
88             use constant THISDIR => dirname abs_path __FILE__;
89             my ($THISFILE, $THISDIR);
90             BEGIN { $THISFILE = abs_path __FILE__ }
91             BEGIN { $THISDIR = dirname abs_path __FILE__ }
92              
93             =head1 DESCRIPTION
94              
95             Exports package variables by request that represent the current source file or
96             directory containing that file. Dynamic or constant sub versions can also be
97             requested. Paths will be absolute with symlinks resolved.
98              
99             Note that the package variable or constant sub will be exported to the current
100             package globally. If the same package will be used in multiple files, use the
101             dynamic sub export so the file path will be calculated when the sub is called.
102              
103             For cases where this module cannot be loaded beforehand, the last section of
104             the L shows how to perform the same task with core modules.
105              
106             =head1 EXPORTS
107              
108             =head2 $THISFILE
109              
110             =head2 &THISFILE
111              
112             =head2 THISFILE
113              
114             print "$THISFILE\n";
115             my $file = THISFILE;
116              
117             Absolute path to the current source file. Behavior is undefined when called
118             without a source file (e.g. from the command line or STDIN). C<$THISFILE> will
119             export a package variable, C<&THISFILE> will export a dynamic subroutine, and
120             C will export an inlinable constant.
121              
122             =head2 $THISDIR
123              
124             =head2 &THISDIR
125              
126             =head2 THISDIR
127              
128             print "$THISDIR\n";
129             my $dir = THISDIR;
130              
131             Absolute path to the directory containing the current source file, or the
132             current working directory when called without a source file (e.g. from the
133             command line or STDIN). C<$THISDIR> will export a package variable, C<&THISDIR>
134             will export a dynamic subroutine, and C will export an inlinable
135             constant.
136              
137             =head1 BUGS
138              
139             Report any issues on the public bugtracker.
140              
141             =head1 AUTHOR
142              
143             Dan Book
144              
145             =head1 COPYRIGHT AND LICENSE
146              
147             This software is Copyright (c) 2019 by Dan Book.
148              
149             This is free software, licensed under:
150              
151             The Artistic License 2.0 (GPL Compatible)
152              
153             =head1 SEE ALSO
154              
155             L, L, L