Shell-Perl-0.0022/000755 000765 000024 00000000000 11536752033 014513 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/bin/000755 000765 000024 00000000000 11536752033 015263 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/Changes000644 000765 000024 00000010370 11536741600 016005 0ustar00ferreirastaff000000 000000 Revision history for Perl extension Shell::Perl. 0.0022 Mar 12, 2011 - no real change - Fix test again for 5.6 sake - Improved Makefile.PL / META.yml 0.0021 Mar 12, 2011 - no real change - New test fix for happy 5.6 testing 0.0020 Mar 10, 2011 - no real change - Test fixes for keeping 5.6 happy 0.0019 Mar 9, 2011 - Dumper updated to work with Data::Dump 1.16+ 0.0018 Oct 25, 2008 - fix t/11version.t to deal with IPC::Cmd $err as an error message (undef on success) rather than an error code (0 on success) [Thanks, Andreas, for spotting that] http://rt.cpan.org/Ticket/Display.html?id=40157 0.0017 Mar 9, 2008 - assume this is not supposed to work for Perls under 5.6.0 - cope with noisy 5.6 blib at t/20expect_quit.t (illustrated by test report http://www.nntp.perl.org/group/perl.cpan.testers/2008/03/msg1099937.html) - pirl now accepts switches --version and -v - added IPC::Cmd and Test::Deep as prerequisites for testing 0.0016 Mar 3, 2008 - quit is now a method - history is now persistent across sections (should work with T::RL::Gnu and T::RL::Perl) - new dependencies: File::HomeDir, Path::Class, and File::Slurp 0.0015 Jul 27, 2007 - fixed 'quit' - the first of the Expect tests: t/20expect_quit.t - pirl now accepts switches --ornaments and --noornaments 0.0014 Jul 26, 2007 - Shell::Perl now prints to the output stream of the associated term - new test t/10compile.t - :x is the same as :exit, :quit, :q - quit is an alias to "sub { exit }" in the sandbox package 0.0013 Jun 21, 2007 - the dumpers now deparse Perl code - added new dumper based on Data::Dump::Streamer, no docs by now (try it with ":set out DDS") 0.0012 Jun 21, 2007 - added an experimental "dump history" command (RT #26973, by mgrimes) - hopefully get rid of the double newline in eval output 0.0011 Jun 21, 2007 [worked around Mar 15, 2007] - some minor improvements to Makefile.PL - conformance to META.yml specification - when dumping YAML, prefer YAML::Syck to YAML if available - we have a bug to fix: the REPL and the running interpreter share global state (like $_) and so relying on these between lines is not nice (to say the least) 0.0010 Mar 14, 2007 - this is a read-eval-print loop and not a read-eval-loop, doh - total rewrite for the implementation of dumpers - new output style with the plain dumper (idea borrowed from Sepia by Sean O'Rourke) - Data::Dump, Data::Dumper, YAML are only required at runtime and fail gracefully if not there - the preferred dumper is via Data::Dump, but it falls back to Data::Dumper, YAML and the plain dumper according to availability - fix bug: inline contexts (like #scalar) were not being respected for printing - Makefile.PL required ExtUtils::MakeMaker 6.31 and we are more tolerant now (thanks, Lorn) - now the right line number is used at warnings and errors (Lorn again) 0.0009 Mar 13, 2007 - forgot README in MANIFEST - the default evaluation package is now "Shell::Perl::sandbox" 0.0008 Mar 13, 2007 - cmarcelo: some doc typos fixed - a SEE ALSO section - first CPAN release 0.0007 Mar 7, 2007 - added some POD to Shell.pm and pirl source files 0.0006 Feb 23, 2007 - sources imported to Google code (no history :(, yet) - patches by cmarcelo: * implement list and void contexts for evaluation * implement context override in a per-input basis - we have tests now, even though t/98pod-coverage.t does not pass yet 0.0005 Jan 27, 2007 - relax the restrictions during eval - no strict qw(vars subs) 0.0004 Jan 25, 2007 - the same changes as before, now working 0.0003 Jan 25, 2007 - prompt changes with the script name - psh renamed to pirl - borked 0.0002 ? 0.0001 ? Shell-Perl-0.0022/lib/000755 000765 000024 00000000000 11536752033 015261 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/Makefile.PL000644 000765 000024 00000002475 11536735121 016474 0ustar00ferreirastaff000000 000000 use 5.006; use ExtUtils::MakeMaker; my $EUMM_VERSION = eval $ExtUtils::MakeMaker::VERSION; WriteMakefile( NAME => 'Shell::Perl', VERSION_FROM => 'lib/Shell/Perl.pm', PREREQ_PM => { Term::ReadLine => 0, File::Basename => 0, Class::Accessor => 0, Getopt::Long => 0, File::Slurp => 0, File::HomeDir => 0, Path::Class => 0, # test requires 'Test::More' => 0, 'Test::Deep' => 0, 'IPC::Cmd' => 0, }, EXE_FILES => [ 'bin/pirl' ], ($] >= 5.005 ? ( ABSTRACT_FROM => 'lib/Shell/Perl.pm', AUTHOR => 'A. R. Ferreira ', ) : ()), ($EUMM_VERSION >= 6.31 ? ( LICENSE => 'perl', ) : ()), ($EUMM_VERSION > 6.4501 ? ( META_MERGE => { recommends => { # optional tests 'Test::Pod' => 0, 'Test::Pod::Coverage' => 0, 'Test::Script' => 0, 'Test::Expect' => 0, }, resources => { repository => 'http://github.com/aferreira/pirl', }, }, ) : ()), ); # recommended: # # - -one_of: [ YAML::Syck, YAML ] # - Data::Dump # - Data::Dumper # - Data::Dump::Streamer # Shell-Perl-0.0022/MANIFEST000644 000765 000024 00000000456 11535743374 015660 0ustar00ferreirastaff000000 000000 bin/pirl lib/Shell/Perl.pm lib/Shell/Perl/Dumper.pm Makefile.PL MANIFEST This list of files Changes README t/01use.t t/02basic.t t/10compile.t t/11version.t t/20expect_quit.t t/50isolated.t t/90pod.t t/98pod-coverage.t META.yml Module meta-data (added by MakeMaker) Shell-Perl-0.0022/META.yml000644 000765 000024 00000001673 11536752033 015773 0ustar00ferreirastaff000000 000000 --- #YAML:1.0 name: Shell-Perl version: 0.0022 abstract: A read-eval-print loop in Perl author: - A. R. Ferreira license: perl distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: Class::Accessor: 0 File::Basename: 0 File::HomeDir: 0 File::Slurp: 0 Getopt::Long: 0 IPC::Cmd: 0 Path::Class: 0 Term::ReadLine: 0 Test::Deep: 0 Test::More: 0 resources: repository: http://github.com/aferreira/pirl no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.56 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 recommends: Test::Expect: 0 Test::Pod: 0 Test::Pod::Coverage: 0 Test::Script: 0 Shell-Perl-0.0022/README000644 000765 000024 00000001515 11535737424 015403 0ustar00ferreirastaff000000 000000 Shell-Perl version 0.0013 =========================== This is the implementation of a simple command-line interpreter for Perl. After installing the module, you invoke it like this $ pirl Welcome to the Perl shell. Type ':help' for more information pirl @> or in Windows > pirl INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: Term:ReadLine Data::Dumper YAML or YAML::Syck Data::Dump Class::Accessor and recommends Test::Pod 1.18 Test::Pod::Coverage 1.04 Test::Script COPYRIGHT AND LICENCE Copyright (C) 2007 by Adriano R. Ferreira This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Shell-Perl-0.0022/t/000755 000765 000024 00000000000 11536752033 014756 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/t/01use.t000755 000765 000024 00000000202 10763035217 016074 0ustar00ferreirastaff000000 000000 #!perl -T use Test::More tests => 1; use_ok('Shell::Perl'); diag( "Testing Shell::Perl $Shell::Perl::VERSION, Perl $], $^X" ); Shell-Perl-0.0022/t/02basic.t000755 000765 000024 00000000250 10763035217 016365 0ustar00ferreirastaff000000 000000 #!perl -T use Test::More tests => 3; BEGIN { use_ok('Shell::Perl'); } my $sh = Shell::Perl->new(); ok($sh, 'defined return of new()'); isa_ok($sh, 'Shell::Perl'); Shell-Perl-0.0022/t/10compile.t000644 000765 000024 00000000256 10763035217 016736 0ustar00ferreirastaff000000 000000 use Test::More; eval "use Test::Script"; plan skip_all => "Test::Script required for testing" if $@; plan( tests => 1 ); script_compiles_ok( 'bin/pirl', 'pirl compiles'); Shell-Perl-0.0022/t/11version.t000644 000765 000024 00000001165 11536741537 017004 0ustar00ferreirastaff000000 000000 use Test::More tests => 8; my @pirl = ( $^X, '-Mblib', 'blib/script/pirl' ); use IPC::Cmd qw( run ); use Test::Deep; for my $switch ( '-v', '--version' ) { my ( $ok, $err, $full_buf, $out_buf, $err_buf ) = run( command => [ @pirl, $switch ] ); ok( $ok, "'pirl $switch' run ok" ); ok( !$err, 'no error'); cmp_deeply( $out_buf, [ re(qr/\AThis is pirl/) ], 'printed version info' ); my $NO_STDERR_OUTPUT = ($] < 5.008) ? [re(qr/Using .* lib \n/msx)] # cope with noisy 5.6 blib : []; cmp_deeply( $err_buf, $NO_STDERR_OUTPUT, 'no output to STDERR' ) or diag("err_buf= (@$err_buf)"); } Shell-Perl-0.0022/t/20expect_quit.t000644 000765 000024 00000001057 11536176446 017652 0ustar00ferreirastaff000000 000000 use Test::More; eval "use Test::Expect"; plan skip_all => "Test::Expect required for testing" if $@; # test pirl and its many quit commands plan( tests => 2*6 ); for my $quit_command ( ':quit', ':q', ':exit', ':x', 'exit', 'quit' ) { expect_run( command => "$^X -Mblib blib/script/pirl --noornaments", prompt => 'pirl @> ', quit => $quit_command, ); expect_like( qr/\A (?: Using .*? blib \n )? # cope with noisy 5.6 blib Welcome /msx, "welcome message" ); } Shell-Perl-0.0022/t/50isolated.t000644 000765 000024 00000001063 11535740107 017112 0ustar00ferreirastaff000000 000000 #perl -T use Test::More 'no_plan'; BEGIN { use_ok('Shell::Perl'); } my $sh = Shell::Perl->new; $_ = ' $_ = 1000 '; my $val = $sh->eval($_); is($val, 1000); $_ = ' $_ '; my $val2 = $sh->eval($_); TODO: { local $TODO = 'needs separating the REPL and the interpreter states'; is($val2, 1000); } # this test script touches at a very sensitive # issue in the implementation of a REPL - # the state of the loop must be kept separate # from the state of the running interpreter. # By state, we mean those global variables like # $_ and everything else. Shell-Perl-0.0022/t/90pod.t000755 000765 000024 00000000253 10763035217 016100 0ustar00ferreirastaff000000 000000 #!perl -T use strict; use Test::More; eval "use Test::Pod 1.18"; plan skip_all => "Test::Pod 1.18 required for testing POD" if $@; all_pod_files_ok(all_pod_files(".")); Shell-Perl-0.0022/t/98pod-coverage.t000644 000765 000024 00000000255 10763035217 017700 0ustar00ferreirastaff000000 000000 #perl -T use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; all_pod_coverage_ok(); Shell-Perl-0.0022/lib/Shell/000755 000765 000024 00000000000 11536752033 016330 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/lib/Shell/Perl/000755 000765 000024 00000000000 11536752033 017232 5ustar00ferreirastaff000000 000000 Shell-Perl-0.0022/lib/Shell/Perl.pm000644 000765 000024 00000044713 11536741627 017610 0ustar00ferreirastaff000000 000000 package Shell::Perl; use 5.006; use strict; use warnings; # /Id: Perl.pm 1131 2007-01-27 17:43:35Z me / # don't erase that for now # $Id: /iperl/lib/Shell/Perl.pm 2317 2008-03-09T16:22:00.577930Z a.r.ferreira@gmail.com $ our $VERSION = '0.0022'; use base qw(Class::Accessor); # soon use base qw(Shell::Base); Shell::Perl->mk_accessors(qw( out_type dumper context package term ornaments )); # XXX use_strict use Term::ReadLine; use Shell::Perl::Dumper; # out_type defaults to one of 'D', 'DD', 'Y', 'P'; # dumper XXX # context defaults to 'list' # package defaults to __PACKAGE__ . '::sandbox' # XXX use_strict defaults to 0 sub new { my $self = shift; my $sh = $self->SUPER::new({ context => 'list', # print context @_ }); $sh->_init; return $sh; } my %dumper_for = ( 'D' => 'Shell::Perl::Data::Dump', 'DD' => 'Shell::Perl::Data::Dumper', 'Y' => 'Shell::Perl::Dumper::YAML', 'Data::Dump' => 'Shell::Perl::Data::Dump', 'Data::Dumper' => 'Shell::Perl::Data::Dumper', 'YAML' => 'Shell::Perl::Dumper::YAML', 'DDS' => 'Shell::Perl::Data::Dump::Streamer', 'P' => 'Shell::Perl::Dumper::Plain', 'plain' => 'Shell::Perl::Dumper::Plain', ); sub _init { my $self = shift; # loop until you find one available alternative for dump format my $dumper_class; for my $format ( qw(D DD DDS Y P) ) { if ($dumper_for{$format}->is_available) { #$self->print("format: $format\n"); $self->set_out($format); last } # XXX this is not working 100% - and I have no clue about it } $self->set_package( __PACKAGE__ . '::sandbox' ); } sub _shell_name { require File::Basename; return File::Basename::basename($0); } sub print { my $self = shift; print {$self->term->OUT} @_; } ## # XXX remove: code and docs ## sub out { ## my $self = shift; ## ## # XXX I want to improve this: preferably with an easy way to add dumpers ## if ($self->context eq 'scalar') { ## $self->print($self->dumper->dump_scalar(shift), "\n"); ## } else { # list ## $self->print($self->dumper->dump_list(@_), "\n"); ## } ## } # XXX I want to improve this: preferably with an easy way to add dumpers =begin private =item B<_print_scalar> $sh->_print_scalar($answer); That corresponds to the 'print' in the read-eval-print loop (in scalar context). It outputs the evaluation result after passing it through the current dumper. =end private =cut sub _print_scalar { # XXX make public, document my $self = shift; $self->print($self->dumper->dump_scalar(shift)); } =begin private =item B<_print_scalar> $sh->_print_list(@answers); That corresponds to the 'print' in the read-eval-print loop (in list context). It outputs the evaluation result after passing it through the current dumper. =end private =cut sub _print_list { # XXX make public, document my $self = shift; $self->print($self->dumper->dump_list(@_)); } sub _warn { shift; my $shell_name = _shell_name; warn "$shell_name: ", @_, "\n"; } sub set_out { my $self = shift; my $type = shift; my $dumper_class = $dumper_for{$type}; if (!defined $dumper_class) { $self->_warn("unknown dumper $type"); return; } if ($dumper_class->is_available) { $self->dumper($dumper_class->new); $self->out_type($type); } else { $self->_warn("can't load dumper $dumper_class"); } } sub _ctx { my $context = shift; if ($context =~ /^(s|scalar|\$)$/i) { return 'scalar'; } elsif ($context =~ /^(l|list|@)$/i) { return 'list'; } elsif ($context =~ /^(v|void|_)$/i) { return 'void'; } else { return undef; } } sub set_ctx { my $self = shift; my $context = _ctx shift; if ($context) { $self->context($context); } else { $self->_warn("unknown context $context"); } } sub set_package { my $self = shift; my $package = shift; if ($package =~ /( [a-zA-Z_] \w* :: )* [a-zA-Z_] \w* /x) { $self->package($package); no strict 'refs'; *{ "${package}::quit" } = sub { $self->quit }; } else { $self->_warn("bad package name $package"); } } use constant HELP => <<'HELP'; Shell commands: (begin with ':') :e(x)it or :q(uit) - leave the shell :set out (D|DD|DDS|Y|P) - setup the output format :set ctx (scalar|list|void|s|l|v|$|@|_) - setup the eval context :set package - set package in which shell eval statements :reset - reset the environment :dump history - (experimental) print the history to STDOUT or a file :h(elp) - get this help screen HELP sub help { print HELP; } # :reset is a nice idea - but I wanted more like CPAN reload # I retreated the current implementation of :reset # because %main:: is used as the evaluation package # and %main:: = () is too severe by now sub reset { my $self = shift; my $package = $self->package; return if $package eq 'main'; # XXX don't reset %main:: no strict 'refs'; %{"${package}::"} = (); #%main:: = (); # this segfaults at my machine } sub prompt_title { my $self = shift; my $shell_name = _shell_name; my $sigil = { scalar => '$', list => '@', void => '' }->{$self->{context}}; return "$shell_name $sigil> "; } sub _readline { my $self = shift; return $self->term->readline($self->prompt_title); } sub _history_file { # XXX require Path::Class; require File::HomeDir; return Path::Class::file( File::HomeDir->my_home, '.pirl-history' )->stringify; } sub _read_history { # XXX belongs to Shell::Perl::ReadLine my $term = shift; my $h = _history_file; #warn "read history from $h\n"; # XXX if ( $term->Features->{readHistory} ) { $term->ReadHistory( $h ); } elsif ( $term->Features->{setHistory} ) { if ( -e $h ) { require File::Slurp; my @h = File::Slurp::read_file( $h ); chomp @h; $term->SetHistory( @h ); } } else { # warn "Your ReadLine doesn't support setHistory\n"; } } sub _write_history { # XXX belongs to Shell::Perl::ReadLine my $term = shift; my $h = _history_file; #warn "write history to $h\n"; # XXX if ( $term->Features->{writeHistory} ) { $term->WriteHistory( $h ); } elsif ( $term->Features->{getHistory} ) { require File::Slurp; my @h = map { "$_\n" } $term->GetHistory; File::Slurp::write_file( $h, @h ); } else { # warn "Your ReadLine doesn't support getHistory\n"; } } sub _new_term { my $self = shift; my $name = shift; my $term = Term::ReadLine->new( $name ); _read_history( $term ); return $term; } sub run { my $self = shift; my $shell_name = _shell_name; $self->term( my $term = $self->_new_term( $shell_name ) ); $term->ornaments($self->ornaments); # XXX my $prompt = "$shell_name > "; print "Welcome to the Perl shell. Type ':help' for more information\n\n"; REPL: while ( defined ($_ = $self->_readline) ) { # trim s/^\s+//g; s/\s+$//g; # Shell commands start with ':' followed by something else # which is not ':', so we can use things like '::my_subroutine()'. if (/^:[^:]/) { last REPL if /^:(exit|quit|q|x)/; $self->set_out($1) if /^:set out (\S+)/; $self->set_ctx($1) if /^:set ctx (\S+)/; $self->set_package($1) if /^:set package (\S+)/; $self->reset if /^:reset/; $self->help if /^:h(elp)?/; $self->dump_history($1) if /^:dump history(?:\s+(\S*))?/; # unknown shell command ?! next REPL; } my $context; $context = _ctx($1) if s/#(s|scalar|\$|l|list|\@|v|void|_)\z//; $context = $self->context unless $context; if ( $context eq 'scalar' ) { my $out = $self->eval($_); if ($@) { warn "ERROR: $@"; next } $self->_print_scalar($out); } elsif ( $context eq 'list' ) { my @out = $self->eval($_); if ($@) { warn "ERROR: $@"; next } $self->_print_list(@out); } elsif ( $context eq 'void' ) { $self->eval($_); if ($@) { warn "ERROR: $@"; next } } else { # XXX should not happen } } $self->quit; } # $shell->eval($exp) sub eval { my $self = shift; my $exp = shift; my $package = $self->package; # XXX gotta restore $_, etc. return eval <term ); $self->print( "Bye.\n" ); # XXX exit; } sub run_with_args { my $self = shift; # XXX do something with @ARGV (Getopt) my %options = ( ornaments => 1 ); if ( @ARGV ) { # only require Getopt::Long if there are actually command line arguments require Getopt::Long; Getopt::Long::GetOptions( \%options, 'ornaments!', 'version|v' ); } my $shell = Shell::Perl->new(%options); if ( $options{version} ) { $shell->_show_version; } else { $shell->run; } } sub _show_version { my $self = shift; printf "This is %s, version %s (%s, using Shell::Perl %s)\n", _shell_name, $main::VERSION, $0, $Shell::Perl::VERSION; exit 0; } sub dump_history { my $self = shift; my $file = shift; if ( !$self->term->Features->{getHistory} ) { print "Your Readline doesn't support getHistory\n"; return; } if ( $file ) { open( my $fh, ">>", $file ) or do { warn "Couldn't open '$file' for history dump\n"; return; }; for ( $self->term->GetHistory ) { print $fh $_, "\n"; } close $fh; print "Dumped history to '$file'\n\n"; } else { print $_, "\n" for($self->{term}->GetHistory); print "\n"; } return 1; } 1; # OUTPUT Data::Dump, Data::Dumper, YAML, others # document: use a different package when eval'ing # reset the environment # implement shell commands (:quit, :set, :exit, etc.) # how to implement array contexts? # IDEA: command ":set ctx scalar | list | void" # terminators "#s" "#l" "#v" "#$" #@ #_ # allow multiline entries. how? ##sub set {} # sets up the instance variables of the shell ## ##sub run {} # run the read-eval-print loop ## ##sub read {} # read a chunk ## ##sub readline {} # read a line ## ##sub eval {} ## ##sub print {} ## ##sub warn {} ## ##sub help { shift->print(HELP) } ## ##sub out { ? } # svn:keywords Id # svn:eol-style LF __END__ =head1 NAME Shell::Perl - A read-eval-print loop in Perl =head1 SYNOPSYS use Shell::Perl; Shell::Perl->run_with_args; =head1 DESCRIPTION This is the implementation of a command-line interpreter for Perl. I wrote this because I was tired of using B when needing a calculator with a real language within. Ah, that and because it was damn easy to write it. This module is the heart of the B script provided with B distribution, along with this module. =head2 EXAMPLE SESSION $ pirl Welcome to the Perl shell. Type ':help' for more information pirl @> 1+1 2 pirl @> use YAML qw(Load Dump); () pirl @> $data = Load("--- { a: 1, b: [ 1, 2, 3] }\n"); { a => 1, b => [1, 2, 3] } pirl @> $var = 'a 1 2 3'; $var =~ /(\w+) (\d+) (\d+)/ ("a", 1, 2) pirl @> :q =head2 COMMANDS Most of the time, the shell reads Perl statements, evaluates them and outputs the result. There are a few commands (started by ':') that are handled by the shell itself. =over 4 =item :h(elp) Handy for remembering what the shell commands are. =item :q(uit) Leave the shell. The Perl statement C will work too. SYNONYMS: :exit, :x =item :set out (D|DD|DDS|Y|P) Changes the dumper for the expression results used before output. The current supported are: =over 4 =item D C =item DD C, the good and old core module =item DDS C =item Y C =item P a plain dumper ("$ans" or "@ans") =back When creating the shell, the dump format is searched among the available ones in the order "D", "DD", "DDS", "Y" and "P". That means L is preferred and will be used if available/installed. Otherwise, L is tried, and so on. Read more about dumpers at L. =item :set ctx (scalar|list|void|s|l|v|$|@|_) Changes the default context used to evaluate the entered expression. The default is C<'list'>. Intuitively, 'scalar', 's' and '$' are synonyms, just like 'list', 'l', and '@' or 'void', 'v', '_'. There is a nice way to override the default context in a given expression. Just a '#' followed by one of 'scalar|list|void|s|l|v|$|@|_' at the end of the expression. pirl @> $var = 'a 1 2 3'; $var =~ /(\w+) (\d+) (\d+)/ ("a", 1, 2) pirl @> $var = 'a 1 2 3'; $var =~ /(\w+) (\d+) (\d+)/ #scalar 1 =item :reset Resets the environment, erasing the symbols created at the current evaluation package. See the section L<"ABOUT EVALUATION">. =back =head2 METHODS Remember this is an alpha version, so the API may change and that includes the methods documented here. So consider this section as implementation notes for a while. In later versions, some of these information may be promoted to a public status. Others may be hidden or changed and even disappear without further notice. =over 4 =item B $sh = Shell::Version->new; The constructor. =item B Shell::Perl->run_with_args; Starts the read-eval-print loop after reading options from C<@ARGV>. It is a class method. If an option B<-v> or B<--version> is provided, instead of starting the REPL, it prints the script identification and exits with 0. $ pirl -v This is pirl, version 0.0017 (bin/pirl, using Shell::Perl 0.0017) =item B $sh->run; The same as C but with no code for interpreting command-line arguments. It is an instance method, so that Crun_with_args> is kind of: Shell::Perl->new->run; =item B $answer = $sh->eval($exp); @answer = $sh->eval($exp); Evaluates the user input given in C<$exp> as Perl code and returns the result. That is the 'eval' part of the read-eval-print loop. =item B $sh->print(@args); Prints a list of args at the output stream currently used by the shell. =item B $sh->help; Outputs the help as provided by the command ":help". =item B $sh->reset; Does nothing by now, but it will. =item B $sh->dump_history(); $sh->dump_history($file); Prints the readline history to C or the optional file. Used to implement experimental command ":dump history". This is experimental code and should change in the future. More control should be added and integrated with other terminal features. =item B $sh->set_ctx($context); Assigns to the current shell context. The argument must be one of C< ( 'scalar', 'list', 'void', 's', 'l', 'v', '$', '@', '_' ) >. =item B $sh->set_package($package); Changes current evaluation package. Doesn't change if the new package name is malformed. =item B $sh->set_out($dumper); Changes the current dumper used for printing the evaluation results. Actually must be one of "D" (for Data::Dump), "DD" (for Data::Dumper), "DDS" (for Data::Dump::Streamer), "Y" (for YAML) or "P" (for plain string interpolation). =item B $prompt = $sh->prompt_title; Returns the current prompt which changes with executable name and context. For example, "pirl @>", "pirl $>", and "pirl >". =item B $sh->quit; This method is invoked when these commands and statements are parsed by the REPL: :q :quit :x :exit quit exit It runs the shutdown procedures for a smooth termination of the shell. For example, it saves the terminal history file. =back =head1 GORY DETAILS =head2 ABOUT EVALUATION When the statement read is evaluated, this is done at a different package, which is C by default. So: $ perl -Mlib=lib bin/pirl Welcome to the Perl shell. Type ':help' for more information pirl @> $a = 2; 2 pirl @> :set out Y # output in YAML pirl @> \%Shell::Perl::sandbox:: --- BEGIN: !!perl/glob: PACKAGE: Shell::Perl::sandbox NAME: BEGIN a: !!perl/glob: PACKAGE: Shell::Perl::sandbox NAME: a SCALAR: 2 This package serves as an environment for the current shell session and :reset can wipe it away. pirl @> :reset pirl @> \%Shell::Perl::sandbox:: --- BEGIN: !!perl/glob: PACKAGE: Shell::Perl::sandbox NAME: BEGIN =head1 TO DO There is a lot to do, as always. Some of the top priority tasks are: =over 4 =item * Accept multiline statements;. =item * Refactor the code to promote easy customization of features. =back =head1 SEE ALSO This project is hosted at Google Code: http://code.google.com/p/iperl/ To know about interactive Perl interpreters, there are two FAQS contained in L which are good starting points. Those are How can I use Perl interactively? http://perldoc.perl.org/perlfaq3.html#How-can-I-use-Perl-interactively%3f Is there a Perl shell? http://perldoc.perl.org/perlfaq3.html#How-can-I-use-Perl-interactively%3f An extra list of Perl shells can be found here: http://www.focusresearch.com/gregor/document/psh-1.1.html#other_perl_shells =head1 BUGS It is a one-line evaluator by now. I don't know what happens if you eval within an eval. I don't expect good things to come. (Lorn who prodded me about this will going to find it out and then I will tell you.) There are some quirks with Term::Readline (at least on Windows). There are more bugs. I am lazy to collect them all and list them now. Please report bugs via CPAN RT L or L. =head1 AUTHORS Adriano R. Ferreira, Eferreira@cpan.orgE Caio Marcelo, Ecmarcelo@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright (C) 2007–2011 by Adriano R. Ferreira This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut # Local variables: # c-indentation-style: bsd # c-basic-offset: 4 # indent-tabs-mode: nil # End: # vim: expandtab shiftwidth=4: Shell-Perl-0.0022/lib/Shell/Perl/Dumper.pm000644 000765 000024 00000021243 11535742700 021025 0ustar00ferreirastaff000000 000000 package Shell::Perl::Dumper; use 5; use strict; use warnings; # $Id$ our $VERSION = '0.0019'; use base qw(Class::Accessor); # to get a new() for free package Shell::Perl::Dumper::Plain; our @ISA = qw(Shell::Perl::Dumper); # to get a new() for free sub is_available { return 1; # always available - no dependency but Perl } sub dump_scalar { shift; return "$_[0]" . "\n"; } sub dump_list { shift; local $" = "\t"; return "@_" . "\n"; } package Shell::Perl::Data::Dump; our @ISA = qw(Shell::Perl::Dumper); # to get a new() for free # XXX make a Data::Dump object an instance variable sub _dump_code_filter { my ($ctx, $object_ref) = @_; return undef unless $ctx->is_code; require B::Deparse; my $code = 'sub ' . (B::Deparse->new)->coderef2text($object_ref); return { dump => $code }; } sub is_available { return eval { require Data::Dump::Filtered; 1 }; } sub dump_scalar { shift; require Data::Dump::Filtered; return Data::Dump::Filtered::dump_filtered(shift, \&_dump_code_filter) . "\n"; } sub dump_list { shift; require Data::Dump::Filtered; return Data::Dump::Filtered::dump_filtered(@_, \&_dump_code_filter) . "\n"; } package Shell::Perl::Data::Dumper; our @ISA = qw(Shell::Perl::Dumper); # XXX make a Data::Dumper object an instance variable # but OO Data::Dumper is very annoying sub is_available { return eval { require Data::Dumper; 1 }; } sub dump_scalar { shift; require Data::Dumper; local $Data::Dumper::Deparse = 1; return Data::Dumper->Dump([shift], [qw($var)]); } sub dump_list { #goto &dump_scalar if @_==2; # fallback to dump_scalar if only one shift; require Data::Dumper; local $Data::Dumper::Deparse = 1; return Data::Dumper->Dump([[@_]], [qw(*var)]); } package Shell::Perl::Dumper::YAML; our @ISA = qw(Shell::Perl::Dumper); sub _require_one_of { my @modules = @_; for (@modules) { my $ret = eval "require $_; 1"; warn "pirl: $_ loaded ok\n" if $ret; # XXX return $_ if $ret; } return undef } our $YAML_PACKAGE; sub is_available { #return eval { require YAML; 1 }; $YAML_PACKAGE = _require_one_of(qw(YAML::Syck YAML)); if ($YAML_PACKAGE) { $YAML_PACKAGE->import(qw(Dump)); do { no strict 'refs'; ${ $YAML_PACKAGE . '::DumpCode' } = 1 }; return 1 } else { return undef; } } sub dump_scalar { shift; #require YAML; # done by &is_available return Dump(shift); } sub dump_list { # XXX shift; #require YAML; # done by &is_available return Dump(@_); } package Shell::Perl::Data::Dump::Streamer; our @ISA = qw(Shell::Perl::Dumper); sub is_available { return eval { require Data::Dump::Streamer; 1 }; } sub dump_scalar { shift; require Data::Dump::Streamer; return Data::Dump::Streamer::Dump(shift)->Names('$var')->Out; } sub dump_list { #goto &dump_scalar if @_==2; # fallback to dump_scalar if only one shift; require Data::Dump::Streamer; return Data::Dump::Streamer::Dump([@_])->Names('*var')->Out; } 1; # svn:keywords Id # svn:eol-style LF __END__ =head1 NAME Shell::Perl::Dumper - Dumpers for Shell::Perl =head1 SYNOPSYS use Shell::Perl::Dumper; $dumper = Shell::Perl::Dumper::Plain->new; print $dumper->dump_scalar($scalar); print $dumper->dump_list(@list); =head1 DESCRIPTION In C, the result of the evaluation is transformed into a string to be printed. As this result may be a pretty complex data structure, the shell provides a hook for you to pretty-print these answers just the way you want. By default, C will try to convert the results via C. That means the output will be Perl code that may be run to get the data structure again. Alternatively, the shell may use C or C with almost the same result with respect to the representation as Perl code. (But the output of the modules differ enough for sufficiently complex data.) Other options are to set the output to produce YAML or a plain simple-minded solution which basically turns the result to string via simple interpolation. All of these are implemented via I. Dumpers are meant to be used like that: $dumper = Some::Dumper::Class->new; # build a dumper $s = $dumper->dump_scalar($scalar); # from scalar to string $s = $dumper->dump_list(@list); # from list to string =head2 METHODS The following methods compose the expected API of a dumper, as used by L. =over 4 =item B $dumper = $class->new(@args); Constructs a dumper. =item B $s = $dumper->dump_scalar($scalar); Turns a scalar into a string representation. =item B $s = $dumper->dump_list(@list); Turns a list into a string representation. =item B $ok = $class->is_available This is an I class method. If it exists, it means that the class has external dependencies (like C depends on C) and whether these may be loaded when needed. If they can, this method returns true. Otherwise, returning false means that a dumper instance of this class probably cannot work. This is typically because the dependency is not installed or cannot be loaded due to an installation problem. This is the algorithm used by L XXX XXX XXX 1. =back =head1 THE STANDARD DUMPERS L provides four standard dumpers: * Shell::Perl::Data::Dump * Shell::Perl::Data::Dumper * Shell::Perl::Data::Dump::Streamer * Shell::Perl::Dumper::YAML * Shell::Perl::Dumper::Plain which corresponds to the four options of the command C< :set out >: "D", "DD", "DDS", "Y", and "P" respectively. =head2 Data::Dump The package C implements a dumper which uses L to turn Perl variables into a string representation. It is used like this: use Shell::Perl::Dumper; if (!Shell::Perl::Data::Dump->is_available) { die "the dumper cannot be loaded correctly" } $dumper = Shell::Perl::Data::Dump->new; print $dumper->dump_scalar($scalar); print $dumper->dump_list(@list); Examples of its output: pirl > :set out D pirl > { a => 3 } #scalar { a => 3 } pirl > (1, 2, "a") #list (1, 2, "a") =head2 Data::Dumper The package C implements a dumper which uses L to turn Perl variables into a string representation. It is used like this: use Shell::Perl::Dumper; if (!Shell::Perl::Data::Dumper->is_available) { die "the dumper cannot be loaded correctly" } $dumper = Shell::Perl::Data::Dumper->new; print $dumper->dump_scalar($scalar); print $dumper->dump_list(@list); Examples of its output: pirl > :set out DD pirl > { a => 3 } #scalar @var = ( { 'a' => 3 } ); pirl > (1, 2, "a") #list @var = ( 1, 2, 'a' ); =head2 YAML The package C implements a dumper which uses L or L to turn Perl variables into a string representation. It is used like this: use Shell::Perl::Dumper; if (!Shell::Perl::Dumper::YAML->is_available) { die "the dumper cannot be loaded correctly" } $dumper = Shell::Perl::Dumper::YAML->new; print $dumper->dump_scalar($scalar); print $dumper->dump_list(@list); Examples of its output: pirl > :set out Y pirl @> { a => 3 } #scalar --- a: 3 pirl @> (1, 2, "a") #list --- 1 --- 2 --- a When loading, C is preferred to C. If it is not avaiable, the C module is the second option. =head2 Data::Dump::Streamer The documentation is yet to be written. =head2 Plain Dumper The package C implements a dumper which uses string interpolation to turn Perl variables into strings. It is used like this: use Shell::Perl::Dumper; $dumper = Shell::Perl::Dumper::Plain->new; print $dumper->dump_scalar($scalar); print $dumper->dump_list(@list); Examples of its output: pirl > :set out P pirl > { a => 3 } #scalar HASH(0x1094d2c0) pirl > (1, 2, "a") #list 1 2 a =head1 SEE ALSO Shell::Perl =head1 BUGS Please report bugs via CPAN RT L or L. =head1 AUTHORS Adriano R. Ferreira, Eferreira@cpan.orgE Caio Marcelo, Ecmarcelo@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright (C) 2007–2011 by Adriano R. Ferreira This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Shell-Perl-0.0022/bin/pirl000755 000765 000024 00000003044 11535741015 016155 0ustar00ferreirastaff000000 000000 #!/usr/bin/perl use 5.006; use strict; use warnings; # /Id: pirl 1124 2007-01-25 19:36:07Z me / # don't erase that for now # $Id: /iperl/bin/pirl 2321 2008-03-09T16:47:36.686169Z a.r.ferreira@gmail.com $ our $VERSION = '0.0019'; use Shell::Perl (); Shell::Perl->run_with_args; __END__ =head1 NAME pirl - A read-eval-print loop in Perl (see Shell::Perl) =head1 SYNOPSIS pirl pirl --noornaments pirl --version pirl -v =head1 EXAMPLE SESSION $ pirl Welcome to the Perl shell. Type ':help' for more information pirl @> 1+1 2 pirl @> use YAML qw(Load Dump); () pirl @> $data = Load("--- { a: 1, b: [ 1, 2, 3] }\n"); { a => 1, b => [1, 2, 3] } pirl @> $var = 'a 1 2 3'; $var =~ /(\w+) (\d+) (\d+)/ ("a", 1, 2) pirl @> :q =head1 DESCRIPTION This script is the command-line interface to C which does it all. By now, read the fine details at C documentation. =head1 OPTIONS --ornaments - turn on terminal ornaments (default) --noornaments - turn off terminal organments --version, -v - prints version info and exits with 0 =head1 SEE ALSO Shell::Perl =head1 BUGS Please report bugs via CPAN RT L. =head1 AUTHOR Adriano R. Ferreira, Eferreira@cpan.orgE Caio Marcelo, Ecmarcelo@cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright (C) 2007–2011 by Adriano R. Ferreira This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut