# No dependencies except for perl ≥ v5.10
use strict;
-use warnings;
+use warnings qw(FATAL utf8);
use Data::Dumper;
use IPC::Open2;
use POSIX qw(locale_h);
use Pod::Usage;
use v5.10;
use utf8;
-use open ':encoding(utf8)';
+use open ':encoding(UTF-8)';
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
# reads in a whole file
sub slurp {
- open(my $fh, '<', shift) or die "$!";
+ my ($filename) = @_;
+ open(my $fh, '<', $filename) or die "$!";
local $/;
- <$fh>;
+ my $result;
+ eval {
+ $result = <$fh>;
+ };
+ if ($@) {
+ warn "Could not read $filename: $@";
+ return undef;
+ } else {
+ return $result;
+ }
}
my $entry_type = 'both';
'dmenu=s' => \$dmenu_cmd,
'entry-type=s' => \$entry_type,
'version' => sub {
- say "dmenu-desktop 1.2 © 2012 Michael Stapelberg";
+ say "dmenu-desktop 1.3 © 2012 Michael Stapelberg";
exit 0;
},
'help' => sub {
# Extract all “Name” and “Exec” keys from the [Desktop Entry] group
# and store them in $apps{$base}.
my %names;
- my @lines = split("\n", slurp($file));
+ my $content = slurp($file);
+ next unless defined($content);
+ my @lines = split("\n", $content);
for my $line (@lines) {
my $first = substr($line, 0, 1);
next if $line eq '' || $first eq '#';
next if (!exists($apps{$app}->{Type}) ||
$apps{$app}->{Type} ne 'Application');
+ # Skip broken files (Type=application, but no Exec key).
+ if (!exists($apps{$app}->{Exec}) ||
+ $apps{$app}->{Exec} eq '') {
+ warn 'File ' . $apps{$app}->{_Location} . ' is broken: it contains Type=Application, but no Exec key/value pair.';
+ next;
+ }
+
# Don’t offer apps which have NoDisplay == true or Hidden == true.
# See http://wiki.xfce.org/howto/customize-menu#hide_menu_entries
# for the difference between NoDisplay and Hidden.
if ($entry_type eq 'command' || $entry_type eq 'both') {
my ($command) = split(' ', $apps{$app}->{Exec});
+
+ # Don’t add “geany” if “Geany” is already present.
+ my @keys = map { lc } keys %choices;
+ next if lc(basename($command)) ~~ @keys;
+
$choices{basename($command)} = $app;
}
}
exit $status unless $status == 0;
my $choice = <$dmenu_out>;
+# dmenu ≥ 4.4 adds a newline after the choice
+chomp($choice);
my $app;
# Exact match: the user chose “Avidemux (GTK+)”
if (exists($choices{$choice})) {
=head1 VERSION
-Version 1.2
+Version 1.3
=head1 AUTHOR