Openbox:Pipemenus:Dirsmenu

From Openbox

(Difference between revisions)
Jump to: navigation, search
m (Fixed a minor bug (escape a literal ^ rather than beginning of string))
(It now uses Perl's File::Find instead of GNU find and added some more configuration options)
Line 7: Line 7:
 
  # Openbox menu to recursively list directories and files.
 
  # Openbox menu to recursively list directories and files.
 
  use File::Basename;
 
  use File::Basename;
  sub say {print @_, "\n"}
+
  use File::Find;
 +
use Cwd 'abs_path';
 
   
 
   
  # set starting directory - this changes when the script is called with an argument (used for listing subdirectories)
+
  sub say { print @_, "\n"; }
my $base_dir = '/';
+
  sub print_files;
# path to this script (needed as it calls itself to list subdirectories)
+
  sub print_dirs;
my $path = "$ENV{HOME}/obmenus";
+
  # your file browser
+
  my $browser = 'Thunar';
+
 
   
 
   
  # when listing subdirectories, set the starting dir accordingly
+
  ##################################################################################################
  if ( "$ARGV[0]" ne "" ) { $base_dir = "$ARGV[0]"; }
+
  ########################################## CONFIGURATION #########################################
 +
##################################################################################################
 
   
 
   
  # escape possible single quotes in filename when using find
+
  # set default starting directory
  my $tmp = $base_dir;
+
  our $base_dir = '/';
  $base_dir =~ s/'/'"'"'/g;
+
  # your file browser
+
our $browser = 'Thunar';
  # directories and links to such as submenus (in alphabetic order, hidden first)
+
  # true to show hidden files and directories
  my @dirs = sort split /\n/, `find -L \'$base_dir\' -maxdepth 1 -type d`;
+
  our $hidden = 1;
  # all other types of files as items (in alphabetic order, hidden first)
+
  # true to show ..
  my @files = sort split /\n/, `find -L \'$base_dir\' -maxdepth 1 ! -type d`;
+
  our $show_up = 0;
 
   
 
   
  $base_dir = $tmp;
+
  ##################################################################################################
undef $tmp;
+
 
   
 
   
 +
# path to this script needed because it calls itself to list subdirectories
 +
our $path = abs_path $0;
 +
# when listing subdirectories, set the starting dir accordingly
 +
$base_dir = shift if $ARGV[0];
 
  # replace some special characters by their html codes
 
  # replace some special characters by their html codes
  $base_dir =~ s/&/&/g;
+
  $base_dir =~ s/&/&/g;
  $base_dir =~ s/"/"/g;
+
  $base_dir =~ s/"/"/g;
  $base_dir =~ s/\$/$/g;
+
  $base_dir =~ s/\$/$/g;
  $base_dir =~ s/</&amp;#60;/g;
+
  $base_dir =~ s/</&#60;/g;
  $base_dir =~ s/=/&amp;#61;/g;
+
  $base_dir =~ s/=/&#61;/g;
  $base_dir =~ s/>/&amp;#62;/g;
+
  $base_dir =~ s/>/&#62;/g;
  $base_dir =~ s/\\/&amp;#92;/g;
+
  $base_dir =~ s/\\/&#92;/g;
 
  # escape special characters in bash
 
  # escape special characters in bash
 
  $base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 
  $base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 +
 
   
 
   
 
  say "<openbox_pipe_menu>";
 
  say "<openbox_pipe_menu>";
Line 48: Line 51:
 
  say "<separator />";
 
  say "<separator />";
 
   
 
   
  # print directories first
+
find ( { preprocess => \&print_dirs, wanted => \&print_files }, $base_dir);
  DIRS: foreach my $dir (@dirs) {
+
      $dir =~ s/&/&amp;amp;/g;
+
say "</openbox_pipe_menu>";
      $dir =~ s/"/&amp;#34;/g;
+
      $dir =~ s/\$/&amp;#36;/g;
+
  ##################################################################################################
      $dir =~ s/</&amp;#60;/g;
+
########################################### SUBROUTINES ##########################################
      $dir =~ s/=/&amp;#61;/g;
+
##################################################################################################
      $dir =~ s/>/&amp;#62;/g;
+
      $dir =~ s/\\/&amp;#92;/g;
+
sub print_dirs {
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
    my @dirs = sort grep { -d && ( !$hidden ? $_ !~ /^\./ : 1 ) && ( !$show_up ? $_ !~ /^\.\.$/ : 1 ) } @_;
      my $stripped_dir = basename($dir);
+
    my @files = sort grep { ( not -d ) && ( !$hidden ? $_ !~ /^\./ : 1 ) } @_;
      $stripped_dir =~ s/_/__/g;
+
    for ( @dirs ) {
# escape special characters in bash
+
next if $_ eq '.';
      $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
$_ = $File::Find::dir . "/" . $_;
# exclude . from directory list
+
# replace some special characters by their html codes
      if ( "$dir" eq "$base_dir" ) { next DIRS; }
+
$_ =~ s/&/&amp;/g;
      say "<menu id=\"$dir\" label=\"$stripped_dir\" execute=\"$path/dirsmenu $dir\" />";
+
$_ =~ s/"/&#34;/g;
 +
$_ =~ s/\$/&#36;/g;
 +
$_ =~ s/</&#60;/g;
 +
$_ =~ s/=/&#61;/g;
 +
$_ =~ s/>/&#62;/g;
 +
$_ =~ s/\\/&#92;/g;
 +
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
 +
( my $label = basename $_ ) =~ s/_/__/g;
 +
# escape special characters in bash
 +
$_ =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 +
say "<menu id=\"$_\" label=\"$label\" execute=\"$path $_\" />";
 +
    }
 +
    return @files;
 
  }
 
  }
 
   
 
   
  # print files next
+
  sub print_files {
foreach my $file (@files) {
+
    return if $_ eq '.';
     $file =~ s/&/&amp;amp;/g;
+
     $_ = $File::Find::dir . "/" . $_;
     $file =~ s/"/&amp;#34;/g;
+
    # replace some special characters by their html codes
     $file =~ s/\$/&amp;#36;/g;
+
    $_ =~ s/&/&amp;/g;
     $file =~ s/</&amp;#60;/g;
+
     $_ =~ s/"/&#34;/g;
     $file =~ s/=/&amp;#61;/g;
+
     $_ =~ s/\$/&#36;/g;
     $file =~ s/>/&amp;#62;/g;
+
     $_ =~ s/</&#60;/g;
     $file =~ s/\\/&amp;#92;/g;
+
     $_ =~ s/=/&#61;/g;
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
     $_ =~ s/>/&#62;/g;
     my $stripped_file = basename($file);
+
     $_ =~ s/\\/&#92;/g;
    $stripped_file =~ s/_/__/g;
+
    # replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
# escape special characters in bash
+
     ( my $label = basename $_ ) =~ s/_/__/g;
     $file =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
    # escape special characters in bash
     say "<item label=\"$stripped_file\">";
+
     $_ =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
     say " <action name=\"Execute\"><execute>xdg-open $file </execute></action>";
+
     say "<item label=\"$label\">";
 +
     say " <action name=\"Execute\"><execute>xdg-open $_ </execute></action>";
 
     say "</item>";
 
     say "</item>";
 
  }
 
  }
 
say "</openbox_pipe_menu>";
 

Revision as of 11:45, 20 September 2014

Dirsmenuv2.jpg

Another pipe menu for recursive directory listing. I tried to keep the code as simple and short as possible. It uses find to get the directories and the other files in the current directory and lists them in alphabetic order while making each directory a submenu. It escapes special characters and prints the underscore correctly (unlike obbrowser).

dirsmenu:

#!/usr/bin/perl
# Openbox menu to recursively list directories and files.
use File::Basename;
use File::Find;
use Cwd 'abs_path';

sub say { print @_, "\n"; }
sub print_files;
sub print_dirs;

##################################################################################################
########################################## CONFIGURATION #########################################
##################################################################################################

# set default starting directory
our $base_dir = '/';
# your file browser
our $browser = 'Thunar';
# true to show hidden files and directories
our $hidden = 1;
# true to show ..
our $show_up = 0;

##################################################################################################

# path to this script needed because it calls itself to list subdirectories
our $path = abs_path $0;
# when listing subdirectories, set the starting dir accordingly
$base_dir = shift if $ARGV[0];
# replace some special characters by their html codes
$base_dir =~ s/&/&/g;
$base_dir =~ s/"/"/g;
$base_dir =~ s/\$/$/g;
$base_dir =~ s/</</g;
$base_dir =~ s/=/=/g;
$base_dir =~ s/>/>/g;
$base_dir =~ s/\\/\/g;
# escape special characters in bash
$base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;


say "<openbox_pipe_menu>";
say "<item label=\"Open in $browser\">";
say " <action name=\"Execute\"><execute>$browser $base_dir </execute></action>";
say "</item>";
say "<separator />";

find ( { preprocess => \&print_dirs, wanted => \&print_files }, $base_dir);

say "</openbox_pipe_menu>";

##################################################################################################
########################################### SUBROUTINES ##########################################
##################################################################################################

sub print_dirs {
    my @dirs = sort grep { -d && ( !$hidden ? $_ !~ /^\./ : 1 ) && ( !$show_up ? $_ !~ /^\.\.$/ : 1 ) } @_;
    my @files = sort grep { ( not -d ) && ( !$hidden ? $_ !~ /^\./ : 1 ) } @_;
    for ( @dirs ) {
	next if $_ eq '.';
	$_ = $File::Find::dir . "/" . $_;
	# replace some special characters by their html codes
	$_ =~ s/&/&/g;
	$_ =~ s/"/"/g;
	$_ =~ s/\$/$/g;
	$_ =~ s/</</g;
	$_ =~ s/=/=/g;
	$_ =~ s/>/>/g;
	$_ =~ s/\\/\/g;
	# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
	( my $label = basename $_ ) =~ s/_/__/g;
	# escape special characters in bash
	$_ =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
	say "<menu id=\"$_\" label=\"$label\" execute=\"$path $_\" />";
    }
    return @files;
}

sub print_files {
    return if $_ eq '.';
    $_ = $File::Find::dir . "/" . $_;
    # replace some special characters by their html codes
    $_ =~ s/&/&/g;
    $_ =~ s/"/"/g;
    $_ =~ s/\$/$/g;
    $_ =~ s/</</g;
    $_ =~ s/=/=/g;
    $_ =~ s/>/>/g;
    $_ =~ s/\\/\/g;
    # replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
    ( my $label = basename $_ ) =~ s/_/__/g;
    # escape special characters in bash
    $_ =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
    say "<item label=\"$label\">";
    say " <action name=\"Execute\"><execute>xdg-open $_ </execute></action>";
    say "</item>";
}