#!/usr/bin/env perl # This software is released under the same license and terms as perl # itself. # # This is a script for switching to directories from the command line # by grepping through a cache file. The target platform is OS X, # although that's more a convenience than an absolute requirement. use strict; use warnings; use File::Find; use Tie::File; use MacPerl; my $command = "cd"; my $cache_path = $ENV{HOME} . "/.jump_cache.txt"; my $includes_file = $ENV{HOME} . "/.jump_includes.txt"; my $excludes_file = $ENV{HOME} . "/.jump_excludes.txt"; # The includes file should contain a list of directories to scan, one # per line. open(FILE, $includes_file) || die("Could not open $includes_file"); my @roots=; chomp(@roots); close(FILE); # The excludes file should contain directories to be ignored, one per # line. open(FILE, $excludes_file) || die("Could not open $excludes_file"); my @excludes=; chomp(@excludes); close(FILE); sub WantedFiles { return unless (-d); # Ignore excluded directories my $directory_name = $_; if (grep $_ eq $directory_name, @excludes) { return $File::Find::prune = 1; } return if (/^\./); my $short_name = $File::Find::name; for (my $i=0; $i < @roots; $i++) { $short_name =~ s/^$roots[$i]/$i~/; } print CACHE $short_name . "\n"; } sub execCommand { my $path = shift; if ($command eq "cd") { my @applescript = ("tell application \"Terminal\"", "do script \"cd '$path'\"", "end tell"); MacPerl::DoAppleScript(join("\n",@applescript)) or die $@; exit; } else { exec $command, $path; exit; } } # The first argument describes what to do with the destination. It # should be a valid shell command, or "crawl" to rebuild the cache # file. Should probably be "--cd" or "--open" (if OS X). if ($ARGV[0] =~ m/^--/) { ($command = $ARGV[0]) =~ s/^--//; if ($command eq "crawl") { open CACHE, ">$cache_path"; foreach (@roots) { print CACHE "$_\n"; } find(\&WantedFiles, @roots); exit; } shift @ARGV; } my $search_for; if ($#ARGV > 0) { $search_for = "\/" . join("\.+", @ARGV) . "\$"; } else { $search_for = $ARGV[0] . "\$"; } $search_for =~ s/[^a-zA-Z0-9.+\/\$]/\./g; tie my @cache, "Tie::File", $cache_path, memory => 500; my @matches = grep(/$search_for/i, @cache); # If no matches, try again without the trailing "$" unless (@matches) { chop($search_for); @matches = grep(/$search_for/i, @cache); } # If still no matches, give up unless (@matches) { print "No matches.\n"; exit; } map {s/^(\d+)~/$roots[$1]/} @matches; # If one match, take immediate action if ($#matches == 0) { execCommand($matches[0]); } # If multiple matches, prompt for selection my $counter = 1; foreach (@matches) { my $padded = sprintf("%3s", "$counter)"); print $padded; print " " . $_ . "\n"; $counter++; } print "Which one? "; my $selection = ; chomp($selection); if ($selection eq 'q') { exit; } execCommand($matches[$selection - 1]);