File Coverage

lib/Package/Abbreviate.pm
Criterion Covered Total %
statement 50 51 98.0
branch 26 30 86.6
condition 1 3 33.3
subroutine 7 7 100.0
pod 2 2 100.0
total 86 93 92.4


line stmt bran cond sub pod time code
1             package Package::Abbreviate;
2              
3 3     3   132693 use strict;
  3         8  
  3         137  
4 3     3   18 use warnings;
  3         5  
  3         109  
5 3     3   19 use Carp;
  3         11  
  3         3202  
6              
7             our $VERSION = '0.01';
8              
9             sub new {
10 18     18 1 9995 my ($class, $max, $opts) = @_;
11              
12 18 50 33     201 croak "requires max length of abbreviation" unless $max && $max =~ /^\d+$/;
13              
14 18 50       23 bless {%{$opts || {}}, max => $max}, $class;
  18         134  
15             }
16              
17             sub abbr {
18 18     18 1 118 my ($self, @packages) = @_;
19              
20 18 100       62 return $self->_abbr($packages[0]) if @packages == 1;
21              
22 4         7 my @abbreviation = map { $self->_abbr($_) } @packages;
  8         17  
23              
24             # validation: everything should be unique
25             # (as long as packages are unique)
26 4         7 my (%seen, $num_of_dupes);
27 4         6 for (@abbreviation) {
28 8 100       35 $num_of_dupes++ if $seen{$_}++;
29             }
30 4 100       10 if ($num_of_dupes) {
31 2         3 %seen = ();
32 2         4 for (@packages) {
33 4 100       13 $num_of_dupes-- if $seen{$_}++;
34             }
35 2 100       11 $self->_error("Max length ($self->{max}) was too small and found duplicated abbreviations") if $num_of_dupes;
36             }
37 3         15 return @abbreviation;
38             }
39              
40             sub _abbr {
41 22     22   32 my ($self, $package) = @_;
42 22         42 my $max = $self->{max};
43 22         33 my $excess = length($package) - $max;
44 22 100       56 return $package unless $excess > 0;
45              
46 18         21 my $abbreviation = $package;
47 18         88 while($abbreviation =~ /(?:^|::)([A-Z]+[^A-Z][^:]+::)/) {
48 36         61 my $part = $1;
49 36         186 $excess -= (my $abbr = ucfirst $part) =~ s/[^A-Z:]//g;
50 36 50       98 $abbr = lcfirst $abbr if $part =~ /^[a-z]/;
51 36         403 $abbreviation =~ s/$part/$abbr/;
52 36 100       230 return $abbreviation unless $excess > 0;
53             }
54 10 100       29 if ($self->{eager}) {
55 9         42 my @parts = split /::/, $abbreviation;
56 9         25 my $n = int(($excess + 1) / 2);
57 9 100       26 if ($n < @parts - 1) {
58 2         14 $abbreviation = join '::', join('', @parts[0..$n]), @parts[$n+1..@parts-1];
59             } else {
60 7         36 $excess -= $parts[-1] =~ s/[^A-Z]//g;
61 7 100       17 if ($excess > 0) {
62 2         7 $abbreviation = join '', @parts;
63             } else {
64 5         16 $abbreviation = join '::', @parts;
65             }
66             }
67             }
68              
69 10 100       37 $self->_error("Max length ($self->{max}) was too small to abbreviate $package") if length($abbreviation) > $max;
70              
71 8         29 return $abbreviation;
72             }
73              
74             sub _error {
75 3     3   5 my ($self, $message) = @_;
76 3 50       544 croak $message if $self->{croak};
77 0           carp $message;
78             }
79              
80             1;
81              
82             __END__