Changeset e6cec01


Ignore:
Timestamp:
Dec 28, 2009, 12:03:29 AM (10 years ago)
Author:
Nelson Elhage <nelhage@mit.edu>
Branches:
master, release-1.6, release-1.7, release-1.8, release-1.9
Children:
dc8f6e0
Parents:
880311d
git-author:
Nelson Elhage <nelhage@mit.edu> (12/27/09 23:48:30)
git-committer:
Nelson Elhage <nelhage@mit.edu> (12/28/09 00:03:29)
Message:
Completion: Add a helper function to complete paths.

Add tests as well.

[Thanks to davidben@mit.edu for bug reports and helping to clarify the
 $dir vs $pfx distinction in the code]
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • perl/lib/BarnOwl/Completion/Util.pm

    r69c27e6 re6cec01  
    55
    66use base qw(Exporter);
    7 our @EXPORT_OK = qw(complete_flags);
     7our @EXPORT_OK = qw(complete_flags complete_file);
    88
    99use Getopt::Long;
     10use Cwd qw(abs_path);
     11use File::Basename qw(dirname basename);
     12
    1013
    1114sub complete_flags {
     
    6770    }
    6871}
     72
     73sub expand_tilde {
     74    # Taken from The Perl Cookbook, recipe 7.3
     75    my $path = shift;
     76    $path =~ s{ ^ ~ ( [^/]* ) }
     77                { $1
     78                  ? (getpwnam($1))[7]
     79                  : ( $ENV{HOME} || $ENV{LOGDIR}
     80                      || (getpwuid($>))[7]
     81                     )
     82              }ex;
     83    return $path;
     84}
     85
     86sub splitfile {
     87    my $path = shift;
     88    if ($path =~ m{^(.*/)([^/]*)$}) {
     89        return ($1, $2);
     90    } else {
     91        return ('', $path);
     92    }
     93}
     94
     95sub complete_file {
     96    my $string = shift;
     97
     98    return ['~/', '~/', 0] if $string eq '~';
     99
     100    my $path = abs_path(expand_tilde($string));
     101    my $dir;
     102    if ($string =~ m{/$} || $string eq '' || basename($string) eq '.') {
     103        $dir = $path;
     104    } else {
     105        $dir = dirname($path);
     106    }
     107    return unless -d $dir;
     108
     109    my ($pfx, $base) = splitfile($string);
     110   
     111    opendir(my $dh, $dir) or return;
     112    my @dirs = readdir($dh);
     113    close($dh);
     114
     115    my @out;
     116    for my $d (@dirs) {
     117        # Skip dotfiles unless explicitly requested
     118        if($d =~ m{^[.]} && $base !~ m{^[.]}) {
     119            next;
     120        }
     121       
     122        my ($text, $value, $done) = ($d, "${pfx}${d}", 1);
     123
     124        if (-d "$dir/$d") {
     125            $text .= "/";
     126            $value .= "/";
     127            $done = 0;
     128        }
     129        push @out, [$text, $value, $done];
     130    }
     131    return @out;
     132}
  • t/completion.t

    r1167bf1 re6cec01  
    289289              \&complete_filter_expr);
    290290
     291# Test complete_files
     292use BarnOwl::Completion::Util qw(complete_file);
     293use File::Temp;
     294use File::Path qw(mkpath);
     295
     296my $tmpdir = File::Temp::tempdir(CLEANUP => 1);
     297
     298# Make sure $tmpdir does not have a trailing /
     299$tmpdir =~ s{/$}{};
     300$ENV{HOME} = $tmpdir;
     301
     302sub touch {
     303    my $path = shift;
     304    system("touch", "$path");
     305}
     306
     307mkpath("$tmpdir/.owl/",
     308       "$tmpdir/.owl/modules/",
     309       "$tmpdir/Public/",
     310       "$tmpdir/Private/",
     311       "$tmpdir/.ours",
     312       "$tmpdir/www");
     313touch("$tmpdir/.zephyr.subs");
     314touch("$tmpdir/wheee");
     315touch("$tmpdir/.owl/startup");
     316
     317sub completion_value {
     318    my $c = shift;
     319    return $c unless ref($c) eq 'ARRAY';
     320    return $c->[1];
     321}
     322
     323sub test_file {
     324    my $spec  = shift;
     325    my $pfx   = shift;
     326    my $dirs  = shift;
     327    my $files = shift;
     328
     329    my $expect = [ sort {$a->[1] cmp $b->[1]}
     330        ((map {["$_/", defined($pfx)?"$pfx/$_/":"$_/", 0]} @$dirs),
     331         (map {["$_",  defined($pfx)?"$pfx/$_" :$_   , 1]} @$files))
     332       ];
     333
     334    local $Test::Builder::Level = $Test::Builder::Level + 1;
     335
     336    my @got = complete_file($spec);
     337
     338    @got = grep {completion_value($_) =~ m{^\Q$spec\E}} @got;
     339    @got = sort {completion_value($a) cmp completion_value($b)} @got;
     340
     341    use Data::Dumper;
     342    is_deeply(\@got, $expect);
     343}
     344
     345is_deeply([complete_file("~")], [["~/", "~/", 0]]);
     346
     347chdir($tmpdir);
     348test_file("$tmpdir/", $tmpdir,
     349          [qw(Public Private www)],
     350          [qw(wheee)]);
     351
     352test_file("./", ".",
     353          [qw(Public Private www)],
     354          [qw(wheee)]);
     355
     356test_file("", undef, [qw(Public Private www)], [qw(wheee)]);
     357
     358test_file("./.owl/", "./.owl",
     359          [qw(modules)],
     360          [qw(startup)]);
     361
     362test_file("~/", "~",
     363          [qw(Public Private www)],
     364          [qw(wheee)]);
     365
     366test_file("P", undef, [qw(Public Private)], []);
     367
     368test_file("$tmpdir/.", $tmpdir,
     369          [qw(. .. .owl .ours)],
     370          [qw(.zephyr.subs)]);
    2913711;
    292372
Note: See TracChangeset for help on using the changeset viewer.