File Coverage

blib/lib/Acme/MetaSyntactic/MultiList.pm
Criterion Covered Total %
statement 120 124 96.7
branch 20 22 90.9
condition 17 21 80.9
subroutine 23 23 100.0
pod 7 7 100.0
total 187 197 94.9


line stmt bran cond sub pod time code
1             package Acme::MetaSyntactic::MultiList;
2 11     11   73470 use strict;
  11         44  
  11         324  
3 11     11   573 use Acme::MetaSyntactic (); # do not export metaname and friends
  11         24  
  11         186  
4 11     11   3259 use Acme::MetaSyntactic::RemoteList;
  11         26  
  11         359  
5 11     11   67 use List::Util qw( shuffle );
  11         24  
  11         1056  
6 11     11   77 use Carp;
  11         21  
  11         1522  
7              
8             our @ISA = qw( Acme::MetaSyntactic::RemoteList );
9             our $VERSION = '1.000';
10              
11             sub init {
12 10     10 1 284 my ($self, $data) = @_;
13 10         32 my $class = caller(0);
14              
15 10   66     114 $data ||= Acme::MetaSyntactic->load_data($class);
16 11     11   81 no strict 'refs';
  11         24  
  11         5703  
17              
18             # note: variables mentioned twice to avoid a warning
19              
20 10   100     19 my $sep = ${"$class\::Separator"} = ${"$class\::Separator"} ||= '/';
  10         39  
  10         74  
21 10         276 my $tail = qr/$sep?[^$sep]*$/;
22              
23             # compute all categories
24 10         54 my @categories = ( [ $data->{names}, '' ] );
25 10 100       24 while ( my ( $h, $k ) = @{ shift @categories or []} ) {
  65         289  
26 55 100       140 if ( ref $h eq 'HASH' ) {
27             push @categories,
28 15 100       57 map { [ $h->{$_}, ( $k ? "$k$sep$_" : $_ ) ] } keys %$h;
  45         190  
29             }
30             else { # leaf
31 40         244 my @items = split /\s+/, $h;
32 40         122 while ($k) {
33 50         78 push @{ ${"$class\::MultiList"}{$k} }, @items;
  50         71  
  50         293  
34 50         362 $k =~ s!$tail!!;
35             }
36             }
37             }
38              
39 10   50     42 ${"$class\::Default"} = ${"$class\::Default"} = $data->{default} || ':all';
  10         81  
  10         129  
40 10         164 ${"$class\::Theme"} = ${"$class\::Theme"} = ( split /::/, $class )[-1];
  10         36  
  10         73  
41              
42 10         54 *{"$class\::import"} = sub {
43 5     5   38 my $callpkg = caller(0);
44 5         11 my $theme = ${"$class\::Theme"};
  5         23  
45 5         34 my $meta = $class->new;
46 5     1   42 *{"$callpkg\::meta$theme"} = sub { $meta->name(@_) };
  5         2194  
  1         5  
47 10         71 };
48              
49 10         95 ${"$class\::meta"} = ${"$class\::meta"} = $class->new();
  10         78  
  10         55  
50             }
51              
52             sub name {
53 92     92 1 11330 my ( $self, $count ) = @_;
54 92         241 my $class = ref $self;
55              
56 92 50       244 if ( !$class ) { # called as a class method!
57 0         0 $class = $self;
58 11     11   98 no strict 'refs';
  11         24  
  11         684  
59 0         0 $self = ${"$class\::meta"};
  0         0  
60             }
61              
62 92 100 100     383 if ( defined $count && $count == 0 ) {
63 11     11   73 no strict 'refs';
  11         23  
  11         1943  
64             return wantarray
65 45         578 ? shuffle @{ $self->{base} }
66 45 50       127 : scalar @{ $self->{base} };
  0         0  
67             }
68              
69 47   100     150 $count ||= 1;
70 47         87 my $list = $self->{cache};
71 47 100       70 if ( @{ $self->{base} } ) {
  47         114  
72 45         112 push @$list, shuffle @{ $self->{base} } while @$list < $count;
  48         383  
73             }
74 47         203 splice( @$list, 0, $count );
75             }
76              
77             sub new {
78 18     18 1 8750 my $class = shift;
79              
80 11     11   156 no strict 'refs';
  11         34  
  11         1861  
81 18         67 my $self = bless { @_, cache => [] }, $class;
82              
83             # compute some defaults
84 18   66     71 $self->{category} ||= ${"$class\::Default"};
  4         21  
85              
86             # fall back to last resort (FIXME should we carp()?)
87 1         5 $self->{category} = ${"$class\::Default"}
88             if $self->{category} ne ':all'
89 18 100 100     55 && !exists ${"$class\::MultiList"}{ $self->{category} };
  17         102  
90              
91 18         61 $self->_compute_base();
92 18         41 return $self;
93             }
94              
95             sub _compute_base {
96 74     74   157 my ($self) = @_;
97 74         144 my $class = ref $self;
98              
99             # compute the base list for this category
100 11     11   119 no strict 'refs';
  11         25  
  11         1982  
101 74         122 my %seen;
102             $self->{base} = [
103 695         1937 grep { !$seen{$_}++ }
104 88         133 map { @{ ${"$class\::MultiList"}{$_} } }
  88         128  
  88         594  
105             $self->{category} eq ':all'
106 2         44 ? ( keys %{"$class\::MultiList"} )
107             : ( $self->{category} )
108 74 100       256 ];
109 74         321 return;
110             }
111              
112 32     32 1 254 sub category { $_[0]->{category} }
113              
114             sub categories {
115 7     7 1 1198 my $class = shift;
116 7 100       46 $class = ref $class if ref $class;
117              
118 11     11   83 no strict 'refs';
  11         33  
  11         1113  
119 7         22 return keys %{"$class\::MultiList"};
  7         67  
120             }
121              
122             sub has_category {
123 6     6 1 579 my ($class, $category) = @_;
124 6 100       22 $class = ref $class if ref $class;
125              
126 11     11   79 no strict 'refs';
  11         21  
  11         1052  
127 6         9 return exists ${"$class\::MultiList"}{$category};
  6         44  
128             }
129              
130             sub theme {
131 2   66 2 1 19 my $class = ref $_[0] || $_[0];
132 11     11   75 no strict 'refs';
  11         33  
  11         750  
133 2         6 return ${"$class\::Theme"};
  2         18  
134             }
135              
136             1;
137              
138             __END__