Add the @INC completion driver. Needs some tweaking, but it's generally there
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / CompletionDriver / INC.pm
CommitLineData
f1f5a418 1package Devel::REPL::Plugin::CompletionDriver::INC;
2use Devel::REPL::Plugin;
3use File::Next;
4use File::Spec;
5use namespace::clean -except => [ 'meta' ];
6
7around complete => sub {
8 my $orig = shift;
9 my ($self, $text, $document) = @_;
10
11 my $last = $self->last_ppi_element($document, 'PPI::Statement::Include');
12
13 return $orig->(@_)
14 unless $last->isa('PPI::Statement::Include');
15
16 my @elements = $last->children;
17 shift @elements; # use or require
18
19 # too late for us to care, they're completing on something like
20 # use List::Util qw(m
21 # OR they just have "use " and are tab completing. we'll spare them the flood
22 return $orig->(@_)
23 if @elements != 1;
24
25 my $package = shift @elements;
26 my $outsep = '::';
27 my $insep = '::';
28 my $keep_extension = 0;
29
30 # require "Module"
31 if ($package->isa('PPI::Token::Quote'))
32 {
33 $outsep = $insep = '/';
34 $keep_extension = 1;
35 }
36 elsif ($package =~ /'/)
37 {
38 # the goofball is using the ancient ' package sep, we'll humor him
39 $outsep = q{'};
40 $insep = "'|::";
41 }
42
43 my @directories = split $insep, $package;
44
45 # split drops trailing fields
46 push @directories, '' if $package =~ /(?:$insep)$/;
47 my $final = pop @directories;
48 my $final_re = qr/^\Q$final/;
49
50 my @found;
51
52 INC: for (@INC)
53 {
54 my $path = $_;
55 for my $subdir (@directories)
56 {
57 $path = File::Spec->catdir($path, $subdir);
58 -d $path or next INC;
59 }
60
61 opendir((my $dirhandle), $path);
62 for my $match (grep { $_ =~ $final_re } readdir $dirhandle)
63 {
64 $match =~ s/\..*// unless $keep_extension;
65 push @found, join $outsep, @directories, $match;
66 }
67 }
68
69 return $orig->(@_), @found;
70};
71
721;
73