Add Devel::REPL::Plugin::MutliLine::PPI
Sartak [Fri, 21 Sep 2007 00:06:05 +0000 (00:06 +0000)]
git-svn-id: http://dev.catalyst.perl.org/repos/bast/trunk/Devel-REPL@3760 bd8105ee-0ff8-0310-8827-fb3f25b6796d

Makefile.PL
lib/Devel/REPL/Plugin/MultiLine/PPI.pm [new file with mode: 0644]

index c1f1666..43cccc0 100644 (file)
@@ -17,6 +17,7 @@ requires 'File::Spec';
 requires 'Term::ReadLine';
 requires 'Lexical::Persistence';
 requires 'Data::Dump::Streamer';
+requires 'PPI';
 
 auto_install;
 WriteAll;
diff --git a/lib/Devel/REPL/Plugin/MultiLine/PPI.pm b/lib/Devel/REPL/Plugin/MultiLine/PPI.pm
new file mode 100644 (file)
index 0000000..177484f
--- /dev/null
@@ -0,0 +1,52 @@
+package Devel::REPL::Plugin::MultiLine::PPI;
+
+use Moose::Role;
+use PPI;
+use namespace::clean -except => [ 'meta' ];
+
+has 'continuation_prompt' => (
+  is => 'rw', required => 1, lazy => 1,
+  default => sub { '> ' }
+);
+
+around 'read' => sub {
+  my $orig = shift;
+  my ($self, @args) = @_;
+  my $line = $self->$orig(@args);
+
+  if (defined $line) {
+    while (needs_continuation($line)) {
+      my $orig_prompt = $self->prompt;
+      $self->prompt($self->continuation_prompt);
+
+      my $append = $self->read(@args);
+      $line .= $append if defined($append);
+
+      $self->prompt($orig_prompt);
+
+      # ^D means "shut up and eval already"
+      return $line if !defined($append);
+    }
+  }
+  return $line;
+};
+
+sub needs_continuation
+{
+  my $line = shift;
+  my $document = PPI::Document->new(\$line);
+  return 0 if !defined($document);
+
+  # this could use more logic, such as returning 1 on s/foo/ba<Enter>
+  my $unfinished_structure = sub
+  {
+    my ($document, $element) = @_;
+    return 0 unless $element->isa('PPI::Structure');
+    return 1 unless $element->start && $element->finish;
+    return 0;
+  };
+
+  return $document->find_any($unfinished_structure);
+}
+
+1;