File Coverage

lib/Filter/QuasiQuote.pm
Criterion Covered Total %
statement 88 93 94.6
branch 29 36 80.5
condition 3 3 100.0
subroutine 6 6 100.0
pod 2 2 100.0
total 128 140 91.4


line stmt bran cond sub pod time code
1             package Filter::QuasiQuote;
2              
3 3     3   92210 use strict;
  3         8  
  3         110  
4 3     3   18 no warnings;
  3         6  
  3         170  
5             #use Smart::Comments;
6              
7             our $VERSION = '0.07';
8              
9 3     3   3576 use Filter::Util::Call qw(filter_read);
  3         18712  
  3         7163  
10              
11             our $Debug;
12              
13             sub import {
14 4     4   1053 my ($type, @arguments) = @_ ;
15             #warn $type;
16 4         15 my ($package, $filename, $line) = caller;
17             #warn "$package";
18 4         29 my $self = bless {
19             file => $filename,
20             line => $line,
21             quoted => undef,
22             method => undef,
23             ignore_once => undef,
24             pos_diff => 0,
25             }, $type;
26 4         248 Filter::Util::Call::real_import($self, $package, 0) ;
27             }
28              
29             sub filter {
30 115     115 1 154 my ($self) = @_ ;
31             #warn "SELF: $self";
32 115         112 my($status) ;
33              
34 115         642 $status = filter_read;
35             #warn scalar(s/\r//g);
36             #warn "Last char: ", ord(substr($_, -1, 1));
37 115         124 my $changed;
38 115 100       693 if ($status > 0) {
39 111         1133 $self->{pos_diff} = 0;
40 111         199 $self->{line}++;
41 111         98 my ($i, $buf);
42 111         121 while (1) {
43 335         560 $i++;
44 335         1386 $self->debug("Pos ", pos, ", Pass $i, Line $self->{line}");
45 335 100       1203 if (/\G\s+/gc) { $buf .= $& }
  98         177  
46 335 100       1786 if (/\G\[:(\w+)\|(.*?)\|\]/gc) {
    100          
    100          
    100          
47             #warn "$1 => $2";
48 51         136 my ($meth, $s) = ($1, $2);
49 51         69 my $len = length($&);
50 51         65 my $to = pos;
51              
52 51 50       113 if (defined $self->{method}) {
53 0         0 die "Syntax error at $self->{file}, line $self->{line}: Quasiquotes cannot be nested.\n";
54             }
55              
56             #warn "to: $to\n";
57             #warn "len: $len\n";
58 51 100       199 if ($self->can($meth)) {
59             #warn "POS diff: $self->{pos_diff}";
60 40         322 my $col = $to - $self->{pos_diff} - $len + 1;
61 40         131 my $res = $self->$meth($s, $self->{file}, $self->{line}, $col);
62             #$self->debug("Pos BEFORE change \$_: ", pos($_));
63 40         1717 substr($_, $to - $len, $len, $res);
64 40         46 $changed = 1; pos($_) = $to - $len + length($res);
  40         107  
65 40         155 $self->{pos_diff} = length($res) - $len;
66             #$self->debug("Pos AFTER change \$_: ", pos($_));
67             ### $_
68             }
69             }
70             elsif (/\G\[:(\w+)\|(.*)/gc) {
71 16         42 my ($meth, $s) = ($1, $2);
72 16         65 my $len = length($&);
73 16         21 my $to = pos $_;
74             #warn "len: $len to: $to match: $&\n";
75 16 100       61 if (!$self->can($meth)) {
76 4         17 $self->debug("Ignoring starting $meth at $self->{line} (pos $to, pass $i)");
77 4         4 $self->{ignore_once} = 1;
78             #$self->{method} = $meth;
79 4         8 last;
80             }
81              
82 12         28 substr($_, $to - $len, $len, ' ');
83 12         15 $changed = 1;
84 12         26 my $col = $to - $self->{pos_diff} - $len + 1;
85 12         34 $self->{saved_pos} = [$self->{line}, $col];
86             ### $_
87              
88 12 50       138 if (!defined $self->{method}) {
89 12         22 $self->{quoted} = $s;
90 12         27 $self->{method} = $meth;
91             } else {
92 0         0 die "Syntax error at $self->{file}, line $self->{line}: Quasiquotes cannot be nested.\n";
93             }
94 12         18 last;
95             }
96             elsif (/\G\|\]/gc) {
97 16         126 my $s = $buf;
98 16         32 my $len = length($buf . $&);
99 16         24 my $to = pos;
100 16         82 $self->debug("Found closing tag: ", ref $self, " (pos $to, pass $i, line $self->{line})");
101 16 100       43 if ($self->{ignore_once}) {
102 4 50       28 $self->debug("Ignoring closing $self->{method} at $self->{line} (pos $to, pass $i)") if $self->{method};
103 4         10 undef $self->{ignore_once};
104 4         4 undef $self->{method};
105 4         11 undef $self->{quoted};
106 4         8 next;
107             }
108              
109 12         21 my $meth = $self->{method};
110 12 50       267 if (!defined $meth) {
111             #warn $self;
112             #warn "POS: ", pos;
113 0         0 die ref $self, ": Syntax error at $self->{file}, line $self->{line}: Pending closing quasiquote. (pos $to, pass $i)\n";
114             }
115             #warn "POS diff: $self->{pos_diff}";
116 12         17 my $pos = $self->{saved_pos};
117 12         22 my ($line, $col);
118 12 50       23 if (!$pos) { $line = $self->{line}; $col = 0 }
  0         0  
  0         0  
119 12         33 else { ($line, $col) = @$pos }
120 12         60 my $res = $self->$meth($self->{quoted} . $s, $self->{file}, $line, $col);
121 12         457 undef $self->{method};
122 12         19 undef $self->{quoted};
123 12         31 substr($_, $to - $len, $len, $res);
124 12         16 $changed = 1; pos($_) = $to - $len + length($res);
  12         30  
125 12         33 $self->{pos_diff} = length($res) - $len;
126              
127             #$changed = 1;
128             }
129             elsif (/\G[^\|\[]+|\G./gc) {
130             #print "Ignored: $_";
131             #last;
132             #warn $&;
133 157         275 $buf .= $&;
134             }
135             else {
136 95         558 last;
137             }
138             }
139 111 100 100     415 if (!$changed && defined $self->{method}) {
140 6         60 $self->{quoted} .= $_;
141 6         10 $_ = "\n"; $changed = 1;
  6         8  
142             }
143             #warn "$self->{file}: line $self->{line}: $_";
144             }
145 115 100       325 $self->debug("Processed: (line $self->{line}): $_") if $changed;
146 115         721 s/\n//gs;
147 115 50       408 $_ .= "\n" unless substr($_, -1, 1) eq "\n";
148             #warn $status;
149 115         9724 $status ;
150             }
151              
152             sub debug {
153 407     407 1 984 my $self = shift;
154 407 50       963 warn ref $self, ": ", join('', @_), "\n" if $Debug;
155             }
156              
157             1;
158             __END__