increment $VERSION after 1.003029 release
[p5sagit/Devel-REPL.git] / lib / Devel / REPL.pm
1 package Devel::REPL;
2 # ABSTRACT: A modern perl interactive shell
3
4 our $VERSION = '1.003030';
5
6 use Term::ReadLine;
7 use Moose;
8 use namespace::autoclean;
9 use 5.008001; # backwards compat, doesn't warn like 5.8.1
10
11 with 'MooseX::Object::Pluggable';
12
13 use Devel::REPL::Error;
14
15 has 'term' => (
16   is => 'rw',
17   lazy => 1,
18   default => sub { Term::ReadLine->new('Perl REPL') }
19 );
20
21 has 'prompt' => (
22   is => 'rw',
23   default => sub { '$ ' }
24 );
25
26 has 'out_fh' => (
27   is => 'rw',
28   lazy => 1,
29   default => sub { shift->term->OUT || \*STDOUT; }
30 );
31
32 has 'exit_repl' => (
33   is => 'rw',
34   default => sub { 0 }
35 );
36
37 sub run {
38   my ($self) = @_;
39   while ($self->run_once_safely) {
40     # keep looping unless we want to exit REPL
41     last if $self->exit_repl;
42   }
43 }
44
45 sub 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
59 sub run_once {
60   my ($self) = @_;
61
62   my $line = $self->read;
63   return unless defined($line);     # undefined value == EOF
64
65   my @ret = $self->formatted_eval($line);
66
67   $self->print(@ret) unless $self->exit_repl;
68
69   return 1;
70 }
71
72 sub formatted_eval {
73   my ( $self, @args ) = @_;
74
75   my @ret = $self->eval(@args);
76
77   return $self->format(@ret);
78 }
79
80 sub format {
81   my ( $self, @stuff ) = @_;
82
83   if ( $self->is_error($stuff[0]) ) {
84     return $self->format_error(@stuff);
85   } else {
86     return $self->format_result(@stuff);
87   }
88 }
89
90 sub format_result {
91   my ( $self, @stuff ) = @_;
92
93   return @stuff;
94 }
95
96 sub format_error {
97   my ( $self, $error ) = @_;
98   return $error->stringify;
99 }
100
101 sub is_error {
102   my ( $self, $thingy ) = @_;
103   blessed($thingy) and $thingy->isa("Devel::REPL::Error");
104 }
105
106 sub read {
107   my ($self) = @_;
108   return $self->term->readline($self->prompt);
109 }
110
111 sub eval {
112   my ($self, $line) = @_;
113   my $compiled = $self->compile($line);
114   return $compiled unless defined($compiled) and not $self->is_error($compiled);
115   return $self->execute($compiled);
116 }
117
118 sub compile {
119   my ( $_REPL, @args ) = @_;
120   my $compiled = eval $_REPL->wrap_as_sub(@args);
121   return $_REPL->error_return("Compile error", $@) if $@;
122   return $compiled;
123 }
124
125 sub wrap_as_sub {
126   my ($self, $line, %args) = @_;
127   return qq!sub {\n!. ( $args{no_mangling} ? $line : $self->mangle_line($line) ).qq!\n}\n!;
128 }
129
130 sub mangle_line {
131   my ($self, $line) = @_;
132   return $line;
133 }
134
135 sub execute {
136   my ($self, $to_exec, @args) = @_;
137   my @ret = eval { $to_exec->(@args) };
138   return $self->error_return("Runtime error", $@) if $@;
139   return @ret;
140 }
141
142 sub error_return {
143   my ($self, $type, $error) = @_;
144   return Devel::REPL::Error->new( type => $type, message => $error );
145 }
146
147 sub print {
148   my ($self, @ret) = @_;
149   my $fh = $self->out_fh;
150   no warnings 'uninitialized';
151   print $fh "@ret";
152   print $fh "\n" if $self->term->ReadLine =~ /Gnu/;
153 }
154
155 1;
156 __END__
157
158 =pod
159
160 =head1 SYNOPSIS
161
162   my $repl = Devel::REPL->new;
163   $repl->load_plugin($_) for qw(History LexEnv);
164   $repl->run
165
166 Alternatively, use the 're.pl' script installed with the distribution
167
168   system$ re.pl
169
170 =head1 DESCRIPTION
171
172 This is an interactive shell for Perl, commonly known as a REPL - Read,
173 Evaluate, Print, Loop. The shell provides for rapid development or testing
174 of code without the need to create a temporary source code file.
175
176 Through a plugin system, many features are available on demand. You can also
177 tailor the environment through the use of profiles and run control files, for
178 example to pre-load certain Perl modules when working on a particular project.
179
180 =head1 USAGE
181
182 To start a shell, follow one of the examples in the L</"SYNOPSIS"> above.
183
184 Once running, the shell accepts and will attempt to execute any code given. If
185 the code executes successfully you'll be shown the result, otherwise an error
186 message 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.
193
194  $_
195
196 In the first example above you see the output of the command (C<Hello,
197 world!>), if any, and then the return value of the statement (C<1>). Following
198 that example, an error is returned when the execution of some code fails.
199
200 Note that the lack of semicolon on the end is not a mistake - the code is
201 run inside a Block structure (to protect the REPL in case the code blows up),
202 which means a single statement doesn't require the semicolon. You can add one
203 if you like, though.
204
205 If you followed the first example in the L</"SYNOPSIS"> above, you'll have the
206 L<History|Devel::REPL::Plugin::History> and L<LexEnv|Devel::REPL::Plugin::LexEnv>
207 plugins loaded (and there are many more available).
208 Although 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.
210 C<!53>). The LexEnv plugin ensures that lexical variables declared with the
211 C<my> keyword will automatically persist between statements executed in the
212 REPL shell.
213
214 When you C<use> any Perl module, the C<import()> will work as expected - the
215 exported 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.
222
223  $_ use Carp
224
225  $_ carp "I'm dieeeing!\n"
226  I'm dieeeing!
227   at /usr/share/perl5/Lexical/Persistence.pm line 327
228  1
229  $_
230
231 To 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
236
237 =head2 Run Control Files
238
239 For particular projects you might well end up running the same commands each
240 time the REPL shell starts up - loading Perl modules, setting configuration,
241 and so on. A run control file lets you have this done automatically, and you
242 can have multiple files for different projects.
243
244 By default the C<re.pl> program looks for C<< $HOME/.re.pl/repl.rc >>, and
245 runs whatever code is in there as if you had entered it at the REPL shell
246 yourself.
247
248 To set a new run control file that's also in that directory, pass it as a
249 filename like so:
250
251  system$ re.pl --rcfile myproject.pc
252
253 If the filename happens to contain a forward slash, then it's used absolutely,
254 or realive to the current working directory:
255
256  system$ re.pl --rcfile /path/to/my/project/repl.rc
257
258 Within the run control file you might want to load plugins. This is covered in
259 L</"The REPL shell object"> section, below.
260
261 =head2 Profiles
262
263 To allow for the sharing of run control files, you can fashion them into a
264 Perl module for distribution (perhaps via the CPAN). For more information on
265 this feature, please see the L<Devel::REPL::Profile> manual page.
266
267 A 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
269 C<Minimal> profile):
270
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>
285
286 =head2 Plugins
287
288 Plugins are a way to add functionality to the REPL shell, and take advantage of
289 C<Devel::REPL> being based on the L<Moose> object system for Perl 5. This
290 means it's simple to 'hook into' many steps of the R-E-P-L process. Plugins
291 can change the way commands are interpreted, or the way their results are
292 output, or even add commands to the shell environment.
293
294 A number of plugins ship with C<Devel::REPL>, and more are available on the
295 CPAN. Some of the shipped plugins are loaded in the default profile, mentioned
296 above.  These plugins can be loaded in your F< $HOME/.re.pl/repl.rc > like:
297
298   load_plugin qw( CompletionDriver::Global DumpHistory );
299
300 Writing your own plugins is not difficult, and is discussed in the
301 L<Devel::REPL::Plugin> manual page, along with links to the manual pages of
302 all the plugins shipped with C<Devel::REPL>.
303
304 =head2 The REPL shell object
305
306 From time to time you'll want to interact with or manipulate the
307 C<Devel::REPL> shell object itself; that is, the instance of the shell you're
308 currently running.
309
310 The object is always available through the C<$_REPL> variable. One common
311 requirement is to load an additional plugin, after your profile and run
312 control 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
322 =head1 OPTIONAL FEATURES
323
324 In 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
325 additional plugins. You can install any of these features by installing this
326 distribution interactively (e.g. C<cpanm --interactive Devel::REPL>).
327
328 =for comment I hope to automatically generate this data via a Pod::Weaver section
329
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
342
343 =head1 SEE ALSO
344
345 =for :list
346 * L<A comparison of various REPLs|https://www.shadowcat.co.uk/blog/matt-s-trout/mstpan-17/>
347
348 =cut