make bump
[p5sagit/lib-with-preamble.git] / lib / lib / with / preamble.pm
1 package lib::with::preamble;
2
3 use strict;
4 use warnings FATAL => 'all';
5 use File::Spec;
6 use PerlIO::via::dynamic;
7
8 our $VERSION = '0.001001'; # 0.1.1
9
10 sub require_with_preamble {
11   my ($arrayref, $filename) = @_;
12   my (undef, $preamble, @libs) = @$arrayref;
13   foreach my $cand (map File::Spec->catfile($_, $filename), @libs) {
14     if (-f $cand) {
15       if (open my $fh, '<', $cand) {
16         return with_preamble($preamble."\n#line 1 $cand\n", $fh);
17       }
18     }
19   }
20 }
21
22 sub with_preamble {
23   my ($preamble, $fh) = @_;
24   PerlIO::via::dynamic->new(untranslate => sub {
25     $preamble and $_[1] =~ s/\A/$preamble/, undef($preamble);
26   })->via($fh);
27   return $fh;
28 }
29
30 sub import {
31   my ($class, $preamble, @libs) = @_;
32   return unless defined($preamble) and @libs;
33   unshift @INC, [ \&require_with_preamble, $preamble, @libs ];
34 }
35
36 1;
37
38 =head1 NAME
39
40 lib::with::preamble - invent your own default perl setup
41
42 =head1 SYNOPSIS
43
44   use lib::with::preamble 'use v5.16; use strictures 1;', 'lib';
45
46 The above will load .pm files from lib/ - but they'll act as if your code
47 always started with 'use v5.16; use strictures 1;'.
48
49 =head1 USING THIS IN A DISTRIBUTION
50
51 To use this in a dist, you'll want to create two files -
52
53   # my/lib.pm
54   use lib::with::preamble 'use v5.16; use strictures 1;', 'lib';
55   1;
56
57   # my/filter
58   print "use v5.16;\nuse strictures 1;\n#line 1\n";
59   while (<STDIN>) { print }
60
61 and then tell your Makefile.PL to use the filter -
62
63   WriteMakefile(
64     ...
65     PM_FILTER => 'perl my/filter'
66   );
67
68 Then during development instead of doing
69
70   $ perl -Ilib bin/script-to-test
71
72 you'll want to do -
73
74   $ perl -Mmy::lib bin/script-to-test
75
76 and for prove -
77
78   $ PERL5OPT=-Mmy::lib prove t/some-test.t
79
80 but once you run
81
82   $ make
83
84 your blib/ will get populated with files that already have your
85 preamble added, so
86
87   $ prove -b t/some-test.t
88
89 will just work, as will
90
91   $ make test
92
93 and when your users install your module, the .pm files will already have
94 the preamble at the top, so your installed files will look like
95
96   # My/Foo.pm
97   use v5.16;
98   use strictures 1;
99   # line 1
100   package My::Foo;
101   ...
102
103 and everything should work, without you even needing to add this module
104 as a dependency.
105
106 Patches to document an equivalent for those of you using L<Dist::Zilla>
107 (and L<Module::Build>, even if I don't like the bedamned thing) would be
108 very welcome.
109
110 =head1 WARNING
111
112 This is as much a proof of concept as anything else at this point, so the
113 interface is NOT guaranteed to be stable. Especially since this is meant
114 to be a sort of implicit sugar, and history has proven that other people
115 are much better at designing APIs to sugar than I am.
116
117 But provided you're using it the way I describe above, the my/filter script
118 isn't dependent on anything, so your users will be insulated from that.
119
120 So please do have a play around and see if it works for you.
121
122 =head1 AUTHOR
123
124 mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
125
126 =head1 CONTRIBUTORS
127
128 None yet. Well volunteered? :)
129
130 =head1 COPYRIGHT
131
132 Copyright (c) 2013 the lib::with::preamble L</AUTHOR> and L</CONTRIBUTORS>
133 as listed above.
134
135 =head1 LICENSE
136
137 This library is free software and may be distributed under the same terms
138 as perl itself.
139
140 =cut