My configuration files for Debian/Ubuntu applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

145 lines
4.9 KiB

  1. --[[
  2. Licensed under GNU General Public License v2
  3. * (c) 2017, Simon Désaulniers <sim.desaulniers@gmail.com>
  4. * (c) 2017, Uli Schlachter
  5. * (c) 2017, Jeferson Siqueira <jefersonlsiq@gmail.com>
  6. --]]
  7. -- Menu iterator with Naughty notifications
  8. -- lain.util.menu_iterator
  9. local naughty = require("naughty")
  10. local helpers = require("lain.helpers")
  11. local atable = require("awful.util").table
  12. local assert = assert
  13. local pairs = pairs
  14. local tconcat = table.concat
  15. local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility
  16. local state = { cid = nil }
  17. local function naughty_destroy_callback(reason)
  18. local closed = naughty.notificationClosedReason
  19. if reason == closed.expired or reason == closed.dismissedByUser then
  20. local actions = state.index and state.menu[state.index - 1][2]
  21. if actions then
  22. for _,action in pairs(actions) do
  23. -- don't try to call nil callbacks
  24. if action then action() end
  25. end
  26. state.index = nil
  27. end
  28. end
  29. end
  30. -- Iterates over a menu.
  31. -- After the timeout, callbacks associated to the last visited choice are
  32. -- executed. Inputs:
  33. -- * menu: a list of {label, {callbacks}} pairs
  34. -- * timeout: time to wait before confirming the menu selection
  35. -- * icon: icon to display in the notification of the chosen label
  36. local function iterate(menu, timeout, icon)
  37. timeout = timeout or 4 -- default timeout for each menu entry
  38. icon = icon or nil -- icon to display on the menu
  39. -- Build the list of choices
  40. if not state.index then
  41. state.menu = menu
  42. state.index = 1
  43. end
  44. -- Select one and display the appropriate notification
  45. local label
  46. local next = state.menu[state.index]
  47. state.index = state.index + 1
  48. if not next then
  49. label = "Cancel"
  50. state.index = nil
  51. else
  52. label, _ = unpack(next)
  53. end
  54. state.cid = naughty.notify({
  55. text = label,
  56. icon = icon,
  57. timeout = timeout,
  58. screen = mouse.screen,
  59. replaces_id = state.cid,
  60. destroy = naughty_destroy_callback
  61. }).id
  62. end
  63. -- Generates a menu compatible with the first argument of `iterate` function and
  64. -- suitable for the following cases:
  65. -- * all possible choices individually (partition of singletons);
  66. -- * all possible subsets of the set of choices (powerset).
  67. --
  68. -- Inputs:
  69. -- * args: an array containing the following members:
  70. -- * choices: Array of choices (string) on which the menu will be
  71. -- generated.
  72. -- * name: Displayed name of the menu (in the form "name: choices").
  73. -- * selected_cb: Callback to execute for each selected choice. Takes
  74. -- the choice as a string argument. Can be `nil` (no action
  75. -- to execute).
  76. -- * rejected_cb: Callback to execute for each rejected choice (possible
  77. -- choices which are not selected). Takes the choice as a
  78. -- string argument. Can be `nil` (no action to execute).
  79. -- * extra_choices: An array of extra { choice_str, callback_fun } pairs to be
  80. -- added to the menu. Each callback_fun can be `nil`.
  81. -- * combination: The combination of choices to generate. Possible values:
  82. -- "powerset" and "single" (default).
  83. -- Output:
  84. -- * m: menu to be iterated over.
  85. local function menu(args)
  86. local choices = assert(args.choices or args[1])
  87. local name = assert(args.name or args[2])
  88. local selected_cb = args.selected_cb
  89. local rejected_cb = args.rejected_cb
  90. local extra_choices = args.extra_choices or {}
  91. local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices)
  92. for _, c in pairs(extra_choices) do
  93. ch_combinations = atable.join(ch_combinations, {{c[1]}})
  94. end
  95. local m = {} -- the menu
  96. for _,c in pairs(ch_combinations) do
  97. if #c > 0 then
  98. local cbs = {}
  99. -- selected choices
  100. for _,ch in pairs(c) do
  101. if atable.hasitem(choices, ch) then
  102. cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil
  103. end
  104. end
  105. -- rejected choices
  106. for _,ch in pairs(choices) do
  107. if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then
  108. cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil
  109. end
  110. end
  111. -- add user extra choices (like the choice "None" for example)
  112. for _,x in pairs(extra_choices) do
  113. if x[1] == c[1] then
  114. cbs[#cbs + 1] = x[2]
  115. end
  116. end
  117. m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs }
  118. end
  119. end
  120. return m
  121. end
  122. return { iterate = iterate, menu = menu }