more pod patches
[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.
96
97=item 2.
98
99Set up a module that does a C<use Filter::Util::Call>.
100
101=item 3.
102
103Within that module, create an C<import> subroutine.
104
105=item 4.
106
107Within the C<import> subroutine do a call to C<filter_add>, passing
108it either a subroutine reference.
109
110=item 5.
111
112Within the subroutine reference, call C<filter_read> or C<filter_read_exact>
113to "prime" $_ with source code data from the source file that will
114C<use> your module. Check the status value returned to see if any
115source code was actually read in.
116
117=item 6.
118
119Process the contents of $_ to change the source code in the desired manner.
120
121=item 7.
122
123Return the status value.
124
125=item 8.
126
127If the act of unimporting your module (via a C<no>) should cause source
128code filtering to cease, create an C<unimport> subroutine, and have it call
129C<filter_del>. Make sure that the call to C<filter_read> or
130C<filter_read_exact> in step 5 will not accidentally read past the
131C<no>. Effectively this limits source code filters to line-by-line
132operation, unless the C<import> subroutine does some fancy
133pre-pre-parsing of the source code it's filtering.
134
135=back
136
137For example, here is a minimal source code filter in a module named
138BANG.pm. It simply converts every occurrence of the sequence C<BANG\s+BANG>
139to the sequence C<die 'BANG' if $BANG> in any piece of code following a
140C<use BANG;> statement (until the next C<no BANG;> statement, if any):
141
142 package BANG;
bbc7dcd2 143
b38acab9 144 use Filter::Util::Call ;
145
146 sub import {
147 filter_add( sub {
148 my $caller = caller;
149 my ($status, $no_seen, $data);
150 while ($status = filter_read()) {
151 if (/^\s*no\s+$caller\s*;\s*$/) {
152 $no_seen=1;
153 last;
154 }
155 $data .= $_;
156 $_ = "";
157 }
158 $_ = $data;
159 s/BANG\s+BANG/die 'BANG' if \$BANG/g
160 unless $status < 0;
161 $_ .= "no $class;\n" if $no_seen;
162 return 1;
163 })
164 }
165
166 sub unimport {
167 filter_del();
168 }
169
170 1 ;
171
7bf0340c 172This level of sophistication puts filtering out of the reach of
173many programmers.
b38acab9 174
175
176=head2 A Solution
177
7bf0340c 178The Filter::Simple module provides a simplified interface to
b38acab9 179Filter::Util::Call; one that is sufficient for most common cases.
180
181Instead of the above process, with Filter::Simple the task of setting up
182a source code filter is reduced to:
183
184=over 4
185
186=item 1.
187
188Set up a module that does a C<use Filter::Simple sub { ... }>.
189
190=item 2.
191
192Within the anonymous subroutine passed to C<use Filter::Simple>, process the
193contents of $_ to change the source code in the desired manner.
194
195=back
196
197In other words, the previous example, would become:
198
199 package BANG;
bbc7dcd2 200
b38acab9 201 use Filter::Simple sub {
202 s/BANG\s+BANG/die 'BANG' if \$BANG/g;
203 };
204
205 1 ;
206
207
208=head2 How it works
209
210The Filter::Simple module exports into the package that C<use>s it (e.g.
211package "BANG" in the above example) two automagically constructed
212subroutines -- C<import> and C<unimport> -- which take care of all the
213nasty details.
214
215In addition, the generated C<import> subroutine passes its own argument
216list to the filtering subroutine, so the BANG.pm filter could easily
217be made parametric:
218
219 package BANG;
bbc7dcd2 220
b38acab9 221 use Filter::Simple sub {
222 my ($die_msg, $var_name) = @_;
223 s/BANG\s+BANG/die '$die_msg' if \${$var_name}/g;
224 };
225
226 # and in some user code:
227
228 use BANG "BOOM", "BAM; # "BANG BANG" becomes: die 'BOOM' if $BAM
229
230
231The specified filtering subroutine is called every time a C<use BANG>
232is encountered, and passed all the source code following that call,
233up to either the next C<no BANG;> call or the end of the source file
234(whichever occurs first). Currently, any C<no BANG;> call must appear
235by itself on a separate line, or it is ignored.
236
237
238=head1 AUTHOR
239
240Damian Conway (damian@conway.org)
241
242=head1 COPYRIGHT
243
244 Copyright (c) 2000, Damian Conway. All Rights Reserved.
245 This module is free software. It may be used, redistributed
246and/or modified under the terms of the Perl Artistic License
247 (see http://www.perl.com/perl/misc/Artistic.html)