Openbox:Pipemenus:Dirsmenu

From Openbox

Revision as of 06:22, 10 November 2014 by AaylaSecura (Talk | contribs)

Jump to: navigation, search
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.

dirsmenu:

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

sub say { print @_, "\n"; }
sub print_files;
sub print_dirs;
sub fix_html (\$);

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

# set default starting directory
our $base_dir = '/';
# true to show hidden files and directories
our $hidden = 1;
# true to show ..
our $show_up = 0;
# true to show gtk bookmarks at the top of the root menu
our $show_bookmarks = 0;
# file from which to read bookmarks
our $gtk_bookmarks_file = "$ENV{HOME}/.gtk-bookmarks";
# show 'Open in browser' entry
our $browse = 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 = $ARGV[0] if $ARGV[0];
say "<openbox_pipe_menu>";

if ( $browse ) {
  local $base_dir = $base_dir;
  # replace some special characters by their html codes
  fix_html $base_dir;
  # escape special characters in bash
  $base_dir =~ s/(\ |'|`|!|\^|&amp|\*|\(|\)|\[|\]|\{|\}|&#..)/\\$1/g;
  
  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] ) {
    open GTK_BKM, "$ENV{HOME}/.gtk-bookmarks" or die "No such file\n";
    while ( <GTK_BKM> ) {
        chomp;
        $_ =~ s/^\s+|\s+$//g; # remove leading and trailing spaces
        next unless $_; # ignore empty lines
        my ($bookmark, $label) = split ' ', $_; # cannot have spaces in filenames, even if they are escaped
        ( $label ) = $bookmark =~ m|[^/]*$|g if $bookmark =~ m|^file://| && $label; # if no label is provided, take the base name for files
        $label = $bookmark unless $label; # for any other urls, take the whole url
	# 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 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>";

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

sub print_dirs {
    my @dirs = sort grep { -d && $_ ne '.' && ( !$hidden ? $_ !~ /^\./ : 1 ) && ( !$show_up ? $_ !~ /^\.\.$/ : 1 ) } @_;
    my @files = sort grep { ( not -d ) && ( !$hidden ? $_ !~ /^\./ : 1 ) } @_;
    for ( @dirs ) {
	$_ = $File::Find::dir . "/" . $_;
	# replace some special characters by their html codes
	fix_html $_;
	# 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
    fix_html $_;
    # 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>";
}

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