typo in change#4892
[p5sagit/p5-mst-13.2.git] / lib / File / DosGlob.pm
index e0887d1..e6fc311 100644 (file)
@@ -6,21 +6,6 @@
 
 package File::DosGlob;
 
-unless (caller) {
-    $| = 1;
-    while (@ARGV) {
-       #
-       # We have to do this one by one for compatibility reasons.
-       # If an arg doesn't match anything, we are supposed to return
-       # the original arg.  I know, it stinks, eh?
-       #
-       my $arg = shift;
-       my @m = doglob(1,$arg);
-       print (@m ? join("\0", sort @m) : $arg);
-       print "\0" if @ARGV;
-    }
-}
-
 sub doglob {
     my $cond = shift;
     my @retval = ();
@@ -100,15 +85,64 @@ sub doglob {
 }
 
 #
-# this can be used to override CORE::glob
-# by saying C<use File::DosGlob 'glob';>.
+# this can be used to override CORE::glob in a specific
+# package by saying C<use File::DosGlob 'glob';> in that
+# namespace.
 #
-sub glob { doglob(1,@_) }
+
+# context (keyed by second cxix arg provided by core)
+my %iter;
+my %entries;
+
+sub glob {
+    my $pat = shift;
+    my $cxix = shift;
+    my @pat;
+
+    # glob without args defaults to $_
+    $pat = $_ unless defined $pat;
+
+    # extract patterns
+    if ($pat =~ /\s/) {
+       require Text::ParseWords;
+       @pat = Text::ParseWords::parse_line('\s+',0,$pat);
+    }
+    else {
+       push @pat, $pat;
+    }
+
+    # assume global context if not provided one
+    $cxix = '_G_' unless defined $cxix;
+    $iter{$cxix} = 0 unless exists $iter{$cxix};
+
+    # if we're just beginning, do it all first
+    if ($iter{$cxix} == 0) {
+       $entries{$cxix} = [doglob(1,@pat)];
+    }
+
+    # chuck it all out, quick or slow
+    if (wantarray) {
+       delete $iter{$cxix};
+       return @{delete $entries{$cxix}};
+    }
+    else {
+       if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
+           return shift @{$entries{$cxix}};
+       }
+       else {
+           # return undef for EOL
+           delete $iter{$cxix};
+           delete $entries{$cxix};
+           return undef;
+       }
+    }
+}
 
 sub import {
     my $pkg = shift;
-    my $callpkg = caller(0);
+    return unless @_;
     my $sym = shift;
+    my $callpkg = ($sym =~ s/^GLOBAL_// ? 'CORE::GLOBAL' : caller(0));
     *{$callpkg.'::'.$sym} = \&{$pkg.'::'.$sym} if $sym eq 'glob';
 }
 
@@ -120,25 +154,26 @@ __END__
 
 File::DosGlob - DOS like globbing and then some
 
-perlglob.bat - a more capable perlglob.exe replacement
-
 =head1 SYNOPSIS
 
     require 5.004;
-    use File::DosGlob 'glob';  # override CORE::glob
+    
+    # override CORE::glob in current package
+    use File::DosGlob 'glob';
+    
+    # override CORE::glob in ALL packages (use with extreme caution!)
+    use File::DosGlob 'GLOBAL_glob';
+
     @perlfiles = glob  "..\\pe?l/*.p?";
     print <..\\pe?l/*.p?>;
     
-    # from the command line
+    # from the command line (overrides only in main::)
     > perl -MFile::DosGlob=glob -e "print <../pe*/*p?>"
-    
-    > perlglob ../pe*/*p?
 
 =head1 DESCRIPTION
 
 A module that implements DOS-like globbing with a few enhancements.
-This file is also a portable replacement for perlglob.exe.  It
-is largely compatible with perlglob.exe (the M$ setargv.obj
+It is largely compatible with perlglob.exe (the M$ setargv.obj
 version) in all but one respect--it understands wildcards in
 directory components.
 
@@ -149,13 +184,14 @@ backslashes and forward slashes are both accepted, and preserved.
 You may have to double the backslashes if you are putting them in
 literally, due to double-quotish parsing of the pattern by perl.
 
-When invoked as a program, it will print null-separated filenames
-to standard output.
-
-While one may replace perlglob.exe with this, usage by overriding
-CORE::glob via importation should be much more efficient, because
-it avoids launching a separate process, and is therefore strongly
-recommended.
+Spaces in the argument delimit distinct patterns, so
+C<glob('*.exe *.dll')> globs all filenames that end in C<.exe>
+or C<.dll>.  If you want to put in literal spaces in the glob
+pattern, you can escape them with either double quotes, or backslashes.
+e.g. C<glob('c:/"Program Files"/*/*.dll')>, or
+C<glob('c:/Program\ Files/*/*.dll')>.  The argument is tokenized using
+C<Text::ParseWords::parse_line()>, so see L<Text::ParseWords> for details
+of the quoting rules used.
 
 Extending it to csh patterns is left as an exercise to the reader.
 
@@ -170,7 +206,7 @@ pandering to DOS habits.  Needs a dose of optimizium too.
 
 =head1 AUTHOR
 
-Gurusamy Sarathy <gsar@umich.edu>
+Gurusamy Sarathy <gsar@activestate.com>
 
 =head1 HISTORY
 
@@ -178,6 +214,14 @@ Gurusamy Sarathy <gsar@umich.edu>
 
 =item *
 
+Support for globally overriding glob() (GSAR 3-JUN-98)
+
+=item *
+
+Scalar context, independent iterator context fixes (GSAR 15-SEP-97)
+
+=item *
+
 A few dir-vs-file optimizations result in glob importation being
 10 times faster than using perlglob.exe, and using perlglob.bat is
 only twice as slow as perlglob.exe (GSAR 28-MAY-97)
@@ -197,5 +241,9 @@ Initial version (GSAR 20-FEB-97)
 
 perl
 
+perlglob.bat
+
+Text::ParseWords
+
 =cut