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