Commit | Line | Data |
e4ac8502 |
1 | package Devel::REPL::Plugin::Completion; |
2 | |
3 | use Moose::Role; |
4 | use namespace::clean -except => [ 'meta' ]; |
5 | |
ac71b56c |
6 | |
e4ac8502 |
7 | # push the given string in the completion list |
8 | sub push_completion |
9 | { |
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; |
14 | }; |
15 | |
16 | # return the namespace of the module given |
17 | sub get_namespace |
18 | { |
19 | my ($self, $module) = @_; |
20 | my $namespace; |
21 | eval '$namespace = \%'.$module.'::'; |
22 | return $namespace; |
23 | } |
24 | |
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 |
29 | sub BEFORE_PLUGIN |
30 | { |
31 | my ($self) = @_; |
32 | # set the completion function |
33 | $self->term->Attribs->{completion_entry_function} = |
34 | $self->term->Attribs->{list_completion_function}; |
e4ac8502 |
35 | $self->term->Attribs->{completion_word} = []; |
ac71b56c |
36 | |
e4ac8502 |
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); |
43 | } |
44 | } |
45 | closedir(CURDIR); |
46 | } |
47 | |
e4ac8502 |
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 { |
52 | my $orig = shift; |
53 | my ($self, $line) = @_; |
54 | my @ret = $self->$orig($line); |
ac71b56c |
55 | |
56 | # the namespace of the loaded module |
fb1f6874 |
57 | if ($line =~ /\buse\s+(\S+)/) { |
e4ac8502 |
58 | my $module = $1; |
fb1f6874 |
59 | foreach my $keyword (keys %{$self->get_namespace($module) || {}}) { |
e4ac8502 |
60 | $self->push_completion($keyword); |
61 | } |
62 | } |
ac71b56c |
63 | |
64 | # parses the lexical environment for new variables to add to |
65 | # the completion list |
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 /^${var}$/, @{$self->term->Attribs->{completion_word}}; |
71 | } |
72 | |
e4ac8502 |
73 | return @ret; |
74 | }; |
75 | |
76 | 1; |