File Coverage

blib/lib/Module/Format/Module.pm
Criterion Covered Total %
statement 59 64 92.1
branch 10 14 71.4
condition 2 2 100.0
subroutine 15 15 100.0
pod 7 7 100.0
total 93 102 91.1


line stmt bran cond sub pod time code
1             package Module::Format::Module;
2             $Module::Format::Module::VERSION = '0.0.8';
3 4     4   61181 use warnings;
  4         15  
  4         130  
4 4     4   22 use strict;
  4         7  
  4         7112  
5              
6              
7             sub _new
8             {
9 20     20   36 my $class = shift;
10 20         44 my $self = bless {}, $class;
11 20         54 $self->_init(@_);
12 20         84 return $self;
13             }
14              
15             sub _components
16             {
17 76     76   119 my $self = shift;
18              
19 76 100       179 if (@_)
20             {
21 20         41 $self->{_components} = shift;
22             }
23 76         423 return $self->{_components};
24             }
25              
26             sub _init
27             {
28 20     20   36 my ( $self, $args ) = @_;
29              
30 20         33 $self->_components( [ @{ $args->{_components} } ] );
  20         66  
31              
32 20         33 return;
33             }
34              
35              
36             sub from_components
37             {
38 4     4 1 1535 my ( $class, $args ) = @_;
39              
40 4         10 return $class->_new( { _components => [ @{ $args->{components} } ] } );
  4         17  
41             }
42              
43              
44             my $dash_re = qr{(?:\w+-)*\w+};
45             my $colon_re = qr{(?:\w+::)*\w+};
46              
47             my @formats_by_priority = (
48             {
49             name => 'rpm_dash',
50             regex => qr{\Aperl-$dash_re\z},
51             input => sub {
52             my ( $class, $value ) = @_;
53              
54             if ( $value !~ s{\Aperl-}{} )
55             {
56             die "rpm_dash value does not start with the 'perl-' prefix.";
57             }
58              
59             return $class->_calc_components_from_string(
60             { format => 'dash', value => $value } );
61             },
62             format => sub {
63             my ($self) = @_;
64              
65             return 'perl-' . $self->format_as('dash');
66             },
67             },
68             {
69             name => 'rpm_colon',
70             regex => qr{\Aperl\($colon_re\)\z},
71             input => sub {
72             my ( $class, $value ) = @_;
73              
74             if ( $value !~ m{\Aperl\(((?:\w+::)*\w+)\)\z} )
75             {
76             die "Improper value for rpm_colon";
77             }
78              
79             return $class->_calc_components_from_string(
80             { format => 'colon', value => $1 } );
81             },
82             format => sub {
83             my ($self) = @_;
84              
85             return 'perl(' . $self->format_as('colon') . ')';
86             },
87             },
88             {
89             name => 'colon',
90             regex => qr{\A$colon_re\z},
91             input => sub {
92             my ( $class, $value ) = @_;
93             return [ split( /::/, $value, -1 ) ];
94             },
95             format => sub {
96             my ($self) = @_;
97              
98             return join( '::', @{ $self->_components() } );
99             },
100             },
101             {
102             name => 'dash',
103             regex => qr{\A$dash_re\z},
104             input => sub {
105             my ( $class, $value ) = @_;
106             return [ split( /-/, $value, -1 ) ];
107             },
108             format => sub {
109             my ($self) = @_;
110              
111             return join( '-', @{ $self->_components() } );
112             },
113             },
114             {
115             name => 'unix',
116             regex => qr{\A(?:\w+/)*\w+\.pm\z},
117             input => sub {
118             my ( $class, $value ) = @_;
119              
120             if ( $value !~ s{\.pm\z}{} )
121             {
122             die "Cannot find a .pm suffix in the 'unix' format.";
123             }
124              
125             return [ split( m{/}, $value, -1 ) ];
126             },
127             format => sub {
128             my ($self) = @_;
129              
130             return join( '/', @{ $self->_components() } ) . '.pm';
131             },
132             },
133             {
134             name => 'debian',
135             format => sub {
136             my ($self) = @_;
137              
138             return 'lib' . lc( $self->format_as('dash') ) . '-perl';
139             },
140             },
141             );
142              
143             my %formats = ( map { $_->{name} => $_ } @formats_by_priority );
144              
145             sub _calc_components_from_string
146             {
147 21     21   40 my ( $class, $args ) = @_;
148              
149 21         36 my $format = $args->{format};
150 21         35 my $value = $args->{value};
151              
152 21 50       48 if ( exists( $formats{$format} ) )
153             {
154 21 50       60 if ( my $handler = $formats{$format}->{'input'} )
155             {
156 21         53 return $class->$handler($value);
157             }
158             else
159             {
160 0         0 die "Format $format is output-only!";
161             }
162             }
163             else
164             {
165 0         0 die "Unknown format '$format'!";
166             }
167             }
168              
169             sub from
170             {
171 16     16 1 2386 my ( $class, $args ) = @_;
172              
173 16         28 my $format = $args->{format};
174 16         47 my $value = $args->{value};
175              
176 16         42 return $class->_new(
177             {
178             _components => $class->_calc_components_from_string($args)
179             }
180             );
181             }
182              
183              
184             sub get_components_list
185             {
186 18     18 1 5200 my $self = shift;
187              
188 18         34 return [ @{ $self->_components() } ];
  18         42  
189             }
190              
191              
192             sub format_as
193             {
194 46     46 1 116 my ( $self, $format ) = @_;
195              
196 46 50       116 if ( exists( $formats{$format} ) )
197             {
198 46         97 my $handler = $formats{$format}->{'format'};
199 46         110 return $self->$handler();
200             }
201             else
202             {
203 0         0 die "Unknown format '$format';";
204             }
205              
206 0         0 return;
207             }
208              
209              
210             sub clone
211             {
212 1     1 1 229 my $self = shift;
213              
214             return
215 1         3 ref($self)
216             ->from_components( { components => $self->get_components_list() } );
217             }
218              
219              
220             sub _all
221             {
222 4     4   13 my ( $cb, $l ) = @_;
223              
224 4         13 foreach (@$l)
225             {
226 9 100       22 if ( not $cb->($_) )
227             {
228 1         7 return;
229             }
230             }
231              
232 3         14 return 1;
233             }
234              
235             sub is_sane
236             {
237 4     4 1 18 my $self = shift;
238              
239 4     9   24 return _all( sub { m{\A\w+\z}; }, $self->_components() );
  9         57  
240             }
241              
242              
243             sub from_guess
244             {
245 10     10 1 3061 my ( $class, $args ) = @_;
246              
247 10         23 my $dummy_format_string;
248              
249 10         26 my $string = $args->{value};
250 10   100     45 my $out_format_ref = ( $args->{format_ref} || ( \$dummy_format_string ) );
251              
252             # TODO : After the previous line the indentation in vim is reset to the
253             # first column.
254              
255 10         28 foreach my $format_record (@formats_by_priority)
256             {
257 31 50       92 if ( my $regex = $format_record->{regex} )
258             {
259 31 100       191 if ( $string =~ $regex )
260             {
261 10         24 my $format_id = $format_record->{name};
262              
263 10         17 ${$out_format_ref} = $format_id;
  10         19  
264              
265 10         49 return $class->from(
266             { value => $string, format => $format_id, } );
267             }
268             }
269             }
270              
271 0           die "Could not guess the format of the value '$string'!";
272             }
273              
274              
275             1; # End of Module::Format::Module
276              
277             __END__