Advertisement
rexroof

dmenu_run.pl rewrite

May 28th, 2014
462
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 3.73 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4.  
  5. # dmenu_run.pl - run dmenu, showing most used results first.
  6. #                use -r option to remove something from the database
  7.  
  8. # written by Rex Roof <dmenu@rexroof.com>  -  February 2013
  9. #    released for free under the creative commons CC BY  license.
  10. #         http://creativecommons.org/licenses/by/3.0
  11. #
  12. #   Install by copying to dmenu_run.pl in your path and chmod ugo+x
  13. #   then replace your dmenu_run execution with dmenu_run.pl
  14.  
  15. # path to dmenu
  16. my $DMENU_EXEC = "/bin/dmenu";
  17.  
  18. use Storable qw(nstore retrieve);
  19. use IPC::Open2;
  20.  
  21. my $STO = $ENV{HOME} . "/.dmenu_cache.sto";
  22. # if we have a cache dir, use it.
  23. my $CACHEDIR = $ENV{XDG_CACHE_HOME} || $ENV{HOME} . "/.cache";
  24. if ( -d $CACHEDIR ) {
  25.     $STO = "$CACHEDIR/dmenu_run.sto";
  26. }
  27.  
  28.  
  29. # process command line arguments
  30. my @dmenu_opts = ();
  31. my $remove_key = '';
  32. foreach my $bit ( @ARGV ) {
  33.  
  34.   if ( $remove_key eq '_CATCH_ME_' ) {
  35.      $remove_key = $bit;
  36.      next;
  37.   }
  38.  
  39.   if ( $bit =~ m/^-r(.*)/ ) {
  40.     if ( $1 )  {
  41.       $remove_key = $1;
  42.     } else {
  43.       # catch the next command line arg as the remove key
  44.       $remove_key = '_CATCH_ME_';
  45.     }
  46.   } else {
  47.     push @dmenu_opts, $bit;
  48.   }
  49. }
  50. if ( $remove_key eq '_CATCH_ME_' ) {
  51.    die HELP_MESSAGE();
  52. }
  53.  
  54.  
  55.  
  56. # searching $PATH environment
  57. my @dirs = split /:/, $ENV{PATH};
  58. my $count_ref = {};
  59. if ( -f $STO ) {
  60.     $count_ref = retrieve($STO);
  61. }
  62. # store our last rebuild time in this special key
  63. $count_ref->{'--last-rebuild'} = 1 unless ( $count_ref->{'--last-rebuild'} );
  64.  
  65. ## this section checks each directory in our path, looking for modification
  66. #    times since our last check
  67. #
  68. # the gap is the time since our check, in days
  69. my $gap = ( ( $^T - $count_ref->{'--last-rebuild'} ) / 86400 );
  70. foreach my $dir (@dirs) {
  71.     next unless ( -d $dir );
  72.  
  73.     if ( ( -M $dir ) <= $gap ) {
  74.         if ( opendir( my $dh, $dir ) ) {
  75.         F: while ( my $f = readdir $dh ) {
  76.  
  77.                 # only index executable files.
  78.                 next F unless ($f);
  79.                 next F unless ( -x "$dir/$f" );
  80.                 next F unless ( -f "$dir/$f" );
  81.  
  82.                 $count_ref->{$f} = 1 unless ( $count_ref->{$f} );
  83.             }
  84.  
  85.             # update our rebuild time
  86.             $count_ref->{'--last-rebuild'} = time();
  87.             nstore $count_ref, $STO;
  88.         }
  89.         else {
  90.             warn "opendir on $dir failed. $!";
  91.         }
  92.     }
  93. }
  94.  
  95. # if we have a cmd line argument to delete key
  96. if ( $remove_key ) {
  97.    if ( $remove_key ) {
  98.     if ( $count_ref->{ $remove_key } ) {
  99.         delete $count_ref->{ $remove_key };
  100.     }
  101.     nstore $count_ref, $STO;
  102.     print "purged \'$remove_key\' from database.\n";
  103.    } else {
  104.      HELP_MESSAGE();
  105.    }
  106.   exit;
  107. }
  108.  
  109. # execute dmenu to prompt the user
  110. my $pid = open2( my $fh_out, my $fh_in, $DMENU_EXEC,@dmenu_opts );
  111. foreach  # run fancy_sort on our keys
  112.     my $bit ( sort { fancy_sort( $a, $b, $count_ref ) } keys %{$count_ref} )
  113. {
  114.  
  115.     next if ( $bit =~ m/^--/ );
  116.  
  117.     print $fh_in $bit;
  118.     print $fh_in $/;
  119. }
  120. close($fh_in) or warn $!;
  121.  
  122. my $cmd = (<$fh_out>);
  123. exit unless ($cmd);
  124. chomp($cmd);
  125. close($fh_out) or warn $!;
  126.  
  127. # make sure our dmenu process exits.
  128. waitpid( $pid, 0 );
  129.  
  130. # store away our Storable file before we exec
  131. $count_ref->{$cmd}++;
  132. nstore $count_ref, $STO;
  133.  
  134. # execute our chosen command
  135. exec($cmd);
  136.  
  137. # exit;
  138.  
  139. sub fancy_sort {
  140.     my $a   = shift;
  141.     my $b   = shift;
  142.     my $ref = shift;
  143.  
  144.     # this sorts by execution count, then alphabetically
  145.     return ( $ref->{$b} <=> $ref->{$a} || $a cmp $b );
  146. }
  147.  
  148. sub HELP_MESSAGE {
  149.    print "usage: $0 [-r key]\n\t removes key from dmenu application index\n";
  150.    return;
  151. }
  152. sub VERSION_MESSAGE { return 1 };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement