File Coverage

blib/lib/Devel/REPL/Plugin/CompletionDriver/INC.pm
Criterion Covered Total %
statement 23 23 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod 0 1 0.0
total 31 32 96.8


line stmt bran cond sub pod time code
1 2     2   4394 use strict;
  2         5  
  2         64  
2 2     2   9 use warnings;
  2         5  
  2         103  
3             # ABSTRACT: Complete module names in use and require
4              
5             our $VERSION = '1.003029';
6              
7             use Devel::REPL::Plugin;
8 2     2   11 use Devel::REPL::Plugin::Completion; # die early if cannot load
  2         4  
  2         14  
9 2     2   8841 use File::Next;
  2         4  
  2         42  
10 2     2   627 use File::Spec;
  2         1900  
  2         67  
11 2     2   16 use namespace::autoclean;
  2         7  
  2         38  
12 2     2   9  
  2         4  
  2         24  
13             my $self = shift;
14             $self->load_plugin('Completion');
15 1     1 0 2 }
16 1         6  
17             around complete => sub {
18             my $orig = shift;
19             my ($self, $text, $document) = @_;
20              
21             my $last = $self->last_ppi_element($document, 'PPI::Statement::Include');
22              
23             return $orig->(@_)
24             unless $last->isa('PPI::Statement::Include');
25              
26             my @elements = $last->children;
27             shift @elements; # use or require
28              
29             # too late for us to care, they're completing on something like
30             # use List::Util qw(m
31             # OR they just have "use " and are tab completing. we'll spare them the flood
32             return $orig->(@_)
33             if @elements != 1;
34              
35             my $package = shift @elements;
36             my $outsep = '::';
37             my $insep = "::";
38             my $keep_extension = 0;
39             my $prefix = '';
40              
41             # require "Foo/Bar.pm" -- not supported yet, ->string doesn't work for
42             # partially completed elements
43             #if ($package->isa('PPI::Token::Quote'))
44             #{
45             # # we need to strip off the leading quote and stash it
46             # $package = $package->string;
47             # my $start = index($package->quote, $package);
48             # $prefix = substr($package->quote, 0, $start);
49              
50             # # we're completing something like: require "Foo/Bar.pm"
51             # $outsep = $insep = '/';
52             # $keep_extension = 1;
53             #}
54             if ($package =~ /'/)
55             {
56             # the goofball is using the ancient ' package sep, we'll humor him
57             $outsep = "'";
58             $insep = "'|::";
59             }
60              
61             my @directories = split $insep, $package;
62              
63             # split drops trailing fields
64             push @directories, '' if $package =~ /(?:$insep)$/;
65             my $final = pop @directories;
66             my $final_re = qr/^\Q$final/;
67              
68             my @found;
69              
70             # most VCSes don't litter every single fucking directory with garbage. if you
71             # know of any other, just stick them in here. No one wants to complete
72             # Devel::REPL::Plugin::.svn
73             my %ignored =
74             (
75             '.' => 1,
76             '..' => 1,
77             '.svn' => 1,
78             );
79              
80             # this will take a directory and add to @found all of the possible matches
81             my $add_recursively;
82             $add_recursively = sub {
83             my ($path, $iteration, @more) = @_;
84             opendir((my $dirhandle), $path) || return;
85             for (grep { !$ignored{$_} } readdir $dirhandle)
86             {
87             my $match = $_;
88              
89             # if this is the first time around, we need respect whatever the user had
90             # at the very end when he pressed tab
91             next if $iteration == 0 && $match !~ $final_re;
92              
93             my $fullmatch = File::Spec->rel2abs($match, $path);
94             if (-d $fullmatch)
95             {
96             $add_recursively->($fullmatch, $iteration + 1, @more, $match);
97             }
98             else
99             {
100             $match =~ s/\..*// unless $keep_extension;
101             push @found, join '', $prefix,
102             join $outsep, @directories, @more, $match;
103             }
104             }
105             };
106              
107             # look through all of
108             INC: for (@INC)
109             {
110             my $path = $_;
111              
112             # match all of the fragments they have, so "use Moose::Meta::At<tab>"
113             # will only begin looking in ../Moose/Meta/
114             for my $subdir (@directories)
115             {
116             $path = File::Spec->catdir($path, $subdir);
117             -d $path or next INC;
118             }
119              
120             $add_recursively->($path, 0);
121             }
122              
123             return $orig->(@_), @found;
124             };
125              
126             1;
127              
128              
129             =pod
130              
131             =encoding UTF-8
132              
133             =head1 NAME
134              
135             Devel::REPL::Plugin::CompletionDriver::INC - Complete module names in use and require
136              
137             =head1 VERSION
138              
139             version 1.003029
140              
141             =head1 SUPPORT
142              
143             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Devel-REPL>
144             (or L<bug-Devel-REPL@rt.cpan.org|mailto:bug-Devel-REPL@rt.cpan.org>).
145              
146             There is also an irc channel available for users of this distribution, at
147             L<C<#devel> on C<irc.perl.org>|irc://irc.perl.org/#devel-repl>.
148              
149             =head1 AUTHOR
150              
151             Shawn M Moore, C<< <sartak at gmail dot com> >>
152              
153             =head1 COPYRIGHT AND LICENCE
154              
155             This software is copyright (c) 2007 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L<http://www.shadowcatsystems.co.uk/>).
156              
157             This is free software; you can redistribute it and/or modify it under
158             the same terms as the Perl 5 programming language system itself.
159              
160             =cut