Have LexEnv wrap find_variable to first look at lexical variables. The around doesn...
[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 => (
314f2293 8 is => 'rw',
9 isa => 'ArrayRef',
10 lazy => 1,
11 default => sub { [] },
1989c3d2 12);
ac71b56c 13
1989c3d2 14has match_index => (
314f2293 15 is => 'rw',
16 isa => 'Int',
17 lazy => 1,
18 default => sub { 0 },
1989c3d2 19);
e4ac8502 20
97d28d6b 21has no_term_class_warning => (
22 isa => "Bool",
23 is => "rw",
24 default => 0,
25);
26
1989c3d2 27sub BEFORE_PLUGIN {
28 my ($self) = @_;
e4ac8502 29
1989c3d2 30 my $weakself = $self;
31 weaken($weakself);
ac71b56c 32
1989c3d2 33 $self->term->Attribs->{attempted_completion_function} = sub {
34 $weakself->_completion(@_);
35 };
e4ac8502 36}
37
97d28d6b 38sub AFTER_PLUGIN {
39 my ($self) = @_;
40
41 warn "Term::ReadLine::Gnu is required for the Completion plugin to work"
42 unless $self->term->isa("Term::ReadLine::Gnu") and !$self->no_term_class_warning;
43}
44
1989c3d2 45sub _completion {
46 my ($self, $text, $line, $start, $end) = @_;
47
48 # we're discarding everything after the cursor for completion purposes
314f2293 49 # we can't just use $text because we want all the code before the cursor to
50 # matter, not just the current word
1989c3d2 51 substr($line, $end) = '';
52
53 my $document = PPI::Document->new(\$line);
54 return unless defined($document);
55
314f2293 56 $document->prune('PPI::Token::Whitespace');
57
1989c3d2 58 my @matches = $self->complete($text, $document);
ac71b56c 59
1989c3d2 60 # iterate through the completions
61 return $self->term->completion_matches($text, sub {
62 my ($text, $state) = @_;
63
64 if (!$state) {
65 $self->current_matches(\@matches);
66 $self->match_index(0);
67 }
68 else {
69 $self->match_index($self->match_index + 1);
ac71b56c 70 }
71
1989c3d2 72 return $self->current_matches->[$self->match_index];
73 });
74}
75
76sub complete {
77 return ();
78}
e4ac8502 79
8051a5e0 80# recursively find the last element
81sub last_ppi_element {
82 my ($self, $document, $type) = @_;
83 my $last = $document;
84 while ($last->can('last_element') && defined($last->last_element)) {
85 $last = $last->last_element;
86 return $last if $type && $last->isa($type);
87 }
88 return $last;
89}
90
e4ac8502 911;
1989c3d2 92