diff --git a/ChangeLog b/ChangeLog index 5d1a745e..ad4bdfbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ Changes since version 0.63.1: (Richard Frith-Macdonald ) - Fixed broken panels. - Renamed se.po to sv.po +- New version of wkdemenu.pl (from Malcolm Cowe ) Changes since version 0.63.0: diff --git a/util/wkdemenu.pl b/util/wkdemenu.pl index cd85f620..33efc95d 100644 --- a/util/wkdemenu.pl +++ b/util/wkdemenu.pl @@ -8,19 +8,21 @@ # be used along with KDE (http://www.kde.org). # # -# The default directory, ~/.kde/share/applnk/apps, will contain various +# 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 AppName.kdelnk files, it can be specified on the command line. +# 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. # -# Command line usage: -# -d -f -s yes (print to STDOUT) +# Usage: kde2wmaker.pl [ Options... ] # -# Example command with args: -# -d ~/.kde/share/applnk -f ~/.kde2wmaker.menu -s yes +# Options: +# +# -d +# -f +# -t # # When the script is run, it will write out a proper Window Maker "External # Menu" entry, that can be included in the menu. When the External Menu has @@ -41,14 +43,75 @@ # If done using WPrefs, simply "Add External Menu" from the drop down menu, # then type: $HOME/.kde2wmaker.menu into the "Menu Path/Directory List" # textbox. -# 4) Some KDE entries, such as "Pine" will require a terminal to execute it. -# There is a terminal varable 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. +# 4) 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. # # # Michael Hokenson - logan@dct.com - +# +# +#--------------------------------------------------------------------- +# +# 21st January 2001. +# +# This script has been competely re-written to allow recursion of the +# KDE menu directories to an arbitrary depth, fixing a major +# functional limitation in the original script. To do this, I have +# rewritten the code to traverse directories recursively, introducing +# a subroutine, process_dir() to carry out the task. +# +# wkdemenu.pl provides an excellent extension to the user interface in +# Window Maker, working well with the "Generated Submenu" feature. +# +# +# Summary of New Features +# ----------------------- +# +# Added support for menus of arbitrary depth. +# +# Added basic internationalisation based on KDE's language +# setting. The language is taken from "~/.kde/share/config/kdeglobals" +# or from "~/.kderc". +# +# Corrected the generation of menu names, incorporating +# internationalisation, where appropriate. +# +# Changed the double quotes to two single quotes in application names +# so that they do not break the Menu parser in Window Maker. +# +# Stripped off the arguments to commands on the Exec= line, except in +# a few KDE specific cases (e.g. kfmclient). The extra options are +# only usable by KDE and were preventing many applications from +# launching, since they could parse the option %c or %s, for example. +# This "feature" will probably need a more formal or interactive way +# of specifying exceptions in the future. +# +# Added a command line option for specifying the X terminal to +# use. This still defaults to xterm, but could be used to specify +# aterm, etc. +# +# +# 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. +# +# Optimise the code. This is my first proper PERL script, and I'm sure +# there's a better way. =) +# +# +# Malcolm Cowe, malk@271m.net. ### ### Variables @@ -57,180 +120,238 @@ ### The External Menu file, this should NEVER point to the root menu file $menufile = "$ENV{'HOME'}/.kde2wmaker.menu"; -### Base directory, location of all the KDE AppName.kdelnk files -$basedir = "$ENV{'HOME'}/.kde/share/applnk/apps"; +### Base directory, location of all the KDE AppName.kdelnk files + +### Malcolm Cowe, 21/01/2001. +### 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="/usr"; +$basedir = $prefix."/share/applnk"; +### - Malcolm Cowe, 21/01/2001. -### Terminal to use +### Terminal to use. May be specified on the command line with the -t +### switch. $term = "xterm"; ### Print to STDOUT, default is YES, a filename is specified $stdout = 1; +### + Malcolm Cowe, 21/01/2001. +### 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 = ) { + chomp($line); + ### Grab the Language + if($line =~ /^Language=/) { + $kdeLanguage = $line; + $kdeLanguage =~ s/Language=//; + ($kdeLanguage) = split /:/,$kdeLanguage; + last; + } + } + close(KDERC); +} + +### - Malcolm Cowe, 21/01/2001. + ### -### Begin work +### 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; - } - undef($last); - } elsif($arg =~ /^-/) { - if($arg =~ /^-[dfs]$/) { - $last = $arg; - } else { - die("Unknown option: $arg\n\nUsage: kde2wmaker.pl\n\t-d [-f ]\n"); - &Usage; - } - } + if($last) { + if($last eq "-d") { + $basedir = $arg; + } + elsif($last eq "-f") { + $menufile = $arg; + $stdout = 0; + } + ### + Malcolm Cowe, 21/01/2001. + elsif($last eq "-t") { + $term = $arg; + } + ### - Malcolm Cowe, 21/01/2001. + undef($last); + } elsif($arg =~ /^-/) { + ### + Malcolm Cowe, 21/01/2001. + if($arg =~ /^-[dfst]$/) { + $last = $arg; + } else { + die("Unknown option: $arg\n\nUsage: kde2wmaker.pl [ Options... ]\n". + "\n\tOptions:\n\n". + "\t\t-d \n". + "\t\t-f \n". + "\t\t-t \n"); + ### - Malcolm Cowe, 21/01/2001. + &Usage; + } + } } -### Make sure we actually exist +### Make sure the KDE Menu's Top Level Directory exists. if(-d $basedir) { - ### Start some error checking - $errors = 0; + ### 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"); + } - ### See if there is an old menu file. If there is, rename it - unless($stdout) { - if(-e $menufile) { - print "\tFound $menufile, renaming\n\n"; - rename $menufile, "$menufile.old"; - } - } + ### Start the main menu entry + if($stdout) { + ### + Malcolm Cowe, 21/01/2001. + print STDOUT "\"KDE Applications\" MENU\n"; + process_dir (STDOUT, $basedir); + print STDOUT "\"KDE Applications\" END\n"; + } else { + print MENUFILE "\"KDE Applications\" MENU\n"; + process_dir (MENUFILE, $basedir); + print MENUFILE "\"KDE Applications\" END\n"; + ### - Malcolm Cowe, 21/01/2001. + } - ### Read in the directories - opendir(KDE,$basedir); - @dirs = readdir(KDE); - closedir(KDE); - - ### Make sure there is actually something in $basedir - if($#dirs <= 1) { - print "ERROR:\n\tNothing found in $basedir\n\n"; - exit(0); - } - - ### Begin writing the menu - unless($stdout) { - open(MENUFILE,"> $menufile"); - } - - ### Start the main menu entry - if($stdout) { - print "\t\"KDE Applications\" MENU\n"; - } else { - print MENUFILE "\t\"KDE Applications\" MENU\n"; - } - - ### Begin processing the directories - foreach $dir(@dirs) { - - ### Handle each directory unless if its hidden (starts with .) - unless($dir =~ /^\./) { - ### Print out the sub directories - if($stdout) { - print "\t\t\"$dir\" MENU\n"; - } else { - print MENUFILE "\t\t\"$dir\" MENU\n"; - } - - ### Look in each directory and process individual files - opendir(SUB,"$basedir/$dir"); - @subdirs = readdir(SUB); - closedir(SUB); - - ### Process files in each sub directory - foreach $sub(@subdirs) { - - ### Once again, process all files but those that are hidden - unless($sub =~ /^\./) { - - ### Open the files - open(SUB,"$basedir/$dir/$sub"); - - ### Search through the contents of the file - while($line = ) { - chop($line); - ### Grab the name - if($line =~ /^Name=/) { - $pname = $line; - $pname =~ s/Name=//; - } - ### Grab the command - if($line =~ /^Exec=/) { - $pargs = $line; - $pargs =~ s/Exec=//; - } - ### If Terminal=1, then we need to execute a term - if($line =~ /^Terminal=1$/) { - $pargs = "$term -T \"$pname\" -e $pargs"; - } - } - - close(SUB); - - ### Some error checking on the Name and Exec - if($pname eq "") { - $pname = $sub; - $pname =~ s/\.kdelnk//; - } - if($pargs eq "") { - $error = 1; - $pargs = $sub; - $pargs =~ s/\.kdelnk//; - print "WARNING:\n\tNo Exec for $pname, using $pargs\n"; - } - - ### Begin printing menu items - if($stdout) { - print "\t\t\t\"$pname\" EXEC $pargs\n"; - } else { - print MENUFILE "\t\t\t\"$pname\" EXEC $pargs\n"; - } - } - } - - ### Print the end of the sub menu - if($stdout) { - print "\t\t\"$dir\" END\n"; - } else { - print MENUFILE "\t\t\"$dir\" END\n"; - } - } - } - - ### Finish off the main menu entry - if($stdout) { - print "\t\"KDE Applications\" END\n"; - } else { - print MENUFILE "\t\"KDE Applications\" END\n"; - } - - unless($stdout) { - close(MENUFILE); - } - - ### Yaya! - if($errors) { - print "\n.. Finished. There were errors.\n"; - } -# else { -# print "\n.. Finished.\n"; -# } - - exit(0); } else { - ### Error out :/ - print "ERROR:\n\t$basedir not found\n\tTry another directory.\n"; - exit(0); + ### Error out :/ + print STDERR "ERROR:\n\t$basedir not found\n\tTry another directory.\n"; + exit(0); } -### -### End work :)) -### +# End of Main Iteration. + +### + Malcolm Cowe, 21/01/2001. + +### process_dir() works it's way through each file and directory in +### the tree and generates the menu output to be used by Window Maker. + +sub process_dir { + + my $OUT = @_[0]; + my $path = @_[1]; + my $item; + my @tld; + my ($gotLang, $gotDef, $gotExec); + my $inDesktop; + + ### tld == Top Level Directory. + opendir(TLD, $path) || return; + @tld = readdir(TLD); + closedir(TLD); + + foreach $item(@tld) { + $gotLang = 0; + $gotDef = 0; + $gotExec = 0; + $inDesktop = 0; + + ### Ignore hidden files and directories. + unless($item =~ /^\./) { + if (-d "$path/$item") { + print $OUT "\"$item\" MENU\n"; + process_dir($OUT, "$path/$item"); + print $OUT "\"$item\" END\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 = ) { + 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\[\]=/ && (!$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 + if($line =~ /^Exec=/ && !$gotExec) { + $pargs = $line; + $pargs =~ s/^Exec=//s; + # Strip off all command line options unless the + # application is "kfmclient". + if ($pargs !~ /^kfmclient/ + && $pargs !~ /^kcmshell/ + && $pargs !~ /^kdesu/){ + ($pargs) = split(/\s/, $pargs); + } + $gotExec = 1; + } + ### If Terminal=1, then we need to execute a term + if($line =~ /^Terminal=1$/) { + $pargs = "$term -T \"$pname\" -e $pargs"; + } + } + elsif ($line =~ /^\[Desktop\ Entry\]/ || + $line =~ /^\[KDE\ Desktop\ Entry\]/) { + $inDesktop = 1; + } + } + + close(SUB); + ### Begin printing menu items + print $OUT "\t\"$pname\" EXEC $pargs\n"; + } + } + } + + return; +} +### - Malcolm Cowe, 21/01/2001.