Openbox:Pipemenus:Dirsmenu

From Openbox

(Difference between revisions)
Jump to: navigation, search
m
m
 
(2 intermediate revisions by one user not shown)
Line 9: Line 9:
 
  # Openbox menu to recursively list directories and files.
 
  # Openbox menu to recursively list directories and files.
 
  use File::Basename;
 
  use File::Basename;
  use File::Find;
+
  use File::Find::Rule;
 
  use Cwd 'abs_path';
 
  use Cwd 'abs_path';
 +
use File::Spec::Functions qw/ catdir catfile /;
 
  use warnings;
 
  use warnings;
 +
use strict;
 
   
 
   
  sub say { print @_, "\n"; }
+
  sub say { print "$_\n" for @_; }
  sub print_files;
+
  sub print_browse;
  sub print_dirs;
+
sub print_bookmarks;
 +
sub item;
 +
  sub menu;
 
  sub fix_html (\$);
 
  sub fix_html (\$);
 
   
 
   
Line 23: Line 27:
 
   
 
   
 
  # set default starting directory
 
  # set default starting directory
  our $base_dir = '/';
+
  my $base_dir = '/';
 
  # true to show hidden files and directories
 
  # true to show hidden files and directories
  our $hidden = 1;
+
  my $show_hidden = 1;
 
  # true to show ..
 
  # true to show ..
  our $show_up = 0;
+
  my $show_up = 0;
 
  # true to show gtk bookmarks at the top of the root menu
 
  # true to show gtk bookmarks at the top of the root menu
  our $show_bookmarks = 0;
+
  my $show_bookmarks = 1;
 
  # file from which to read bookmarks
 
  # file from which to read bookmarks
  our $gtk_bookmarks_file = "$ENV{HOME}/.gtk-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
 
  # path to this script needed because it calls itself to list subdirectories
  our $path = abs_path $0;
+
  my $path = abs_path $0;
 
  # when listing subdirectories, set the starting dir accordingly
 
  # when listing subdirectories, set the starting dir accordingly
  $base_dir = $ARGV[0] if $ARGV[0];
+
  $base_dir = abs_path $ARGV[0] if $ARGV[0];
  { local $base_dir = $base_dir;
+
   
 +
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
 
   # replace some special characters by their html codes
   fix_html $base_dir;
+
  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
 
   # escape special characters in bash
   $base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
   $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
    
+
   menu $dir, $_, $dir;
  say "<openbox_pipe_menu>";
+
  say "<item label=\"Open in browser\">";
+
  say " <action name=\"Execute\"><execute>xdg-open $base_dir </execute></action>";
+
  say "</item>";
+
  say "<separator />";
+
 
  }
 
  }
 
   
 
   
  if ( $show_bookmarks && ! $ARGV[0] ) {
+
  for ( sort { lc $a cmp lc $b } File::Find::Rule
    open GTK_BKM, "$ENV{HOME}/.gtk-bookmarks" or die "No such file\n";
+
      ->relative
    while ( <GTK_BKM> ) {
+
      ->maxdepth( 1 )
        chomp;
+
      ->file()
        $_ =~ s/^\s+|\s+$//g; # remove leading and trailing spaces
+
      ->name( $show_hidden ? qr/.*/ : qr/^[^.].*/ )
        next unless $_; # ignore empty lines
+
      ->in( $base_dir )) {
        my ($bookmark, $label) = split ' ', $_; # cannot have spaces in filenames, even if they are escaped
+
  # replace some special characters by their html codes
        ( $label ) = $bookmark =~ m|[^/]*$|g if $bookmark =~ m|^file://| && $label; # if no label is provided, take the base name for files
+
  my $file = catfile($base_dir, $_);
        $label = $bookmark unless $label; # for any other urls, take the whole url
+
  fix_html $file;
# replace some special characters by their html codes
+
  fix_html $_;
fix_html $bookmark;
+
  # replace the underscore with a double underscore in the label to
        fix_html $label;
+
  # prevent openbox from interpreting it as a keyboard accelerator
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
  $_ =~ s/_/__/g;
$label =~ s/_/__/g;
+
  # escape special characters in bash
# escape special characters in bash
+
  $file =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
$bookmark =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
  item $_, $file;
        # print menu for files and items for any other urls
+
        if ( $bookmark =~ s|^file://|| ) {
+
    say "<menu id=\"$bookmark\" label=\"$label\" execute=\"$path $bookmark\" />";
+
        } else {
+
            say "<item label=\"$label\">";
+
            say " <action name=\"Execute\"><execute>xdg-open $bookmark </execute></action>";
+
            say "</item>";
+
        }
+
    }
+
    say "<separator />";
+
    close GTK_BKM;
+
 
  }
 
  }
 
find ( { preprocess => \&print_dirs, wanted => \&print_files }, "$base_dir");
 
 
   
 
   
 
  say "</openbox_pipe_menu>";
 
  say "</openbox_pipe_menu>";
 +
exit 0;
 
   
 
   
 
  ##################################################################################################
 
  ##################################################################################################
Line 89: Line 100:
 
  ##################################################################################################
 
  ##################################################################################################
 
   
 
   
  sub print_dirs {
+
  sub print_browse {
    my @dirs = sort grep { -d && $_ ne '.' && ( !$hidden ? $_ !~ /^\./ : 1 ) && ( !$show_up ? $_ !~ /^\.\.$/ : 1 ) } @_;
+
  my $dir = shift || $base_dir;
    my @files = sort grep { ( not -d ) && ( !$hidden ? $_ !~ /^\./ : 1 ) } @_;
+
  # replace some special characters by their html codes
    for ( @dirs ) {
+
  fix_html $dir;
$_ = $File::Find::dir . "/" . $_;
+
  # escape special characters in bash
# replace some special characters by their html codes
+
  $dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
fix_html $_;
+
  item "Open in browser", $dir;
# replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
  say "<separator />";
( 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 {
+
  sub print_bookmarks {
     return if $_ eq '.';
+
  open GTK_BKM, '<', $gtk_bookmarks_file or die "No such file $gtk_bookmarks_file\n";
     $_ = $File::Find::dir . "/" . $_;
+
  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
 
     # replace some special characters by their html codes
     fix_html $_;
+
     fix_html $bookmark;
     # replace the underscore with a double underscore in the label to prevent openbox from interpreting it as a keyboard accelerator
+
    fix_html $label;
     ( my $label = basename $_ ) =~ s/_/__/g;
+
     # 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
 
     # escape special characters in bash
     $_ =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
+
     $bookmark =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
     say "<item label=\"$label\">";
+
      
    say " <action name=\"Execute\"><execute>xdg-open $_ </execute></action>";
+
    # print menu/item for directories/files and items for any other urls
    say "</item>";
+
    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 (\$) {
 
  sub fix_html (\$) {
    my $ref = shift;
+
  my $ref = shift;
    $$ref =~ s/&/&amp;/g;
+
  $$ref =~ s/&/&amp;/g;
    $$ref =~ s/"/&#34;/g;
+
  $$ref =~ s/"/&#34;/g;
    $$ref =~ s/\$/&#36;/g;
+
  $$ref =~ s/\$/&#36;/g;
    $$ref =~ s/</&#60;/g;
+
  $$ref =~ s/</&#60;/g;
    $$ref =~ s/=/&#61;/g;
+
  $$ref =~ s/=/&#61;/g;
    $$ref =~ s/>/&#62;/g;
+
  $$ref =~ s/>/&#62;/g;
    $$ref =~ s/\\/&#92;/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