I no longer use this plugin in my bundle
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / Completion.pm
CommitLineData
1716b200 1use strict;
2use warnings;
e4ac8502 3package Devel::REPL::Plugin::Completion;
1716b200 4
54beb05d 5our $VERSION = '1.003027';
6
1989c3d2 7use Devel::REPL::Plugin;
8use Scalar::Util 'weaken';
9use PPI;
aa8b7647 10use namespace::autoclean;
e4ac8502 11
1989c3d2 12has current_matches => (
fd81abf1 13 is => 'rw',
14 isa => 'ArrayRef',
15 lazy => 1,
16 default => sub { [] },
1989c3d2 17);
ac71b56c 18
1989c3d2 19has match_index => (
fd81abf1 20 is => 'rw',
21 isa => 'Int',
22 lazy => 1,
23 default => sub { 0 },
1989c3d2 24);
e4ac8502 25
97d28d6b 26has no_term_class_warning => (
fd81abf1 27 isa => "Bool",
28 is => "rw",
29 default => 0,
30);
31
32has do_readline_filename_completion => ( # so default is no if Completion loaded
33 isa => "Bool",
34 is => "rw",
35 lazy => 1,
36 default => sub { 0 },
97d28d6b 37);
38
839614c7 39before 'read' => sub {
fd81abf1 40 my ($self) = @_;
e4ac8502 41
fd81abf1 42 if ((!$self->term->isa("Term::ReadLine::Gnu") and !$self->term->isa("Term::ReadLine::Perl"))
43 and !$self->no_term_class_warning) {
44 warn "Term::ReadLine::Gnu or Term::ReadLine::Perl is required for the Completion plugin to work";
45 $self->no_term_class_warning(1);
46 }
839614c7 47
fd81abf1 48 my $weakself = $self;
49 weaken($weakself);
ac71b56c 50
fd81abf1 51 if ($self->term->isa("Term::ReadLine::Gnu")) {
52 $self->term->Attribs->{attempted_completion_function} = sub {
53 $weakself->_completion(@_);
54 };
55 }
c8fafb5a 56
fd81abf1 57 if ($self->term->isa("Term::ReadLine::Perl")) {
58 $self->term->Attribs->{completion_function} = sub {
59 $weakself->_completion(@_);
60 };
61 }
f2833460 62
839614c7 63};
97d28d6b 64
1989c3d2 65sub _completion {
c8fafb5a 66 my $is_trp = scalar(@_) == 4 ? 1 : 0;
67 my ($self, $text, $line, $start, $end) = @_;
68 $end = $start+length($text) if $is_trp;
69
70 # we're discarding everything after the cursor for completion purposes
71 # we can't just use $text because we want all the code before the cursor to
72 # matter, not just the current word
73 substr($line, $end) = '';
74
75 my $document = PPI::Document->new(\$line);
76 return unless defined($document);
77
78 $document->prune('PPI::Token::Whitespace');
79
80 my @matches = $self->complete($text, $document);
81
82 # iterate through the completions
83 if ($is_trp) {
84 if (scalar(@matches)) {
85 return @matches;
86 } else {
fd81abf1 87 return ($self->do_readline_filename_completion) ? readline::rl_filename_list($text) : () ;
c8fafb5a 88 }
89 } else {
fd81abf1 90 $self->term->Attribs->{attempted_completion_over} = 1 unless $self->do_readline_filename_completion;
c8fafb5a 91 if (scalar(@matches)) {
92 return $self->term->completion_matches($text, sub {
93 my ($text, $state) = @_;
94
95 if (!$state) {
96 $self->current_matches(\@matches);
97 $self->match_index(0);
98 }
99 else {
100 $self->match_index($self->match_index + 1);
101 }
102
103 return $self->current_matches->[$self->match_index];
104 });
105 } else {
c8fafb5a 106 return;
107 }
108 }
1989c3d2 109}
110
111sub complete {
fd81abf1 112 return ();
1989c3d2 113}
e4ac8502 114
8051a5e0 115# recursively find the last element
116sub last_ppi_element {
fd81abf1 117 my ($self, $document, $type) = @_;
118 my $last = $document;
119 while ($last->can('last_element') && defined($last->last_element)) {
120 $last = $last->last_element;
121 return $last if $type && $last->isa($type);
122 }
123 return $last;
8051a5e0 124}
125
e4ac8502 1261;
1989c3d2 127
cfd1094b 128__END__
129
130=head1 NAME
131
132Devel::REPL::Plugin::Completion - Extensible tab completion
133
1a00e38d 134=head1 NOTE
135
136By default, the Completion plugin explicitly does I<not> use the Gnu readline
137or Term::ReadLine::Perl fallback filename completion.
138
139Set the attribute C<do_readline_filename_completion> to 1 to enable this feature.
140
30b459d4 141=head1 AUTHOR
142
143Shawn M Moore, C<< <sartak at gmail dot com> >>
144
cfd1094b 145=cut
146