line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Acme::MetaSyntactic; |
2
|
|
|
|
|
|
|
$Acme::MetaSyntactic::VERSION = '1.014'; |
3
|
23
|
|
|
23
|
|
524563
|
use strict; |
|
23
|
|
|
|
|
149
|
|
|
23
|
|
|
|
|
576
|
|
4
|
23
|
|
|
23
|
|
111
|
use warnings; |
|
23
|
|
|
|
|
41
|
|
|
23
|
|
|
|
|
529
|
|
5
|
22
|
|
|
22
|
|
122
|
use Carp; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
1106
|
|
6
|
22
|
|
|
22
|
|
119
|
use File::Basename; |
|
22
|
|
|
|
|
43
|
|
|
22
|
|
|
|
|
1373
|
|
7
|
22
|
|
|
22
|
|
117
|
use File::Spec; |
|
22
|
|
|
|
|
39
|
|
|
22
|
|
|
|
|
448
|
|
8
|
22
|
|
|
22
|
|
96
|
use File::Glob; |
|
22
|
|
|
|
|
35
|
|
|
22
|
|
|
|
|
6672
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# some class data |
11
|
|
|
|
|
|
|
our $Theme = 'foo'; # default theme |
12
|
|
|
|
|
|
|
our %META; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# private class method |
15
|
|
|
|
|
|
|
sub _find_themes { |
16
|
23
|
|
|
23
|
|
118
|
my ( $class, @dirs ) = @_; |
17
|
|
|
|
|
|
|
return |
18
|
|
|
|
|
|
|
map @$_, |
19
|
496
|
|
|
|
|
1429
|
grep { $_->[0] !~ /^[A-Z]/ } # remove the non-theme subclasses |
20
|
496
|
|
|
|
|
8169
|
map { [ ( fileparse( $_, qr/\.pm$/ ) )[0] => $_ ] } |
21
|
23
|
|
|
|
|
70
|
map { File::Glob::bsd_glob( File::Spec->catfile( $_, qw( Acme MetaSyntactic *.pm ) ) ) } @dirs; |
|
233
|
|
|
|
|
8850
|
|
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# fetch the list of standard themes |
25
|
|
|
|
|
|
|
$META{$_} = 0 for keys %{ { __PACKAGE__->_find_themes(@INC) } }; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# the functions actually hide an instance |
28
|
|
|
|
|
|
|
my $meta = Acme::MetaSyntactic->new( $Theme ); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# END OF INITIALISATION |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# support for use Acme::MetaSyntactic 'foo' |
33
|
|
|
|
|
|
|
# that automatically loads the required classes |
34
|
|
|
|
|
|
|
sub import { |
35
|
13
|
|
|
13
|
|
87
|
my $class = shift; |
36
|
|
|
|
|
|
|
|
37
|
3
|
|
|
|
|
18
|
my @themes = ( grep { $_ eq ':all' } @_ ) |
38
|
13
|
50
|
|
|
|
45
|
? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first |
|
0
|
|
|
|
|
0
|
|
39
|
|
|
|
|
|
|
: @_; |
40
|
|
|
|
|
|
|
|
41
|
13
|
100
|
|
|
|
41
|
$Theme = $themes[0] if @themes; |
42
|
13
|
|
|
|
|
55
|
$meta = Acme::MetaSyntactic->new( $Theme ); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# export the metaname() function |
45
|
22
|
|
|
22
|
|
142
|
no strict 'refs'; |
|
22
|
|
|
|
|
47
|
|
|
22
|
|
|
|
|
7285
|
|
46
|
13
|
|
|
|
|
38
|
my $callpkg = caller; |
47
|
13
|
|
|
|
|
31
|
*{"$callpkg\::metaname"} = \&metaname; # standard theme |
|
13
|
|
|
|
|
67
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# load the classes in @themes |
50
|
13
|
|
|
|
|
4528
|
for my $theme( @themes ) { |
51
|
3
|
|
|
|
|
259
|
eval "require Acme::MetaSyntactic::$theme; import Acme::MetaSyntactic::$theme;"; |
52
|
3
|
100
|
|
|
|
157
|
croak $@ if $@; |
53
|
2
|
|
|
0
|
|
13
|
*{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; |
|
2
|
|
|
|
|
2386
|
|
|
0
|
|
|
|
|
0
|
|
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub new { |
58
|
55
|
|
|
55
|
1
|
8205
|
my ( $class, @args ) = ( @_ ); |
59
|
55
|
|
|
|
|
96
|
my $theme; |
60
|
55
|
100
|
|
|
|
200
|
$theme = shift @args if @args % 2; |
61
|
55
|
100
|
|
|
|
199
|
$theme = $Theme unless $theme; # same default everywhere |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# defer croaking until name() is actually called |
64
|
55
|
|
|
|
|
369
|
bless { theme => $theme, args => { @args }, meta => {} }, $class; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# CLASS METHODS |
68
|
|
|
|
|
|
|
sub add_theme { |
69
|
6
|
|
|
6
|
1
|
1526
|
my $class = shift; |
70
|
6
|
|
|
|
|
18
|
my %themes = @_; |
71
|
|
|
|
|
|
|
|
72
|
6
|
|
|
|
|
20
|
for my $theme ( keys %themes ) { |
73
|
6
|
100
|
|
|
|
197
|
croak "The theme $theme already exists!" if exists $META{$theme}; |
74
|
5
|
|
|
|
|
8
|
my @badnames = grep { !/^[a-z_]\w*$/i } @{$themes{$theme}}; |
|
15
|
|
|
|
|
61
|
|
|
5
|
|
|
|
|
13
|
|
75
|
5
|
100
|
|
|
|
93
|
croak "Invalid names (@badnames) for theme $theme" |
76
|
|
|
|
|
|
|
if @badnames; |
77
|
|
|
|
|
|
|
|
78
|
4
|
|
|
|
|
15
|
my $code = << "EOC"; |
79
|
|
|
|
|
|
|
package Acme::MetaSyntactic::$theme; |
80
|
|
|
|
|
|
|
use strict; |
81
|
|
|
|
|
|
|
use Acme::MetaSyntactic::List; |
82
|
|
|
|
|
|
|
our \@ISA = qw( Acme::MetaSyntactic::List ); |
83
|
4
|
|
|
|
|
18
|
our \@List = qw( @{$themes{$theme}} ); |
84
|
|
|
|
|
|
|
1; |
85
|
|
|
|
|
|
|
EOC |
86
|
4
|
|
|
3
|
|
267
|
eval $code; |
|
3
|
|
|
3
|
|
18
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
74
|
|
|
3
|
|
|
|
|
540
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
119
|
|
87
|
4
|
|
|
|
|
13
|
$META{$theme} = 1; # loaded |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# export the metatheme() function |
90
|
22
|
|
|
22
|
|
138
|
no strict 'refs'; |
|
22
|
|
|
|
|
39
|
|
|
22
|
|
|
|
|
2464
|
|
91
|
4
|
|
|
|
|
10
|
my $callpkg = caller; |
92
|
4
|
|
|
3
|
|
17
|
*{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; |
|
4
|
|
|
|
|
29
|
|
|
3
|
|
|
|
|
568
|
|
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# load the content of __DATA__ into a structure |
97
|
|
|
|
|
|
|
# this class method is used by the other Acme::MetaSyntactic classes |
98
|
|
|
|
|
|
|
sub load_data { |
99
|
20
|
|
|
20
|
1
|
832
|
my ($class, $theme ) = @_; |
100
|
20
|
|
|
|
|
48
|
my $data = {}; |
101
|
|
|
|
|
|
|
|
102
|
20
|
|
|
|
|
39
|
my $fh; |
103
|
22
|
|
|
22
|
|
131
|
{ no strict 'refs'; $fh = *{"$theme\::DATA"}{IO}; } |
|
22
|
|
|
|
|
50
|
|
|
22
|
|
|
|
|
11297
|
|
|
20
|
|
|
|
|
40
|
|
|
20
|
|
|
|
|
37
|
|
|
20
|
|
|
|
|
103
|
|
104
|
|
|
|
|
|
|
|
105
|
20
|
|
|
|
|
49
|
my $item; |
106
|
|
|
|
|
|
|
my @items; |
107
|
20
|
|
|
|
|
51
|
$$item = ""; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
{ |
110
|
20
|
|
|
|
|
35
|
local $_; |
|
20
|
|
|
|
|
41
|
|
111
|
20
|
|
|
|
|
319
|
while (<$fh>) { |
112
|
149
|
100
|
|
|
|
534
|
/^#\s*(\w+.*)$/ && do { |
113
|
62
|
|
|
|
|
130
|
push @items, $item; |
114
|
62
|
|
|
|
|
93
|
$item = $data; |
115
|
62
|
|
|
|
|
76
|
my $last; |
116
|
62
|
|
|
|
|
362
|
my @keys = split m!\s+|\s*/\s*!, $1; |
117
|
62
|
|
100
|
|
|
448
|
$last = $item, $item = $item->{$_} ||= {} for @keys; |
118
|
62
|
|
|
|
|
209
|
$item = \( $last->{ $keys[-1] } = "" ); |
119
|
62
|
|
|
|
|
265
|
next; |
120
|
|
|
|
|
|
|
}; |
121
|
87
|
|
|
|
|
153
|
s/#.*//; # remove end-of-line comments |
122
|
87
|
|
|
|
|
381
|
$$item .= $_; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# avoid leaving all the DATA handles open |
127
|
20
|
|
|
|
|
137
|
close $fh; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# clean up the items |
130
|
20
|
|
|
|
|
68
|
for( @items, $item ) { |
131
|
82
|
|
|
|
|
273
|
$$_ =~ s/\A\s*//; |
132
|
82
|
|
|
|
|
453
|
$$_ =~ s/\s*\z//; |
133
|
82
|
|
|
|
|
369
|
$$_ =~ s/\s+/ /g; |
134
|
|
|
|
|
|
|
} |
135
|
20
|
|
|
|
|
116
|
return $data; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# main function |
139
|
2
|
|
|
2
|
1
|
1763
|
sub metaname { $meta->name( @_ ) }; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# corresponding method |
142
|
|
|
|
|
|
|
sub name { |
143
|
26
|
|
|
26
|
1
|
2906
|
my $self = shift; |
144
|
26
|
|
|
|
|
47
|
my ( $theme, $count ); |
145
|
|
|
|
|
|
|
|
146
|
26
|
100
|
|
|
|
64
|
if (@_) { |
147
|
19
|
|
|
|
|
43
|
( $theme, $count ) = @_; |
148
|
19
|
100
|
|
|
|
101
|
( $theme, $count ) = ( $self->{theme}, $theme ) |
149
|
|
|
|
|
|
|
if $theme =~ /^(?:0|[1-9]\d*)$/; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
else { |
152
|
7
|
|
|
|
|
32
|
( $theme, $count ) = ( $self->{theme}, 1 ); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
26
|
100
|
|
|
|
79
|
if( ! exists $self->{meta}{$theme} ) { |
156
|
22
|
|
|
|
|
76
|
my ( $Theme, $category ) = split /\//, $theme, 2; |
157
|
22
|
100
|
|
|
|
63
|
if( ! $META{$Theme} ) { |
158
|
12
|
|
|
|
|
674
|
eval "require Acme::MetaSyntactic::$Theme;"; |
159
|
12
|
100
|
|
|
|
455
|
croak "Metasyntactic list $Theme does not exist!" if $@; |
160
|
9
|
|
|
|
|
22
|
$META{$theme} = 1; # loaded |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
$self->{meta}{$theme} |
163
|
19
|
|
|
|
|
63
|
= "Acme::MetaSyntactic::$Theme"->new( %{ $self->{args} }, |
|
19
|
|
|
|
|
114
|
|
164
|
|
|
|
|
|
|
( category => $category )x!! $category ); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
23
|
|
|
|
|
93
|
$self->{meta}{$theme}->name( $count ); |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# other methods |
171
|
9
|
100
|
|
9
|
1
|
527
|
sub themes { wantarray ? ( sort keys %META ) : scalar keys %META } |
172
|
4
|
100
|
|
4
|
1
|
29
|
sub has_theme { $_[1] ? exists $META{$_[1]} : 0 } |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
1; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
__END__ |