Move to Moo for fast bootstrapping.
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / OutputCache.pm
CommitLineData
cf51843c 1package Devel::REPL::Plugin::OutputCache;
2
6a5409bc 3use Devel::REPL::Plugin;
e2d0b019 4use namespace::sweep;
5use MooX::Types::MooseLike::Base qw(ArrayRef Bool);
cf51843c 6
7has output_cache => (
8 is => 'rw',
e2d0b019 9 isa => ArrayRef,
cf51843c 10 default => sub { [] },
11 lazy => 1,
12);
13
588f0734 14has warned_about_underscore => (
15 is => 'rw',
e2d0b019 16 isa => Bool,
17 default => sub { 0 },
588f0734 18 lazy => 1,
19);
20
cf51843c 21around 'eval' => sub {
22 my $orig = shift;
23 my ($self, $line) = @_;
24
588f0734 25 my $has_underscore = *_{CODE};
26 if ($has_underscore && !$self->warned_about_underscore) {
27 warn "OutputCache: Sub _ already defined.";
28 $self->warned_about_underscore(1);
29 }
30 else {
31 # if _ is removed, then we should warn about it again if it comes back
32 $self->warned_about_underscore(0);
33 }
34
35 # this needs to be a postfix conditional for 'local' to work
36 local *_ = sub () { $self->output_cache->[-1] } unless $has_underscore;
cf51843c 37
38 my @ret;
39 if (wantarray) {
40 @ret = $self->$orig($line);
41 }
42 else {
43 $ret[0] = $self->$orig($line);
44 }
45
46 push @{ $self->output_cache }, @ret > 1 ? \@ret : $ret[0];
47 return wantarray ? @ret : $ret[0];
48};
49
501;
51
52__END__
53
54=head1 NAME
55
56Devel::REPL::Plugin::OutputCache - remember past results, _ is most recent
57
58=head1 SYNOPSIS
59
60 > 21 / 7
61 3
62 > _ * _
63 9
64 > sub { die "later" }
65 sub { die "later" }
66 > _->()
67 Runtime error: later
68
69=head1 DESCRIPTION
70
71Re-using results is very useful when working in a REPL. With C<OutputCache> you
72get C<_>, which holds the past result. The benefit is that you can build up
73your result instead of having to type it in all at once, or store it in
74intermediate variables. C<OutputCache> also provides
75C<< $_REPL->output_cache >>, an array reference of all results in this session.
76
77Devel::REPL already has a similar plugin, L<Devel::REPL::Plugin::History>.
78There are some key differences though:
79
80=over 4
81
82=item Input vs Output
83
84C<History> remembers input. C<OutputCache> remembers output.
85
86=item Munging vs Pure Perl
87
88C<History> performs regular expressions on your input. C<OutputCache> provides
89the C<_> sub as a hook to get the most recent result, and
90C<< $_REPL->output_cache >> for any other results.
91
92=item Principle of Least Surprise
93
94C<History> will replace exclamation points in any part of the input. This is
95problematic if you accidentally include one in a string, or in a C<not>
96expression. C<OutputCache> uses a regular (if oddly named) subroutine so Perl
97does the parsing -- no surprises.
98
99=back
100
101=head1 CAVEATS
102
103The C<_> sub is shared across all packages. This means that if a module is
104using the C<_> sub, then there is a conflict and you should not use this
105plugin. For example, L<Jifty> uses the C<_> sub for localization. Jifty is the
106only known user.
107
108=head1 SEE ALSO
109
110C<Devel::REPL>, C<Devel::REPL::Plugin::History>
111
112=head1 AUTHOR
113
114Shawn M Moore, C<< <sartak at gmail dot com> >>
115
116=head1 COPYRIGHT AND LICENSE
117
118Copyright (C) 2007 by Shawn M Moore
119
120This library is free software; you can redistribute it and/or modify
121it under the same terms as Perl itself.
122
123=cut