increment $VERSION after 1.003029 release
[p5sagit/Devel-REPL.git] / lib / Devel / REPL.pm
CommitLineData
afe61f9c 1package Devel::REPL;
9d2a4940 2# ABSTRACT: A modern perl interactive shell
afe61f9c 3
77327851 4our $VERSION = '1.003030';
54beb05d 5
afe61f9c 6use Term::ReadLine;
7use Moose;
aa8b7647 8use namespace::autoclean;
089a0c4e 9use 5.008001; # backwards compat, doesn't warn like 5.8.1
59aedffc 10
afe61f9c 11with 'MooseX::Object::Pluggable';
12
e22aa835 13use Devel::REPL::Error;
14
afe61f9c 15has 'term' => (
b595a818 16 is => 'rw',
2df2b90e 17 lazy => 1,
afe61f9c 18 default => sub { Term::ReadLine->new('Perl REPL') }
19);
20
21has 'prompt' => (
b595a818 22 is => 'rw',
afe61f9c 23 default => sub { '$ ' }
24);
25
26has 'out_fh' => (
b595a818 27 is => 'rw',
28 lazy => 1,
afe61f9c 29 default => sub { shift->term->OUT || \*STDOUT; }
30);
31
57719095 32has 'exit_repl' => (
b595a818 33 is => 'rw',
57719095 34 default => sub { 0 }
35);
36
afe61f9c 37sub run {
38 my ($self) = @_;
e22aa835 39 while ($self->run_once_safely) {
57719095 40 # keep looping unless we want to exit REPL
41 last if $self->exit_repl;
afe61f9c 42 }
43}
44
e22aa835 45sub run_once_safely {
46 my ($self, @args) = @_;
47
48 my $ret = eval { $self->run_once(@args) };
49
50 if ($@) {
51 my $error = $@;
52 eval { $self->print("Error! - $error\n"); };
53 return 1;
54 } else {
55 return $ret;
56 }
57}
58
afe61f9c 59sub run_once {
60 my ($self) = @_;
e22aa835 61
afe61f9c 62 my $line = $self->read;
57719095 63 return unless defined($line); # undefined value == EOF
e22aa835 64
65 my @ret = $self->formatted_eval($line);
66
57719095 67 $self->print(@ret) unless $self->exit_repl;
e22aa835 68
afe61f9c 69 return 1;
70}
71
e22aa835 72sub formatted_eval {
73 my ( $self, @args ) = @_;
74
75 my @ret = $self->eval(@args);
76
77 return $self->format(@ret);
78}
79
80sub format {
81 my ( $self, @stuff ) = @_;
82
c3bbf326 83 if ( $self->is_error($stuff[0]) ) {
e22aa835 84 return $self->format_error(@stuff);
85 } else {
86 return $self->format_result(@stuff);
87 }
88}
89
90sub format_result {
91 my ( $self, @stuff ) = @_;
92
93 return @stuff;
94}
95
96sub format_error {
97 my ( $self, $error ) = @_;
98 return $error->stringify;
99}
100
c3bbf326 101sub is_error {
102 my ( $self, $thingy ) = @_;
103 blessed($thingy) and $thingy->isa("Devel::REPL::Error");
104}
105
afe61f9c 106sub read {
107 my ($self) = @_;
108 return $self->term->readline($self->prompt);
109}
110
911a1c24 111sub eval {
112 my ($self, $line) = @_;
c3bbf326 113 my $compiled = $self->compile($line);
114 return $compiled unless defined($compiled) and not $self->is_error($compiled);
115 return $self->execute($compiled);
911a1c24 116}
117
118sub compile {
e22aa835 119 my ( $_REPL, @args ) = @_;
120 my $compiled = eval $_REPL->wrap_as_sub(@args);
c3bbf326 121 return $_REPL->error_return("Compile error", $@) if $@;
911a1c24 122 return $compiled;
123}
124
125sub wrap_as_sub {
e22aa835 126 my ($self, $line, %args) = @_;
127 return qq!sub {\n!. ( $args{no_mangling} ? $line : $self->mangle_line($line) ).qq!\n}\n!;
911a1c24 128}
129
130sub mangle_line {
131 my ($self, $line) = @_;
132 return $line;
133}
134
afe61f9c 135sub execute {
48ddfeae 136 my ($self, $to_exec, @args) = @_;
137 my @ret = eval { $to_exec->(@args) };
138 return $self->error_return("Runtime error", $@) if $@;
afe61f9c 139 return @ret;
140}
141
911a1c24 142sub error_return {
143 my ($self, $type, $error) = @_;
e22aa835 144 return Devel::REPL::Error->new( type => $type, message => $error );
911a1c24 145}
146
afe61f9c 147sub print {
148 my ($self, @ret) = @_;
149 my $fh = $self->out_fh;
59aedffc 150 no warnings 'uninitialized';
afe61f9c 151 print $fh "@ret";
a66625d6 152 print $fh "\n" if $self->term->ReadLine =~ /Gnu/;
afe61f9c 153}
154
9d2a4940 1551;
156__END__
59aedffc 157
9d2a4940 158=pod
59aedffc 159
160=head1 SYNOPSIS
161
162 my $repl = Devel::REPL->new;
163 $repl->load_plugin($_) for qw(History LexEnv);
164 $repl->run
165
166Alternatively, use the 're.pl' script installed with the distribution
167
950232b2 168 system$ re.pl
169
408564af 170=head1 DESCRIPTION
171
172This is an interactive shell for Perl, commonly known as a REPL - Read,
173Evaluate, Print, Loop. The shell provides for rapid development or testing
174of code without the need to create a temporary source code file.
175
176Through a plugin system, many features are available on demand. You can also
177tailor the environment through the use of profiles and run control files, for
178example to pre-load certain Perl modules when working on a particular project.
179
180=head1 USAGE
181
182To start a shell, follow one of the examples in the L</"SYNOPSIS"> above.
183
184Once running, the shell accepts and will attempt to execute any code given. If
185the code executes successfully you'll be shown the result, otherwise an error
186message will be returned. Here are a few examples:
187
188 $_ print "Hello, world!\n"
189 Hello, world!
190 1
191 $_ nosuchfunction
192 Compile error: Bareword "nosuchfunction" not allowed while "strict subs" in use at (eval 130) line 5.
20d9434d 193
194 $_
408564af 195
196In the first example above you see the output of the command (C<Hello,
197world!>), if any, and then the return value of the statement (C<1>). Following
198that example, an error is returned when the execution of some code fails.
199
200Note that the lack of semicolon on the end is not a mistake - the code is
201run inside a Block structure (to protect the REPL in case the code blows up),
202which means a single statement doesn't require the semicolon. You can add one
203if you like, though.
204
6aa58492 205If you followed the first example in the L</"SYNOPSIS"> above, you'll have the
8d5343b5 206L<History|Devel::REPL::Plugin::History> and L<LexEnv|Devel::REPL::Plugin::LexEnv>
207plugins loaded (and there are many more available).
408564af 208Although the shell might support "up-arrow" history, the History plugin adds
209"bang" history to that so you can re-execute chosen commands (with e.g.
210C<!53>). The LexEnv plugin ensures that lexical variables declared with the
211C<my> keyword will automatically persist between statements executed in the
212REPL shell.
213
214When you C<use> any Perl module, the C<import()> will work as expected - the
215exported functions from that module are available for immediate use:
216
217 $_ carp "I'm dieeeing!\n"
218 String found where operator expected at (eval 129) line 5, near "carp "I'm dieeeing!\n""
219 (Do you need to predeclare carp?)
220 Compile error: syntax error at (eval 129) line 5, near "carp "I'm dieeeing!\n""
221 BEGIN not safe after errors--compilation aborted at (eval 129) line 5.
20d9434d 222
223 $_ use Carp
224
408564af 225 $_ carp "I'm dieeeing!\n"
226 I'm dieeeing!
227 at /usr/share/perl5/Lexical/Persistence.pm line 327
228 1
20d9434d 229 $_
408564af 230
73d11b24 231To quit from the shell, hit C<Ctrl+D> or C<Ctrl+C>.
232
233 MSWin32 NOTE: control keys won't work if TERM=dumb
234 because readline functionality will be disabled.
235
408564af 236
237=head2 Run Control Files
238
239For particular projects you might well end up running the same commands each
240time the REPL shell starts up - loading Perl modules, setting configuration,
241and so on. A run control file lets you have this done automatically, and you
242can have multiple files for different projects.
243
244By default the C<re.pl> program looks for C<< $HOME/.re.pl/repl.rc >>, and
245runs whatever code is in there as if you had entered it at the REPL shell
246yourself.
247
248To set a new run control file that's also in that directory, pass it as a
249filename like so:
250
251 system$ re.pl --rcfile myproject.pc
252
0e0d2539 253If the filename happens to contain a forward slash, then it's used absolutely,
408564af 254or realive to the current working directory:
255
256 system$ re.pl --rcfile /path/to/my/project/repl.rc
257
258Within the run control file you might want to load plugins. This is covered in
259L</"The REPL shell object"> section, below.
260
261=head2 Profiles
262
263To allow for the sharing of run control files, you can fashion them into a
264Perl module for distribution (perhaps via the CPAN). For more information on
265this feature, please see the L<Devel::REPL::Profile> manual page.
266
e72070d7 267A C<Standard> profile ships with C<Devel::REPL>; it loads the following plugins
268(note that some of these require optional features -- or you can also use the
269C<Minimal> profile):
408564af 270
f4d48832 271=for :list
272* L<Devel::REPL::Plugin::History>
273* L<Devel::REPL::Plugin::LexEnv>
274* L<Devel::REPL::Plugin::DDS>
275* L<Devel::REPL::Plugin::Packages>
276* L<Devel::REPL::Plugin::Commands>
277* L<Devel::REPL::Plugin::MultiLine::PPI>
278* L<Devel::REPL::Plugin::Colors>
279* L<Devel::REPL::Plugin::Completion>
280* L<Devel::REPL::Plugin::CompletionDriver::INC>
281* L<Devel::REPL::Plugin::CompletionDriver::LexEnv>
282* L<Devel::REPL::Plugin::CompletionDriver::Keywords>
283* L<Devel::REPL::Plugin::CompletionDriver::Methods>
284* L<Devel::REPL::Plugin::ReadlineHistory>
408564af 285
286=head2 Plugins
287
0e0d2539 288Plugins are a way to add functionality to the REPL shell, and take advantage of
408564af 289C<Devel::REPL> being based on the L<Moose> object system for Perl 5. This
290means it's simple to 'hook into' many steps of the R-E-P-L process. Plugins
291can change the way commands are interpreted, or the way their results are
292output, or even add commands to the shell environment.
293
294A number of plugins ship with C<Devel::REPL>, and more are available on the
295CPAN. Some of the shipped plugins are loaded in the default profile, mentioned
8d5343b5 296above. These plugins can be loaded in your F< $HOME/.re.pl/repl.rc > like:
cfb85b27 297
298 load_plugin qw( CompletionDriver::Global DumpHistory );
408564af 299
300Writing your own plugins is not difficult, and is discussed in the
301L<Devel::REPL::Plugin> manual page, along with links to the manual pages of
302all the plugins shipped with C<Devel::REPL>.
303
304=head2 The REPL shell object
305
306From time to time you'll want to interact with or manipulate the
307C<Devel::REPL> shell object itself; that is, the instance of the shell you're
308currently running.
309
310The object is always available through the C<$_REPL> variable. One common
311requirement is to load an additional plugin, after your profile and run
312control files have already been executed:
313
314 $_ $_REPL->load_plugin('Timing');
315 1
316 $_ print "Hello again, world!\n"
317 Hello again, world!
318 Took 0.00148296356201172 seconds.
319 1
320 $_
321
e72070d7 322=head1 OPTIONAL FEATURES
408564af 323
e72070d7 324In addition to the prerequisites declared in this distribution, which should be automatically installed by your L<CPAN> client, there are a number of optional features, used by
325additional plugins. You can install any of these features by installing this
326distribution interactively (e.g. C<cpanm --interactive Devel::REPL>).
408564af 327
e72070d7 328=for comment I hope to automatically generate this data via a Pod::Weaver section
ab213f1f 329
f4d48832 330=for :list
331* Completion plugin - extensible tab completion
332* DDS plugin - better format results with Data::Dump::Streamer
333* DDC plugin - even better format results with Data::Dumper::Concise
334* INC completion driver - tab complete module names in use and require
335* Interrupt plugin - traps SIGINT to kill long-running lines
336* Keywords completion driver - tab complete Perl keywords and operators
337* LexEnv plugin - variables declared with "my" persist between statements
338* MultiLine::PPI plugin - continue reading lines until all blocks are closed
339* Nopaste plugin - upload a session\'s input and output to a Pastebin
340* PPI plugin - PPI dumping of Perl code
341* Refresh plugin - automatically reload libraries with Module::Refresh
408564af 342
1282c944 343=head1 SEE ALSO
344
345=for :list
5c6afa7b 346* L<A comparison of various REPLs|https://www.shadowcat.co.uk/blog/matt-s-trout/mstpan-17/>
1282c944 347
59aedffc 348=cut