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   47026 use strict;
  11         31  
  11         262  
3 11     11   305 use Acme::MetaSyntactic (); # do not export metaname and friends
  11         20  
  11         174  
4 11     11   1678 use Acme::MetaSyntactic::RemoteList;
  11         25  
  11         296  
5 11     11   61 use List::Util qw( shuffle );
  11         22  
  11         741  
6 11     11   55 use Carp;
  11         22  
  11         1071  
7              
8             our @ISA = qw( Acme::MetaSyntactic::RemoteList );
9             our $VERSION = '1.000';
10              
11             sub init {
12 10     10 1 244 my ($self, $data) = @_;
13 10         32 my $class = caller(0);
14              
15 10   66     91 $data ||= Acme::MetaSyntactic->load_data($class);
16 11     11   68 no strict 'refs';
  11         23  
  11         4276  
17              
18             # note: variables mentioned twice to avoid a warning
19              
20 10   100     16 my $sep = ${"$class\::Separator"} = ${"$class\::Separator"} ||= '/';
  10         36  
  10         64  
21 10         213 my $tail = qr/$sep?[^$sep]*$/;
22              
23             # compute all categories
24 10         48 my @categories = ( [ $data->{names}, '' ] );
25 10 100       20 while ( my ( $h, $k ) = @{ shift @categories or []} ) {
  65         273  
26 55 100       141 if ( ref $h eq 'HASH' ) {
27             push @categories,
28 15 100       57 map { [ $h->{$_}, ( $k ? "$k$sep$_" : $_ ) ] } keys %$h;
  45         176  
29             }
30             else { # leaf
31 40         257 my @items = split /\s+/, $h;
32 40         100 while ($k) {
33 50         87 push @{ ${"$class\::MultiList"}{$k} }, @items;
  50         67  
  50         289  
34 50         351 $k =~ s!$tail!!;
35             }
36             }
37             }
38              
39 10   50     35 ${"$class\::Default"} = ${"$class\::Default"} = $data->{default} || ':all';
  10         65  
  10         58  
40 10         76 ${"$class\::Theme"} = ${"$class\::Theme"} = ( split /::/, $class )[-1];
  10         41  
  10         53  
41              
42 10         50 *{"$class\::import"} = sub {
43 5     5   28 my $callpkg = caller(0);
44 5         10 my $theme = ${"$class\::Theme"};
  5         17  
45 5         18 my $meta = $class->new;
46 5     1   23 *{"$callpkg\::meta$theme"} = sub { $meta->name(@_) };
  5         1344  
  1         4  
47 10         65 };
48              
49 10         101 ${"$class\::meta"} = ${"$class\::meta"} = $class->new();
  10         69  
  10         47  
50             }
51              
52             sub name {
53 92     92 1 12246 my ( $self, $count ) = @_;
54 92         183 my $class = ref $self;
55              
56 92 50       227 if ( !$class ) { # called as a class method!
57 0         0 $class = $self;
58 11     11   75 no strict 'refs';
  11         24  
  11         526  
59 0         0 $self = ${"$class\::meta"};
  0         0  
60             }
61              
62 92 100 100     348 if ( defined $count && $count == 0 ) {
63 11     11   55 no strict 'refs';
  11         21  
  11         1319  
64             return wantarray
65 45         413 ? shuffle @{ $self->{base} }
66 45 50       110 : scalar @{ $self->{base} };
  0         0  
67             }
68              
69 47   100     162 $count ||= 1;
70 47         87 my $list = $self->{cache};
71 47 100       76 if ( @{ $self->{base} } ) {
  47         115  
72 45         133 push @$list, shuffle @{ $self->{base} } while @$list < $count;
  48         416  
73             }
74 47         212 splice( @$list, 0, $count );
75             }
76              
77             sub new {
78 18     18 1 11081 my $class = shift;
79              
80 11     11   62 no strict 'refs';
  11         25  
  11         1379  
81 18         79 my $self = bless { @_, cache => [] }, $class;
82              
83             # compute some defaults
84 18   66     82 $self->{category} ||= ${"$class\::Default"};
  4         25  
85              
86             # fall back to last resort (FIXME should we carp()?)
87 1         4 $self->{category} = ${"$class\::Default"}
88             if $self->{category} ne ':all'
89 18 100 100     59 && !exists ${"$class\::MultiList"}{ $self->{category} };
  17         111  
90              
91 18         64 $self->_compute_base();
92 18         60 return $self;
93             }
94              
95             sub _compute_base {
96 74     74   134 my ($self) = @_;
97 74         130 my $class = ref $self;
98              
99             # compute the base list for this category
100 11     11   102 no strict 'refs';
  11         26  
  11         1380  
101 74         112 my %seen;
102             $self->{base} = [
103 695         1593 grep { !$seen{$_}++ }
104 88         126 map { @{ ${"$class\::MultiList"}{$_} } }
  88         111  
  88         440  
105             $self->{category} eq ':all'
106 2         19 ? ( keys %{"$class\::MultiList"} )
107             : ( $self->{category} )
108 74 100       214 ];
109 74         267 return;
110             }
111              
112 32     32 1 227 sub category { $_[0]->{category} }
113              
114             sub categories {
115 7     7 1 1290 my $class = shift;
116 7 100       25 $class = ref $class if ref $class;
117              
118 11     11   63 no strict 'refs';
  11         24  
  11         754  
119 7         16 return keys %{"$class\::MultiList"};
  7         56  
120             }
121              
122             sub has_category {
123 6     6 1 449 my ($class, $category) = @_;
124 6 100       17 $class = ref $class if ref $class;
125              
126 11     11   60 no strict 'refs';
  11         20  
  11         728  
127 6         9 return exists ${"$class\::MultiList"}{$category};
  6         33  
128             }
129              
130             sub theme {
131 2   66 2 1 10 my $class = ref $_[0] || $_[0];
132 11     11   58 no strict 'refs';
  11         23  
  11         497  
133 2         4 return ${"$class\::Theme"};
  2         13  
134             }
135              
136             1;
137              
138             __END__