/X/awesome/delightful/utils.lua

https://bitbucket.org/dbellavista/linux-stuff · Lua · 264 lines · 220 code · 18 blank · 26 comment · 75 complexity · 9059653d121fd46ce0003dbd4ae00e23 MD5 · raw file

  1. -------------------------------------------------------------------------------
  2. --
  3. -- Common utility routines for Delightful widgets for Awesome 3.4
  4. -- Copyright (C) 2011 Tuomas Jormola <tj@solitudo.net>
  5. --
  6. -- Licensed under the terms of GNU General Public License Version 2.0.
  7. --
  8. -------------------------------------------------------------------------------
  9. local awful_util = require('awful.util')
  10. local beautiful = require('beautiful')
  11. local freedesktop_utils = require('freedesktop.utils')
  12. local pairs = pairs
  13. local print = print
  14. local string = { format = string.format }
  15. local table = { insert = table.insert }
  16. local tostring = tostring
  17. local type = type
  18. module('delightful.utils')
  19. -- get configuration with defaults applied
  20. function get_empty_config(config_description)
  21. local empty_config = {}
  22. for config_id, config_description_entry in pairs(config_description) do
  23. local config_key = config_description_entry.name
  24. empty_config[config_key] =
  25. evaluate_config_value(config_description_entry.default,
  26. empty_config, config_description_entry.coerce)
  27. end
  28. return empty_config
  29. end
  30. -- fully evaluate given configuration against description
  31. function normalize_config(config_data, config_description)
  32. for config_id, config_description_entry in pairs(config_description) do
  33. local config_key = config_description_entry.name
  34. local config_value
  35. if config_data[config_key] == nil then
  36. config_value = config_description_entry.default
  37. else
  38. config_value = config_data[config_key]
  39. end
  40. config_data[config_key] =
  41. evaluate_config_value(config_value,
  42. config_data,
  43. config_description_entry.coerce)
  44. end
  45. return config_data
  46. end
  47. -- evaluate a configuration value
  48. function evaluate_config_value(value, data, coerce)
  49. if type(value) == 'function' then
  50. value = value(data)
  51. end
  52. if coerce then
  53. value = coerce(value)
  54. end
  55. if value ~= nil and type(value) == 'string' and #value < 1 then
  56. value = nil
  57. elseif value ~= nil and type(value) == 'table' then
  58. local elemnum = 0
  59. for _ in pairs(value) do
  60. elemnum = elemnum + 1
  61. end
  62. if elemnum == 0 then
  63. value = nil
  64. end
  65. end
  66. return value
  67. end
  68. -- validate configuration against description
  69. function validate_config(config_data, config_description)
  70. local validation_errors = {}
  71. -- check required options
  72. for config_id, config_description_entry in pairs(config_description) do
  73. local config_key = config_description_entry.name
  74. if config_description_entry.required and config_data[config_key] == nil then
  75. table.insert(validation_errors,
  76. string.format('Required configuration option missing or empty: %s', config_key))
  77. end
  78. end
  79. -- validate options
  80. for config_id, config_description_entry in pairs(config_description) do
  81. local config_key = config_description_entry.name
  82. if config_description_entry.validate and config_data[config_key] ~= nil then
  83. local is_valid, error_string = config_description_entry.validate(config_data[config_key])
  84. if not is_valid then
  85. table.insert(validation_errors,
  86. string.format('Invalid configuration option "%s": %s', config_key, error_string))
  87. end
  88. end
  89. end
  90. -- check unknown options
  91. for config_key, config_value in pairs(config_data) do
  92. local description_found = false
  93. for config_id, config_description_entry in pairs(config_description) do
  94. if config_key == config_description_entry.name then
  95. description_found = true
  96. break
  97. end
  98. end
  99. if not description_found then
  100. table.insert(validation_errors,
  101. string.format('Unknown configuration option: %s', config_key))
  102. end
  103. end
  104. return #validation_errors > 0 and validation_errors
  105. end
  106. -- return a string from validation errors
  107. function format_validation_errors(validation_errors)
  108. local error_string = ''
  109. for error_index, error_entry in pairs(validation_errors) do
  110. error_string = string.format('%s%s', error_string, error_entry)
  111. if error_index < #validation_errors then
  112. error_string = string.format('%s\n', error_string)
  113. end
  114. end
  115. return error_string
  116. end
  117. -- configuration validators
  118. function config_string(value)
  119. if type(value) ~= 'string' then
  120. return false, 'must be a string'
  121. end
  122. return true
  123. end
  124. function config_table(value)
  125. if type(value) ~= 'table' then
  126. return false, 'must be a table'
  127. end
  128. return true
  129. end
  130. function config_int(value)
  131. if type(value) ~= 'number' then
  132. return false, 'must be an integer'
  133. end
  134. if not tostring(value):find('^-?%d+$') then
  135. return false, 'must be an integer'
  136. end
  137. return true
  138. end
  139. function config_number(value)
  140. if type(value) ~= 'number' then
  141. return false, 'must be a number'
  142. end
  143. if not tostring(value):find('^-?%d+%.?%d*$') then
  144. return false, 'must be a number'
  145. end
  146. return true
  147. end
  148. function config_boolean(value)
  149. if type(value) ~= 'boolean' then
  150. return false, 'must be true or false'
  151. end
  152. return true
  153. end
  154. function config_file(value)
  155. if type(value) ~= 'string' then
  156. return false, 'invalid file name'
  157. end
  158. if not awful_util.file_readable(value) then
  159. return false, 'file not readable'
  160. end
  161. return true
  162. end
  163. -- type coersions
  164. function coerce_table(value)
  165. if value == nil or type(value) == 'table' then
  166. return value
  167. else
  168. return { value }
  169. end
  170. end
  171. -- return the full paths to icon files using the description
  172. function find_icon_files(icon_description)
  173. if not icon_description then
  174. return
  175. end
  176. -- Ensure GNOME icon theme is available
  177. local previous_icon_theme = freedesktop_utils.icon_theme
  178. local have_gnome_icon_theme = false
  179. if freedesktop_utils.icon_theme then
  180. have_gnome_icon_theme = freedesktop_utils.icon_theme == 'gnome'
  181. end
  182. if not have_gnome_icon_theme then
  183. freedesktop_utils.icon_theme = 'gnome'
  184. end
  185. -- Load icons
  186. local icon_files = {}
  187. for name, info in pairs(icon_description) do
  188. -- try icon defined in the Awesome theme
  189. if beautiful[info.beautiful_name] then
  190. icon_files[name] = beautiful[info.beautiful_name]
  191. end
  192. -- if no icon in the theme, try default
  193. if not icon_files[name] and info.default_icon then
  194. local default_icon
  195. if type(info.default_icon) == 'function' then
  196. default_icon = info.default_icon()
  197. else
  198. default_icon = info.default_icon
  199. end
  200. icon_files[name] = freedesktop_utils.lookup_icon({ icon = default_icon })
  201. end
  202. end
  203. if not have_gnome_icon_theme then
  204. freedesktop_utils.icon_theme = previous_icon_theme
  205. end
  206. return icon_files
  207. end
  208. -- check if the given colors are defined in the Awesome theme
  209. function find_theme_color(colors)
  210. if type(colors) ~= 'table' then
  211. colors = { colors }
  212. end
  213. for _, theme_color_key in pairs(colors) do
  214. if beautiful[theme_color_key] then
  215. return beautiful[theme_color_key]
  216. end
  217. end
  218. return
  219. end
  220. -- pad a string with spaces
  221. function pad_string_with_spaces(s, width)
  222. if not width then
  223. return s
  224. end
  225. if not s then
  226. s = ''
  227. end
  228. local s_head = s:sub(1, width)
  229. local space = ' '
  230. return string.format('%s%s', awful_util.escape(s_head), space:rep(width - #s_head))
  231. end
  232. -- print an error message
  233. function print_error(ident, error_string)
  234. if not ident then
  235. return
  236. end
  237. if not error_string then
  238. error_string = ident
  239. ident = nil
  240. end
  241. local text = ''
  242. if ident then
  243. text = string.format('[%s] ', ident)
  244. end
  245. print(string.format('%s%s', text, error_string))
  246. end