File Coverage

blib/lib/String/CamelSnakeKebab.pm
Criterion Covered Total %
statement 27 27 100.0
branch 6 6 100.0
condition n/a
subroutine 11 11 100.0
pod 1 6 16.6
total 45 50 90.0


line stmt bran cond sub pod time code
1             package String::CamelSnakeKebab;
2 4     4   496160 use strict;
  4         44  
  4         109  
3 4     4   20 use warnings;
  4         7  
  4         168  
4              
5 4         31 use Sub::Exporter -setup => { exports => [qw/
6             lower_camel_case
7             upper_camel_case
8             lower_snake_case
9             upper_snake_case
10             constant_case
11             kebab_case
12             http_header_case
13             word_split
14 4     4   1444 /]};
  4         31898  
15              
16             our $VERSION = "0.06";
17              
18             our %UPPER_CASE_HTTP_HEADERS = map { $_ => 1 }
19             qw/ CSP ATT WAP IP HTTP CPU DNT SSL UA TE WWW XSS MD5 /;
20              
21             sub http_header_caps {
22 21     21 0 103 my ($string) = @_;
23 21 100       116 return uc $string if $UPPER_CASE_HTTP_HEADERS{uc $string};
24 12         54 return ucfirst $string;
25             }
26              
27             # A pattern that matches all known word separators
28             our $WORD_SEPARATOR_PATTERN = qr/
29             (?:
30             \s+ |
31             _ |
32             - |
33             (?<=[A-Z])(?=[A-Z][a-z]) |
34             (?<=[^A-Z_-])(?=[A-Z]) |
35             (?<=[A-Za-z0-9])(?=[^A-Za-z0-9])
36             )
37             /x;
38              
39             sub word_split {
40 34     34 1 17225 split $WORD_SEPARATOR_PATTERN, $_[0];
41             }
42              
43             sub convert_case {
44 24     24 0 77 my ($first_coderef, $rest_coderef, $separator, $string) = @_;
45              
46 24 100       80 return '' if $string eq '';
47              
48 23         57 my ($first, @rest) = word_split($string);
49              
50 23 100       77 $first = '' unless $first;
51              
52 23         64 my @words = $first_coderef->($first);
53 23         76 push @words, $rest_coderef->($_) for @rest;
54              
55 23         170 return join $separator, @words;
56             }
57              
58             # Need to do this because I can't make lc a code reference via \&CORE::lc
59             # unless the user has perl v5.16
60 12     12 0 38 sub lc { lc shift }
61 4     4 0 12 sub uc { uc shift }
62 9     9 0 30 sub ucfirst { ucfirst shift }
63              
64             our %CONVERSION_RULES = (
65             'lower_camel_case' => [ \&lc, \&ucfirst, "" ],
66             'upper_camel_case' => [ \&ucfirst, \&ucfirst, "" ],
67             'lower_snake_case' => [ \&lc, \&lc, "_" ],
68             'upper_snake_case' => [ \&ucfirst, \&ucfirst, "_" ],
69             'constant_case' => [ \&uc, \&uc, "_" ],
70             'kebab_case' => [ \&lc, \&lc, "-" ],
71             'http_header_case' => [ \&http_header_caps, \&http_header_caps, "-" ],
72             );
73              
74             {
75             # Foreach rule, dynamically install a sub in this package
76 4     4   3340 no strict 'refs';
  4         8  
  4         414  
77             for my $rule ( keys %CONVERSION_RULES ) {
78             my $args = $CONVERSION_RULES{$rule};
79 24     24   30793 *{$rule} = sub { convert_case(@$args, @_) };
80             }
81             }
82              
83             =head1 NAME
84              
85             String::CamelSnakeKebab - word case conversion
86              
87             =head1 SYNPOSIS
88              
89             use String::CamelSnakeKebab qw/:all/;
90              
91             lower_camel_case 'flux-capacitor'
92             # => 'fluxCapacitor
93              
94             upper_camel_case 'flux-capacitor'
95             # => 'FluxCapacitor
96              
97             lower_snake_case 'ASnakeSlithersSlyly'
98             # => 'a_snake_slithers_slyly'
99              
100             upper_snake_case 'ASnakeSlithersSlyly'
101             # => 'A_Snake_Slithers_Slyly'
102              
103             constant_case "I am constant"
104             # => "I_AM_CONSTANT"
105              
106             kebab_case 'Peppers_Meat_Pineapple'
107             # => 'peppers-meat-pineapple'
108              
109             http_header_case "x-ssl-cipher"
110             # => "X-SSL-Cipher"
111              
112             word_split 'ASnakeSlithersSlyly'
113             # => ["A", "Snake", "Slithers", "Slyly"]
114              
115             word_split 'flux-capacitor'
116             # => ["flux", "capacitor"]
117              
118              
119             =head1 DESCRIPTION
120              
121             Camel-Snake-Kebab is a Clojure library for word case conversions. This library
122             is ported from the original Clojure.
123              
124             =head1 METHODS
125              
126             =head2 lower_camel_case()
127              
128             =head2 upper_camel_case()
129              
130             =head2 lower_snake_case()
131              
132             =head2 upper_snake_case()
133              
134             =head2 constant_case()
135              
136             =head2 kebab_case()
137              
138             =head2 http_header_case()
139              
140             =head2 word_split()
141              
142             =head1 ERROR HANDLING
143              
144             Invalid input is usually indicated by returning the empty string. So you may
145             want to check the return value. This happens if you pass in something crazy
146             like "___" or "_-- _" or "". Because what does it mean to lower camel case
147             "_-- _"? I don't know and I don't want to think about it any more.
148              
149             =head1 SEE ALSO
150              
151             The original Camel Snake Kebab Clojure library: L
152              
153             =head1 AUTHOR
154              
155             Eric Johnson (kablamo)
156              
157             =cut
158              
159             1;