File Coverage

blib/lib/Perl/Shell.pm
Criterion Covered Total %
statement 60 91 65.9
branch 5 22 22.7
condition n/a
subroutine 19 24 79.1
pod 2 2 100.0
total 86 139 61.8


line stmt bran cond sub pod time code
1             package Perl::Shell;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Perl::Shell - A Python-style "command line interpreter" for Perl
8              
9             =head1 SYNOPSIS
10              
11             C:\Document and Settings\adamk> perlthon
12             Perl 5.10.1 (Sat Oct 17 22:14:49 2009) [Win32 strawberryperl 5.10.1.0 #1 33 i386]
13             Type "help;", "copyright;", or "license;" for more information.
14            
15             >>> print "Hello World!\n";
16             Hello World!
17            
18             >>>
19              
20             =head1 DESCRIPTION
21              
22             B
23              
24             B
25              
26             This module provides a lookalike implementation of a "command line
27             interpreter" for Perl, in the style of the Python equivalent.
28              
29             This is part an attempt to make Perl more approachable (both in general
30             and specifically for Python programmers), partly an exercise to force
31             myself to explore Python's usability aspects, partly a way to provide
32             Strawberry Perl with a "Perl (command line)" start menu entry, and
33             partly as fodder for a funny lightning talk.
34              
35             On the command line, you can start the shell with "perlthon".
36              
37             =head2 Features
38              
39             Multi-line statements are supported correctly by using L to
40             detect statement boundaries (something it can do very reliably).
41              
42             >>> print
43             ... "Hello World!\n"
44             ... ;
45             Hello World!
46            
47             >>>
48              
49             Lexical variables are supported correctly across multiple statements.
50              
51             >>> my $foo = "Hello World!\n";
52            
53             >>> print $foo;
54             Hello World!
55            
56             >>>
57              
58             Package scoping and state are correctly preserved across multiple
59             statments.
60              
61             >>> package Foo;
62            
63             >>> sub bar {
64             ... print "Hello World!\n";
65             ... }
66            
67             >>> Foo::bar();
68             Hello World!
69            
70             >>>
71              
72             =head1 FUNCTIONS
73              
74             =cut
75              
76 3     3   45659 use 5.006;
  3         10  
  3         113  
77 3     3   16 use strict;
  3         5  
  3         96  
78 3     3   25 use Config;
  3         6  
  3         122  
79 3     3   15 use Carp ();
  3         4  
  3         79  
80 3     3   2729 use Params::Util 1.00 '_INSTANCE';
  3         16114  
  3         274  
81 3     3   3191 use Term::ReadLine 0 ();
  3         10765  
  3         87  
82 3     3   3074 use PPI 1.205 ();
  3         511374  
  3         227  
83              
84             our $VERSION = '0.04';
85              
86              
87              
88              
89              
90             ######################################################################
91             # Content
92              
93 3     3   32 use constant INTRO => <<"END_TEXT";
  3         5  
  3         2683  
94             Perl $Config{version} ($Config{cf_time}) [$Config{myuname}]
95             Type "help;", "copyright;", or "license;" for more information.
96             END_TEXT
97              
98 3     3   10022 use constant HELP => <<"END_TEXT";
  3         8  
  3         152  
99             Type help() for interactive help, or help(object) for help about object.
100             END_TEXT
101              
102 3     3   38 use constant COPYRIGHT => <<"END_TEXT";
  3         4  
  3         277  
103             Perl is Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
104             2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Larry Wall and others.
105             All rights reserved.
106             END_TEXT
107              
108 3     3   16 use constant LICENSE => <<"END_TEXT";
  3         5  
  3         1748  
109             This program is free software; you can redistribute it and/or modify
110             it under the terms of either:
111              
112             a) the GNU General Public License as published by the Free
113             Software Foundation; either version 1, or (at your option) any
114             later version, or
115              
116             b) the "Artistic License" which comes with this Kit.
117              
118             This program is distributed in the hope that it will be useful,
119             but WITHOUT ANY WARRANTY; without even the implied warranty of
120             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
121             the GNU General Public License or the Artistic License for more details.
122              
123             You should have received a copy of the Artistic License with this
124             Kit, in the file named "Artistic". If not, I'll be glad to provide one.
125              
126             You should also have received a copy of the GNU General Public License
127             along with this program in the file named "Copying". If not, write to the
128             Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
129             Boston, MA 02110-1301, USA or visit their web page on the internet at
130             http://www.gnu.org/copyleft/gpl.html.
131              
132             For those of you that choose to use the GNU General Public License,
133             my interpretation of the GNU General Public License is that no Perl
134             script falls under the terms of the GPL unless you explicitly put
135             said script under the terms of the GPL yourself. Furthermore, any
136             object code linked with perl does not automatically fall under the
137             terms of the GPL, provided such object code only adds definitions
138             of subroutines and variables, and does not otherwise impair the
139             resulting interpreter from executing any standard Perl script. I
140             consider linking in C subroutines in this manner to be the moral
141             equivalent of defining subroutines in the Perl language itself. You
142             may sell such an object file as proprietary provided that you provide
143             or offer to provide the Perl source, as specified by the GNU General
144             Public License. (This is merely an alternate way of specifying input
145             to the program.) You may also sell a binary produced by the dumping of
146             a running Perl script that belongs to you, provided that you provide or
147             offer to provide the Perl source as specified by the GPL. (The
148             fact that a Perl interpreter and your code are in the same binary file
149             is, in this case, a form of mere aggregation.) This is my interpretation
150             of the GPL. If you still have concerns or difficulties understanding
151             my intent, feel free to contact me. Of course, the Artistic License
152             spells all this out for your protection, so you may prefer to use that.
153             END_TEXT
154              
155              
156              
157              
158              
159             #####################################################################
160             # Top Level Commands
161              
162             sub main::help () {
163 0     0   0 print HELP;
164             }
165              
166             sub main::copyright () {
167 0     0   0 print COPYRIGHT;
168             }
169              
170             sub main::license () {
171 0     0   0 print LICENSE;
172             }
173              
174              
175              
176              
177              
178             #####################################################################
179             # Shell Functions
180              
181             =pod
182              
183             =head2 shell
184              
185             Perl::Shell::shell();
186              
187             The C function starts up the command line shell. It takes no
188             parameters and returns when the user does an exit().
189              
190             Lexical and package persistance is B maintained between multiple
191             shell runs.
192              
193             =cut
194              
195             sub shell {
196             # Set up the lexical scope for the session
197 0     0 1 0 my $state = Perl::Shell::_State->new;
198              
199             # Say hello to the user
200 0         0 print INTRO;
201              
202             # The main command loop
203 0         0 my @buffer = ();
204 0         0 my $package = 'main';
205 0         0 while ( 1 ) {
206             # Read in a line
207 0 0       0 my $line = _readline(@buffer ? '... ' : '>>> ');
208 0 0       0 unless ( defined $line ) {
209 0         0 die "Failed to readline\n";
210             }
211 0         0 push @buffer, $line;
212              
213             # Continue if the statement is not complete
214 0 0       0 next unless complete( @buffer );
215              
216             # Execute the code
217 0         0 local $@;
218 0         0 my $code = join "\n", @buffer;
219 0         0 my @rv = eval {
220 0         0 $state->do($code);
221             };
222 0 0       0 print "ERROR: $@" if $@;
223 0         0 print "\n";
224              
225             # Clean up for the next command
226 0         0 @buffer = ();
227             }
228             }
229              
230             my $term;
231             sub _readline {
232 0     0   0 my $prompt = shift;
233 0 0       0 if ( -t STDIN ) {
234 0 0       0 unless ( $term ) {
235 0         0 require Term::ReadLine;
236 0         0 $term = Term::ReadLine->new('Perl-Shell');
237             }
238 0         0 return $term->readline($prompt);
239             } else {
240 0         0 print $prompt;
241 0         0 my $line = <>;
242 0 0       0 chomp if defined $line;
243 0         0 return $line;
244             }
245             }
246              
247              
248              
249              
250              
251             #####################################################################
252             # Support Functions
253              
254             =head2 complete
255              
256             my $done = Perl::Shell::complete(@code);
257              
258             The C function takes one or more strings of Perl code
259             (which it will join as lines if there are more than one) and uses
260             PPI to determine is the code is a "complete" Perl document.
261              
262             That is, does the code represent a string of Perl where the topmost
263             level of nesting ( i.e. sub { ... } ) and the end of the string marks
264             a natural statement boundary.
265              
266             Returns true if the code is a complete document, or false if not.
267              
268             This function is documented and supported as a convenience for other
269             people implementing similar functionality (and may be moved into PPI
270             itself at a later time).
271              
272             =cut
273              
274             # To be "complete" a fragment of Perl must have no open structures
275             # and terminate with a clear statement end.
276             sub complete {
277 2     2 1 508 my $string = join "\n", @_;
278              
279             # As a quick and dirty way to check for a clear statement
280             # end, we append a semi-colon to the string. If this is
281             # subsequently parsed as a null statement, we know the
282             # string is a complete document.
283             # The newline is added to get us out of comment blocks
284             # and similar line-specific things.
285 2         3 $string .= "\n;";
286              
287             # Parse the string into a document
288 2         17 my $document = PPI::Document->new( \$string );
289 2 50       3190 unless ( $document ) {
290 0         0 die "PPI failed to parse document";
291             }
292              
293             # The document must end in a null statement
294 2 100       12 unless ( _INSTANCE($document->child(-1), 'PPI::Statement::Null') ) {
295 1         15 return '';
296             }
297              
298             # The document must not contain any open braces
299             $document->find_any( sub {
300 8 50   8   145 $_[1]->isa('PPI::Structure') and ! $_[1]->finish
301 1 50       36 } ) and return '';
302              
303             # The document is complete
304 1         23 return 1;
305             }
306              
307              
308              
309              
310              
311             ######################################################################
312             # Enhanced Lexical::Persistance with sticky package
313              
314             # Should probably move this to its own file at some point.
315              
316             package Perl::Shell::_State;
317              
318 3     3   2880 use Lexical::Persistence 1.01 ();
  3         24623  
  3         785  
319              
320             our @ISA = 'Lexical::Persistence';
321              
322             # Package changes are tracked by temporarily passing it via a global.
323             # This does not contain permanent state, and so shouldn't suffer most
324             # of the normal problems caused by globals.
325             our $PACKAGE = undef;
326              
327             sub new {
328 1     1   13 my $class = shift;
329 1         12 my $self = $class->SUPER::new(@_);
330              
331             # Set the initial package
332 1         27 $self->{package} = 'main';
333              
334 1         3 return $self;
335             }
336              
337             sub get_package {
338 8     8   726 $_[0]->{package};
339             }
340              
341             sub set_package {
342 6     6   16 $_[0]->{package} = $_[1];
343             }
344              
345             sub prepare {
346 6     6   22 my $self = shift;
347 6         10 my $code = shift;
348 6         13 my $package = $self->get_package;
349              
350             # Put the package handling tight around the code to execute
351 6         16 $code = <<"END_PERL";
352             package $self->{package};
353              
354             $code
355              
356             BEGIN {
357             \$Perl::Shell::_State::PACKAGE = __PACKAGE__;
358             }
359             END_PERL
360              
361             # Hand off to the parent version
362 6         19 return $self->SUPER::prepare($code, @_);
363             }
364              
365             # Modifications to the package are tracked at compile-time
366             sub compile {
367 6     6   31 my $self = shift;
368 6         23 my $sub = $self->SUPER::compile(@_);
369              
370             # Save the package state
371 6         696 $self->set_package($PACKAGE);
372              
373 6         15 return $sub;
374             }
375              
376             1;
377              
378             =pod
379              
380             =head1 SUPPORT
381              
382             Bugs should be reported via the CPAN bug tracker at
383              
384             L
385              
386             For other issues, or commercial enhancement or support, contact the author.
387              
388             =head1 AUTHOR
389              
390             Adam Kennedy Eadamk@cpan.orgE
391              
392             =head1 ACKNOWLEGEMENTS
393              
394             Thanks to Ingy for suggesting that this module should exist.
395              
396             =head1 COPYRIGHT
397              
398             Copyright 2008 - 2010 Adam Kennedy.
399              
400             This program is free software; you can redistribute
401             it and/or modify it under the same terms as Perl itself.
402              
403             The full text of the license can be found in the
404             LICENSE file included with this module.
405              
406             =cut