--[[ Licensed under GNU General Public License v2 * (c) 2017, Simon Désaulniers * (c) 2017, Uli Schlachter * (c) 2017, Jeferson Siqueira --]] -- Menu iterator using naughty.notify local naughty = require("naughty") local util = require("lain.util") local state = { cid = nil } local function naughty_destroy_callback(reason) if reason == naughty.notificationClosedReason.expired or reason == naughty.notificationClosedReason.dismissedByUser then local actions = state.index and state.menu[state.index - 1][2] if actions then for _,action in pairs(actions) do -- don't try to call nil callbacks if action then action() end end state.index = nil end end end -- Iterates over a list of pairs {label, {callbacks}}. After timeout, the last -- visited choice associated callbacks are executed. -- * menu: a list of pairs {label, {callbacks} -- * timeout: time to wait before confirming menu selection -- * icon: icon to display left to the choiced label local function iterate(menu, timeout, icon) timeout = timeout or 4 -- default timeout for each menu entry icon = icon or nil -- icon to display on the menu -- Build the list of choices if not state.index then state.menu = menu state.index = 1 end -- Select one and display the appropriate notification local label, action local next = state.menu[state.index] state.index = state.index + 1 if not next then label = "Cancel" state.index = nil else label, _ = unpack(next) end state.cid = naughty.notify({ text = label, icon = icon, timeout = timeout, screen = mouse.screen, replaces_id = state.cid, destroy = naughty_destroy_callback }).id end -- 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 }