4 Freedesktop.org compliant desktop entries and menu
8 Licensed under GNU General Public License v2
9 * (c) 2016, Luke Bonham
10 * (c) 2014, Harvey Mittens
14 local awful_menu = require("awful.menu")
15 local menu_gen = require("menubar.menu_gen")
16 local menu_utils = require("menubar.utils")
17 local icon_theme = require("menubar.icon_theme")
19 local io, pairs, string, table, os = io, pairs, string, table, os
21 -- Add support for NixOS systems too
22 table.insert(menu_gen.all_menu_dirs, string.format("%s/.nix-profile/share/applications", os.getenv("HOME")))
24 -- Expecting a wm_name of awesome omits too many applications and tools
25 menu_utils.wm_name = ""
31 -- Determines if a path points to a directory, by checking if it can be read
32 -- (which is `nil` also for empty files) and if its size is not 0.
34 -- @param path the path to check
35 function menu.is_dir(path)
36 local f = io.open(path)
37 return f and not f:read(0) and f:seek("end") ~= 0 and f:close()
40 -- Remove non existent paths in order to avoid issues
41 local existent_paths = {}
42 for k,v in pairs(menu_gen.all_menu_dirs) do
43 if menu.is_dir(v) then
44 table.insert(existent_paths, v)
47 menu_gen.all_menu_dirs = existent_paths
49 -- Determines whether an table includes a certain element
50 -- @param tab a given table
51 -- @param val the element to search for
52 -- @return true if the given string is found within the search table; otherwise, false if not
53 function menu.has_value (tab, val)
54 for index, value in pairs(tab) do
55 if val:find(value) then
62 -- Use MenuBar parsing utils to build a menu for Awesome
64 function menu.build(args)
65 local args = args or {}
66 local icon_size = args.icon_size
67 local before = args.before or {}
68 local after = args.after or {}
69 local skip_items = args.skip_items or {}
70 local sub_menu = args.sub_menu or false
73 local _menu = awful_menu({ items = before })
75 menu_gen.generate(function(entries)
77 for k, v in pairs(menu_gen.all_categories) do
78 table.insert(result, { k, {}, v.icon })
82 for k, v in pairs(entries) do
83 for _, cat in pairs(result) do
84 if cat[1] == v.category then
85 if not menu.has_value(skip_items, v.name) then
86 table.insert(cat[2], { v.name, v.cmdline, v.icon })
93 -- Cleanup things a bit
94 for i = #result, 1, -1 do
97 -- Remove unused categories
98 table.remove(result, i)
100 --Sort entries alphabetically (by name)
101 table.sort(v[2], function (a, b) return string.byte(a[1]) < string.byte(b[1]) end)
102 -- Replace category name with nice name
103 v[1] = menu_gen.all_categories[v[1]].name
107 -- Sort categories alphabetically also
108 table.sort(result, function(a, b) return string.byte(a[1]) < string.byte(b[1]) end)
110 -- Add menu item to hold the generated menu
112 result = {{sub_menu, result}}
116 for _, v in pairs(result) do _menu:add(v) end
117 for _, v in pairs(after) do _menu:add(v) end
122 for _,v in pairs(menu_gen.all_categories) do
123 v.icon = icon_theme():find_icon_path(v.icon_name, icon_size)
127 -- Hold the menu in the module