File Coverage

blib/lib/PerlX/QuoteOperator.pm
Criterion Covered Total %
statement 61 61 100.0
branch 15 18 83.3
condition 6 9 66.6
subroutine 11 11 100.0
pod 1 1 100.0
total 94 100 94.0


line stmt bran cond sub pod time code
1             package PerlX::QuoteOperator;
2 5     5   81484 use strict;
  5         14  
  5         208  
3 5     5   29 use warnings;
  5         9  
  5         139  
4 5     5   100 use 5.008001;
  5         18  
  5         158  
5              
6 5     5   2418 use Devel::Declare ();
  5         21409  
  5         111  
7 5     5   3186 use Text::Balanced ();
  5         78933  
  5         148  
8 5     5   40 use base 'Devel::Declare::Context::Simple';
  5         8  
  5         2640  
9              
10             our $VERSION = '0.07';
11             our $qtype = __PACKAGE__ . '::qtype';
12             our $parser = __PACKAGE__ . '::parser';
13             our $debug = __PACKAGE__ . '::debug';
14              
15             sub import {
16 10     10   461 my ($self, $name, $param, $caller) = @_;
17            
18             # not importing unless name & parameters provided (TBD... check these)
19 10 100 66     101 return unless $name && $param;
20            
21             # called directly and not via a PerlX::QuoteOperator::* module
22 9 50       21 unless ($caller) {
23 9         14 $caller = caller;
24 9         41 $self = __PACKAGE__->new;
25             }
26            
27             # quote like operator to emulate. Default is qq// unless -emulate is provided
28 9   50     82 $self->{ $qtype } = $param->{ -emulate } || 'qq';
29            
30             # invoke my heath robinson parser or not?
31             # (not using parser means just insert quote operator and leave to Perl)
32 9   100     33 $self->{ $parser } = $param->{ -parser } || 0;
33            
34             # debug or not to debug... that is the question
35 9   50     34 $self->{ $debug } = $param->{ -debug } || 0;
36              
37             # Create D::D trigger for $name in calling program
38             Devel::Declare->setup_for(
39             $caller, {
40 16     16   407 $name => { const => sub { $self->parser(@_) } },
41             },
42 9         67 );
43            
44 5     5   64247 no strict 'refs';
  5         11  
  5         1490  
45 9         214 *{$caller.'::'.$name} = $param->{ -with };
  9         327  
46             }
47              
48             sub parser {
49 16     16 1 20 my $self = shift;
50 16         49 $self->init(@_);
51 16         115 $self->skip_declarator; # skip past "http"
52 16         351 $self->skipspace;
53              
54 16         108 my $line = $self->get_linestr; # get me current line of code
55              
56 16 100       76 if ( $self->{ $parser } ) {
57             # find start & end of quote operator
58 5         10 my $pos = $self->offset; # position just after "http"
59 5         15 my $opener = substr( $line, $pos, 1 );
60 5         12 my $closer = _closing_delim( $opener );
61 5 100       10 if ($closer eq $opener) {
62 2         2 do { $pos++ } until substr( $line, $pos, 1 ) eq $closer;
  24         36  
63             }
64             else {
65 3         5 my $text = substr($line, $pos);
66 3         10 my ($capture, $remaining) = Text::Balanced::extract_bracketed($text, $opener);
67 3         609 $pos += length $capture;
68 3         5 $pos--;
69             }
70            
71             # and wrap sub() around quote operator (needed for lists)
72 5         9 substr( $line, $pos + 1, 0 ) = ')';
73 5         15 substr( $line, $self->offset, 0 ) = '(' . $self->{ $qtype };
74            
75             }
76             else {
77             # Can rely on Perl parser for everything.. just insert quote-like operator
78 11         67 substr( $line, $self->offset, 0 ) = q{ } . $self->{ $qtype };
79             }
80              
81             # eg: qURL(http://www.foo.com/baz) => qURL qq(http://www.foo.com/baz)
82             # pass back to parser
83 16         81 $self->set_linestr( $line );
84 16 50       88 warn "$line\n" if $self->{ $debug };
85              
86 16         104 return;
87             }
88              
89             sub _closing_delim {
90 5     5   7 my $d = shift;
91 5 100       17 return ')' if $d eq '(';
92 4 100       8 return '}' if $d eq '{';
93 3 100       8 return ']' if $d eq '[';
94 2 50       7 return '>' if $d eq '<';
95 2         4 return $d;
96             }
97              
98             1;
99              
100              
101             __END__