use File::Spec;
use namespace::clean -except => [ 'meta' ];
+with qw(
+ Devel::REPL::Plugin::Completion
+);
+
around complete => sub {
my $orig = shift;
my ($self, $text, $document) = @_;
my $package = shift @elements;
my $outsep = '::';
- my $insep = '::';
+ my $insep = "::";
my $keep_extension = 0;
+ my $prefix = '';
- # require "Module"
- if ($package->isa('PPI::Token::Quote'))
- {
- $outsep = $insep = '/';
- $keep_extension = 1;
- }
- elsif ($package =~ /'/)
+ # require "Foo/Bar.pm" -- not supported yet, ->string doesn't work for
+ # partially completed elements
+ #if ($package->isa('PPI::Token::Quote'))
+ #{
+ # # we need to strip off the leading quote and stash it
+ # $package = $package->string;
+ # my $start = index($package->quote, $package);
+ # $prefix = substr($package->quote, 0, $start);
+
+ # # we're completing something like: require "Foo/Bar.pm"
+ # $outsep = $insep = '/';
+ # $keep_extension = 1;
+ #}
+ if ($package =~ /'/)
{
- # the goofball is using the ancient ' package sep, we'll humor him
- $outsep = q{'};
- $insep = "'|::";
+ # the goofball is using the ancient ' package sep, we'll humor him
+ $outsep = "'";
+ $insep = "'|::";
}
my @directories = split $insep, $package;
my @found;
+ # most VCSes don't litter every single fucking directory with garbage. if you
+ # know of any other, just stick them in here. noone wants to complete
+ # Devel::REPL::Plugin::.svn
+ my %ignored =
+ (
+ '.' => 1,
+ '..' => 1,
+ '.svn' => 1,
+ );
+
+ # this will take a directory and add to @found all of the possible matches
+ my $add_recursively;
+ $add_recursively = sub {
+ my ($path, $iteration, @more) = @_;
+ opendir((my $dirhandle), $path);
+ for (grep { !$ignored{$_} } readdir $dirhandle)
+ {
+ my $match = $_;
+
+ # if this is the first time around, we need respect whatever the user had
+ # at the very end when he pressed tab
+ next if $iteration == 0 && $match !~ $final_re;
+
+ my $fullmatch = File::Spec->rel2abs($match, $path);
+ if (-d $fullmatch)
+ {
+ $add_recursively->($fullmatch, $iteration + 1, @more, $match);
+ }
+ else
+ {
+ $match =~ s/\..*// unless $keep_extension;
+ push @found, join '', $prefix,
+ join $outsep, @directories, @more, $match;
+ }
+ }
+ };
+
+ # look through all of
INC: for (@INC)
{
my $path = $_;
+
+ # match all of the fragments they have, so "use Moose::Meta::At<tab>"
+ # will only begin looking in ../Moose/Meta/
for my $subdir (@directories)
{
$path = File::Spec->catdir($path, $subdir);
-d $path or next INC;
}
- opendir((my $dirhandle), $path);
- for my $match (grep { $_ =~ $final_re } readdir $dirhandle)
- {
- $match =~ s/\..*// unless $keep_extension;
- push @found, join $outsep, @directories, $match;
- }
+ $add_recursively->($path, 0);
}
return $orig->(@_), @found;
1;
+__END__
+
+=head1 NAME
+
+Devel::REPL::Plugin::CompletionDriver::INC - Complete module names in use and require
+
+=head1 AUTHOR
+
+Shawn M Moore, C<< <sartak at gmail dot com> >>
+
+=cut
+