My Awesome Config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
7.9KB

  1. -- Grab environment
  2. local io = io
  3. local os = os
  4. local table = table
  5. local type = type
  6. local ipairs = ipairs
  7. local pairs = pairs
  8. module("freedesktop.utils")
  9. terminal = 'xterm'
  10. icon_theme = nil
  11. all_icon_sizes = {
  12. '128x128',
  13. '96x96',
  14. '72x72',
  15. '64x64',
  16. '48x48',
  17. '36x36',
  18. '32x32',
  19. '24x24',
  20. '22x22',
  21. '16x16'
  22. }
  23. all_icon_types = {
  24. 'apps',
  25. 'actions',
  26. 'devices',
  27. 'places',
  28. 'categories',
  29. 'status',
  30. 'mimetypes'
  31. }
  32. all_icon_paths = { os.getenv("HOME") .. '/.icons/', '/usr/share/icons/' }
  33. icon_sizes = {}
  34. local mime_types = {}
  35. function get_lines(...)
  36. local f = io.popen(...)
  37. return function () -- iterator
  38. local data = f:read()
  39. if data == nil then f:close() end
  40. return data
  41. end
  42. end
  43. function file_exists(filename)
  44. local file = io.open(filename, 'r')
  45. local result = (file ~= nil)
  46. if result then
  47. file:close()
  48. end
  49. return result
  50. end
  51. function lookup_icon(arg)
  52. if arg.icon:sub(1, 1) == '/' and (arg.icon:find('.+%.png') or arg.icon:find('.+%.xpm')) then
  53. -- icons with absolute path and supported (AFAICT) formats
  54. return arg.icon
  55. else
  56. local icon_path = {}
  57. local icon_themes = {}
  58. local icon_theme_paths = {}
  59. if icon_theme and type(icon_theme) == 'table' then
  60. icon_themes = icon_theme
  61. elseif icon_theme then
  62. icon_themes = { icon_theme }
  63. end
  64. for i, theme in ipairs(icon_themes) do
  65. for j, path in ipairs(all_icon_paths) do
  66. table.insert(icon_theme_paths, path .. theme .. '/')
  67. end
  68. -- TODO also look in parent icon themes, as in freedesktop.org specification
  69. end
  70. table.insert(icon_theme_paths, '/usr/share/icons/hicolor/') -- fallback theme cf spec
  71. local isizes = icon_sizes
  72. for i, sz in ipairs(all_icon_sizes) do
  73. table.insert(isizes, sz)
  74. end
  75. for i, icon_theme_directory in ipairs(icon_theme_paths) do
  76. for j, size in ipairs(arg.icon_sizes or isizes) do
  77. for k, icon_type in ipairs(all_icon_types) do
  78. table.insert(icon_path, icon_theme_directory .. size .. '/' .. icon_type .. '/')
  79. end
  80. end
  81. end
  82. -- lowest priority fallbacks
  83. table.insert(icon_path, '/usr/share/pixmaps/')
  84. table.insert(icon_path, '/usr/share/icons/')
  85. table.insert(icon_path, '/usr/share/app-install/icons/')
  86. for i, directory in ipairs(icon_path) do
  87. if (arg.icon:find('.+%.png') or arg.icon:find('.+%.xpm')) and file_exists(directory .. arg.icon) then
  88. return directory .. arg.icon
  89. elseif file_exists(directory .. arg.icon .. '.png') then
  90. return directory .. arg.icon .. '.png'
  91. elseif file_exists(directory .. arg.icon .. '.xpm') then
  92. return directory .. arg.icon .. '.xpm'
  93. end
  94. end
  95. end
  96. end
  97. function lookup_file_icon(arg)
  98. load_mime_types()
  99. local extension = arg.filename:match('%a+$')
  100. local mime = mime_types[extension] or ''
  101. local mime_family = mime:match('^%a+') or ''
  102. -- possible icons in a typical gnome theme (i.e. Tango icons)
  103. local possible_filenames = {
  104. mime,
  105. 'gnome-mime-' .. mime,
  106. mime_family,
  107. 'gnome-mime-' .. mime_family,
  108. extension
  109. }
  110. for i, filename in ipairs(possible_filenames) do
  111. local icon = lookup_icon({icon = filename, icon_sizes = (arg.icon_sizes or all_icon_sizes)})
  112. if icon then
  113. return icon
  114. end
  115. end
  116. -- If we don't find ad icon, then pretend is a plain text file
  117. return lookup_icon({ icon = 'txt', icon_sizes = arg.icon_sizes or all_icon_sizes })
  118. end
  119. --- Load system MIME types
  120. -- @return A table with file extension <--> MIME type mapping
  121. function load_mime_types()
  122. if #mime_types == 0 then
  123. for line in io.lines('/etc/mime.types') do
  124. if not line:find('^#') then
  125. local parsed = {}
  126. for w in line:gmatch('[^%s]+') do
  127. table.insert(parsed, w)
  128. end
  129. if #parsed > 1 then
  130. for i = 2, #parsed do
  131. mime_types[parsed[i]] = parsed[1]:gsub('/', '-')
  132. end
  133. end
  134. end
  135. end
  136. end
  137. end
  138. --- Parse a .desktop file
  139. -- @param file The .desktop file
  140. -- @param requested_icon_sizes A list of icon sizes (optional). If this list is given, it will be used as a priority list for icon sizes when looking up for icons. If you want large icons, for example, you can put '128x128' as the first item in the list.
  141. -- @return A table with file entries.
  142. function parse_desktop_file(arg)
  143. local program = { show = true, file = arg.file }
  144. for line in io.lines(arg.file) do
  145. for key, value in line:gmatch("(%w+)=(.+)") do
  146. program[key] = value
  147. end
  148. end
  149. -- Don't show the program if NoDisplay is true
  150. -- Only show the program if there is not OnlyShowIn attribute
  151. -- or if it's equal to 'awesome'
  152. if program.NoDisplay == "true" or program.OnlyShowIn ~= nil and program.OnlyShowIn ~= "awesome" then
  153. program.show = false
  154. end
  155. -- Look up for a icon.
  156. if program.Icon then
  157. program.icon_path = lookup_icon({ icon = program.Icon, icon_sizes = (arg.icon_sizes or all_icon_sizes) })
  158. if program.icon_path ~= nil and not file_exists(program.icon_path) then
  159. program.icon_path = nil
  160. end
  161. end
  162. -- Split categories into a table.
  163. if program.Categories then
  164. program.categories = {}
  165. for category in program.Categories:gmatch('[^;]+') do
  166. table.insert(program.categories, category)
  167. end
  168. end
  169. if program.Exec then
  170. if program.Name == nil then
  171. program.Name = ""
  172. end
  173. local cmdline = program.Exec:gsub('%%c', program.Name)
  174. cmdline = cmdline:gsub('%%[fmuFMU]', '')
  175. cmdline = cmdline:gsub('%%k', program.file)
  176. if program.icon_path then
  177. cmdline = cmdline:gsub('%%i', '--icon ' .. program.icon_path)
  178. else
  179. cmdline = cmdline:gsub('%%i', '')
  180. end
  181. if program.Terminal == "true" then
  182. cmdline = terminal .. ' -e ' .. cmdline
  183. end
  184. program.cmdline = cmdline
  185. end
  186. return program
  187. end
  188. --- Parse a directory with .desktop files
  189. -- @param dir The directory.
  190. -- @param icons_size, The icons sizes, optional.
  191. -- @return A table with all .desktop entries.
  192. function parse_desktop_files(arg)
  193. local programs = {}
  194. local files = get_lines('find '.. arg.dir ..' -name "*.desktop" 2>/dev/null')
  195. for file in files do
  196. arg.file = file
  197. table.insert(programs, parse_desktop_file(arg))
  198. end
  199. return programs
  200. end
  201. --- Parse a directory files and subdirs
  202. -- @param dir The directory.
  203. -- @param icons_size, The icons sizes, optional.
  204. -- @return A table with all .desktop entries.
  205. function parse_dirs_and_files(arg)
  206. local files = {}
  207. local paths = get_lines('find '..arg.dir..' -maxdepth 1 -type d')
  208. for path in paths do
  209. if path:match("[^/]+$") then
  210. local file = {}
  211. file.filename = path:match("[^/]+$")
  212. file.path = path
  213. file.show = true
  214. file.icon = lookup_icon({ icon = "folder", icon_sizes = (arg.icon_sizes or all_icon_sizes) })
  215. table.insert(files, file)
  216. end
  217. end
  218. local paths = get_lines('find '..arg.dir..' -maxdepth 1 -type f')
  219. for path in paths do
  220. if not path:find("%.desktop$") then
  221. local file = {}
  222. file.filename = path:match("[^/]+$")
  223. file.path = path
  224. file.show = true
  225. file.icon = lookup_file_icon({ filename = file.filename, icon_sizes = (arg.icon_sizes or all_icon_sizes) })
  226. table.insert(files, file)
  227. end
  228. end
  229. return files
  230. end