All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
3 Licensed under GNU General Public License v2
4 * (c) 2017, Simon Désaulniers <sim.desaulniers@gmail.com>
5 * (c) 2017, Uli Schlachter
6 * (c) 2017, Jeferson Siqueira <jefersonlsiq@gmail.com>
10 -- Menu iterator with Naughty notifications
11 -- lain.util.menu_iterator
13 local naughty = require("naughty")
14 local util = require("lain.util")
15 local atable = require("awful.util").table
18 local tconcat = table.concat
21 local state = { cid = nil }
23 local function naughty_destroy_callback(reason)
24 local closed = naughty.notificationClosedReason
25 if reason == closed.expired or reason == closed.dismissedByUser then
26 local actions = state.index and state.menu[state.index - 1][2]
28 for _,action in pairs(actions) do
29 -- don't try to call nil callbacks
30 if action then action() end
37 -- Iterates over a menu.
38 -- After the timeout, callbacks associated to the last visited choice are
40 -- * menu: a list of {label, {callbacks}} pairs
41 -- * timeout: time to wait before confirming the menu selection
42 -- * icon: icon to display in the notification of the chosen label
43 local function iterate(menu, timeout, icon)
44 local timeout = timeout or 4 -- default timeout for each menu entry
45 local icon = icon or nil -- icon to display on the menu
47 -- Build the list of choices
48 if not state.index then
53 -- Select one and display the appropriate notification
55 local next = state.menu[state.index]
56 state.index = state.index + 1
62 label, _ = unpack(next)
65 state.cid = naughty.notify({
69 screen = mouse.screen,
70 replaces_id = state.cid,
71 destroy = naughty_destroy_callback
75 -- Generates a menu compatible with the first argument of `iterate` function and
76 -- suitable for the following cases:
77 -- * all possible choices individually (partition of singletons);
78 -- * all possible subsets of the set of choices (powerset).
81 -- * args: an array containing the following members:
82 -- * choices: Array of choices (string) on which the menu will be
84 -- * name: Displayed name of the menu (in the form "name: choices").
85 -- * selected_cb: Callback to execute for each selected choice. Takes
86 -- the choice as a string argument. Can be `nil` (no action
88 -- * rejected_cb: Callback to execute for each rejected choice (possible
89 -- choices which are not selected). Takes the choice as a
90 -- string argument. Can be `nil` (no action to execute).
91 -- * extra_choices: An array of extra { choice_str, callback_fun } pairs to be
92 -- added to the menu. Each callback_fun can be `nil`.
93 -- * combination: The combination of choices to generate. Possible values:
94 -- "powerset" and "single" (default).
96 -- * m: menu to be iterated over.
97 local function menu(args)
98 local choices = assert(args.choices or args[1])
99 local name = assert(args.name or args[2])
100 local selected_cb = args.selected_cb
101 local rejected_cb = args.rejected_cb
102 local extra_choices = args.extra_choices or {}
104 local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices)
106 for _,c in pairs(extra_choices) do
107 ch_combinations = atable.join(ch_combinations, {{c[1]}})
110 local m = {} -- the menu
112 for _,c in pairs(ch_combinations) do
117 for _,ch in pairs(c) do
118 if atable.hasitem(choices, ch) then
119 cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
124 for _,ch in pairs(choices) do
125 if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then
126 cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil
130 -- add user extra choices (like the choice "None" for example)
131 for _,x in pairs(extra_choices) do
137 m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs }
144 return { iterate = iterate, menu = menu }