1 package Devel::REPL::Plugin::Completion;
4 use namespace::clean -except => [ 'meta' ];
7 # push the given string in the completion list
10 my ($self, $string) = @_;
11 $self->term->Attribs->{completion_entry_function} =
12 $self->term->Attribs->{list_completion_function};
13 push @{$self->term->Attribs->{completion_word}}, $string;
16 # return the namespace of the module given
19 my ($self, $module) = @_;
21 eval '$namespace = \%'.$module.'::';
25 # we wrap the run method to init the completion list
26 # with filenames found in the current dir and init
27 # the completion list.
28 # yes, this is our 'init the plugin' stuff actually
32 # set the completion function
33 $self->term->Attribs->{completion_entry_function} =
34 $self->term->Attribs->{list_completion_function};
35 $self->term->Attribs->{completion_word} = [];
37 # now put each file in curdir in the completion list
38 my $curdir = File::Spec->curdir();
39 if (opendir(CURDIR, $curdir)) {
40 while (my $file = readdir(CURDIR)) {
41 next if $file =~ /^\.+$/; # we skip "." and ".."
42 $self->push_completion($file);
48 # wrap the eval one to catch each 'use' statement in order to
49 # load the namespace in the completion list (module functions and friends)
50 # we do that around the eval method cause we want the module to be actually loaded.
51 around 'eval' => sub {
53 my ($self, $line) = @_;
54 my @ret = $self->$orig($line);
56 # the namespace of the loaded module
57 if ($line =~ /\buse\s+(\S+)/) {
59 foreach my $keyword (keys %{$self->get_namespace($module) || {}}) {
60 $self->push_completion($keyword);
64 # parses the lexical environment for new variables to add to
66 my $lex = $self->lexical_environment;
67 foreach my $var (keys %{$lex->get_context('_')}) {
68 $var = substr($var, 1); # we drop the variable idiom as it confuses the completion
69 $self->push_completion($var) unless
70 grep $_ eq $var, @{$self->term->Attribs->{completion_word}};