refactor formatting/printing shit, introduce error object for error_return
[p5sagit/Devel-REPL.git] / lib / Devel / REPL.pm
index 89c3a8b..406cb42 100644 (file)
@@ -2,10 +2,15 @@ package Devel::REPL;
 
 use Term::ReadLine;
 use Moose;
-use namespace::clean;
+use namespace::clean -except => [ 'meta' ];
+use 5.008001; # backwards compat, doesn't warn like 5.8.1
+
+our $VERSION = '1.002001'; # 1.2.1
 
 with 'MooseX::Object::Pluggable';
 
+use Devel::REPL::Error;
+
 has 'term' => (
   is => 'rw', required => 1,
   default => sub { Term::ReadLine->new('Perl REPL') }
@@ -23,20 +28,67 @@ has 'out_fh' => (
 
 sub run {
   my ($self) = @_;
-  while ($self->run_once) {
+  while ($self->run_once_safely) {
     # keep looping
   }
 }
 
+sub run_once_safely {
+  my ($self, @args) = @_;
+
+  my $ret = eval { $self->run_once(@args) };
+
+  if ($@) {
+    my $error = $@;
+    eval { $self->print("Error! - $error\n"); };
+    return 1;
+  } else {
+    return $ret;
+  }
+}
+
 sub run_once {
   my ($self) = @_;
+
   my $line = $self->read;
   return unless defined($line); # undefined value == EOF
-  my @ret = $self->eval($line);
+
+  my @ret = $self->formatted_eval($line);
+
   $self->print(@ret);
+
   return 1;
 }
 
+sub formatted_eval {
+  my ( $self, @args ) = @_;
+
+  my @ret = $self->eval(@args);
+
+  return $self->format(@ret);
+}
+
+sub format {
+  my ( $self, @stuff ) = @_;
+
+  if ( blessed($stuff[0]) and $stuff[0]->isa("Devel::REPL::Error") ) {
+    return $self->format_error(@stuff);
+  } else {
+    return $self->format_result(@stuff);
+  }
+}
+
+sub format_result {
+  my ( $self, @stuff ) = @_;
+
+  return @stuff;
+}
+
+sub format_error {
+  my ( $self, $error ) = @_;
+  return $error->stringify;
+}
+
 sub read {
   my ($self) = @_;
   return $self->term->readline($self->prompt);
@@ -51,15 +103,15 @@ sub eval {
 }
 
 sub compile {
-  my ($self, $line) = @_;
-  my $compiled = eval $self->wrap_as_sub($line);
-  return (undef, $self->error_return("Compile error", $@)) if $@;
+  my ( $_REPL, @args ) = @_;
+  my $compiled = eval $_REPL->wrap_as_sub(@args);
+  return (undef, $_REPL->error_return("Compile error", $@)) if $@;
   return $compiled;
 }
 
 sub wrap_as_sub {
-  my ($self, $line) = @_;
-  return qq!sub {\n!.$self->mangle_line($line).qq!\n}\n!;
+  my ($self, $line, %args) = @_;
+  return qq!sub {\n!. ( $args{no_mangling} ? $line : $self->mangle_line($line) ).qq!\n}\n!;
 }
 
 sub mangle_line {
@@ -76,13 +128,55 @@ sub execute {
 
 sub error_return {
   my ($self, $type, $error) = @_;
-  return "${type}: ${error}";
+  return Devel::REPL::Error->new( type => $type, message => $error );
 }
 
 sub print {
   my ($self, @ret) = @_;
   my $fh = $self->out_fh;
+  no warnings 'uninitialized';
   print $fh "@ret";
+  print $fh "\n" if $self->term->ReadLine =~ /Gnu/;
 }
 
+=head1 NAME
+
+Devel::REPL - a modern perl interactive shell
+
+=head1 SYNOPSIS
+
+  my $repl = Devel::REPL->new;
+  $repl->load_plugin($_) for qw(History LexEnv);
+  $repl->run
+
+Alternatively, use the 're.pl' script installed with the distribution
+
+  system$ re.pl
+
+=head1 AUTHOR
+
+Matt S Trout - mst (at) shadowcatsystems.co.uk (L<http://www.shadowcatsystems.co.uk/>)
+
+=head1 CONTRIBUTORS
+
+=over 4
+
+=item Stevan Little - stevan (at) iinteractive.com
+
+=item Alexis Sukrieh - sukria+perl (at) sukria.net
+
+=item epitaph
+
+=item mgrimes - mgrimes (at) cpan dot org
+
+=item Shawn M Moore - sartak (at) gmail.com
+
+=back
+
+=head1 LICENSE
+
+This library is free software under the same terms as perl itself
+
+=cut
+
 1;