Giant blob of minor changes
[dotfiles/.git] / .config / awesome / freedesktop / menu.lua
1 --[[
2
3      Awesome-Freedesktop
4      Freedesktop.org compliant desktop entries and menu
5
6      Menu section
7
8      Licensed under GNU General Public License v2
9       * (c) 2016, Luke Bonham
10       * (c) 2014, Harvey Mittens
11
12 --]]
13
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")
18
19 local io, pairs, string, table, os = io, pairs, string, table, os
20
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")))
23
24 -- Expecting a wm_name of awesome omits too many applications and tools
25 menu_utils.wm_name = ""
26
27 -- Menu
28 -- freedesktop.menu
29 local menu = {}
30
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.
33 -- @author blueyed
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()
38 end
39
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)
45     end
46 end
47 menu_gen.all_menu_dirs = existent_paths
48
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
56             return true
57         end
58     end
59     return false
60 end
61
62 -- Use MenuBar parsing utils to build a menu for Awesome
63 -- @return awful.menu
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
71
72     local result     = {}
73     local _menu      = awful_menu({ items = before })
74
75     menu_gen.generate(function(entries)
76         -- Add category icons
77         for k, v in pairs(menu_gen.all_categories) do
78             table.insert(result, { k, {}, v.icon })
79         end
80
81         -- Get items table
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 })
87                     end
88                     break
89                 end
90             end
91         end
92
93         -- Cleanup things a bit
94         for i = #result, 1, -1 do
95             local v = result[i]
96             if #v[2] == 0 then
97                 -- Remove unused categories
98                 table.remove(result, i)
99             else
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
104             end
105         end
106
107         -- Sort categories alphabetically also
108         table.sort(result, function(a, b) return string.byte(a[1]) < string.byte(b[1]) end)
109
110         -- Add menu item to hold the generated menu
111         if sub_menu then
112             result = {{sub_menu, result}}
113         end
114
115         -- Add items to menu
116         for _, v in pairs(result) do _menu:add(v) end
117         for _, v in pairs(after)  do _menu:add(v) end
118     end)
119
120     -- Set icon size
121     if icon_size then
122         for _,v in pairs(menu_gen.all_categories) do
123             v.icon = icon_theme():find_icon_path(v.icon_name, icon_size)
124         end
125     end
126
127     -- Hold the menu in the module
128     menu.menu = _menu
129
130     return _menu
131 end
132
133 return menu