Hi:

I'm sending this to freshmeat as well, thought it might be of use to the
readership.  It's a hack of a perl script for WM and KDE which I modified
for Blackbox and KDE.  Modifications welcome, and enjoy!

EAM


#!/usr/bin/perl
#
#
# bbkdemenu.pl
# by Erick A. Medina
# based on a script by Malcolm Cowe ([EMAIL PROTECTED])
#
#
# This script is made for users of Blackbox (http://bb.alug.org) 
# to be used along with KDE (http://www.kde.org).
#
#
# The default directory, /usr/share/applnk, will contain various
# sub-directories such as Development, Editors, Internet, etc. If for some
# reason, you wish to use an alternate (parent) directory that contains the
# various applnk files, it can be specified on the command line.
#
# The directory, if an alternate is specified, MUST be a parent directory to
# any/all sub-directories.
#
# Usage: bbkdemenu.pl [ Options... ]
#
#        Options:
#
#                -d <KDE App.kdelnk dir>
#                -f <output menufile>
#                -t <X terminal application>
#
# When the script is run, it will write out a proper Blackbox submenu 
# entry that can be included in the menu. When the External Menu has
# been correctly configured, the root menu will display a sub-menu
containing
# all of the KDE related items found. The script only needs to be run
when/if
# KDE is updated.
#
# 
# Installation and Configuration:
#
# 1) If /usr/bin/perl is not the location of the perl binary on your system,
#    the first line should be changed to reflect upon it's location.
# 2) Run the script as follows: perl bbkdemenu.pl -f kdemenu
# 3) Copy the kdemenu file to ~/.blackbox/kdemenu
# 4) Configure Blackbox's menu by editing ~/.blackbox/kdemenu
#    This could be done with any text editor. Insert
#    the following line (if done with a text editor) into the menu file:
#
#      [include] (~/.blackbox/kdemenu)
#
# 5) Some KDE entries, such as "Pine" will require a terminal to
#    execute it.  There is a terminal variable below. You may use any
#    terminal, XTerm is the default. Any command line options such as:
#    -fg -bg, etc. can be specified in this variable as well.
#
#
# (from Michael Hokenson - [EMAIL PROTECTED])
#
#
# To Do
# -----
#
# Programmatically determine the system location for the KDE menu
# directory. 
#
# Organise the output alphabetically, with directories appearing
# before files.
#
# Find a better way to parse the exec lines. In the short term,
# provide a user mechanism for generating exceptions to the curtailing
# of command line options. In the longer term, emulate what KDE does
# with these command line features.
#
#
###
### Variables
###

### The External Menu file, this should NEVER point to the root menu file
$menufile = "$ENV{'HOME'}/.blackbox/kdemenu";

### Base directory, location of all the KDE AppName.kdelnk files +
### Change the base directory default to point at the system files,
### not the user files. Need to find a way of determining the prefix
### programmatically.
$prefix="/opt/kde2";
$basedir = $prefix."/share/applnk";

### Terminal to use. May be specified on the command line with the -t
### switch. 
$term = "konsole";

### Print to STDOUT, default is YES, unless a filename is specified
$stdout = 1;

### KDE Locale Support

### Support for KDE internationalisation so that menu entries appear
### in the language chosen by the user. Also gets around some problems
### with the KDE applnk file format.

### The Locale is stored in one of two places, depending on the
### version of KDE that is running.
$kde2cf="$ENV{'HOME'}/.kde/share/config/kdeglobals";
$kde1cf="$ENV{'HOME'}/.kderc";
$kdeLanguage = "";

### Open the file, if it exists, otherwise provide a default language.
unless(open KDERC, $kde2cf) {
  unless(open KDERC, $kde1cf) {
    $kdeLanguage = "C";
  }
}

if ( $kdeLanguage == ""){
  $kdeLanguage = "C";
  ### Search through the contents of the file
  while($line = <KDERC>) {
    chomp($line);
    ### Grab the Language
    if($line =~ /^Language=/) {
      $kdeLanguage = $line;
      $kdeLanguage =~ s/Language=//;
      ($kdeLanguage) = split /:/,$kdeLanguage;
      last;
    }
  }
  close(KDERC);
}


###
### Begin Main Iteration.
###

### Process command line arguments
foreach $arg(@ARGV) {
  if($last) {
    if($last eq "-d") {
      $basedir = $arg;
    }
    elsif($last eq "-f") {
      $menufile = $arg;
      $stdout = 0;
    }
    elsif($last eq "-t") {
      $term = $arg;
    }
    undef($last);
  } elsif($arg =~ /^-/) {
    if($arg =~ /^-[dfst]$/) {
      $last = $arg;
    } else {
      die("Unknown option: $arg\n\nUsage: bbkdemenu.pl [ Options... ]\n".
          "\n\tOptions:\n\n".
          "\t\t-d <KDE App.kdelnk dir>\n".
          "\t\t-f <output menufile>\n".
          "\t\t-t <X terminal application>\n");
      &Usage;
    }
  }
}

### Make sure the KDE Menu's Top Level Directory exists.
if(-d $basedir) {

  ### See if there is an old menu file. If there is, rename it
  unless($stdout) {
    if(-e $menufile) {
      print STDERR "\tFound $menufile, renaming\n\n";
      rename $menufile, "$menufile.old";
    }
    open(MENUFILE,"> $menufile");
  }

  ### Start the main menu entry
  if($stdout) {
    print STDOUT "[submenu]\ (KDE)\n";
    process_dir (STDOUT, $basedir);
    print STDOUT "[end]\ (KDE)\n";
  } else {
    print MENUFILE "[submenu]\ (KDE)\n";
    process_dir (MENUFILE, $basedir);
    print MENUFILE "[end]\ (KDE)\n";
  }

} else {
  ### Error out :/
  print STDERR "ERROR:\n\t$basedir not found\n\tTry another directory.\n";
  exit(0);
}

# End of Main Iteration.

### process_dir() works it's way through each file and directory in
### the tree and generates the menu output to be used by Blackbox.

sub process_dir {

  my $OUT = @_[0];
  my $path = @_[1];
  my $item;
  my @tld;
  my ($gotLang, $gotDef, $gotExec, $inTerm);
  my $inDesktop;

  ### tld == Top Level Directory.
  opendir(TLD, $path) || return;
  @tld = readdir(TLD);
  closedir(TLD);

  foreach $item(@tld) {
    $gotLang = 0;
    $gotDef = 0;
    $gotExec = 0;
    $inTerm = 0;
    $inDesktop = 0;

    ### Ignore hidden files and directories.
    unless($item =~ /^\./) {
      if (-d "$path/$item") {
        print $OUT "[submenu]\ ($item)\n";
        process_dir($OUT, "$path/$item");
        print $OUT "[end]\ ($item)\n";
      }
      else {
        # Process the contents of the applnk file to generate a menu
        # entry for the application.

        open(SUB,"$path/$item");

        ### Search through the contents of the file
        while($line = <SUB>) {
          chomp($line);
          ### Get the application's name. This is stored in the
          ### [Desktop Entry] section of the applnk description.
          ###
          ### The application's name can have one of these forms:
          ### Name=
          ### Name[]=
          ### Name[language]=
          ###
          ### Get the default name anyway (one of the first two, just
          ### in case there is no language specific entry).
          if ($inDesktop) {
            # Make sure we are in fact still in the [Desktop Entry]
            # section.
            if ($line =~ /^\[/) {
              $inDesktop = 0;
            }
            ### Extract the Name of the Application
            elsif ($line =~ /^Name\[?\]?=/
                   && (!$gotDef || !gotLang)) {
              $pname = $line;
              $pname =~ s/^Name\[?\]?=//s;
              $pname =~ s/\"/\'\'/g;
              $gotDef = 1;
            }
            elsif ($line =~ /^Name\[$kdeLanguage\]=/ && !$gotLang) {
              $pname = $line;
              $pname =~ s/^Name\[$kdeLanguage\]=//s;
              $pname =~ s/\"/\'\'/g;
              $gotLang = 1;
            }
            ### Grab the command
            elsif($line =~ /^Exec=/ && !$gotExec) {
              $pargs = $line;
              $pargs =~ s/^Exec=//s;
              # Strip off all command line options unless the
              # application is "kfmclient", etc.
              if ($pargs !~ /^kfmclient/
                  && $pargs !~ /^kcmshell/
                  && $pargs !~ /^\/bin\/bash/
                  && $pargs !~ /^kdesu/){
                ($pargs) = split(/\s/, $pargs);
              }
              else {
                # A double check to remove any dubious characters from
                # the command line of the exceptions listed in the
                # above "if" statement. The only culprit so far is the
                # KDE 1 kfmclient command line.
                $pargs =~ s/\%[a-zA-Z]//g;
                }
              $gotExec = 1;
            }
            ### If Terminal=1, then we need to execute application
            ### within a terminal window.
            elsif($line =~ /^Terminal=(1|true)$/i) {
              $inTerm=1;
            }
          }
          elsif ($line =~ /^\[(KDE\ )?Desktop\ Entry\]/){
            $inDesktop = 1;
          }
        }

        close(SUB);
        ### Begin printing menu items

        if ($inTerm) {
          $pargs = "$term -T \"$pname\" -e $pargs";
        }
        print $OUT "[exec]\ ($pname) {$pargs}\n";
      }
    }
  }

  return;
}
### - Erick A. Medina 2/11/01, based on Malcolm Cowe, 21/01/2001.

Reply via email to