[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] macperl_grep.pl



Recently I was faced with an annoying problem: I knew I had written a
piece of code I now wanted to use, but didn't know where it was on my
hard drive, or even what the file it was in could be called. I wanted
something like BBEdit's multiple-file recursive grep, but alas, that
searches only the data fork, and as we all know, MacPerl droplets keep
their source in the resource fork -- and I was passably sure it was in a
droplet!

So I wrote this script, below, or at
<http://www.lenzo.com/~sburke/pub/mac/macperl_grep.pl>

While the part about accessing the resource fork might not make sense
(unless you already know about such things, of course), I suggest that
you read and understand at least most of the rest of the code, both for
your own edification and so you can customize it.

(A note: if you feed in a bad regexp (e.g. "(foo(" ), the script will
harmlessly die, complaining about, yup, a bad regexp.  So don't do
that.)


#!Perl
# macperl_grep.pl     1998-04-10 Sean M. Burke (sburke@netadventure.net)
#
# Search given MacPerl files for lines matching a given regexp.
#
# A "MacPerl file" is very loosely defined as anything that
#  is a TEXT file, or is owned by (AKA was created by) MacPerl.
#
# Drop files or folders on this script (which you should resave as
#  a droplet).
#
# If you drop any folders on this script, their contents
#  will be recursed and only filenames matching a (second) given
#  regexp (if they are also TEXTs or created by MacPerl) will be
#  searched.
#
#! This is different from, say, the Multi-File Search in BBEdit in
#!  that this will search text resource #128 (where droplets et al.
#!  keep their source) in addition to data forks.
#
# I'm not calling this a general grepper for the Mac, because for
#  that I'd want to grep other kinds of resources besides just
#  TEXT resources (much less just TEXT #128)

use Mac::Memory;
use Mac::Resources;
use File::Find;

$debug = 0; # 0 = normal output, 1 = verbose, 2 = really verbose

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

exit unless @ARGV;

@files = ();
@directories = ();
foreach(@ARGV) {
  if(-f $_) { push(@files, $_) } else { push(@directories, $_) } 
}

$regexp = MacPerl::Ask('Regexp to search for in file content', '');
exit if $regexp eq '';

if(@directories) {
  $filename_regexp = MacPerl::Ask(
   'Regexp to match filenames against', '.');
  exit if $filename_regexp eq '';
}

print "Starting to search for /$regexp/...\n";

# first, search specified files
foreach(@files) { &grep_perl($_) }

# recurse directories
find(sub {
        unless($_ ne "Icon\cm"
               and ! /\.(txt|s?html?)$/si # TEXTs that are non-Perly
               and /$filename_regexp/oi
               and -f $File::Find::name) {
          print "Not looking at $File::Find::name\n" if $debug > 1;
          return;
        } # otherwise...
        &grep_perl($File::Find::name);
     } ,
     @directories) if @directories;
print "Done.\n\n";
exit;

#--------------------------------------------------------------------------

sub grep_perl {
  my $SPEC = $_[0];
  my $handle_128 = undef;

  print "Looking at $SPEC\n" if $debug;
  my($creator, $type) = MacPerl::GetFileInfo($SPEC);

  unless( $creator eq 'MrPL' or $creator eq 'McPL' or
   $type eq 'TEXT') {
    print "  bad owner/creator; skipping.\n" if $debug;
    return;
  }

  my $refnum = FSpOpenResFile($SPEC, 1);
 Reslook:
  if(defined($refnum)) {
    $handle_128 = Get1Resource('TEXT', 128);# Look for a TEXT #128
    if( $handle_128 ) {
      my @lines = split("\cm", $handle_128->get);
      CloseResFile $refnum;

      print scalar(@lines), " lines in $SPEC TEXT #128\n" if $debug;

      for (my $line_number = 0; $line_number < @lines; $line_number++) {
        next unless $lines[$line_number] =~ /$regexp/oi;
        chomp($lines[$line_number]); # may or may not be necessary
        print "$SPEC\xC5", 1 + $line_number,
"\xC5$lines[$line_number]\n";
      }  # \xC5 = the MacAscii swoosh-equals
      return; # don't look in the data fork
    } else { # resource, but no TEXT #128
      print "  no text #128...\n" if $debug;
      CloseResFile $refnum;
    }
  }

  return unless -s $SPEC;

  # if we get this far, look in the data fork
  print "  looking at $SPEC\'s data fork...\n" if $debug;
  if(open(IN, "$SPEC")) {
    local($_);

    # If you want to add heuristics to isolate just Perl scripts
    #  and not other text files, do so here, then seek() back
    #  to the start of the file.
    # Also maybe do newline conversion (by setting $/) if you're
    #  net sure all your Perl files are in Mac newline (CR) format
    while(<IN>){
      next unless /$regexp/oi;
      chomp($_);
      print "$_[0]\xC5$.\xC5$_\n";
    }  # \xC5 = the MacAscii swoosh-equals
  }
  close(IN);
  print "  moving on...\n" if $debug;

}

__END__

***** Want to unsubscribe from this list?
***** Send mail with body "unsubscribe" to mac-perl-request@iis.ee.ethz.ch