Overlapping set of keychords
I try to adapt Key chords to apply commonly used styles to Inkscape objects on macOS.
The list of key chords are shown in this graphic

The author has published his key chord setup on github https://github.com/gillescastel/inkscape-shortcut-manager for linux.
I have already managed to adapt the creation of svg snippets for pasting. The remaining issue is that defining a large overlapping set of key chords using https://github.com/knu/hs-knu/blob/master/chord.lua does not work as expected. Only a subset works.
knu = require("knu")
-- Function to guard a given object from GC
guard = knu.runtime.guard
-- Keychords (48x)
keychords = {}
-- work
keychords[1] = {"f", "space"}
keychords[2] = {"w", "space"}
keychords[3] = {"b", "space"}
keychords[4] = {"s", "space"}
keychords[5] = {"d", "space"}
keychords[6] = {"e", "space"}
-- do not work
keychords[7] = {"s", "f"}
keychords[8] = {"d", "f"}
keychords[9] = {"e", "f"}
keychords[10] = {"s", "w"}
keychords[11] = {"d", "w"}
keychords[12] = {"e", "w"}
keychords[13] = {"s", "g"}
keychords[14] = {"d", "g"}
keychords[15] = {"e", "g"}
keychords[16] = {"s", "f", "g"}
keychords[17] = {"d", "f", "g"}
keychords[18] = {"e", "f", "g"}
keychords[19] = {"s", "w", "g"}
keychords[20] = {"d", "w", "g"}
keychords[21] = {"e", "w", "g"}
keychords[22] = {"s", "v"}
keychords[23] = {"d", "v"}
keychords[24] = {"e", "v"}
keychords[25] = {"s", "f", "v"}
keychords[26] = {"d", "f", "v"}
keychords[27] = {"e", "f", "v"}
keychords[28] = {"s", "w", "v"}
keychords[29] = {"d", "w", "v"}
keychords[30] = {"e", "w", "v"}
keychords[31] = {"s", "a"}
keychords[32] = {"d", "a"}
keychords[33] = {"e", "a"}
keychords[34] = {"s", "a", "v"}
keychords[35] = {"d", "a", "v"}
keychords[36] = {"e", "a", "v"}
keychords[37] = {"s", "a", "g"}
keychords[38] = {"d", "a", "g"}
keychords[39] = {"e", "a", "g"}
keychords[40] = {"s", "x"}
keychords[41] = {"d", "x"}
keychords[42] = {"e", "x"}
keychords[43] = {"s", "x", "v"}
keychords[44] = {"d", "x", "v"}
keychords[45] = {"e", "x", "v"}
keychords[46] = {"s", "x", "g"}
keychords[47] = {"d", "x", "g"}
keychords[48] = {"e", "x", "g"}
knuchords = {}
for k, v in pairs(keychords) do
knuchords[k] = knu.chord.new({}, v, function() print(hs.inspect.inspect(v)); end, 0.5)
end
local InkscapeWF = hs.window.filter.new("Inkscape")
InkscapeWF
:subscribe(hs.window.filter.windowFocused, function()
print("starting keychords")
for k,v in pairs(knuchords) do
guard(v:start())
end
end)
:subscribe(hs.window.filter.windowUnfocused, function()
print("stopping keychords")
for k,v in pairs(knuchords) do
guard(v:stop())
end
end)
@knu Do you know where the issue is located and how one could resolve it?
That's a massive use case of key chords! I can imagine too many active event taps could lead to an unreliable state because the event loop of the operating system has strict time constraints. Under the hood knu.chord creates one event tap for each chord, so it may not scale well.
Instead of using knu.chord, I'd suggest you use Karabiner-Elements for the chord part, mapping simultaneous non-modifier key combinations to modifiers + single keys, and then define them as hotkeys on Hammerspoon.
Apart from that, I cannot deny an overlapping set of key chords could not work well, depending on the order of definitions. Each event tap created for a key chord holds key events for a certain amount of time, and when those are accumulated to be more than a timeout of the later chord, it will always fail to form.
This could be fixed by making a giant event tap that would check all defined chords, but that's going to be a lot of work.
Thanks for your comments.
I can imagine too many active event taps could lead to an unreliable state because the event loop of the operating system has strict time constraints.
I also suspect this.
Karabiner Elements instead of knu.chord
Instead of using knu.chord, I'd suggest you use Karabiner-Elements for the chord part, mapping simultaneous non-modifier key combinations to modifiers + single keys, and then define them as hotkeys on Hammerspoon.
I have tried Karabiner Elements. Karabiner Elements actually offers also to.shell_command so I do not have to remap to modifier + single key. Since I have written the function create_svg_and_paste(keys) for hammerspoon:
~/.hammerspoon/init.lua
-- Helper function
local function intersect(m,n)
local r={}
for i,v1 in ipairs(m) do
for k,v2 in pairs(n) do
if (v1==v2) then
return true
end
end
end
return false
end
-- Helper function
local function has_value (tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
function create_svg_and_paste(keys)
print(hs.inspect.inspect(keys))
pt = 1.327 -- pixels
w = 1 * pt
thick_width = 4 * pt
very_thick_width = 8 * pt
style = {}
style["stroke-opacity"] = 1
if intersect({"s", "a", "d", "g", "h", "x", "e"}, keys)
then
style["stroke"] = "black"
style["stroke-width"] = w
style["marker-end"] = "none"
style["marker-start"] = "none"
style["stroke-dasharray"] = "none"
else
style["stroke"] = "none"
end
if has_value(keys, "g")
then
w = thick_width
style["stroke-width"] = w
end
if has_value(keys, "h")
then
w = very_thick_width
style["stroke-width"] = w
end
if has_value(keys, "a")
then
style['marker-end'] = 'url(#marker-arrow-' .. tostring(w) .. ')'
end
if has_value(keys, "x")
then
style['marker-start'] = 'url(#marker-arrow-' .. tostring(w) .. ')'
style['marker-end'] = 'url(#marker-arrow-' .. tostring(w) .. ')'
end
if has_value(keys, "d")
then
style['stroke-dasharray'] = tostring(w) .. ',' .. tostring(2*pt)
end
if has_value(keys, "e")
then
style['stroke-dasharray'] = tostring(3*pt) .. ',' .. tostring(3*pt)
end
if has_value(keys, "f")
then
style['fill'] = 'black'
style['fill-opacity'] = 0.12
end
if has_value(keys, "b")
then
style['fill'] = 'black'
style['fill-opacity'] = 1
end
if has_value(keys, "w")
then
style['fill'] = 'white'
style['fill-opacity'] = 1
end
if intersect(keys, {"f", "b", "w"})
then
style['marker-end'] = 'none'
style['marker-start'] = 'none'
end
if not intersect(keys, {"f", "b", "w"})
then
style['fill'] = 'none'
style['fill-opacity'] = 1
end
svg = [[
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg>
]]
print(hs.inspect.inspect(style)) -- ENABLE ONLY FOR DEBUGGING
if (style['marker-end'] ~= nil and style['marker-end'] ~= 'none') or
(style['marker-start'] ~= nil and style['marker-start'] ~= 'none')
then
svgtemp = [[
<defs id="marker-defs">
<marker
]]
svgtemp = svgtemp .. 'id="marker-arrow-' .. tostring(w) .. "\"\n"
svgtemp = svgtemp .. 'orient="auto-start-reverse"' .. "\n"
svgtemp = svgtemp .. 'refY="0" refX="0"' .. "\n"
svgtemp = svgtemp .. 'markerHeight="3" markerWidth="2">' .. "\n"
svgtemp = svgtemp .. ' <g transform="scale('.. tostring((2.40 * w + 3.87)/(4.5*w)) .. ')">' .. "\n"
svg = svg .. svgtemp
svgtemp = [[
<path
d="M -1.55415,2.0722 C -1.42464,1.29512 0,0.1295 0.38852,0 0,-0.1295 -1.42464,-1.29512 -1.55415,-2.0722"
style="fill:none;stroke:#000000;stroke-width:{0.6};stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1
inkscape:connector-curvature="0" />
</g>
</marker>
</defs>
]]
svg = svg .. svgtemp
end
style_string = ''
for key, value in pairs(style) do
-- skips nil?
style_string = style_string .. key .. ":" .. " " .. value .. ";"
end
svg = svg .. '<inkscape:clipboard style="' .. style_string .. '" />' .. "\n</svg>"
print(svg) -- ENABLE ONLY FOR DEBUGGING
hs.pasteboard.writeDataForUTI("dyn.ah62d4rv4gu80w5pbq7ww88brrf1g065dqf2gnppxs3xu", svg)
-- get UTI via https://github.com/sindresorhus/Pasteboard-Viewer
hs.eventtap.keyStroke({"shift", "cmd"}, "v")
end
I will simply call the lua-hammerspoon function from the cli
"shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+␣\");create_svg_and_paste({\"e\",\"space\"});'"
~/.config/karabiner/karabiner.json for the 30 shape key chords
"complex_modifications": {
"parameters": {
"basic.simultaneous_threshold_milliseconds": 200,
"basic.to_delayed_action_delay_milliseconds": 500,
"basic.to_if_alone_timeout_milliseconds": 1000,
"basic.to_if_held_down_threshold_milliseconds": 500,
"mouse_motion_to_scroll.speed": 100
},
"rules": [
{
"description": "s+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+␣\");create_svg_and_paste({\"s\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+␣\");create_svg_and_paste({\"d\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+␣\");create_svg_and_paste({\"e\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "f+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "f" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"f+␣\");create_svg_and_paste({\"f\",\"space\"});'" } ],
"conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] } ]
}
]
},
{
"description": "w+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "w" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"w+␣\");create_svg_and_paste({\"w\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "b+space",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "b" }, { "key_code": "spacebar" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"b+␣\");create_svg_and_paste({\"b\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+f",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "f" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+f\");create_svg_and_paste({\"s\",\"f\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+f",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "f" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+f\");create_svg_and_paste({\"d\",\"f\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+f",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "f" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+f\");create_svg_and_paste({\"e\",\"f\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+w",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "w" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+w\");create_svg_and_paste({\"d\",\"w\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+w",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "b" }, { "key_code": "space" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"b+␣\");create_svg_and_paste({\"b\",\"space\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+w",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "w" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+w\");create_svg_and_paste({\"e\",\"w\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+g\");create_svg_and_paste({\"s\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+g\");create_svg_and_paste({\"d\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+g\");create_svg_and_paste({\"e\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+f+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "f" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+f+g\");create_svg_and_paste({\"s\",\"f\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+f+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "f" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+f+g\");create_svg_and_paste({\"d\",\"f\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+f+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "f" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+f+g\");create_svg_and_paste({\"e\",\"f\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+w+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "w" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+w+g\");create_svg_and_paste({\"s\",\"w\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+w+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "w" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+w+g\");create_svg_and_paste({\"d\",\"w\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+w+g",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "w" }, { "key_code": "g" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+w+g\");create_svg_and_paste({\"e\",\"w\",\"g\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+h\");create_svg_and_paste({\"s\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+h\");create_svg_and_paste({\"d\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+h\");create_svg_and_paste({\"e\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+f+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "f" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+f+h\");create_svg_and_paste({\"s\",\"f\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+f+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "f" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+f+h\");create_svg_and_paste({\"d\",\"f\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+f+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "f" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+f+h\");create_svg_and_paste({\"e\",\"f\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "s+w+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "s" }, { "key_code": "w" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"s+w+h\");create_svg_and_paste({\"s\",\"w\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "d+w+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "d" }, { "key_code": "w" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"d+w+h\");create_svg_and_paste({\"d\",\"w\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
},
{
"description": "e+w+h",
"manipulators": [
{
"type": "basic",
"from": { "simultaneous": [ { "key_code": "e" }, { "key_code": "w" }, { "key_code": "h" } ] },
"to_if_alone": [ { "shell_command": "/usr/local/bin/hs -c 'hs.alert(\"e+w+h\");create_svg_and_paste({\"e\",\"w\",\"h\"});'" } ],
"conditions": [{ "type": "frontmost_application_if", "bundle_identifiers": [ "org.inkscape.Inkscape" ] }]
}
]
}
]
},
...
This uses
This is an improvement. So all two-letter combinations work. However, the three-letter combinations do not yet. There are a few options I have not tested comprehensively
"basic.simultaneous_threshold_milliseconds": 200,
"basic.to_if_alone_timeout_milliseconds": 1000,
and the
simultaneous_options detect_key_down_uninterruptedly.
Single hs.eventtap for all key chords
This could be fixed by making a giant event tap that would check all defined chords, but that's going to be a lot of work.
I think this is what the original author did. And I guess this could also be possible with hammerspoon eventtap.