File Coverage

lib/File/Corresponding/File/Profile.pm
Criterion Covered Total %
statement 34 34 100.0
branch 7 8 87.5
condition n/a
subroutine 9 9 100.0
pod 2 3 66.6
total 52 54 96.3


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             File::Corresponding::File::Profile - The definition of what matches
5             and translates to corresponding files
6              
7             =cut
8              
9 6     6   872 use strict;
  6         11  
  6         325  
10             package File::Corresponding::File::Profile;
11             $File::Corresponding::File::Profile::VERSION = '0.004';
12 6     6   971 use Moose;
  6         668640  
  6         35  
13              
14 6     6   30905 use Moose::Util::TypeConstraints;
  6         10  
  6         51  
15 6     6   11117 use Data::Dumper;
  6         9371  
  6         326  
16 6     6   410 use Path::Class;
  6         32063  
  6         251  
17              
18 6     6   1993 use File::Corresponding::File::Found;
  6         16  
  6         2115  
19              
20              
21              
22             =head1 PROPERTIES
23              
24             =head2 name
25              
26             Name/description of this file profile.
27              
28             =cut
29             has 'name' => (is => 'ro', isa => 'Str', default => "");
30              
31              
32              
33              
34             =head2 sprintf
35              
36             sprintf string to construct a file name. It should contain at least
37             one % command to insert a relative file name.
38              
39             Only used if defined.
40              
41             =cut
42             has 'sprintf' => (is => 'ro', isa => 'Maybe[Str]');
43              
44              
45              
46             =head2 regex : RegexRef
47              
48             Regex matching a file. The first capture parens are used to extract
49             the local file name.
50              
51             If coerced from a string, define as qr$regex, i.e. specify the
52             delimiters and any needed flags.
53              
54             =cut
55              
56             subtype RegexRef
57             => as RegexpRef
58             => where { ref($_) eq "Regexp" }; #print "JPL: where: ($_) (" . ref($_) . ")\n";
59             coerce RegexRef
60             => from 'Str'
61             => via { regex_from_qr($_) };
62              
63             has 'regex' => (
64             is => 'rw',
65             isa => 'RegexRef',
66             coerce => 1,
67             required => 1,
68             );
69              
70              
71              
72             =head1 METHODS
73              
74             =head2 matching_file_fragment($file) : ($file_base, $file_fragment) | ()
75              
76             Return two item list with (the base filename, the captured file name
77             fragment) from matching $file against regex, or () if nothing matched.
78              
79             The $file_base is the $file, but with the whole matching regex
80             removed, forming the basis for looking up corresponding files.
81              
82             =cut
83              
84             sub matching_file_fragment {
85 17     17 1 1113 my $self = shift;
86 17         19 my ($file) = @_;
87 17         446 my $regex = $self->regex;
88              
89 17         42 my $file_base = $file;
90 17 100       117 $file_base =~ s/$regex// and return ($file_base, $1);
91              
92 8         20 return ();
93             }
94              
95              
96              
97             =head2 new_found_if_file_exists($matching_profile, $file_base, $fragment) : File::Found | ()
98              
99             Return a new File::Corresponding::File::Found object if a file made up
100             of $file_base, this profile, and $fragment exists in the filesystem.
101              
102             If not, return ().
103              
104             =cut
105              
106             sub new_found_if_file_exists {
107 16     16 1 786 my $self = shift;
108 16         28 my ($matching_profile, $file_base, $fragment) = @_;
109 16 100       398 my $sprintf = $self->sprintf or return ();
110              
111 15         87 my $file = file($file_base, sprintf($sprintf, $fragment));
112              
113 15 100       1453 -e $file or return ();
114              
115 11         507 return File::Corresponding::File::Found->new({
116             # re-coerce into File object to make test happy
117             file => $file . "",
118             matching_profile => $matching_profile,
119             found_profile => $self,
120             });
121             }
122              
123              
124              
125             =head1 SUBROUTINES
126              
127             =head2 rex_from_qr($rex_string) : RegexRef
128              
129             Convert $rex_string to a proper Regex ref, or die with a useful error
130             message.
131              
132             =cut
133             sub regex_from_qr {
134 6     6 0 9 my ($rex_string) = @_;
135 6         327 my $rex = eval "qr $rex_string";
136 6 50       20 $@ and die("Could not parse regexp ($rex_string):
137             $@
138             Correct regex syntax is e.g. '/ prove [.] bat /x'
139             ");
140 6         24 return $rex;
141             }
142              
143              
144              
145             1;
146              
147              
148              
149             __END__