From e88f1e873594bff1cd2894cac47f3d70f0442a79 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 15 Nov 2017 15:02:25 +0100 Subject: [PATCH 1/2] menubar.utils.parse_desktop_file: Use GKeyFile This replaces our own, hand-written parser of desktop files with the one that GLib provides. No functional changes intended. Signed-off-by: Uli Schlachter --- lib/menubar/utils.lua | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/lib/menubar/utils.lua b/lib/menubar/utils.lua index a6a8579b..8f7c69f1 100644 --- a/lib/menubar/utils.lua +++ b/lib/menubar/utils.lua @@ -7,7 +7,6 @@ --------------------------------------------------------------------------- -- Grab environment -local io = io local table = table local ipairs = ipairs local string = string @@ -260,36 +259,26 @@ end -- @return A table with file entries. function utils.parse_desktop_file(file) local program = { show = true, file = file } - local desktop_entry = false -- Parse the .desktop file. -- We are interested in [Desktop Entry] group only. - for line in io.lines(file) do - line = utils.rtrim(line) - if line:find("^%s*#") then - -- Skip comments. - (function() end)() -- I haven't found a nice way to silence luacheck here - elseif not desktop_entry and line == "[Desktop Entry]" then - desktop_entry = true - else - if line:sub(1, 1) == "[" and line:sub(-1) == "]" then - -- A declaration of new group - stop parsing - break - end - - -- Grab the values - for key, value in line:gmatch("(%w+)%s*=%s*(.+)") do - if list_keys[key] then - program[key] = utils.parse_list(value) - else - program[key] = utils.unescape(value) - end - end - end + local keyfile = glib.KeyFile() + if not keyfile:load_from_file(file, glib.KeyFileFlags.NONE) then + return nil end -- In case [Desktop Entry] was not found - if not desktop_entry then return nil end + if not keyfile:has_group("Desktop Entry") then + return nil + end + + for _, key in pairs(keyfile:get_keys("Desktop Entry")) do + if list_keys[key] then + program[key] = keyfile:get_string_list("Desktop Entry", key) + else + program[key] = keyfile:get_string("Desktop Entry", key) + end + end -- In case the (required) 'Name' entry was not found if not program.Name or program.Name == '' then return nil end From 5d21e85bfbc6ee80a4ec7cfe129d9baa7845db0c Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 15 Nov 2017 15:21:22 +0100 Subject: [PATCH 2/2] menubar.utils.parse_desktop_file: Improve type handling This is a slight API break, but should not cause many problems for people. This makes parse_desktop_file() handle the type of keys correctly, so that e.g. booleans are actually parsed as booleans. Also, locale-sensitive entries are now looked up in a way that obeys the current locale. Signed-off-by: Uli Schlachter --- lib/menubar/utils.lua | 64 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/lib/menubar/utils.lua b/lib/menubar/utils.lua index 8f7c69f1..49a6225b 100644 --- a/lib/menubar/utils.lua +++ b/lib/menubar/utils.lua @@ -50,12 +50,53 @@ local escape_sequences = { [ [[\t]] ] = '\t', } ---- The keys in desktop entries whose values are lists of strings. -local list_keys = { - Categories = true, - OnlyShowIn = true, - NotShowIn = true, -} +-- Maps keys in desktop entries to suitable getter function. +-- The order of entries is as in the spec. +-- https://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html +local keys_getters +do + local function get_string(kf, key) + return kf:get_string("Desktop Entry", key) + end + local function get_strings(kf, key) + return kf:get_string_list("Desktop Entry", key, nil) + end + local function get_localestring(kf, key) + return kf:get_locale_string("Desktop Entry", key, nil) + end + local function get_localestrings(kf, key) + return kf:get_locale_string_list("Desktop Entry", key, nil, nil) + end + local function get_boolean(kf, key) + return kf:get_boolean("Desktop Entry", key) + end + + keys_getters = { + Type = get_string, + Version = get_string, + Name = get_localestring, + GenericName = get_localestring, + NoDisplay = get_boolean, + Comment = get_localestring, + Icon = get_localestring, + Hidden = get_boolean, + OnlyShowIn = get_strings, + NotShowIn = get_strings, + DBusActivatable = get_boolean, + TryExec = get_string, + Exec = get_string, + Path = get_string, + Terminal = get_boolean, + Actions = get_strings, + MimeType = get_strings, + Categories = get_strings, + Implements = get_strings, + Keywords = get_localestrings, + StartupNotify = get_boolean, + StartupWMClass = get_string, + URL = get_string, + } +end -- Private section @@ -273,18 +314,17 @@ function utils.parse_desktop_file(file) end for _, key in pairs(keyfile:get_keys("Desktop Entry")) do - if list_keys[key] then - program[key] = keyfile:get_string_list("Desktop Entry", key) - else - program[key] = keyfile:get_string("Desktop Entry", key) + local getter = keys_getters[key] or function(kf, k) + return kf:get_string("Desktop Entry", k) end + program[key] = getter(keyfile, key) end -- In case the (required) 'Name' entry was not found if not program.Name or program.Name == '' then return nil end - -- Don't show program if NoDisplay attribute is false - if program.NoDisplay and string.lower(program.NoDisplay) == "true" then + -- Don't show program if NoDisplay attribute is true + if program.NoDisplay then program.show = false else -- Only check these values is NoDisplay is true (or non-existent)