Files
strangesome/bindings/init.lua
2022-01-01 23:03:14 +01:00

195 lines
5.5 KiB
Lua

--[[
-- handle key- and mousebindings in a sane and readable way
--]]
-- needs
local awful = require("awful")
local gears = require("gears")
local notifications = require("strangesome.notifications")
local debug = notifications.debug_enabled
local debug_msg = notifications.debug_msg
local wrequire = require("strangesome.loader").wrequire
-- define standard commands local to speed up things a little bit
local next = next
local setmetatable = setmetatable
local tonumber = tonumber
-- strangesome.bindings
local bindings = { _NAME = "strangesome.bindings" }
local gearstable = awful.util.table or gears.table
local internalbindings = {}
local separator = "+"
local keyregex = "([^"..separator.."]+)"
-- define named keys with usable aliases
local named_keys = {
{ "Escape", { "esc", "escape" } },
{ "Left", {} },
{ "Right", {} },
{ "Up", {} },
{ "Down", {} },
{ "Enter", {} },
{ "Return", {} },
{ "Print", {} },
{ "Space", {} },
{ "Backspace", {} },
{ "Tab", {} },
{ "XF86AudioMute", {} },
{ "XF86HomePage", {} },
{ "XF86Calculator", {} },
{ "XF86AudioMedia", {} },
{ "XF86AudioPrev", {} },
{ "XF86AudioNext", {} },
{ "XF86AudioPlay", {} },
{ "XF86AudioStop", {} },
{ "XF86MyComputer", {} },
{ "XF86AudioRaiseVolume", {} },
{ "XF86AudioLowerVolume", {} },
-- more to come...
}
local mod_keys = {
{ "Control", { "control", "ctrl" } },
{ "Shift", {} },
{ "Mod1", { "alt", "mod1" } },
{ "Mod4", { "super", "meta", "mod4" } },
}
local mouse_keys = {
{ 1, { "left", "mouseleft", "leftkey", "leftclick" } },
{ 2, { "middle", "mousemiddle", "middlekey", "middleclick" } },
{ 3, { "right", "mouseright", "rightkey", "rightclick" } },
{ 4, { "up", "mouseup", "scrollup" } },
{ 5, { "down", "mousedown", "scrolldown" } },
-- more to come...
}
--[[
-- map = {
-- { "Ctrl+Alt+Super+L", description, function() }
-- }
--]]
function bindings.addkeymap(target, category, map)
if debug then debug_msg("Type of internalbindings["..target.."]: "..type(internalbindings[target])) end
if type(internalbindings[target]) == "nil" then internalbindings[target] = {} end
for _, mapentry in ipairs(map) do
local keys = mapentry[1]
local desc = mapentry[2]
local bindfunc = mapentry[3]
internalbindings[target] = gearstable.join(internalbindings[target],
awful.key(getmodkeys(keys), getkey(keys), bindfunc, {description = desc, group = category})
)
end
if debug then debug_msg("Type of internalbindings["..target.."]: "..type(internalbindings[target])) end
return internalbindings[target]
end
function bindings.addmousemap(target, map)
if debug then debug_msg("Type of internalbindings["..target.."]: "..type(internalbindings[target])) end
if type(internalbindings[target]) == "nil" then internalbindings[target] = {} end
for _, mapentry in ipairs(map) do
local keys = mapentry[1]
local bindfunc = mapentry[2]
internalbindings[target] = gearstable.join(internalbindings[target],
awful.button(getmodkeys(keys), getmousekey(keys), bindfunc)
)
end
if debug then debug_msg("Type of internalbindings["..target.."]: "..type(internalbindings[target])) end
return internalbindings[target]
end
function bindings.export(target)
if type(internalbindings[target]) == "nil" then return {} end
return internalbindings[target]
end
function getmodkeys(keys)
local modkeys = {}
local mkey
for key in string.gmatch(keys, keyregex) do
mkey = ismodkey(key)
if mkey then
modkeys[#modkeys+1] = mkey
end
end
return modkeys
end
function getkey(keys)
local sepregex = "["..separator.."]["..separator.."]"
local key = ""
for str in string.gmatch(keys, keyregex) do
-- single char, always lower case
if string.len(str) == 1 then
key = string.lower(str)
-- named key, see table named_keys above
elseif isnamedkey(str) then
key = isnamedkey(str)
-- match separator key, e.g in "Alt+Super++" for Alt, Super and "+"
elseif string.match(keys, sepregex) then
key = string.lower(separator)
end
end
return key
end
function getmousekey(keys)
local keyregex = "([^"..separator.."]+)"
local key = 0
local mkey
for str in string.gmatch(keys, keyregex) do
-- is number and between 1 and 5
if type(str.tonumber) == "number" then
local num = str.tonumber
if num > 0 and num < 6 then key = num end
-- mousekey, see table mouse_keys above (integers 1 to 5)
elseif ismousekey(str) then
key = ismousekey(str)
end
end
return key
end
function isnamedkey(key)
-- there are no named keys with length 1
if string.len(key) == 1 then return false end
return check_keys_table(key, named_keys)
end
function ismodkey(key)
return check_keys_table(key, mod_keys)
end
function ismousekey(key)
return check_keys_table(key, mouse_keys)
end
function check_keys_table(key, table)
for _, entry in ipairs(table) do
local tkey = entry[1]
local aliases = entry[2]
if next(aliases) == nil then
--no aliases given, check against tkey
if string.lower(key) == string.lower(tkey) then return tkey end
else
for _, alias in ipairs(aliases) do
if string.lower(key) == string.lower(alias) then return tkey end
end
end
end
return false
end
return setmetatable(bindings, { __index = wrequire })