237 lines
7.0 KiB
Lua
237 lines
7.0 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...
|
|
}
|
|
|
|
--[[
|
|
-- targetmap may be a string or a table with one or two entries
|
|
--
|
|
-- map = {
|
|
-- { "Ctrl+Alt+Super+L", "Super+LeftClick", description, function() }
|
|
-- }
|
|
--]]
|
|
function bindings.addkeyandmousemap(targetmap, category, map)
|
|
if type(targetmap) == "string" then
|
|
targetkey = targetmap.."_key"
|
|
targetmouse = targetmap.."_mouse"
|
|
elseif type(targetmap) == "table" then
|
|
if #targetmap == 1 then
|
|
targetkey = targetmap[1].."_key"
|
|
targetmouse = targetmap[1].."_mouse"
|
|
elseif #targetmap == 2 then
|
|
targetkey = targetmap[1]
|
|
targetmouse = targetmap[2]
|
|
end
|
|
else
|
|
return nil
|
|
end
|
|
|
|
if type(internalbindings[targetkey]) == "nil" then internalbindings[targetkey] = {} end
|
|
if type(internalbindings[targetmouse]) == "nil" then internalbindings[targetmouse] = {} end
|
|
for _, mapentry in ipairs(map) do
|
|
local keys = mapentry[1]
|
|
local mkeys = mapentry[2]
|
|
local desc = mapentry[3]
|
|
local bindfunc = mapentry[4]
|
|
if keys then
|
|
internalbindings[targetkey] = gearstable.join(internalbindings[targetkey],
|
|
awful.key(getmodkeys(keys), getkey(keys), bindfunc, {description = desc, group = category})
|
|
)
|
|
end
|
|
if mkeys then
|
|
internalbindings[targetmouse] = gearstable.join(internalbindings[targetmouse],
|
|
awful.button(getmodkeys(mkeys), getmousekey(mkeys), bindfunc)
|
|
)
|
|
end
|
|
end
|
|
return { keys = internalbindings[targetkey], mouse = internalbindings[targetmouse] }
|
|
end
|
|
|
|
--[[
|
|
-- 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 })
|