1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
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
|