X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit%2FDevel-REPL.git;a=blobdiff_plain;f=lib%2FDevel%2FREPL%2FPlugin%2FCompletionDriver%2FINC.pm;h=cdcf74fe1fbab494a8087c0c78129a873e17489d;hp=6ea06d1e4d66f59285d1937f0f0e12a744029f35;hb=afc8677b078de3f125147caf731bd298c8b6d04e;hpb=b0489a7cf229890de0c78c24489240fffc6bf60a diff --git a/lib/Devel/REPL/Plugin/CompletionDriver/INC.pm b/lib/Devel/REPL/Plugin/CompletionDriver/INC.pm index 6ea06d1..cdcf74f 100644 --- a/lib/Devel/REPL/Plugin/CompletionDriver/INC.pm +++ b/lib/Devel/REPL/Plugin/CompletionDriver/INC.pm @@ -1,8 +1,15 @@ +use strict; +use warnings; package Devel::REPL::Plugin::CompletionDriver::INC; use Devel::REPL::Plugin; use File::Next; use File::Spec; -use namespace::clean -except => [ 'meta' ]; +use namespace::autoclean; + +sub BEFORE_PLUGIN { + my $self = shift; + $self->load_plugin('Completion'); +} around complete => sub { my $orig = shift; @@ -24,19 +31,27 @@ around complete => sub { 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{'}; + $outsep = "'"; $insep = "'|::"; } @@ -49,27 +64,57 @@ around complete => sub { 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) || return; + 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" + # 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) - { - if ($match =~ /\./) { - $match =~ s/\..*// unless $keep_extension; - } - # this is another subdirectory, so we're not done completing - else { - $match .= $outsep; - } - push @found, join $outsep, @directories, $match; - } + $add_recursively->($path, 0); } return $orig->(@_), @found; @@ -77,3 +122,15 @@ around complete => sub { 1; +__END__ + +=head1 NAME + +Devel::REPL::Plugin::CompletionDriver::INC - Complete module names in use and require + +=head1 AUTHOR + +Shawn M Moore, C<< >> + +=cut +