File Coverage

blib/lib/Devel/REPL/Plugin/Completion.pm
Criterion Covered Total %
statement 18 47 38.3
branch 0 20 0.0
condition 0 6 0.0
subroutine 6 10 60.0
pod 0 2 0.0
total 24 85 28.2


line stmt bran cond sub pod time code
1 2     2   145525 use strict;
  2         4  
  2         68  
2 2     2   11 use warnings;
  2         3  
  2         131  
3             package Devel::REPL::Plugin::Completion;
4             # ABSTRACT: Extensible tab completion
5              
6             our $VERSION = '1.003027';
7              
8 2     2   11 use Devel::REPL::Plugin;
  2         5  
  2         15  
9 2     2   10231 use Scalar::Util 'weaken';
  2         4  
  2         169  
10 2     2   908 use PPI;
  2         129413  
  2         65  
11 2     2   20 use namespace::autoclean;
  2         4  
  2         88  
12              
13             has current_matches => (
14             is => 'rw',
15             isa => 'ArrayRef',
16             lazy => 1,
17             default => sub { [] },
18             );
19              
20             has match_index => (
21             is => 'rw',
22             isa => 'Int',
23             lazy => 1,
24             default => sub { 0 },
25             );
26              
27             has no_term_class_warning => (
28             isa => "Bool",
29             is => "rw",
30             default => 0,
31             );
32              
33             has do_readline_filename_completion => ( # so default is no if Completion loaded
34             isa => "Bool",
35             is => "rw",
36             lazy => 1,
37             default => sub { 0 },
38             );
39              
40             before 'read' => sub {
41             my ($self) = @_;
42              
43             if ((!$self->term->isa("Term::ReadLine::Gnu") and !$self->term->isa("Term::ReadLine::Perl"))
44             and !$self->no_term_class_warning) {
45             warn "Term::ReadLine::Gnu or Term::ReadLine::Perl is required for the Completion plugin to work";
46             $self->no_term_class_warning(1);
47             }
48              
49             my $weakself = $self;
50             weaken($weakself);
51              
52             if ($self->term->isa("Term::ReadLine::Gnu")) {
53             $self->term->Attribs->{attempted_completion_function} = sub {
54             $weakself->_completion(@_);
55             };
56             }
57              
58             if ($self->term->isa("Term::ReadLine::Perl")) {
59             $self->term->Attribs->{completion_function} = sub {
60             $weakself->_completion(@_);
61             };
62             }
63              
64             };
65              
66             sub _completion {
67 0 0   0     my $is_trp = scalar(@_) == 4 ? 1 : 0;
68 0           my ($self, $text, $line, $start, $end) = @_;
69 0 0         $end = $start+length($text) if $is_trp;
70              
71             # we're discarding everything after the cursor for completion purposes
72             # we can't just use $text because we want all the code before the cursor to
73             # matter, not just the current word
74 0           substr($line, $end) = '';
75              
76 0           my $document = PPI::Document->new(\$line);
77 0 0         return unless defined($document);
78              
79 0           $document->prune('PPI::Token::Whitespace');
80              
81 0           my @matches = $self->complete($text, $document);
82              
83             # iterate through the completions
84 0 0         if ($is_trp) {
85 0 0         if (scalar(@matches)) {
86 0           return @matches;
87             } else {
88 0 0         return ($self->do_readline_filename_completion) ? readline::rl_filename_list($text) : () ;
89             }
90             } else {
91 0 0         $self->term->Attribs->{attempted_completion_over} = 1 unless $self->do_readline_filename_completion;
92 0 0         if (scalar(@matches)) {
93             return $self->term->completion_matches($text, sub {
94 0     0     my ($text, $state) = @_;
95              
96 0 0         if (!$state) {
97 0           $self->current_matches(\@matches);
98 0           $self->match_index(0);
99             }
100             else {
101 0           $self->match_index($self->match_index + 1);
102             }
103              
104 0           return $self->current_matches->[$self->match_index];
105 0           });
106             } else {
107 0           return;
108             }
109             }
110             }
111              
112             sub complete {
113 0     0 0   return ();
114             }
115              
116             # recursively find the last element
117             sub last_ppi_element {
118 0     0 0   my ($self, $document, $type) = @_;
119 0           my $last = $document;
120 0   0       while ($last->can('last_element') && defined($last->last_element)) {
121 0           $last = $last->last_element;
122 0 0 0       return $last if $type && $last->isa($type);
123             }
124 0           return $last;
125             }
126              
127             1;
128              
129             __END__
130              
131             =pod
132              
133             =encoding UTF-8
134              
135             =head1 NAME
136              
137             Devel::REPL::Plugin::Completion - Extensible tab completion
138              
139             =head1 VERSION
140              
141             version 1.003027
142              
143             =head1 NOTE
144              
145             By default, the Completion plugin explicitly does I<not> use the Gnu readline
146             or Term::ReadLine::Perl fallback filename completion.
147              
148             Set the attribute C<do_readline_filename_completion> to 1 to enable this feature.
149              
150             =head1 AUTHOR
151              
152             Shawn M Moore, C<< <sartak at gmail dot com> >>
153              
154             =head1 COPYRIGHT AND LICENSE
155              
156             This software is copyright (c) 2007 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L<http://www.shadowcatsystems.co.uk/>).
157              
158             This is free software; you can redistribute it and/or modify it under
159             the same terms as the Perl 5 programming language system itself.
160              
161             =cut