+-- Generates a menu compatible with the iterate function argument and suitable
+-- for the following cases:
+-- * all possible choices individually.
+-- * all possible choices are all the possible subsets of the set of individual
+-- choices (the powerset)
+--
+-- The following describes the function arguments:
+-- * args: an array containing the following members:
+-- * choices: the list of choices from which to generate the menu
+-- * name: the displayed name of the menu (in the form "name: choices")
+-- * selected_cb: the callback to execute for each selected choice. Takes
+-- the choice as a string argument. The function
+-- menu_iterator.naughty_destroy_callback will handle nil
+-- callbacks. It is then fine to pass nil callbacks.
+-- * rejected_cb: the callback to execute for each rejected choice (in the
+-- set of possible choices, but not selected). Takes the
+-- choice as a string argument. The function
+-- menu_iterator.naughty_destroy_callback will handle nil
+-- callbacks. It is then fine to pass nil callbacks.
+-- * extra_choices: an array of pairs { choice_text, cb } for extra choices to
+-- be added to the menu. The function
+-- menu_iterator.naughty_destroy_callback will handle nil
+-- callbacks. It is then fine to pass nil callbacks.
+-- * combination: the combination of choice to generate. Possible choices
+-- are "powerset" and "single" (the default).
+local function menu(args)
+ local choices = assert(args.choices or args[1])
+ local name = assert(args.name or args[2])
+ local selected_cb = args.selected_cb
+ local rejected_cb = args.rejected_cb
+ local extra_choices = args.extra_choices or {}
+
+ local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices)
+ for _,c in pairs(extra_choices) do
+ ch_combinations = awful.util.table.join(ch_combinations, {{c[1]}})
+ end
+
+ local m = {}
+ for _,c in pairs(ch_combinations) do
+ if #c > 0 then
+ local cbs = {}
+ -- selected choices
+ for _,ch in pairs(c) do
+ if awful.util.table.hasitem(choices, ch) then
+ cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
+ end
+ end
+
+ -- rejected choices
+ for _,ch in pairs(choices) do
+ if not awful.util.table.hasitem(c, ch) and awful.util.table.hasitem(choices, ch) then
+ cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil
+ end
+ end
+
+ -- add user extra choices (like the choice "None" for e.g.)
+ for _,x in pairs(extra_choices) do
+ if x[1] == c[1] then
+ cbs[#cbs + 1] = x[2]
+ end
+ end
+
+ m[#m + 1] = { name .. ": " .. table.concat(c, " + "), cbs }
+ end
+ end
+
+ return m
+end
+
+return {
+ iterate = iterate,
+ menu = menu
+}