local awful = require "awful" local gtable = require "gears.table" local qstore = require "quarrel.store" ---@class QuarrelBind local qbind = {} qstore.bindings = {} ---@alias mouse_button ---| 0 Left mouse button ---| 1 Middle mouse click ---| 2 Right mouse button ---| 3 Scroll up ---| 4 Scroll down ---@alias bind ---| mouse_button ---| string ---@alias modifier ---| "Mod1" Alt ---| "Mod4" Super ---| "Mod5" AltGr ---| "Shift" Shift ---| "Control" Ctrl ---@class Trigger ---@field [1] bind ---@field [2] any Value passed to the press callback ---@class Binding ---@field hidden boolean? Whether the binding shows up in the help menu ---@field mods modifier[]? Modifiers ---@field press fun(...) | fun(any, ...) Function to run when the trigger is pressed ---@field desc string? Description ---@field group string? What group the binding will show up in ---@field triggers Trigger[] | bind ---Get the corresponding binding creation function for a trigger ---@param bind bind ---@return string local function get_binding_function(bind) if type(bind) == "number" and bind <= 5 and bind > 0 then return "button" elseif type(bind) == "string" then return "key" end error("bind can only be a mouse button or a key", 2) end --- Translate a qbind binding into an awful binding ---@param binding Binding ---@param trigger Trigger | bind ---@param multi boolean specifies whether this is a multi trigger bind ---@return awful.key local function translate_binding(binding, trigger, multi) local awful_binding if multi then awful_binding = { modifiers = binding.mods, [get_binding_function(trigger[1])] = trigger[1], on_press = function(...) binding.press(trigger[2], ...) end, } else awful_binding = { modifiers = binding.mods, [get_binding_function(trigger --[[@as bind]])] = trigger, on_press = binding.press, } end awful_binding.description = binding.desc awful_binding.group = binding.group return awful[ get_binding_function(multi and trigger[1] or trigger --[[@as bind]]) ](awful_binding) end --- Create a new binding ---@param binding Binding ---@return awful.key[] function qbind:new(binding) if not binding.hidden then table.insert(qstore.bindings, binding) end binding.mods = binding.mods or {} local awful_bindings = {} if type(binding.triggers) == "table" then for _, trigger in ipairs(binding.triggers --[[@as Trigger[]]) do table.insert(awful_bindings, translate_binding(binding, trigger, true)) end elseif type(binding.triggers) == "string" or type(binding.triggers) == "number" then return translate_binding(binding, binding.triggers --[[@as bind]], false) else error "binding.triggers can only be a string or a table" end -- for some reason multi-trigger bindings only work if i do this -- i spent a day debugging this -- thanks awesome return gtable.join(table.unpack(awful_bindings)) end return qbind