opener-tokenizer-base 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +148 -0
  3. data/bin/tokenizer-base +5 -0
  4. data/bin/tokenizer-de +5 -0
  5. data/bin/tokenizer-en +5 -0
  6. data/bin/tokenizer-es +5 -0
  7. data/bin/tokenizer-fr +5 -0
  8. data/bin/tokenizer-it +5 -0
  9. data/bin/tokenizer-nl +5 -0
  10. data/core/lib/Data/OptList.pm +256 -0
  11. data/core/lib/Params/Util.pm +866 -0
  12. data/core/lib/Sub/Exporter.pm +1101 -0
  13. data/core/lib/Sub/Exporter/Cookbook.pod +309 -0
  14. data/core/lib/Sub/Exporter/Tutorial.pod +280 -0
  15. data/core/lib/Sub/Exporter/Util.pm +354 -0
  16. data/core/lib/Sub/Install.pm +329 -0
  17. data/core/lib/Time/Stamp.pm +808 -0
  18. data/core/load-prefixes.pl +43 -0
  19. data/core/nonbreaking_prefixes/abbreviation_list.kaf +0 -0
  20. data/core/nonbreaking_prefixes/abbreviation_list.txt +444 -0
  21. data/core/nonbreaking_prefixes/nonbreaking_prefix.ca +533 -0
  22. data/core/nonbreaking_prefixes/nonbreaking_prefix.de +781 -0
  23. data/core/nonbreaking_prefixes/nonbreaking_prefix.el +448 -0
  24. data/core/nonbreaking_prefixes/nonbreaking_prefix.en +564 -0
  25. data/core/nonbreaking_prefixes/nonbreaking_prefix.es +758 -0
  26. data/core/nonbreaking_prefixes/nonbreaking_prefix.fr +1027 -0
  27. data/core/nonbreaking_prefixes/nonbreaking_prefix.is +697 -0
  28. data/core/nonbreaking_prefixes/nonbreaking_prefix.it +641 -0
  29. data/core/nonbreaking_prefixes/nonbreaking_prefix.nl +739 -0
  30. data/core/nonbreaking_prefixes/nonbreaking_prefix.pl +729 -0
  31. data/core/nonbreaking_prefixes/nonbreaking_prefix.pt +656 -0
  32. data/core/nonbreaking_prefixes/nonbreaking_prefix.ro +484 -0
  33. data/core/nonbreaking_prefixes/nonbreaking_prefix.ru +705 -0
  34. data/core/nonbreaking_prefixes/nonbreaking_prefix.sk +920 -0
  35. data/core/nonbreaking_prefixes/nonbreaking_prefix.sl +524 -0
  36. data/core/nonbreaking_prefixes/nonbreaking_prefix.sv +492 -0
  37. data/core/split-sentences.pl +114 -0
  38. data/core/text-fixer.pl +169 -0
  39. data/core/tokenizer-cli.pl +363 -0
  40. data/core/tokenizer.pl +145 -0
  41. data/lib/opener/tokenizers/base.rb +84 -0
  42. data/lib/opener/tokenizers/base/version.rb +8 -0
  43. data/opener-tokenizer-base.gemspec +25 -0
  44. metadata +134 -0
@@ -0,0 +1,354 @@
1
+ use strict;
2
+ use warnings;
3
+ package Sub::Exporter::Util;
4
+ {
5
+ $Sub::Exporter::Util::VERSION = '0.984';
6
+ }
7
+ # ABSTRACT: utilities to make Sub::Exporter easier
8
+
9
+ use Data::OptList ();
10
+ use Params::Util ();
11
+
12
+
13
+ sub curry_method {
14
+ my $override_name = shift;
15
+ sub {
16
+ my ($class, $name) = @_;
17
+ $name = $override_name if defined $override_name;
18
+ sub { $class->$name(@_); };
19
+ }
20
+ }
21
+
22
+ BEGIN { *curry_class = \&curry_method; }
23
+
24
+
25
+ sub curry_chain {
26
+ # In the future, we can make \%arg an optional prepend, like the "special"
27
+ # args to the default Sub::Exporter-generated import routine.
28
+ my (@opt_list) = @_;
29
+
30
+ my $pairs = Data::OptList::mkopt(\@opt_list, 'args', 'ARRAY');
31
+
32
+ sub {
33
+ my ($class) = @_;
34
+
35
+ sub {
36
+ my $next = $class;
37
+
38
+ for my $i (0 .. $#$pairs) {
39
+ my $pair = $pairs->[ $i ];
40
+
41
+ unless (Params::Util::_INVOCANT($next)) { ## no critic Private
42
+ my $str = defined $next ? "'$next'" : 'undef';
43
+ Carp::croak("can't call $pair->[0] on non-invocant $str")
44
+ }
45
+
46
+ my ($method, $args) = @$pair;
47
+
48
+ if ($i == $#$pairs) {
49
+ return $next->$method($args ? @$args : ());
50
+ } else {
51
+ $next = $next->$method($args ? @$args : ());
52
+ }
53
+ }
54
+ };
55
+ }
56
+ }
57
+
58
+ # =head2 name_map
59
+ #
60
+ # This utility returns an list to be used in specify export generators. For
61
+ # example, the following:
62
+ #
63
+ # exports => {
64
+ # name_map(
65
+ # '_?_gen' => [ qw(fee fie) ],
66
+ # '_make_?' => [ qw(foo bar) ],
67
+ # ),
68
+ # }
69
+ #
70
+ # is equivalent to:
71
+ #
72
+ # exports => {
73
+ # name_map(
74
+ # fee => \'_fee_gen',
75
+ # fie => \'_fie_gen',
76
+ # foo => \'_make_foo',
77
+ # bar => \'_make_bar',
78
+ # ),
79
+ # }
80
+ #
81
+ # This can save a lot of typing, when providing many exports with similarly-named
82
+ # generators.
83
+ #
84
+ # =cut
85
+ #
86
+ # sub name_map {
87
+ # my (%groups) = @_;
88
+ #
89
+ # my %map;
90
+ #
91
+ # while (my ($template, $names) = each %groups) {
92
+ # for my $name (@$names) {
93
+ # (my $export = $template) =~ s/\?/$name/
94
+ # or Carp::croak 'no ? found in name_map template';
95
+ #
96
+ # $map{ $name } = \$export;
97
+ # }
98
+ # }
99
+ #
100
+ # return %map;
101
+ # }
102
+
103
+
104
+ sub merge_col {
105
+ my (%groups) = @_;
106
+
107
+ my %merged;
108
+
109
+ while (my ($default_name, $group) = each %groups) {
110
+ while (my ($export_name, $gen) = each %$group) {
111
+ $merged{$export_name} = sub {
112
+ my ($class, $name, $arg, $col) = @_;
113
+
114
+ my $merged_arg = exists $col->{$default_name}
115
+ ? { %{ $col->{$default_name} }, %$arg }
116
+ : $arg;
117
+
118
+ if (Params::Util::_CODELIKE($gen)) { ## no critic Private
119
+ $gen->($class, $name, $merged_arg, $col);
120
+ } else {
121
+ $class->$$gen($name, $merged_arg, $col);
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ return %merged;
128
+ }
129
+
130
+
131
+ sub __mixin_class_for {
132
+ my ($class, $mix_into) = @_;
133
+ require Package::Generator;
134
+ my $mixin_class = Package::Generator->new_package({
135
+ base => "$class\:\:__mixin__",
136
+ });
137
+
138
+ ## no critic (ProhibitNoStrict)
139
+ no strict 'refs';
140
+ if (ref $mix_into) {
141
+ unshift @{"$mixin_class" . "::ISA"}, ref $mix_into;
142
+ } else {
143
+ unshift @{"$mix_into" . "::ISA"}, $mixin_class;
144
+ }
145
+ return $mixin_class;
146
+ }
147
+
148
+ sub mixin_installer {
149
+ sub {
150
+ my ($arg, $to_export) = @_;
151
+
152
+ my $mixin_class = __mixin_class_for($arg->{class}, $arg->{into});
153
+ bless $arg->{into} => $mixin_class if ref $arg->{into};
154
+
155
+ Sub::Exporter::default_installer(
156
+ { %$arg, into => $mixin_class },
157
+ $to_export,
158
+ );
159
+ };
160
+ }
161
+
162
+ sub mixin_exporter {
163
+ Carp::cluck "mixin_exporter is deprecated; use mixin_installer instead; it behaves identically";
164
+ return mixin_installer;
165
+ }
166
+
167
+
168
+ sub like {
169
+ sub {
170
+ my ($value, $arg) = @_;
171
+ Carp::croak "no regex supplied to regex group generator" unless $value;
172
+
173
+ # Oh, qr//, how you bother me! See the p5p thread from around now about
174
+ # fixing this problem... too bad it won't help me. -- rjbs, 2006-04-25
175
+ my @values = eval { $value->isa('Regexp') } ? ($value, undef)
176
+ : @$value;
177
+
178
+ while (my ($re, $opt) = splice @values, 0, 2) {
179
+ Carp::croak "given pattern for regex group generater is not a Regexp"
180
+ unless eval { $re->isa('Regexp') };
181
+ my @exports = keys %{ $arg->{config}->{exports} };
182
+ my @matching = grep { $_ =~ $re } @exports;
183
+
184
+ my %merge = $opt ? %$opt : ();
185
+ my $prefix = (delete $merge{-prefix}) || '';
186
+ my $suffix = (delete $merge{-suffix}) || '';
187
+
188
+ for my $name (@matching) {
189
+ my $as = $prefix . $name . $suffix;
190
+ push @{ $arg->{import_args} }, [ $name => { %merge, -as => $as } ];
191
+ }
192
+ }
193
+
194
+ 1;
195
+ }
196
+ }
197
+
198
+ use Sub::Exporter -setup => {
199
+ exports => [ qw(
200
+ like
201
+ name_map
202
+ merge_col
203
+ curry_method curry_class
204
+ curry_chain
205
+ mixin_installer mixin_exporter
206
+ ) ]
207
+ };
208
+
209
+ 1;
210
+
211
+ __END__
212
+ =pod
213
+
214
+ =head1 NAME
215
+
216
+ Sub::Exporter::Util - utilities to make Sub::Exporter easier
217
+
218
+ =head1 VERSION
219
+
220
+ version 0.984
221
+
222
+ =head1 DESCRIPTION
223
+
224
+ This module provides a number of utility functions for performing common or
225
+ useful operations when setting up a Sub::Exporter configuration. All of the
226
+ utilites may be exported, but none are by default.
227
+
228
+ =head1 THE UTILITIES
229
+
230
+ =head2 curry_method
231
+
232
+ exports => {
233
+ some_method => curry_method,
234
+ }
235
+
236
+ This utility returns a generator which will produce an invocant-curried version
237
+ of a method. In other words, it will export a method call with the exporting
238
+ class built in as the invocant.
239
+
240
+ A module importing the code some the above example might do this:
241
+
242
+ use Some::Module qw(some_method);
243
+
244
+ my $x = some_method;
245
+
246
+ This would be equivalent to:
247
+
248
+ use Some::Module;
249
+
250
+ my $x = Some::Module->some_method;
251
+
252
+ If Some::Module is subclassed and the subclass's import method is called to
253
+ import C<some_method>, the subclass will be curried in as the invocant.
254
+
255
+ If an argument is provided for C<curry_method> it is used as the name of the
256
+ curried method to export. This means you could export a Widget constructor
257
+ like this:
258
+
259
+ exports => { widget => curry_method('new') }
260
+
261
+ This utility may also be called as C<curry_class>, for backwards compatibility.
262
+
263
+ =head2 curry_chain
264
+
265
+ C<curry_chain> behaves like C<L</curry_method>>, but is meant for generating
266
+ exports that will call several methods in succession.
267
+
268
+ exports => {
269
+ reticulate => curry_chain([
270
+ new => gather_data => analyze => [ detail => 100 ] => results
271
+ ]),
272
+ }
273
+
274
+ If imported from Spliner, calling the C<reticulate> routine will be equivalent
275
+ to:
276
+
277
+ Splinter->new->gather_data->analyze(detail => 100)->results;
278
+
279
+ If any method returns something on which methods may not be called, the routine
280
+ croaks.
281
+
282
+ The arguments to C<curry_chain> form an optlist. The names are methods to be
283
+ called and the arguments, if given, are arrayrefs to be dereferenced and passed
284
+ as arguments to those methods. C<curry_chain> returns a generator like those
285
+ expected by Sub::Exporter.
286
+
287
+ B<Achtung!> at present, there is no way to pass arguments from the generated
288
+ routine to the method calls. This will probably be solved in future revisions
289
+ by allowing the opt list's values to be subroutines that will be called with
290
+ the generated routine's stack.
291
+
292
+ =head2 merge_col
293
+
294
+ exports => {
295
+ merge_col(defaults => {
296
+ twiddle => \'_twiddle_gen',
297
+ tweak => \&_tweak_gen,
298
+ }),
299
+ }
300
+
301
+ This utility wraps the given generator in one that will merge the named
302
+ collection into its args before calling it. This means that you can support a
303
+ "default" collector in multipe exports without writing the code each time.
304
+
305
+ You can specify as many pairs of collection names and generators as you like.
306
+
307
+ =head2 mixin_installer
308
+
309
+ use Sub::Exporter -setup => {
310
+ installer => Sub::Exporter::Util::mixin_installer,
311
+ exports => [ qw(foo bar baz) ],
312
+ };
313
+
314
+ This utility returns an installer that will install into a superclass and
315
+ adjust the ISA importing class to include the newly generated superclass.
316
+
317
+ If the target of importing is an object, the hierarchy is reversed: the new
318
+ class will be ISA the object's class, and the object will be reblessed.
319
+
320
+ B<Prerequisites>: This utility requires that Package::Generator be installed.
321
+
322
+ =head2 like
323
+
324
+ It's a collector that adds imports for anything like given regex.
325
+
326
+ If you provide this configuration:
327
+
328
+ exports => [ qw(igrep imap islurp exhausted) ],
329
+ collectors => { -like => Sub::Exporter::Util::like },
330
+
331
+ A user may import from your module like this:
332
+
333
+ use Your::Iterator -like => qr/^i/; # imports igre, imap, islurp
334
+
335
+ or
336
+
337
+ use Your::Iterator -like => [ qr/^i/ => { -prefix => 'your_' } ];
338
+
339
+ The group-like prefix and suffix arguments are respected; other arguments are
340
+ passed on to the generators for matching exports.
341
+
342
+ =head1 AUTHOR
343
+
344
+ Ricardo Signes <rjbs@cpan.org>
345
+
346
+ =head1 COPYRIGHT AND LICENSE
347
+
348
+ This software is copyright (c) 2007 by Ricardo Signes.
349
+
350
+ This is free software; you can redistribute it and/or modify it under
351
+ the same terms as the Perl 5 programming language system itself.
352
+
353
+ =cut
354
+
@@ -0,0 +1,329 @@
1
+ package Sub::Install;
2
+
3
+ use warnings;
4
+ use strict;
5
+
6
+ use Carp;
7
+ use Scalar::Util ();
8
+
9
+ =head1 NAME
10
+
11
+ Sub::Install - install subroutines into packages easily
12
+
13
+ =head1 VERSION
14
+
15
+ version 0.926
16
+
17
+ =cut
18
+
19
+ our $VERSION = '0.926';
20
+
21
+ =head1 SYNOPSIS
22
+
23
+ use Sub::Install;
24
+
25
+ Sub::Install::install_sub({
26
+ code => sub { ... },
27
+ into => $package,
28
+ as => $subname
29
+ });
30
+
31
+ =head1 DESCRIPTION
32
+
33
+ This module makes it easy to install subroutines into packages without the
34
+ unslightly mess of C<no strict> or typeglobs lying about where just anyone can
35
+ see them.
36
+
37
+ =head1 FUNCTIONS
38
+
39
+ =head2 install_sub
40
+
41
+ Sub::Install::install_sub({
42
+ code => \&subroutine,
43
+ into => "Finance::Shady",
44
+ as => 'launder',
45
+ });
46
+
47
+ This routine installs a given code reference into a package as a normal
48
+ subroutine. The above is equivalent to:
49
+
50
+ no strict 'refs';
51
+ *{"Finance::Shady" . '::' . "launder"} = \&subroutine;
52
+
53
+ If C<into> is not given, the sub is installed into the calling package.
54
+
55
+ If C<code> is not a code reference, it is looked for as an existing sub in the
56
+ package named in the C<from> parameter. If C<from> is not given, it will look
57
+ in the calling package.
58
+
59
+ If C<as> is not given, and if C<code> is a name, C<as> will default to C<code>.
60
+ If C<as> is not given, but if C<code> is a code ref, Sub::Install will try to
61
+ find the name of the given code ref and use that as C<as>.
62
+
63
+ That means that this code:
64
+
65
+ Sub::Install::install_sub({
66
+ code => 'twitch',
67
+ from => 'Person::InPain',
68
+ into => 'Person::Teenager',
69
+ as => 'dance',
70
+ });
71
+
72
+ is the same as:
73
+
74
+ package Person::Teenager;
75
+
76
+ Sub::Install::install_sub({
77
+ code => Person::InPain->can('twitch'),
78
+ as => 'dance',
79
+ });
80
+
81
+ =head2 reinstall_sub
82
+
83
+ This routine behaves exactly like C<L</install_sub>>, but does not emit a
84
+ warning if warnings are on and the destination is already defined.
85
+
86
+ =cut
87
+
88
+ sub _name_of_code {
89
+ my ($code) = @_;
90
+ require B;
91
+ my $name = B::svref_2object($code)->GV->NAME;
92
+ return $name unless $name =~ /\A__ANON__/;
93
+ return;
94
+ }
95
+
96
+ # See also Params::Util, to which this code was donated.
97
+ sub _CODELIKE {
98
+ (Scalar::Util::reftype($_[0])||'') eq 'CODE'
99
+ || Scalar::Util::blessed($_[0])
100
+ && (overload::Method($_[0],'&{}') ? $_[0] : undef);
101
+ }
102
+
103
+ # do the heavy lifting
104
+ sub _build_public_installer {
105
+ my ($installer) = @_;
106
+
107
+ sub {
108
+ my ($arg) = @_;
109
+ my ($calling_pkg) = caller(0);
110
+
111
+ # I'd rather use ||= but I'm whoring for Devel::Cover.
112
+ for (qw(into from)) { $arg->{$_} = $calling_pkg unless $arg->{$_} }
113
+
114
+ # This is the only absolutely required argument, in many cases.
115
+ Carp::croak "named argument 'code' is not optional" unless $arg->{code};
116
+
117
+ if (_CODELIKE($arg->{code})) {
118
+ $arg->{as} ||= _name_of_code($arg->{code});
119
+ } else {
120
+ Carp::croak
121
+ "couldn't find subroutine named $arg->{code} in package $arg->{from}"
122
+ unless my $code = $arg->{from}->can($arg->{code});
123
+
124
+ $arg->{as} = $arg->{code} unless $arg->{as};
125
+ $arg->{code} = $code;
126
+ }
127
+
128
+ Carp::croak "couldn't determine name under which to install subroutine"
129
+ unless $arg->{as};
130
+
131
+ $installer->(@$arg{qw(into as code) });
132
+ }
133
+ }
134
+
135
+ # do the ugly work
136
+
137
+ my $_misc_warn_re;
138
+ my $_redef_warn_re;
139
+ BEGIN {
140
+ $_misc_warn_re = qr/
141
+ Prototype\ mismatch:\ sub\ .+? |
142
+ Constant subroutine \S+ redefined
143
+ /x;
144
+ $_redef_warn_re = qr/Subroutine\ \S+\ redefined/x;
145
+ }
146
+
147
+ my $eow_re;
148
+ BEGIN { $eow_re = qr/ at .+? line \d+\.\Z/ };
149
+
150
+ sub _do_with_warn {
151
+ my ($arg) = @_;
152
+ my $code = delete $arg->{code};
153
+ my $wants_code = sub {
154
+ my $code = shift;
155
+ sub {
156
+ my $warn = $SIG{__WARN__} ? $SIG{__WARN__} : sub { warn @_ }; ## no critic
157
+ local $SIG{__WARN__} = sub {
158
+ my ($error) = @_;
159
+ for (@{ $arg->{suppress} }) {
160
+ return if $error =~ $_;
161
+ }
162
+ for (@{ $arg->{croak} }) {
163
+ if (my ($base_error) = $error =~ /\A($_) $eow_re/x) {
164
+ Carp::croak $base_error;
165
+ }
166
+ }
167
+ for (@{ $arg->{carp} }) {
168
+ if (my ($base_error) = $error =~ /\A($_) $eow_re/x) {
169
+ return $warn->(Carp::shortmess $base_error);
170
+ }
171
+ }
172
+ ($arg->{default} || $warn)->($error);
173
+ };
174
+ $code->(@_);
175
+ };
176
+ };
177
+ return $wants_code->($code) if $code;
178
+ return $wants_code;
179
+ }
180
+
181
+ sub _installer {
182
+ sub {
183
+ my ($pkg, $name, $code) = @_;
184
+ no strict 'refs'; ## no critic ProhibitNoStrict
185
+ *{"$pkg\::$name"} = $code;
186
+ return $code;
187
+ }
188
+ }
189
+
190
+ BEGIN {
191
+ *_ignore_warnings = _do_with_warn({
192
+ carp => [ $_misc_warn_re, $_redef_warn_re ]
193
+ });
194
+
195
+ *install_sub = _build_public_installer(_ignore_warnings(_installer));
196
+
197
+ *_carp_warnings = _do_with_warn({
198
+ carp => [ $_misc_warn_re ],
199
+ suppress => [ $_redef_warn_re ],
200
+ });
201
+
202
+ *reinstall_sub = _build_public_installer(_carp_warnings(_installer));
203
+
204
+ *_install_fatal = _do_with_warn({
205
+ code => _installer,
206
+ croak => [ $_redef_warn_re ],
207
+ });
208
+ }
209
+
210
+ =head2 install_installers
211
+
212
+ This routine is provided to allow Sub::Install compatibility with
213
+ Sub::Installer. It installs C<install_sub> and C<reinstall_sub> methods into
214
+ the package named by its argument.
215
+
216
+ Sub::Install::install_installers('Code::Builder'); # just for us, please
217
+ Code::Builder->install_sub({ name => $code_ref });
218
+
219
+ Sub::Install::install_installers('UNIVERSAL'); # feeling lucky, punk?
220
+ Anything::At::All->install_sub({ name => $code_ref });
221
+
222
+ The installed installers are similar, but not identical, to those provided by
223
+ Sub::Installer. They accept a single hash as an argument. The key/value pairs
224
+ are used as the C<as> and C<code> parameters to the C<install_sub> routine
225
+ detailed above. The package name on which the method is called is used as the
226
+ C<into> parameter.
227
+
228
+ Unlike Sub::Installer's C<install_sub> will not eval strings into code, but
229
+ will look for named code in the calling package.
230
+
231
+ =cut
232
+
233
+ sub install_installers {
234
+ my ($into) = @_;
235
+
236
+ for my $method (qw(install_sub reinstall_sub)) {
237
+ my $code = sub {
238
+ my ($package, $subs) = @_;
239
+ my ($caller) = caller(0);
240
+ my $return;
241
+ for (my ($name, $sub) = %$subs) {
242
+ $return = Sub::Install->can($method)->({
243
+ code => $sub,
244
+ from => $caller,
245
+ into => $package,
246
+ as => $name
247
+ });
248
+ }
249
+ return $return;
250
+ };
251
+ install_sub({ code => $code, into => $into, as => $method });
252
+ }
253
+ }
254
+
255
+ =head1 EXPORTS
256
+
257
+ Sub::Install exports C<install_sub> and C<reinstall_sub> only if they are
258
+ requested.
259
+
260
+ =head2 exporter
261
+
262
+ Sub::Install has a never-exported subroutine called C<exporter>, which is used
263
+ to implement its C<import> routine. It takes a hashref of named arguments,
264
+ only one of which is currently recognize: C<exports>. This must be an arrayref
265
+ of subroutines to offer for export.
266
+
267
+ This routine is mainly for Sub::Install's own consumption. Instead, consider
268
+ L<Sub::Exporter>.
269
+
270
+ =cut
271
+
272
+ sub exporter {
273
+ my ($arg) = @_;
274
+
275
+ my %is_exported = map { $_ => undef } @{ $arg->{exports} };
276
+
277
+ sub {
278
+ my $class = shift;
279
+ my $target = caller;
280
+ for (@_) {
281
+ Carp::croak "'$_' is not exported by $class" if !exists $is_exported{$_};
282
+ install_sub({ code => $_, from => $class, into => $target });
283
+ }
284
+ }
285
+ }
286
+
287
+ BEGIN { *import = exporter({ exports => [ qw(install_sub reinstall_sub) ] }); }
288
+
289
+ =head1 SEE ALSO
290
+
291
+ =over
292
+
293
+ =item L<Sub::Installer>
294
+
295
+ This module is (obviously) a reaction to Damian Conway's Sub::Installer, which
296
+ does the same thing, but does it by getting its greasy fingers all over
297
+ UNIVERSAL. I was really happy about the idea of making the installation of
298
+ coderefs less ugly, but I couldn't bring myself to replace the ugliness of
299
+ typeglobs and loosened strictures with the ugliness of UNIVERSAL methods.
300
+
301
+ =item L<Sub::Exporter>
302
+
303
+ This is a complete Exporter.pm replacement, built atop Sub::Install.
304
+
305
+ =back
306
+
307
+ =head1 AUTHOR
308
+
309
+ Ricardo Signes, C<< <rjbs@cpan.org> >>
310
+
311
+ Several of the tests are adapted from tests that shipped with Damian Conway's
312
+ Sub-Installer distribution.
313
+
314
+ =head1 BUGS
315
+
316
+ Please report any bugs or feature requests through the web interface at
317
+ L<http://rt.cpan.org>. I will be notified, and then you'll automatically be
318
+ notified of progress on your bug as I make changes.
319
+
320
+ =head1 COPYRIGHT
321
+
322
+ Copyright 2005-2006 Ricardo Signes, All Rights Reserved.
323
+
324
+ This program is free software; you can redistribute it and/or modify it
325
+ under the same terms as Perl itself.
326
+
327
+ =cut
328
+
329
+ 1;