diff options
Diffstat (limited to '.config/awesome/quarrel/bind/init.lua')
-rw-r--r-- | .config/awesome/quarrel/bind/init.lua | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/.config/awesome/quarrel/bind/init.lua b/.config/awesome/quarrel/bind/init.lua new file mode 100644 index 0000000..a851440 --- /dev/null +++ b/.config/awesome/quarrel/bind/init.lua @@ -0,0 +1,119 @@ +local C = require "quarrel.bind.consts" +local awful = require "awful" +local gtable = require "gears.table" + +local M = gtable.crush({ + bindings = {}, +}, C) + +---@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[] | 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 M:new(binding) + if not binding.hidden then + table.insert(self.bindings, binding) + end + binding.mods = binding.mods or {} + + local awful_bindings = {} + + if type(binding.triggers) == "table" then + for _, _trigger in + ipairs(binding.triggers --[[@as bind[] | Trigger[]]) + do + local trigger + if type(_trigger) == "table" then + trigger = _trigger + elseif type(_trigger) == "string" or type(_trigger) == "number" then + trigger = { _trigger, _trigger } + end + 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 (passed in " .. type(binding.triggers) .. ")") + 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 setmetatable(M, { + __call = M.new, +}) |