You are not logged in.

#1 2008-09-14 05:13:53

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,963
Website

.desktop file parser mostly for Openbox

This is just a simple script to help configure the Openbox menu. When run without any options, it will read the *.desktop files under /usr/share/applications/ and print out some information about each file that you can use to create menu entries (name, comment, command, categories, and terminal (boolean)).

If you pass it "-c", it will compare the .desktop file commands against a list of all commands found in your Openbox menu. It will then print a list of commands that were similar but not identical followed by information for all the .desktop files for which no corresponding command was found in the Openbox menu. All identical commands are skipped.

This should make it easy to find files that would have been automatically added to the menu in common DEs. I wrote it after I discovered the zenmap.desktop file on my system while testing lxpanel and realized that I had nothing to keep track of new desktop files.

This will NOT change any files on your system. All it does is print information to the console.



Replace "terminal -x" on the line

my $terminal_command = 'terminal -x ';

with whatever command you use to run terminal applications. Leave the trailing space.


#!/usr/bin/perl
use strict;
use warnings;

my $path_to_desktop_files = '/usr/share/applications/';
my $path_to_openbox_menu = $ENV{HOME}.'/.config/openbox/menu.xml';
my $terminal_command = 'terminal -x ';

my @commands;
my $comparing = 0;
my $possible_matches = '';
my $unmatched = '';

my $args = "@ARGV";
if ($args =~ m/-c/)
{
    $comparing = 1;
    open (my $fh, '<', $path_to_openbox_menu) or die "Unable to open $path_to_openbox_menu\n";
    while (defined(my $line = <$fh>))
    {
        if ($line =~ m/<command>(.+?)<\/command>/i)
        {
            push @commands,$1;
        }
    }
    close $fh;
}


opendir(my $dh,$path_to_desktop_files) or die "Unable to open $path_to_desktop_files: $!\n";
foreach my $file (readdir($dh))
{
    if ($file =~ m/\.desktop$/i)
    {
        &parse_desktop_file($path_to_desktop_files.$file);
    }
}
close $dh;

sub parse_desktop_file
{
    my ($file_path) = @_;
    my ($name,$command,$comment,$categories,$terminal);
    open (my $fh, '<',$file_path) or die "Unable to open $file_path: $!\n";
    while (defined(my $line=<$fh>))
    {
        $name = $1 if ($line =~ m/Name=(.+)\n/i);
        $command = $1 if ($line =~ m/Exec=(.+)\n/i);
        $comment = $1 if ($line =~ m/Comment=(.+)\n/i);
        $categories = $1 if ($line =~ m/Categories=(.+)\n/i);
        $terminal = $1 if ($line =~ m/Terminal=(.+)\n/i);
    }
    close $fh;

    my $already_in_menu = 0;
    if ($comparing)
    {
        my $base_command =  ( ($command =~ m/([^\/\s]+?)(?:\s|$)/) ? $1 : $command);
        my $similar_commands = '';
        foreach my $cmd (@commands)
        {
            my $base_cmd = ( ($cmd =~ m/(?:\Q$terminal_command\E)?([^\/\s]+?)(?:\s|$)/) ? $1 : $cmd );
            if ($base_command eq $base_cmd)
            {
                $already_in_menu = 1;
                if ($cmd ne $command)
                {
                    $similar_commands .= "$cmd\n";
                }
            }
        }
        if (length($similar_commands)>0)
        {
            $possible_matches .= "$command\n--------------------\n$similar_commands\n\n";
        }
    }

    if (!$comparing or !$already_in_menu)
    {
        $unmatched .= "Desktop file: $file_path\n";
        $unmatched .= "name:         $name\n" if defined($name);
        $unmatched .= "command:      $command\n" if defined($command);
        $unmatched .= "comment:      $comment\n" if defined($comment);
        $unmatched .= "categories:   $categories\n" if defined($categories);
        $unmatched .= "terminal:     $terminal\n" if defined($terminal);
        $unmatched .= "\n";
    }
}

if (length($possible_matches)>0)
{
    print "DESKTOP FILE COMMANDS FOLLOWED BY SIMILAR OB MENU COMMANDS\n\n$possible_matches\n"; 
}
if (length($unmatched)>0)
{
    print "UNMATCHED DESKTOP FILE COMMANDS\n\n" if $comparing;
    print "$unmatched\n";
}

My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#2 2008-09-14 08:43:27

bluewind
Administrator
From: Austria
Registered: 2008-07-13
Posts: 172
Website

Re: .desktop file parser mostly for Openbox

obm-xdg, which comes with obmenu, already generates the gnome menu entries for openbox.
http://wiki.archlinux.org/index.php/Openbox#obm-xdg

Once set up you always find the currently installed desktop files in the menu. You don't have to reconfigure to see changes.

Offline

#3 2008-09-14 16:22:19

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,963
Website

Re: .desktop file parser mostly for Openbox

From the wiki:
"NOTE: If you do not have GNOME installed, then you need to install gnome-menus package for obm-xdg to work."

Also, that just generates the submenu which you could only edit through editing the desktop files (unless I missed something). It does not integrate into the pre-existing menu heirarchy which will be highly customized for many (most?) Openbox users. The purpose of this script is to provide information for them to help edit their menu.

I had (re-)installed obmenu to check for this functionality before I wrote the script though but didn't see obm-xdg, so thanks for pointing it out. Still, I see it as having quite different functionality. Maybe others will too.


My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#4 2008-09-24 20:07:25

Daenyth
Forum Fellow
From: Boston, MA
Registered: 2008-02-24
Posts: 1,244

Re: .desktop file parser mostly for Openbox

Xyne I love you. maybe I will try to help you work this for fluxbox.

Offline

#5 2008-09-26 01:53:05

Xyne
Administrator/PM
Registered: 2008-08-03
Posts: 6,963
Website

Re: .desktop file parser mostly for Openbox

*feels the love*

I restructured the code a bit (see below) to make it easier to add support for fluxbox comparison (and anything else). All you would need to do is write a sub that can load the commands found in the fluxbox menu into the array.

(although it goes without saying, of course I'll give you credit in the OP and the eventual PKGBUILD (and anyone else who contributes a loader for some other WM/DE menu commands))

#!/usr/bin/perl
use strict;
use warnings;

my $path_to_desktop_files = '/usr/share/applications/';
my $path_to_openbox_menu = $ENV{HOME}.'/.config/openbox/menu.xml';
my $terminal_command = 'terminal -x ';

my @known_commands;
my $comparing = 0;
my $possible_matches = '';
my $unmatched = '';

my $args = "@ARGV";
if ($args =~ m/-(?:c|-compare) (\S+)/)
{
    my $compare_to = lc($1);
    $comparing = 1;
    if ($compare_to eq 'openbox')
    {
        &load_openbox_menu_commands;
    }
    elsif ($compare_to eq 'fluxbox')
    {
        die "No comparison mode for fluxbox (yet).\n";
    }
    else
    {
        die "No comparison mode for $compare_to\n";
    }

}



opendir(my $dh,$path_to_desktop_files) or die "Unable to open $path_to_desktop_files: $!\n";
foreach my $file (readdir($dh))
{
    if ($file =~ m/\.desktop$/i)
    {
        &parse_desktop_file($path_to_desktop_files.$file);
    }
}
close $dh;

sub parse_desktop_file
{
    my ($file_path) = @_;
    my ($name,$command,$comment,$categories,$terminal);
    open (my $fh, '<',$file_path) or die "Unable to open $file_path: $!\n";
    while (defined(my $line=<$fh>))
    {
        $name = $1 if ($line =~ m/Name=(.+)\n/i);
        $command = $1 if ($line =~ m/Exec=(.+)\n/i);
        $comment = $1 if ($line =~ m/Comment=(.+)\n/i);
        $categories = $1 if ($line =~ m/Categories=(.+)\n/i);
        $terminal = $1 if ($line =~ m/Terminal=(.+)\n/i);
    }
    close $fh;

    my $already_in_menu = 0;
    if ($comparing)
    {
        my $base_command =  ( ($command =~ m/([^\/\s]+?)(?:\s|$)/) ? $1 : $command);
        my $similar_commands = '';
        foreach my $known_cmd (@known_commands)
        {
            my $known_base_cmd = ( ($known_cmd =~ m/(?:\Q$terminal_command\E)?([^\/\s]+?)(?:\s|$)/) ? $1 : $known_cmd );
            if ($base_command eq $known_base_cmd)
            {
                $already_in_menu = 1;
                if ($known_cmd ne $command)
                {
                    $similar_commands .= "$known_cmd\n";
                }
            }
        }
        if (length($similar_commands)>0)
        {
            $possible_matches .= "$command\n--------------------\n$similar_commands\n\n";
        }
    }

    if (!$comparing or !$already_in_menu)
    {
        $unmatched .= "Desktop file: $file_path\n";
        $unmatched .= "name:         $name\n" if defined($name);
        $unmatched .= "command:      $command\n" if defined($command);
        $unmatched .= "comment:      $comment\n" if defined($comment);
        $unmatched .= "categories:   $categories\n" if defined($categories);
        $unmatched .= "terminal:     $terminal\n" if defined($terminal);
        $unmatched .= "\n";
    }
}

if (length($possible_matches)>0)
{
    print "DESKTOP FILE COMMANDS FOLLOWED BY SIMILAR OB MENU COMMANDS\n\n$possible_matches\n"; 
}
if (length($unmatched)>0)
{
    print "UNMATCHED DESKTOP FILE COMMANDS\n\n" if $comparing;
    print "$unmatched\n";
}

sub load_openbox_menu_commands
{
    open (my $fh, '<', $path_to_openbox_menu) or die "Unable to open $path_to_openbox_menu\n";
    while (defined(my $line = <$fh>))
    {
        if ($line =~ m/<command>(.+?)<\/command>/i)
        {
            push @known_commands,$1;
        }
    }
    close $fh;
}

My Arch Linux StuffForum EtiquetteCommunity Ethos - Arch is not for everyone

Offline

#6 2008-09-28 03:58:33

Daenyth
Forum Fellow
From: Boston, MA
Registered: 2008-02-24
Posts: 1,244

Re: .desktop file parser mostly for Openbox

Unfortunately I don't have time to work on this at the moment, but thanks for refactoring. Added to my exponentially-growing todo list...

Offline

Board footer

Powered by FluxBB