Rewrite the Completion plugin using PPI. It's much more powerful and extensible.
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / Completion.pm
CommitLineData
e4ac8502 1package Devel::REPL::Plugin::Completion;
1989c3d2 2use Devel::REPL::Plugin;
3use Scalar::Util 'weaken';
4use PPI;
e4ac8502 5use namespace::clean -except => [ 'meta' ];
6
1989c3d2 7has current_matches => (
8 is => 'rw',
9 isa => 'ArrayRef',
10 lazy => 1,
11 default => sub { [] },
12);
ac71b56c 13
1989c3d2 14has match_index => (
15 is => 'rw',
16 isa => 'Int',
17 lazy => 1,
18 default => sub { 0 },
19);
e4ac8502 20
1989c3d2 21sub BEFORE_PLUGIN {
22 my ($self) = @_;
e4ac8502 23
1989c3d2 24 my $weakself = $self;
25 weaken($weakself);
ac71b56c 26
1989c3d2 27 $self->term->Attribs->{attempted_completion_function} = sub {
28 $weakself->_completion(@_);
29 };
e4ac8502 30}
31
1989c3d2 32sub _completion {
33 my ($self, $text, $line, $start, $end) = @_;
34
35 # we're discarding everything after the cursor for completion purposes
36 substr($line, $end) = '';
37
38 my $document = PPI::Document->new(\$line);
39 return unless defined($document);
40
41 my @matches = $self->complete($text, $document);
ac71b56c 42
1989c3d2 43 # iterate through the completions
44 return $self->term->completion_matches($text, sub {
45 my ($text, $state) = @_;
46
47 if (!$state) {
48 $self->current_matches(\@matches);
49 $self->match_index(0);
50 }
51 else {
52 $self->match_index($self->match_index + 1);
ac71b56c 53 }
54
1989c3d2 55 return $self->current_matches->[$self->match_index];
56 });
57}
58
59sub complete {
60 return ();
61}
e4ac8502 62
631;
1989c3d2 64