awesome/lib/menubar/index_theme.lua
Kazunobu Kuriyama 9ae945c931 Enhance menubar icon path lookup
The way of icon path lookup for `menubar` is enhanced so that it is
based on a theme-oriented way as described in the specification:

  Icon Theme Specification, Ver. 0.12
  http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html

To accomplish this:

 * Add the two new files `icon_theme.lua` and `index_theme.lua`.

   The former implements an icon lookup algorithm suggested in the URL
   above.  The latter implements a helper object to parse the cache file
   `index.theme` of which data is used by the former.

 * Modify `menu_gen.lua` to use the new algorithm.

   - The implementation of `lookup_category_icons` is changed
     accordingly.
   - The values of the field `all_categories.icon_name` are changed file
     names to icon names, i.e., file extensions which are used to
     indicate image file formats are removed.

 * Add the new file `icon_theme_spec.lua` for a unit test for checking
   if `icon_theme.lua` together with `index_theme.lua` works as
   expected.
2015-09-26 11:45:38 +09:00

164 lines
5.3 KiB
Lua

---------------------------------------------------------------------------
--- Class module for parsing an index.theme file
--
-- @author Kazunobu Kuriyama
-- @copyright 2015 Kazunobu Kuriyama
-- @release @AWESOME_VERSION@
-- @classmod menubar.index_theme
---------------------------------------------------------------------------
-- This implementation is based on the specifications:
-- Icon Theme Specification 0.12
-- http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.12.html
local ipairs = ipairs
local setmetatable = setmetatable
local string = string
local table = table
local io = io
-- index.theme groups
local ICON_THEME = "Icon Theme"
-- index.theme keys
local DIRECTORIES = "Directories"
local INHERITS = "Inherits"
-- per-directory subkeys
local TYPE = "Type"
local SIZE = "Size"
local MINSIZE = "MinSize"
local MAXSIZE = "MaxSize"
local THRESHOLD = "Threshold"
local index_theme = { mt = {} }
--- Class constructor of `index_theme`
-- @tparam string icon_theme_name Internal name of icon theme
-- @tparam table base_directories Paths used for lookup
-- @treturn table An instance of the class `index_theme`
index_theme.new = function(cls, icon_theme_name, base_directories)
local self = {}
setmetatable(self, { __index = cls })
-- Initialize the fields
self.icon_theme_name = icon_theme_name
self.base_directory = nil
self[DIRECTORIES] = {}
self[INHERITS] = {}
self.per_directory_keys = {}
-- base_directory
local basedir = nil
local handler = nil
for _, dir in ipairs(base_directories) do
basedir = dir .. "/" .. self.icon_theme_name
handler = io.open(basedir .. "/index.theme", "r")
if handler then
-- Use the index.theme which is found first.
break
end
end
if not handler then
return self
end
self.base_directory = basedir
-- Parse index.theme.
while true do
local line = handler:read()
if not line then
break
end
local group_header = "^%[(.+)%]$"
local group = line:match(group_header)
if group then
if group == ICON_THEME then
while true do
local item = handler:read()
if not item then
break
end
if item:match(group_header) then
handler:seek("cur", -string.len(item) - 1)
break
end
local k, v = item:match("^(%w+)=(.*)$")
if k == DIRECTORIES or k == INHERITS then
string.gsub(v, "([^,]+),?", function(match)
table.insert(self[k], match)
end)
end
end
else
-- This must be a 'per-directory keys' group
local keys = {}
while true do
local item = handler:read()
if not item then
break
end
if item:match(group_header) then
handler:seek("cur", -string.len(item) - 1)
break
end
local k, v = item:match("^(%w+)=(%w+)$")
if k == SIZE or k == MINSIZE or k == MAXSIZE or k == THRESHOLD then
keys[k] = tonumber(v)
elseif k == TYPE then
keys[k] = v
end
end
-- Size is a must. Other keys are optional.
if keys[SIZE] then
-- Set unset keys to the default values.
if not keys[TYPE] then keys[TYPE] = THRESHOLD end
if not keys[MINSIZE] then keys[MINSIZE] = keys[SIZE] end
if not keys[MAXSIZE] then keys[MAXSIZE] = keys[SIZE] end
if not keys[THRESHOLD] then keys[THRESHOLD] = 2 end
self.per_directory_keys[group] = keys
end
end
end
end
handler:close()
return self
end
--- Table of the values of the `Directories` key
-- @treturn table Values of the `Directories` key
index_theme.get_subdirectories = function(self)
return self[DIRECTORIES]
end
--- Table of the values of the `Inherits` key
-- @treturn table Values of the `Inherits` key
index_theme.get_inherits = function(self)
return self[INHERITS]
end
--- Query (part of) per-directory keys of a given subdirectory name.
-- @tparam table subdirectory Icon theme's subdirectory
-- @treturn[1] string Value of the `Type` key
-- @treturn[2] number Value of the `Size` key
-- @treturn[3] number VAlue of the `MinSize` key
-- @treturn[4] number Value of the `MaxSize` key
-- @treturn[5] number Value of the `Threshold` key
index_theme.get_per_directory_keys = function(self, subdirectory)
local keys = self.per_directory_keys[subdirectory]
return keys[TYPE], keys[SIZE], keys[MINSIZE], keys[MAXSIZE], keys[THRESHOLD]
end
index_theme.mt.__call = function(cls, icon_theme_name, base_directories)
return index_theme.new(cls, icon_theme_name, base_directories)
end
return setmetatable(index_theme, index_theme.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80