--------------------------------------------------------------------------- --- Class module for parsing an index.theme file -- -- @author Kazunobu Kuriyama -- @copyright 2015 Kazunobu Kuriyama -- @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 table cls Metatable that will be used. Should always be `index_theme.mt`. -- @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 function index_theme:get_per_directory_keys(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