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))
m
 
(9 intermediate revisions by one user not shown)
Line 1: Line 1:
 
[[Image:Dirsmenuv2.jpg|thumb|right]]
 
[[Image:Dirsmenuv2.jpg|thumb|right]]
  
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'').
+
Another pipe menu for recursive directory listing. I tried to keep the code as simple and short as possible. It uses Perl's ''File::Find'' to get the directories and 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'').
 +
 
 +
You can adjust options such as starting directory, show hidden files, show '..', show bookmarks (can handle any URL, not just local files) and bookmark file location.
  
 
== dirsmenu: ==
 
== dirsmenu: ==
Line 7: Line 9:
 
  # 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::Rule;
 +
use Cwd 'abs_path';
 +
use File::Spec::Functions qw/ catdir catfile /;
 +
use warnings;
 +
use strict;
 
   
 
   
  # set starting directory - this changes when the script is called with an argument (used for listing subdirectories)
+
sub say { print "$_\n" for @_; }
 +
sub print_browse;
 +
sub print_bookmarks;
 +
sub item;
 +
sub menu;
 +
sub fix_html (\$);
 +
 +
##################################################################################################
 +
########################################## CONFIGURATION #########################################
 +
##################################################################################################
 +
 +
  # set default starting directory
 
  my $base_dir = '/';
 
  my $base_dir = '/';
  # path to this script (needed as it calls itself to list subdirectories)
+
  # true to show hidden files and directories
  my $path = "$ENV{HOME}/obmenus";
+
my $show_hidden = 1;
  # your file browser
+
# true to show ..
  my $browser = 'Thunar';
+
  my $show_up = 0;
 +
# true to show gtk bookmarks at the top of the root menu
 +
my $show_bookmarks = 1;
 +
# file from which to read bookmarks
 +
my $gtk_bookmarks_file = "$ENV{HOME}/.gtk-bookmarks";
 +
  # show 'Open in browser' entry
 +
  my $browse = 1;
 +
 +
##################################################################################################
 
   
 
   
 +
# path to this script needed because it calls itself to list subdirectories
 +
my $path = abs_path $0;
 
  # when listing subdirectories, set the starting dir accordingly
 
  # when listing subdirectories, set the starting dir accordingly
  if ( "$ARGV[0]" ne "" ) { $base_dir = "$ARGV[0]"; }
+
  $base_dir = abs_path $ARGV[0] if $ARGV[0];
 
   
 
   
  # escape possible single quotes in filename when using find
+
  say "<openbox_pipe_menu>";
  my $tmp = $base_dir;
+
  print_browse if $browse;
  $base_dir =~ s/'/'"'"'/g;
+
  print_bookmarks if $show_bookmarks && ! $ARGV[0];
 
   
 
   
  # directories and links to such as submenus (in alphabetic order, hidden first)
+
  if ( $show_up && $base_dir ne '/' ) {
my @dirs = sort split /\n/, `find -L \'$base_dir\' -maxdepth 1 -type d`;
+
  # replace some special characters by their html codes
# all other types of files as items (in alphabetic order, hidden first)
+
  my $parent = dirname $base_dir;
my @files = sort split /\n/, `find -L \'$base_dir\' -maxdepth 1 ! -type d`;
+
  fix_html $parent;
 +
  menu "$parent/", '..', $parent;
 +
}
 
   
 
   
  $base_dir = $tmp;
+
  for ( sort { lc $a cmp lc $b } File::Find::Rule
undef $tmp;
+
      ->relative
 +
      ->maxdepth( 1 )
 +
      ->directory
 +
      ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ )
 +
      ->in( $base_dir )) {
 +
  # replace some special characters by their html codes
 +
  my $dir = catdir($base_dir, $_);
 +
  fix_html $dir;
 +
  fix_html $_;
 +
  # replace the underscore with a double underscore in the label to
 +
  # prevent openbox from interpreting it as a keyboard accelerator
 +
  $_ =~ s/_/__/g;
 +
  # escape special characters in bash
 +
  $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 +
  menu $dir, $_, $dir;
 +
}
 
   
 
   
  # replace some special characters by their html codes
+
  for ( sort { lc $a cmp lc $b } File::Find::Rule
$base_dir =~ s/&/&amp;amp;/g;
+
      ->relative
$base_dir =~ s/"/&amp;#34;/g;
+
      ->maxdepth( 1 )
$base_dir =~ s/\$/&amp;#36;/g;
+
      ->file()
$base_dir =~ s/</&amp;#60;/g;
+
      ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ )
$base_dir =~ s/=/&amp;#61;/g;
+
      ->in( $base_dir )) {
$base_dir =~ s/>/&amp;#62;/g;
+
  # replace some special characters by their html codes
$base_dir =~ s/\\/&amp;#92;/g;
+
  my $file = catfile($base_dir, $_);
# escape special characters in bash
+
  fix_html $file;
$base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
  fix_html $_;
 +
  # replace the underscore with a double underscore in the label to
 +
  # prevent openbox from interpreting it as a keyboard accelerator
 +
  $_ =~ s/_/__/g;
 +
  # escape special characters in bash
 +
  $file =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 +
  item $_, $file;
 +
}
 
   
 
   
  say "<openbox_pipe_menu>";
+
  say "</openbox_pipe_menu>";
  say "<item label=\"Open in $browser\">";
+
  exit 0;
say " <action name=\"Execute\"><execute>$browser $base_dir </execute></action>";
+
say "</item>";
+
say "<separator />";
+
 
   
 
   
  # print directories first
+
  ##################################################################################################
  DIRS: foreach my $dir (@dirs) {
+
########################################### SUBROUTINES ##########################################
      $dir =~ s/&/&amp;amp;/g;
+
##################################################################################################
      $dir =~ s/"/&amp;#34;/g;
+
      $dir =~ s/\$/&amp;#36;/g;
+
sub print_browse {
      $dir =~ s/</&amp;#60;/g;
+
  my $dir = shift || $base_dir;
      $dir =~ s/=/&amp;#61;/g;
+
  # replace some special characters by their html codes
      $dir =~ s/>/&amp;#62;/g;
+
  fix_html $dir;
      $dir =~ s/\\/&amp;#92;/g;
+
  # escape special characters in bash
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
  $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
      my $stripped_dir = basename($dir);
+
  item "Open in browser", $dir;
      $stripped_dir =~ s/_/__/g;
+
  say "<separator />";
# escape special characters in bash
+
      $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
# exclude . from directory list
+
      if ( "$dir" eq "$base_dir" ) { next DIRS; }
+
      say "<menu id=\"$dir\" label=\"$stripped_dir\" execute=\"$path/dirsmenu $dir\" />";
+
 
  }
 
  }
 
   
 
   
  # print files next
+
  sub print_bookmarks {
foreach my $file (@files) {
+
  open GTK_BKM, '<', $gtk_bookmarks_file or die "No such file $gtk_bookmarks_file\n";
     $file =~ s/&/&amp;amp;/g;
+
  while ( <GTK_BKM> ) {
     $file =~ s/"/&amp;#34;/g;
+
    chomp;
     $file =~ s/\$/&amp;#36;/g;
+
     $_ =~ s/^\s+|\s+$//g; # remove leading and trailing spaces
     $file =~ s/</&amp;#60;/g;
+
     next unless $_; # ignore empty lines
    $file =~ s/=/&amp;#61;/g;
+
      
     $file =~ s/>/&amp;#62;/g;
+
    # cannot have spaces in filenames, even if they are escaped
     $file =~ s/\\/&amp;#92;/g;
+
    my ($bookmark, $label) = ( $_ =~ m/^([^ ]+)(?:\ (.*)|$)/g );
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
     ## if no label was given take the base name for files
     my $stripped_file = basename($file);
+
    ( $label ) = $bookmark =~ m|[^/]+$|g if $bookmark =~ m|^file://| && ! length $label;
    $stripped_file =~ s/_/__/g;
+
    ## for any other urls, take the whole url
# escape special characters in bash
+
     $label = $bookmark unless length $label;
     $file =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
   
     say "<item label=\"$stripped_file\">";
+
    # replace some special characters by their html codes
     say " <action name=\"Execute\"><execute>xdg-open $file </execute></action>";
+
    fix_html $bookmark;
     say "</item>";
+
     fix_html $label;
 +
    # replace the underscore with a double underscore in the label to
 +
    # prevent openbox from interpreting it as a keyboard accelerator
 +
     $label =~ s/_/__/g;
 +
    # escape special characters in bash
 +
     $bookmark =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
 +
      
 +
    # print menu/item for directories/files and items for any other urls
 +
     if ( $bookmark =~ s|^file://|| && ( -d $bookmark || -l $bookmark ) ) {
 +
      menu $bookmark, $label, $bookmark;
 +
     } else {
 +
      item $label, $bookmark;
 +
    }
 +
  }
 +
  say "<separator />";
 +
  close GTK_BKM;
 
  }
 
  }
 
   
 
   
  say "</openbox_pipe_menu>";
+
  # print a menu for directory
 +
sub menu {
 +
  my $id = shift;
 +
  my $label = shift;
 +
  my $dir = shift;
 +
  say "<menu id=\"$id\" label=\"$label\" execute=\"$path $dir\" />";
 +
}
 +
 +
# print an item
 +
sub item {
 +
  my $label = shift;
 +
  my $file = shift;
 +
  say "  <item label=\"$label\">";
 +
  say "    <action name=\"Execute\">";
 +
  say "      <execute>";
 +
  say "        xdg-open $file";
 +
  say "      </execute>";
 +
  say "    </action>";
 +
  say "  </item>";
 +
}
 +
 +
sub fix_html (\$) {
 +
  my $ref = shift;
 +
  $$ref =~ s/&/&amp;/g;
 +
  $$ref =~ s/"/&#34;/g;
 +
  $$ref =~ s/\$/&#36;/g;
 +
  $$ref =~ s/</&#60;/g;
 +
  $$ref =~ s/=/&#61;/g;
 +
  $$ref =~ s/>/&#62;/g;
 +
  $$ref =~ s/\\/&#92;/g;
 +
}

Latest revision as of 07:17, 26 January 2015

Dirsmenuv2.jpg

Another pipe menu for recursive directory listing. I tried to keep the code as simple and short as possible. It uses Perl's File::Find to get the directories and 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).

You can adjust options such as starting directory, show hidden files, show '..', show bookmarks (can handle any URL, not just local files) and bookmark file location.

[edit] dirsmenu:

#!/usr/bin/perl
# Openbox menu to recursively list directories and files.
use File::Basename;
use File::Find::Rule;
use Cwd 'abs_path';
use File::Spec::Functions qw/ catdir catfile /;
use warnings;
use strict;

sub say { print "$_\n" for @_; }
sub print_browse;
sub print_bookmarks;
sub item;
sub menu;
sub fix_html (\$);

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

# set default starting directory
my $base_dir = '/';
# true to show hidden files and directories
my $show_hidden = 1;
# true to show ..
my $show_up = 0;
# true to show gtk bookmarks at the top of the root menu
my $show_bookmarks = 1;
# file from which to read bookmarks
my $gtk_bookmarks_file = "$ENV{HOME}/.gtk-bookmarks";
# show 'Open in browser' entry
my $browse = 1;

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

# path to this script needed because it calls itself to list subdirectories
my $path = abs_path $0;
# when listing subdirectories, set the starting dir accordingly
$base_dir = abs_path $ARGV[0] if $ARGV[0];

say "<openbox_pipe_menu>";
print_browse if $browse;
print_bookmarks if $show_bookmarks && ! $ARGV[0];

if ( $show_up && $base_dir ne '/' ) {
  # replace some special characters by their html codes
  my $parent = dirname $base_dir;
  fix_html $parent;
  menu "$parent/", '..', $parent;
}

for ( sort { lc $a cmp lc $b } File::Find::Rule
      ->relative
      ->maxdepth( 1 )
      ->directory
      ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ )
      ->in( $base_dir )) {
  # replace some special characters by their html codes
  my $dir = catdir($base_dir, $_);
  fix_html $dir;
  fix_html $_;
  # replace the underscore with a double underscore in the label to
  # prevent openbox from interpreting it as a keyboard accelerator
  $_ =~ s/_/__/g;
  # escape special characters in bash
  $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
  menu $dir, $_, $dir;
}

for ( sort { lc $a cmp lc $b } File::Find::Rule
      ->relative
      ->maxdepth( 1 )
      ->file()
      ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ )
      ->in( $base_dir )) {
  # replace some special characters by their html codes
  my $file = catfile($base_dir, $_);
  fix_html $file;
  fix_html $_;
  # replace the underscore with a double underscore in the label to
  # prevent openbox from interpreting it as a keyboard accelerator
  $_ =~ s/_/__/g;
  # escape special characters in bash
  $file =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
  item $_, $file;
}

say "</openbox_pipe_menu>";
exit 0;

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

sub print_browse {
  my $dir = shift || $base_dir;
  # replace some special characters by their html codes
  fix_html $dir;
  # escape special characters in bash
  $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
  item "Open in browser", $dir;
  say "<separator />";
}

sub print_bookmarks {
  open GTK_BKM, '<', $gtk_bookmarks_file or die "No such file $gtk_bookmarks_file\n";
  while ( <GTK_BKM> ) {
    chomp;
    $_ =~ s/^\s+|\s+$//g;	# remove leading and trailing spaces
    next unless $_;		# ignore empty lines
    
    # cannot have spaces in filenames, even if they are escaped
    my ($bookmark, $label) = ( $_ =~ m/^([^ ]+)(?:\ (.*)|$)/g );
    ## if no label was given take the base name for files
    ( $label ) = $bookmark =~ m|[^/]+$|g if $bookmark =~ m|^file://| && ! length $label;
    ## for any other urls, take the whole url
    $label = $bookmark unless length $label;
    
    # replace some special characters by their html codes
    fix_html $bookmark;
    fix_html $label;
    # replace the underscore with a double underscore in the label to
    # prevent openbox from interpreting it as a keyboard accelerator
    $label =~ s/_/__/g;
    # escape special characters in bash
    $bookmark =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
    
    # print menu/item for directories/files and items for any other urls
    if ( $bookmark =~ s|^file://|| && ( -d $bookmark || -l $bookmark ) ) {
      menu $bookmark, $label, $bookmark;
    } else {
      item $label, $bookmark;
    }
  }
  say "<separator />";
  close GTK_BKM;
}

# print a menu for directory
sub menu {
  my $id = shift;
  my $label = shift;
  my $dir = shift;
  say "<menu id=\"$id\" label=\"$label\" execute=\"$path $dir\" />";
}

# print an item
sub item {
  my $label = shift;
  my $file = shift;
  say "  <item label=\"$label\">";
  say "    <action name=\"Execute\">";
  say "      <execute>";
  say "        xdg-open $file";
  say "      </execute>";
  say "    </action>";
  say "  </item>";
}

sub fix_html (\$) {
  my $ref = shift;
  $$ref =~ s/&/&/g;
  $$ref =~ s/"/"/g;
  $$ref =~ s/\$/$/g;
  $$ref =~ s/</</g;
  $$ref =~ s/=/=/g;
  $$ref =~ s/>/>/g;
  $$ref =~ s/\\/\/g;
}
Personal tools