File Coverage

blib/lib/Text/Naming/Convention.pm
Criterion Covered Total %
statement 87 92 94.5
branch 41 48 85.4
condition 26 27 96.3
subroutine 9 9 100.0
pod 4 4 100.0
total 167 180 92.7


line stmt bran cond sub pod time code
1             package Text::Naming::Convention;
2              
3 2     2   46094 use warnings;
  2         5  
  2         53  
4 2     2   9 use strict;
  2         4  
  2         59  
5 2     2   10 use Carp;
  2         8  
  2         157  
6              
7 2     2   9 use base qw/Exporter/;
  2         3  
  2         2603  
8             our @EXPORT_OK = qw/naming renaming default_convention default_keep_uppers/;
9              
10             our $VERSION = '0.06';
11              
12             my @_valid_conventions = ( '_', '-', 'UpperCamelCase', 'lowerCamelCase' );
13             my $_default_convention = '_';
14              
15             # keep the upper case for word like 'RFC', but not 'bAr', that only take
16             # effect for CamelCase conventions, and not the first word if it's
17             # lowerCamelCase.
18             my $_default_keep_uppers = 1;
19              
20             =head2 default_convention
21              
22             get or set default convention, default is '_'.
23             valid values are ( '_', '-', 'UpperCamelCase', 'lowerCamelCase' ).
24             return the default convention.
25              
26             =cut
27              
28             sub default_convention {
29 3     3 1 20 my $convention = shift;
30 3 100       14 return $_default_convention unless $convention;
31              
32 2 50       4 if ( grep { $_ eq $convention } @_valid_conventions ) {
  8         22  
33 2         3 $_default_convention = $convention;
34             }
35             else {
36 0         0 carp "invalid convention: $convention";
37             }
38 2         8 return $_default_convention;
39             }
40              
41             =head2 default_keep_uppers
42              
43             keep words of uppers or not, here uppers means all uppers like 'BAR', not 'bAr'.
44             default value is true
45              
46             =cut
47              
48             sub default_keep_uppers {
49 2 100   2 1 426 if (@_) {
50 1         2 $_default_keep_uppers = shift;
51             }
52 2         10 return $_default_keep_uppers;
53              
54             }
55              
56             =head2 naming
57              
58             given a list of words, return the named string
59             the last arg can be hashref that supplies option like:
60             { convention => 'UpperCamelCase' }
61              
62             =cut
63              
64             sub naming {
65 14     14 1 3142 my @words = @_;
66 14         24 my $convention = $_default_convention;
67 14         18 my $keep_uppers = $_default_keep_uppers;
68              
69 14 100       33 if ( ref $words[-1] eq 'HASH' ) {
70 10         13 my $option = pop @words;
71              
72             # the last element is option
73 10 50       22 if ( _is_valid_convention( $option->{convention} ) ) {
74 10         17 $convention = $option->{convention};
75             }
76             else {
77 0         0 carp "invlid convention: $option->{convention}";
78             }
79              
80 10 50       23 if ( exists $option->{keep_uppers} ) {
81 0         0 $keep_uppers = $option->{keep_uppers};
82             }
83             }
84              
85 14         21 for my $word (@words) {
86 50 100 100     244 next if $keep_uppers && $word =~ /^[A-Z]+$/ && $convention =~ /Camel/;
      100        
87 46         82 $word = lc $word;
88             }
89              
90 14 100       49 if ( $convention eq '_' ) {
    100          
    100          
    50          
91 4         26 return join '_', @words;
92             }
93             elsif ( $convention eq '-' ) {
94 4         38 return join '-', @words;
95             }
96             elsif ( $convention eq 'UpperCamelCase' ) {
97 3         4 return join '', map { ucfirst } @words;
  11         51  
98             }
99             elsif ( $convention eq 'lowerCamelCase' ) {
100 3         5 my $first = shift @words;
101 3         4 $first = lc $first;
102 3         8 return $first . join '', map { ucfirst } @words;
  8         32  
103             }
104             else {
105 0         0 carp "invalid $convention: $convention";
106             }
107             }
108              
109             sub _is_valid_convention {
110 43     43   53 my $convention = shift;
111 43 50       73 return unless $convention;
112 43         58 return grep { $_ eq $convention } @_valid_conventions;
  172         315  
113             }
114              
115             =head2 renaming
116              
117             given a name, renaming it with another convention.
118             the last arg can be hashref that supplies option like:
119             { convention => 'UpperCamelCase' }
120              
121             return the renamed one.
122              
123             if the convention is the same as the name, just return the name.
124              
125             if without arguments and $_ is defined and it's not a reference, renaming $_
126              
127              
128             =cut
129              
130             sub renaming {
131              
132 42     42 1 5327 my ($name, $option);
133 42 100 100     94 if ( scalar @_ ) {
    100          
134 38         563 $name = shift;
135 38         43 $option = shift;
136             }
137             elsif ( defined $_ && ! ref $_ ) {
138 2         4 $name = $_;
139             }
140             else {
141             return
142 2         13 }
143              
144 40         48 my $convention = $_default_convention;
145              
146 40 100 66     170 if ( $option && ref $option eq 'HASH' ) {
147              
148             # the last element is option
149 33 50       68 if ( _is_valid_convention( $option->{convention} ) ) {
150 33         55 $convention = $option->{convention};
151             }
152             else {
153 0         0 carp "invlid convention: $option->{convention}";
154             }
155              
156             }
157              
158 40 100 100     170 if ( $name =~ /(_)/ || $name =~ /(-)/ ) {
159 8         16 my $from = $1;
160 8 50       17 return $name if $convention eq $from;
161              
162 8 100 100     28 if ( ( $convention eq '_' || $convention eq '-' ) )
163             {
164 4         62 $name =~ s/$from/$convention/g;
165 4         24 return $name;
166             }
167             else {
168 4         41 $name =~ s/$from(.)/uc $1/ge;
  8         21  
169 4 100       21 return ucfirst $name if $convention eq 'UpperCamelCase';
170 2         10 return $name;
171             }
172             }
173             else {
174 32 100 100     103 if ( $convention eq '_' || $convention eq '-' ) {
175             # massage the first word, FOOBar => fooBar
176 19         52 $name =~ s/^([A-Z])([^A-Z])/lc( $1 ) . $2/e;
  8         25  
177 19         42 $name =~ s/^([A-Z]+)(?![a-z])/lc $1/e;
  2         7  
178              
179             # massage the last word, FooBAR => FooBar
180 19         40 $name =~ s/(?<=[A-Z])([A-Z]+(\d+)?)$/lc( $1 )/e;
  2         6  
181              
182             # e.g. fooBARBaz => foo_bar_baz
183             # first step: fooBARBaz => fooBarBaz
184             # second step: fooBarBaz => foo_bar_baz
185 19         38 $name =~ s/([A-Z]+)([A-Z])/(ucfirst lc $1 ) . $2/ge;
  1         4  
186 19         45 $name =~ s/([^A-Z])([A-Z])/$1 . $convention . lc $2/ge;
  17         60  
187             # tr all the weirdly left [A-Z]
188 19         34 $name =~ tr/A-Z/a-z/;
189             }
190             else {
191 13         17 my $from = 'UpperCamelCase';
192 13 100       40 $from = 'lowerCamelCase' if $name =~ /^[^A-Z]/;
193 13 100 100     69 if ( $convention eq 'UpperCamelCase' && $convention ne $from ) {
    100 100        
194 4         20 return ucfirst $name;
195             }
196             elsif ( $convention eq 'lowerCamelCase' && $convention ne $from ) {
197 3         12 $name =~ s/^([A-Z])([^A-Z])/lc( $1 ) . $2/e;
  2         10  
198 3         9 $name =~ s/^([A-Z]+)(?![a-z])/lc $1/e;
  1         4  
199 3         16 return $name;
200             }
201             }
202             }
203 25         112 return $name;
204             }
205              
206             1;
207              
208             __END__