File Coverage

blib/lib/String/CamelSnakeKebab.pm
Criterion Covered Total %
statement 26 26 100.0
branch 6 6 100.0
condition n/a
subroutine 10 10 100.0
pod 0 5 0.0
total 42 47 89.3


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