#!/usr/bin/perl # # This creates, dynamically, menus for fvwm95. It lists files, mostly. # $Id: fvwm95.find,v 1.3 1997/07/12 04:32:32 ryo2 Exp ryo2 $ # Lines per menu $MenuLines = 28; # Include directory tree in the first menu. # Define following line &YES if the directory tree crash fvwm95 $IncludeTree = &YES; # Default file viewer. %s will be replaced by filename. $viewer = 'xterm -sb -ls -T %s -e less %s'; # Start directory $curr = $ENV{'HOME'}; # Files to ignore @ignore = ('*.o', '#*', '*~'); # File name of .mime.types (similar format to xclass-exploror) $mimetypes = ".smime.types"; # The rule to sort by --- Lexico, DirFirst, BySuffix $rule = 'DirFirst'; # Default editor unless ($editor = $ENV{'EDITOR'}) { $editor = 'xterm -sb -ls -T %s -e vi'; } $editor .= " %s"; $usemime = &YES; $debug = &NO; $FileScript = $0; # If this script is placed in the executable path, # use following line instead. #($FileScript) = ($0 =~ /([^\/]+)$/); OPT: while (@ARGV > 0) { $_ = shift; /^-d/ && ($debug = &YES, next); /^-l[\s\t]*(\S)/ && do {$1 =~ /([a-zA-OQ-Z])/ && ($fopt ="-$1"); next}; /^-v[\s\t]*(\S*)/ && do {$1 =~ /edit/ && ($usemime =&NO); next}; /^-n(\S*)/ && do {$1 && push(@primaries, "-name '$1'"); next}; /^-c\s*(\S*)/ && do {$1 && push(@primaries, "-ctime '$1'"); next}; /^-m\s*(\S*)/ && do {$1 && push(@primaries, "-mtime '$1'"); next}; /^-a\s*(\S*)/ && do {$1 && push(@primaries, "-atime '$1'"); next}; /^-u\s*(\S*)/ && do {$1 && push(@primaries, "-user $1"); next}; /^-g\s*(\S*)/ && do {$1 && push(@primaries, "-group $1"); next}; /^-p\s*(\S*)/ && do {$1 && push(@primaries, "-perm '$1'"); next}; /^-s\s*(\S*)/ && do {$1 && push(@primaries, "-size '$1'"); next}; /^-e\s*(\S*)/ && do {$1 && push(@primaries, "-newer '$1'"); next}; /^-t[\s\t]*(\S*)/ && do {$1 !~ /a/ && push(@primaries,"-type '$1'"); next}; /^-U[\s\t]*(\S*)/ && do {$1 && push(@primaries, "-nouser"); next}; /^-G[\s\t]*(\S*)/ && do {$1 && push(@primaries, "-nogroup"); next}; $curr = $_; $curr =~ s,/$,,; last; } # Default search directory is HOME not to search all the file system. $curr || ($curr = $ENV{'HOME'}); $findopt_exist = join("", @primaries); $allopt = "$fopt $curr ". join(" ", @primaries); $debug && $findopt_exist && do { $debstr = "( find $allopt )"; $debstr =~ s/\s+(\S)/ $1/g; }; # Read mime.types if it exists. open(INI, "$ENV{'HOME'}/$mimetypes") && &readMimeTypes; if ($findopt_exist) { $_ = `find $allopt -print`; @fullpaths = split(/\n/); } else { # Get a file list. while (<$curr/*>) { push(@fullpaths, $_); } # Comment following line to exclude dot files. while (<$curr/.*>) { /^$curr\/\.+$/ || push(@fullpaths, $_); } } foreach (@ignore) { s/\./\\\./; s/\*/\.\*/; }; LOOP: foreach (@fullpaths) { s/^$curr\///; -b "$curr/$_" && next; foreach $i (@ignore) { /^.$i$/ && next LOOP; } ($head) = ($_ =~ /^(.)/); # Index whether it's a directory or not. $ftype{$_} = ((-d _) ? "1" : "2") . $head; # Index of Suffixes if ($head eq '.'){ # Move dot files last in case of sorting BySuffixes $head = 'zz'; $ext = 'z' x 5; $trunk = $_; } else { unless (($trunk, $ext) = (/(.*)\.([^\.]+)$/)) { $trunk = $_; } } $fsuf{$_} = "$ext$head$ftype{$_}$trunk"; } $MoreCount = $count = 0; # Re-start a "Files" menu. $buf = "\nDestroyMenu \"Files\"\n"; $buf .= "AddToMenu Files \\\n"; # Title shows the current directory that works as "cd ../". $topdir = ($curr)? $curr : '/'; $buf .= " \"$topdir$debstr%mini-lower.xpm%\" PipeRead \"$FileScript ". &dirname($curr) . "\"\n+ \"\" Nop\n"; # Create directory tree from current path # Define $dircount = $#compdir +1; $buf_tree = ($IncludeTree)? "" : "\nDestroyMenu \"DirTree\"\nAddToMenu DirTree \\\n". " \"Higher Directory\" Nop\n" . "+ \"\" Nop\n"; while (@compdir > 0) { $full = join('/', @compdir); $i = pop(@compdir); $full || last; $buf_tree .= "+ \"$i %mini-ofolder.xpm%\" ". "PipeRead \"$FileScript '$full'\"\n"; } $buf_tree .= "+ \"/ %mini-ofolder.xpm%\" PipeRead \"$FileScript '/'\"\n"; if ($IncludeTree) { $buf .= "$buf_tree\n\+ \"\" Nop\n"; $count += $dircount; $buf_tree = ""; } else { $buf .= "+ \"Jump To...%mini-ofolder.xpm%\" Popup DirTree\n"; $count++; } # Show the list. foreach $file (sort $rule keys %ftype) { # Make a new menu every $MenuLines entries or so... $count++; if ($count == $MenuLines) { # If too many entries, make a new menu. $MoreCount++; $buf .= "+ More... Popup More$MoreCount\n\n"; $buf .= "DestroyMenu \"More$MoreCount\"\n"; $buf .= "AddToMenu More$MoreCount \"More($MoreCount)...\" Nop\n"; $buf .= "+ \"\" Nop\n"; $count = 1; } if (-d "$curr/$file") { $buf .= "+ \"$file%mini-folder.xpm%\" PipeRead \"$FileScript \'$curr/$file\'\"\n"; } else { if (-x "$curr/$file") { # Executable files have "exec" as their menu command. $tmp = "+ \"$file%" . (($usemime)? ("mini-run.xpm%\" Exec $curr/$file\n") : ("mini-edit.xpm%\" Exec ". &edits("$curr/$file") ." &\n")); } else { # Everything else should be viewed by the default viewer. $viewer_tmp = $viewer; $viewer_tmp =~ s,%s,$curr/$file,g; $tmp = "+ \"$file%". (($usemime)? ("mini-doc.xpm%\" Exec $viewer_tmp&\n") : ("mini-edit.xpm%\" Exec ". &edits("$curr/$file") ." &\n")); } $usemime && do { # Execute viewer written in mime.types foreach $i (keys %ACT) { if ($file =~ /^$i$/) { $act = $ACT{$i}; $act =~ s,%s,$curr/$file,g; $tmp = "+ \"$file%$ICON{$i}%\" Exec $act &\n"; last; } } }; $buf .= $tmp; } } $| = 1; print $buf_tree . $buf; exit 0; sub readMimeTypes { local(@each); while () { /^\s*$/ && do {undef $s_pat; undef $s_icon; undef $s_act;}; /^\s*pattern[\s\t]*=[\s\t]*(\S.*)$/i && ($s_pat = $1); /^\s*icon[\s\t]*=[\s\t]*(\S.*)$/i && ($s_icon = $1); /^\s*action[\s\t]*=[\s\t]*(\S.*)$/i && ($s_act = $1); $s_pat && $s_icon && $s_act && do { @each = split(/[\s\t]+/, $s_pat); foreach $i (@each) { $i =~ s/\./\\\./; $i =~ s/\*/\.\*/; $ICON{$i} = $s_icon; $ACT{$i} = $s_act; } }; } } sub DirFirst { $ftype{$a} cmp $ftype{$b}; } sub BySuffix { $fsuf{$a} cmp $fsuf{$b}; } sub Lexico { $a cmp $b; } sub dirname { local($_) = @_; @compdir = split(/\//); pop(@compdir); if ($#compdir < 1) { @compdir = (""); return '/'; } join('/', @compdir); } sub edits { local($path) = @_; local($tmp); $tmp = $editor; $tmp =~ s,%s,$path,g; $tmp; } sub YES {1;} sub NO {undef;}