Adding the Compeltion plugin
sukria [Mon, 20 Aug 2007 17:18:39 +0000 (17:18 +0000)]
git-svn-id: http://dev.catalyst.perl.org/repos/bast/trunk/Devel-REPL@3687 bd8105ee-0ff8-0310-8827-fb3f25b6796d

lib/Devel/REPL/Plugin/Completion.pm [new file with mode: 0644]

diff --git a/lib/Devel/REPL/Plugin/Completion.pm b/lib/Devel/REPL/Plugin/Completion.pm
new file mode 100644 (file)
index 0000000..bbee49a
--- /dev/null
@@ -0,0 +1,80 @@
+package Devel::REPL::Plugin::Completion;
+
+use Moose::Role;
+use namespace::clean -except => [ 'meta' ];
+
+# push the given string in the completion list
+sub push_completion
+{
+    my ($self, $string) = @_;
+    $self->term->Attribs->{completion_entry_function} = 
+        $self->term->Attribs->{list_completion_function};
+    push @{$self->term->Attribs->{completion_word}}, $string;
+};
+
+# return the namespace of the module given
+sub get_namespace
+{
+    my ($self, $module) = @_;
+    my $namespace;
+    eval '$namespace = \%'.$module.'::';
+    return $namespace;
+}
+
+# we wrap the run method to init the completion list 
+# with filenames found in the current dir and init 
+# the completion list.
+# yes, this is our 'init the plugin' stuff actually
+sub BEFORE_PLUGIN 
+{
+    my ($self) = @_;
+    # set the completion function
+    $self->term->Attribs->{completion_entry_function} = 
+        $self->term->Attribs->{list_completion_function};
+
+    # init the completion with an arrayref (could be the Perl built-ins)
+    $self->term->Attribs->{completion_word} = [];
+    
+    # now put each file in curdir in the completion list
+    my $curdir = File::Spec->curdir();
+    if (opendir(CURDIR, $curdir)) {
+        while (my $file = readdir(CURDIR)) {
+            next if $file =~ /^\.+$/; # we skip "." and ".."
+                $self->push_completion($file);
+        }
+    }
+    closedir(CURDIR);
+}
+
+# wrap the read method so we save in the completion list 
+# each variable declaration
+around 'read' => sub {
+  my $orig = shift;
+  my ($self, @args) = @_;
+  my $line = $self->$orig(@args);
+  if (defined $line) {
+      if ($line =~ /\s*[\$\%\@](\S+)\s*=/) {
+          my $str = $1;
+          $self->push_completion($str);
+      }
+  }
+  return $line;
+};
+
+# wrap the eval one to catch each 'use' statement in order to 
+# load the namespace in the completion list (module functions and friends)
+# we do that around the eval method cause we want the module to be actually loaded.
+around 'eval' => sub {
+    my $orig = shift;
+    my ($self, $line) = @_;
+    my @ret = $self->$orig($line);
+    if ($line =~ /use\s+(\S+)/) {
+        my $module = $1;
+        foreach my $keyword (keys %{$self->get_namespace($module)}) {
+            $self->push_completion($keyword);
+        }
+    }
+    return @ret;
+};
+
+1;