Re: bleadperl: s/// failure with \b and /g
[p5sagit/p5-mst-13.2.git] / lib / Filter / Simple.pm
CommitLineData
b38acab9 1package Filter::Simple;
2
3use vars qw{ $VERSION };
4
7bf0340c 5$VERSION = '0.50';
b38acab9 6
7use Filter::Util::Call;
8use Carp;
9
10sub import {
11 my $caller = caller;
12 my ($class, $filter) = @_;
13 croak "Usage: use Filter::Simple sub {...}" unless ref $filter eq CODE;
14 *{"${caller}::import"} = gen_filter_import($caller, $filter);
15 *{"${caller}::unimport"} = \*filter_unimport;
16}
17
18sub gen_filter_import {
19 my ($class, $filter) = @_;
20 return sub {
21 my ($imported_class, @args) = @_;
22 filter_add(
23 sub {
24 my ($status, $off);
25 my $data = "";
26 while ($status = filter_read()) {
27 if (m/^\s*no\s+$class\s*;\s*$/) {
28 $off=1;
29 last;
30 }
31 $data .= $_;
32 $_ = "";
33 }
34 $_ = $data;
35 $filter->(@args) unless $status < 0;
36 $_ .= "no $class;\n" if $off;
37 return length;
38 }
39 );
40 }
41}
42
43sub filter_unimport {
44 filter_del();
45}
46
471;
48
49__END__
50
51=head1 NAME
52
53Filter::Simple - Simplified source filtering
54
b38acab9 55=head1 SYNOPSIS
56
57 # in MyFilter.pm:
58
59 package MyFilter;
60
61 use Filter::Simple sub { ... };
62
63
64 # in user's code:
65
66 use MyFilter;
67
68 # this code is filtered
69
70 no MyFilter;
71
72 # this code is not
73
74
75=head1 DESCRIPTION
76
77=head2 The Problem
78
79Source filtering is an immensely powerful feature of recent versions of Perl.
80It allows one to extend the language itself (e.g. the Switch module), to
81simplify the language (e.g. Language::Pythonesque), or to completely recast the
82language (e.g. Lingua::Romana::Perligata). Effectively, it allows one to use
83the full power of Perl as its own, recursively applied, macro language.
84
85The excellent Filter::Util::Call module (by Paul Marquess) provides a
86usable Perl interface to source filtering, but it is often too powerful
87and not nearly as simple as it could be.
88
89To use the module it is necessary to do the following:
90
91=over 4
92
93=item 1.
94
95Download, build, and install the Filter::Util::Call module.
3b131e01 96(If you are using Perl 5.7.1 or later, you already have Filter::Util::Call.)
b38acab9 97
98=item 2.
99
100Set up a module that does a C<use Filter::Util::Call>.
101
102=item 3.
103
104Within that module, create an C<import> subroutine.
105
106=item 4.
107
108Within the C<import> subroutine do a call to C<filter_add>, passing
109it either a subroutine reference.
110
111=item 5.
112
113Within the subroutine reference, call C<filter_read> or C<filter_read_exact>
114to "prime" $_ with source code data from the source file that will
115C<use> your module. Check the status value returned to see if any
116source code was actually read in.
117
118=item 6.
119
120Process the contents of $_ to change the source code in the desired manner.
121
122=item 7.
123
124Return the status value.
125
126=item 8.
127
128If the act of unimporting your module (via a C<no>) should cause source
129code filtering to cease, create an C<unimport> subroutine, and have it call
130C<filter_del>. Make sure that the call to C<filter_read> or
131C<filter_read_exact> in step 5 will not accidentally read past the
132C<no>. Effectively this limits source code filters to line-by-line
133operation, unless the C<import> subroutine does some fancy
134pre-pre-parsing of the source code it's filtering.
135
136=back
137
138For example, here is a minimal source code filter in a module named
139BANG.pm. It simply converts every occurrence of the sequence C<BANG\s+BANG>
140to the sequence C<die 'BANG' if $BANG> in any piece of code following a
141C<use BANG;> statement (until the next C<no BANG;> statement, if any):
142
143 package BANG;
bbc7dcd2 144
b38acab9 145 use Filter::Util::Call ;
146
147 sub import {
148 filter_add( sub {
149 my $caller = caller;
150 my ($status, $no_seen, $data);
151 while ($status = filter_read()) {
152 if (/^\s*no\s+$caller\s*;\s*$/) {
153 $no_seen=1;
154 last;
155 }
156 $data .= $_;
157 $_ = "";
158 }
159 $_ = $data;
160 s/BANG\s+BANG/die 'BANG' if \$BANG/g
161 unless $status < 0;
162 $_ .= "no $class;\n" if $no_seen;
163 return 1;
164 })
165 }
166
167 sub unimport {
168 filter_del();
169 }
170
171 1 ;
172
7bf0340c 173This level of sophistication puts filtering out of the reach of
174many programmers.
b38acab9 175
176
177=head2 A Solution
178
7bf0340c 179The Filter::Simple module provides a simplified interface to
b38acab9 180Filter::Util::Call; one that is sufficient for most common cases.
181
182Instead of the above process, with Filter::Simple the task of setting up
183a source code filter is reduced to:
184
185=over 4
186
187=item 1.
188
189Set up a module that does a C<use Filter::Simple sub { ... }>.
190
191=item 2.
192
193Within the anonymous subroutine passed to C<use Filter::Simple>, process the
194contents of $_ to change the source code in the desired manner.
195
196=back
197
198In other words, the previous example, would become:
199
200 package BANG;
bbc7dcd2 201
b38acab9 202 use Filter::Simple sub {
203 s/BANG\s+BANG/die 'BANG' if \$BANG/g;
204 };
205
206 1 ;
207
208
209=head2 How it works
210
211The Filter::Simple module exports into the package that C<use>s it (e.g.
212package "BANG" in the above example) two automagically constructed
213subroutines -- C<import> and C<unimport> -- which take care of all the
214nasty details.
215
216In addition, the generated C<import> subroutine passes its own argument
217list to the filtering subroutine, so the BANG.pm filter could easily
218be made parametric:
219
220 package BANG;
bbc7dcd2 221
b38acab9 222 use Filter::Simple sub {
223 my ($die_msg, $var_name) = @_;
224 s/BANG\s+BANG/die '$die_msg' if \${$var_name}/g;
225 };
226
227 # and in some user code:
228
229 use BANG "BOOM", "BAM; # "BANG BANG" becomes: die 'BOOM' if $BAM
230
231
232The specified filtering subroutine is called every time a C<use BANG>
233is encountered, and passed all the source code following that call,
234up to either the next C<no BANG;> call or the end of the source file
235(whichever occurs first). Currently, any C<no BANG;> call must appear
236by itself on a separate line, or it is ignored.
237
238
239=head1 AUTHOR
240
241Damian Conway (damian@conway.org)
242
243=head1 COPYRIGHT
244
245 Copyright (c) 2000, Damian Conway. All Rights Reserved.
7a57cd46 246This module is free software; you can redistribute it and/or
247modify it under the same terms as Perl itself.