File Coverage

blib/lib/String/Flogger.pm
Criterion Covered Total %
statement 41 42 97.6
branch 15 16 93.7
condition 5 6 83.3
subroutine 10 11 90.9
pod 2 2 100.0
total 73 77 94.8


line stmt bran cond sub pod time code
1 2     2   63541 use strict;
  2         6  
  2         110  
2 2     2   15 use warnings;
  2         5  
  2         179  
3             package String::Flogger;
4             # ABSTRACT: string munging for loggers
5             $String::Flogger::VERSION = '1.101245';
6 2     2   2118 use Params::Util qw(_ARRAYLIKE _CODELIKE);
  2         14012  
  2         228  
7 2     2   19 use Scalar::Util qw(blessed);
  2         4  
  2         78  
8 2     2   2130 use Sub::Exporter::Util ();
  2         25295  
  2         133  
9 2     2   25 use Sub::Exporter -setup => [ flog => Sub::Exporter::Util::curry_method ];
  2         3  
  2         11  
10              
11             #pod =head1 SYNOPSIS
12             #pod
13             #pod use String::Flogger qw(flog);
14             #pod
15             #pod my @inputs = (
16             #pod 'simple!',
17             #pod
18             #pod [ 'slightly %s complex', 'more' ],
19             #pod
20             #pod [ 'and inline some data: %s', { look => 'data!' } ],
21             #pod
22             #pod [ 'and we can defer evaluation of %s if we want', sub { 'stuff' } ],
23             #pod
24             #pod sub { 'while avoiding sprintfiness, if needed' },
25             #pod );
26             #pod
27             #pod say flog($_) for @inputs;
28             #pod
29             #pod The above will output:
30             #pod
31             #pod simple!
32             #pod
33             #pod slightly more complex
34             #pod
35             #pod and inline some data: {{{ "look": "data!" }}}
36             #pod
37             #pod and we can defer evaluation of stuff if we want
38             #pod
39             #pod while avoiding sprintfiness, if needed
40             #pod
41             #pod =method flog
42             #pod
43             #pod This method is described in the synopsis.
44             #pod
45             #pod =method format_string
46             #pod
47             #pod $flogger->format_string($fmt, \@input);
48             #pod
49             #pod This method is used to take the formatted arguments for a format string (when
50             #pod C is passed an arrayref) and turn it into a string. By default, it just
51             #pod uses C>.
52             #pod
53             #pod =cut
54              
55             sub _encrefs {
56 13     13   18 my ($self, $messages) = @_;
57 13 100       88 return map { blessed($_) ? sprintf('obj(%s)', "$_")
  13 100       51  
    50          
    100          
58             : ref $_ ? $self->_stringify_ref($_)
59             : defined $_ ? $_
60             : '{{null}}' }
61 13         24 map { _CODELIKE($_) ? scalar $_->() : $_ }
62             @$messages;
63             }
64              
65             my $JSON;
66             sub _stringify_ref {
67 7     7   11 my ($self, $ref) = @_;
68              
69 7 100 100     41 if (ref $ref eq 'SCALAR' or ref $ref eq 'REF') {
70 4         17 my ($str) = $self->_encrefs([ $$ref ]);
71 4         20 return "ref($str)";
72             }
73              
74 3         1851 require JSON::MaybeXS;
75 3   66     13300 $JSON ||= JSON::MaybeXS->new
76             ->ascii(1)
77             ->canonical(1)
78             ->allow_nonref(1)
79             ->space_after(1)
80             ->convert_blessed(1);
81              
82             # This is horrible. Just horrible. I wish I could do this with a callback
83             # passed to JSON: https://rt.cpan.org/Ticket/Display.html?id=54321
84             # -- rjbs, 2013-01-31
85 3     0   72 local *UNIVERSAL::TO_JSON = sub { "obj($_[0])" };
  0         0  
86              
87 3         74 return '{{' . $JSON->encode($ref) . '}}'
88             }
89              
90             sub flog {
91 11     11 1 85 my ($class, $input) = @_;
92              
93 11         15 my $output;
94              
95 11 100       45 if (_CODELIKE($input)) {
96 2         8 $input = $input->();
97             }
98              
99 11 100       44 return $input unless ref $input;
100              
101 9 100       36 if (_ARRAYLIKE($input)) {
102 7         17 my ($fmt, @data) = @$input;
103 7         28 return $class->format_string($fmt, $class->_encrefs(\@data));
104             }
105              
106 2         10 return $class->format_string('%s', $class->_encrefs([$input]));
107             }
108              
109             sub format_string {
110 9     9 1 22 my ($self, $fmt, @input) = @_;
111 9         87 sprintf $fmt, @input;
112             }
113              
114             1;
115              
116             __END__