This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to Filter::Simple 0.50 (just few doc tweaks).
[perl5.git] / lib / Filter / Simple.pm
1 package Filter::Simple;
2
3 use vars qw{ $VERSION };
4
5 $VERSION = '0.50';
6
7 use Filter::Util::Call;
8 use Carp;
9
10 sub 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
18 sub 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
43 sub filter_unimport {
44         filter_del();
45 }
46
47 1;
48
49 __END__
50
51 =head1 NAME
52
53 Filter::Simple - Simplified source filtering
54
55
56 =head1 SYNOPSIS
57
58  # in MyFilter.pm:
59
60          package MyFilter;
61
62          use Filter::Simple sub { ... };
63
64
65  # in user's code:
66
67          use MyFilter;
68
69          # this code is filtered
70
71          no MyFilter;
72
73          # this code is not
74
75
76 =head1 DESCRIPTION
77
78 =head2 The Problem
79
80 Source filtering is an immensely powerful feature of recent versions of Perl.
81 It allows one to extend the language itself (e.g. the Switch module), to 
82 simplify the language (e.g. Language::Pythonesque), or to completely recast the
83 language (e.g. Lingua::Romana::Perligata). Effectively, it allows one to use
84 the full power of Perl as its own, recursively applied, macro language.
85
86 The excellent Filter::Util::Call module (by Paul Marquess) provides a
87 usable Perl interface to source filtering, but it is often too powerful
88 and not nearly as simple as it could be.
89
90 To use the module it is necessary to do the following:
91
92 =over 4
93
94 =item 1.
95
96 Download, build, and install the Filter::Util::Call module.
97
98 =item 2.
99
100 Set up a module that does a C<use Filter::Util::Call>.
101
102 =item 3.
103
104 Within that module, create an C<import> subroutine.
105
106 =item 4.
107
108 Within the C<import> subroutine do a call to C<filter_add>, passing
109 it either a subroutine reference.
110
111 =item 5.
112
113 Within the subroutine reference, call C<filter_read> or C<filter_read_exact>
114 to "prime" $_ with source code data from the source file that will
115 C<use> your module. Check the status value returned to see if any
116 source code was actually read in.
117
118 =item 6.
119
120 Process the contents of $_ to change the source code in the desired manner.
121
122 =item 7.
123
124 Return the status value.
125
126 =item 8.
127
128 If the act of unimporting your module (via a C<no>) should cause source
129 code filtering to cease, create an C<unimport> subroutine, and have it call
130 C<filter_del>. Make sure that the call to C<filter_read> or
131 C<filter_read_exact> in step 5 will not accidentally read past the
132 C<no>. Effectively this limits source code filters to line-by-line
133 operation, unless the C<import> subroutine does some fancy
134 pre-pre-parsing of the source code it's filtering.
135
136 =back
137
138 For example, here is a minimal source code filter in a module named
139 BANG.pm. It simply converts every occurrence of the sequence C<BANG\s+BANG>
140 to the sequence C<die 'BANG' if $BANG> in any piece of code following a
141 C<use BANG;> statement (until the next C<no BANG;> statement, if any):
142
143         package BANG;
144  
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
173 This level of sophistication puts filtering out of the reach of
174 many programmers.
175
176
177 =head2 A Solution
178
179 The Filter::Simple module provides a simplified interface to
180 Filter::Util::Call; one that is sufficient for most common cases.
181
182 Instead of the above process, with Filter::Simple the task of setting up
183 a source code filter is reduced to:
184
185 =over 4
186
187 =item 1.
188
189 Set up a module that does a C<use Filter::Simple sub { ... }>.
190
191 =item 2.
192
193 Within the anonymous subroutine passed to C<use Filter::Simple>, process the
194 contents of $_ to change the source code in the desired manner.
195
196 =back
197
198 In other words, the previous example, would become:
199
200         package BANG;
201  
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
211 The Filter::Simple module exports into the package that C<use>s it (e.g.
212 package "BANG" in the above example) two automagically constructed
213 subroutines -- C<import> and C<unimport> -- which take care of all the
214 nasty details.
215
216 In addition, the generated C<import> subroutine passes its own argument
217 list to the filtering subroutine, so the BANG.pm filter could easily 
218 be made parametric:
219
220         package BANG;
221  
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
232 The specified filtering subroutine is called every time a C<use BANG>
233 is encountered, and passed all the source code following that call,
234 up 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
236 by itself on a separate line, or it is ignored.
237
238
239 =head1 AUTHOR
240
241 Damian Conway (damian@conway.org)
242
243 =head1 COPYRIGHT
244
245  Copyright (c) 2000, Damian Conway. All Rights Reserved.
246  This module is free software. It may be used, redistributed
247 and/or modified under the terms of the Perl Artistic License
248      (see http://www.perl.com/perl/misc/Artistic.html)