refactors multibow

This commit is contained in:
Harald Albrecht 2019-01-07 17:04:49 +01:00
parent 5240d0c08f
commit afb8e3271a
13 changed files with 331 additions and 62 deletions

View File

@ -35,6 +35,7 @@ return {
.. "function insl(f) _BUSTED.insulate(_INSL, f) end;" .. "function insl(f) _BUSTED.insulate(_INSL, f) end;"
.. "function inslit(d, f) _BUSTED.insulate(_INSL, function() _BUSTED.it(d, f) end) end;" .. "function inslit(d, f) _BUSTED.insulate(_INSL, function() _BUSTED.it(d, f) end) end;"
, ,
verbose = true verbose = true,
recursive = true
} }
} }

View File

@ -25,39 +25,45 @@ SOFTWARE.
-- below. -- below.
local k = _G.kdenlive or {} -- module local k = _G.kdenlive or {} -- module
local mb = require "snippets/multibow" require("keybow")
local mk = require("snippets/morekeys")
local mb = require("snippets/multibow")
k.KEY_CLIP_BEGIN = k.KEY_CLIP_BEGIN or 9
k.KEY_PROJECT_BEGIN = k.KEY_PROJECT_BEGIN or 9
k.KEY_CLIP_END = k.KEY_CLIP_END or 0
k.KEY_PROJECT_END = k.KEY_PROJECT_END or 0
-- (Default) key colors for unshifted and shifted keys.
k.COLOR_UNSHIFTED = k.COLOR_UNSHIFTED or {r=0, g=1, b=0}
k.COLOR_SHIFTED = k.COLOR_SHIFTED or {r=1, g=0, b=0}
-- Unshift to primary keymap. For simplification, use it with the "anykey" -- Unshift to primary keymap. For simplification, use it with the "anykey"
-- release handlers, see below. -- release handlers, see below.
function k.unshift(keyno) function k.unshift(keyno)
if keyno == 11 then mb.activate_keymap(k.keymap.name)
print(debug.traceback())
else
mb.activate_keymap(k.keymap.name)
end
end end
-- Key colors for unshifted and shifted keys; keep them rather muted in order
-- to not distract your video editing work.
k.UNSHIFTED_COLOR = {r=0, g=1, b=0}
k.SHIFTED_COLOR = {r=1, g=0, b=0}
k.keymap = { k.keymap = {
name="kdenlive", name="kdenlive",
[9] = {c=k.UNSHIFTED_COLOR}, [k.KEY_CLIP_BEGIN] = {c=k.COLOR_UNSHIFTED, press=function() mb.tap(mk.HOME) end},
[6] = {c=k.UNSHIFTED_COLOR}, [k.KEY_CLIP_END] = {c=k.COLOR_UNSHIFTED, press=function() mb.tap(mk.END) end},
} }
k.keymap_shifted = { k.keymap_shifted = {
name="kdenlive-shifted", name="kdenlive-shifted",
secondary=true, secondary=true,
[k.KEY_PROJECT_BEGIN] = {c=k.COLOR_SHIFTED, press=function() mb.tap(mk.HOME, keybow.LEFT_CTRL) end},
[k.KEY_PROJECT_END] = {c=k.COLOR_SHIFTED, press=function() mb.tap(mk.END, keybow.LEFT_CTRL) end},
[-1] = {release=k.unshift}, [-1] = {release=k.unshift},
[6] = {c=k.SHIFTED_COLOR},
[3] = {c=k.SHIFTED_COLOR},
} }
k.keymap.shift_to = k.keymap_shifted k.keymap.shift_to = k.keymap_shifted
k.keymap_shifted.shift_to = k.keymap k.keymap_shifted.shift_to = k.keymap
mb.register_keymap(k.keymap) mb.register_keymap(k.keymap)
mb.register_keymap(k.keymap_shifted) mb.register_keymap(k.keymap_shifted)
return k -- module return k -- module

View File

@ -20,7 +20,7 @@ cable going off "northwards":
9 6 3 0 9 6 3 0
STEP INTO OUT INTO STEP OUT
]]-- ]]--
@ -33,13 +33,21 @@ vscgo.KEY_STEPINTO = vscgo.KEY_STEPINTO or 6
vscgo.KEY_STEPOVER = vscgo.KEY_STEPOVER or 3 vscgo.KEY_STEPOVER = vscgo.KEY_STEPOVER or 3
vscgo.KEY_STEPOUT = vscgo.KEY_STEPOUT or 0 vscgo.KEY_STEPOUT = vscgo.KEY_STEPOUT or 0
RED = { r=1, g=0, b=0 } vscgo.RED = { r=1, g=0, b=0 }
YELLOW = { r=1, g=0.8, b=0 } vscgo.YELLOW = { r=1, g=0.7, b=0 }
GREEN = { r=0, g=1, b=0 } vscgo.GREEN = { r=0, g=1, b=0 }
BLUE = { r=0, g=0, b=1 } vscgo.BLUE = { r=0, g=0, b=1 }
BLUECYAN = { r=0, g=0.7, b=1 } vscgo.BLUECYAN = { r=0, g=0.7, b=1 }
BLUEGRAY = { r=0.7, g=0.7, b=1 } vscgo.BLUEGRAY = { r=0.7, g=0.7, b=1 }
CYAN = { r=0, g=1, b=1 } vscgo.CYAN = { r=0, g=1, b=1 }
vscgo.COLOR_STOP = vscgo.COLOR_STOP or vscgo.RED
vscgo.COLOR_RELOAD = vscgo.COLOR_RELOAD or vscgo.YELLOW
vscgo.COLOR_TESTPKG = vscgo.COLOR_TESTPKG or vscgo.CYAN
vscgo.COLOR_CONT = vscgo.COLOR_CONT or vscgo.GREEN
vscgo.COLOR_STEPINTO = vscgo.COLOR_STEPINTO or vscgo.BLUECYAN
vscgo.COLOR_STEPOVER = vscgo.COLOR_STEPOVER or vscgo.BLUE
vscgo.COLOR_STEPOUT = vscgo.COLOR_STEPOUT or vscgo.BLUEGRAY
-- AND NOW FOR SOMETHING DIFFERENT: THE REAL MEAT -- -- AND NOW FOR SOMETHING DIFFERENT: THE REAL MEAT --
@ -77,14 +85,14 @@ end
vscgo.keymap = { vscgo.keymap = {
name="vsc-golang-debug", name="vsc-golang-debug",
[vscgo.KEY_STOP] = {c=RED, press=vscgo.debug_stop}, [vscgo.KEY_STOP] = {c=vscgo.COLOR_STOP, press=vscgo.debug_stop},
[vscgo.KEY_RELOAD] = {c=YELLOW, press=vscgo.debug_restart}, [vscgo.KEY_RELOAD] = {c=vscgo.COLOR_RELOAD, press=vscgo.debug_restart},
[vscgo.KEY_TESTPKG] = {c=CYAN, press=vscgo.go_test_package}, [vscgo.KEY_TESTPKG] = {c=vscgo.COLOR_TESTPKG, press=vscgo.go_test_package},
[vscgo.KEY_CONT] = {c=GREEN, press=vscgo.debug_continue}, [vscgo.KEY_CONT] = {c=vscgo.COLOR_CONT, press=vscgo.debug_continue},
[vscgo.KEY_STEPINTO] = {c=BLUECYAN, press=vscgo.debug_stepinto}, [vscgo.KEY_STEPINTO] = {c=vscgo.COLOR_STEPINTO, press=vscgo.debug_stepinto},
[vscgo.KEY_STEPOVER] = {c=BLUE, press=vscgo.debug_stepover}, [vscgo.KEY_STEPOVER] = {c=vscgo.COLOR_STEPOVER, press=vscgo.debug_stepover},
[vscgo.KEY_STEPOUT] = {c=BLUEGRAY, press=vscgo.debug_stepout}, [vscgo.KEY_STEPOUT] = {c=vscgo.COLOR_STEPOUT, press=vscgo.debug_stepout},
} }
mb.register_keymap(vscgo.keymap) mb.register_keymap(vscgo.keymap)

View File

@ -0,0 +1,48 @@
-- Part of Multibow
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
-- Sends a single key tap to the USB host, optionally with modifier keys, such
-- as SHIFT (keybow.LEFT_SHIFT), CTRL (keybow.LEFT_CTRL), et cetera. The "key"
-- parameter can be a string or a Keybow key code, such as keybow.HOME, et
-- cetera.
function mb.tap(key, ...)
mb.tap_times(key, 1, ...)
end
-- Taps the same key multiple times...
function mb.tap_times(key, times, ...)
for modifier_argno = 1, select("#", ...) do
local modifier = select(modifier_argno, ...)
if modifier then; keybow.set_modifier(modifier, keybow.KEY_DOWN); end
end
for tap = 1, times do
keybow.tap_key(key)
keybow.sleep(100)
end
for modifier_argno = 1, select("#", ...) do
local modifier = select(modifier_argno, ...)
if modifier then; keybow.set_modifier(modifier, keybow.KEY_UP); end
end
end

View File

@ -0,0 +1,35 @@
-- Part of Multibow
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
-- Default LED brightness in the [0.1..1] range.
mb.brightness = 1
-- Sets the Keybow key LEDs maximum brightness, in the range [0.1..1].
function mb.set_brightness(brightness)
if brightness < 0.1 then brightness = 0.1 end
if brightness > 1 then brightness = 1 end
mb.brightness = brightness
mb.activate_leds()
end

View File

@ -1,3 +1,5 @@
-- Part of Multibow
--[[ --[[
Copyright 2019 Harald Albrecht Copyright 2019 Harald Albrecht

View File

@ -106,3 +106,6 @@ keybow.MEDIA_SLEEP = 0xf8
keybow.MEDIA_COFFEE = 0xf9 keybow.MEDIA_COFFEE = 0xf9
keybow.MEDIA_REFRESH = 0xfa keybow.MEDIA_REFRESH = 0xfa
keybow.MEDIA_CALC = 0xfb keybow.MEDIA_CALC = 0xfb
return keybow -- module

View File

@ -27,10 +27,13 @@ require "keybow"
mb.path = (...):match("^(.-)[^%/]+$") mb.path = (...):match("^(.-)[^%/]+$")
require(mb.path .. "morekeys") require(mb.path .. "morekeys")
require(mb.path .. "routehandlers") require(mb.path .. "mb/keys")
require(mb.path .. "mb/routehandlers")
require(mb.path .. "mb/leds")
mb.brightness = 0.4 -- Internal variables for housekeeping...
-- The registered keymaps, indexed by their names (.name field). -- The registered keymaps, indexed by their names (.name field).
mb.keymaps = {} mb.keymaps = {}
-- The ordered sequence of primary keymap, in the sequence they were -- The ordered sequence of primary keymap, in the sequence they were
@ -38,24 +41,10 @@ mb.keymaps = {}
mb.primary_keymaps = {} mb.primary_keymaps = {}
-- The currently activated keymap. -- The currently activated keymap.
mb.current_keymap = nil mb.current_keymap = nil
-- A temporary keymap while grabbing. -- A temporary keymap while grabbing.
mb.grab_keymap = nil mb.grab_keymap = nil
--
function mb.tap(keyno, key, ...)
for modifier_argno = 1, select('#', ...) do
local modifier = select(modifier_argno, ...)
if modifier then; keybow.set_modifier(modifier, keybow.KEY_DOWN); end
end
keybow.tap_key(key)
for modifier_argno = 1, select('#', ...) do
local modifier = select(modifier_argno, ...)
if modifier then; keybow.set_modifier(modifier, keybow.KEY_UP); end
end
end
-- Registers a keymap (by name), so it can be easily activated later by its name. -- Registers a keymap (by name), so it can be easily activated later by its name.
-- Multiple keymaps can be registered. Keymaps can be either "primary" by -- Multiple keymaps can be registered. Keymaps can be either "primary" by
-- default, or permanent or secondary keymaps. -- default, or permanent or secondary keymaps.
@ -171,14 +160,6 @@ function mb.ungrab()
end end
-- Sets the Keybow key LEDs maximum brightness, in the range [0.1..1].
function mb.set_brightness(brightness)
if brightness < 0.1 then; brightness = 0.1; end
if brightness > 1 then; brightness = 1; end
mb.brightness = brightness
mb.activate_leds()
end
-- Sets key LED to specific color, taking brightness into consideration. -- Sets key LED to specific color, taking brightness into consideration.
-- The color is a triple (table) with the elements r, g, and b. Each color -- The color is a triple (table) with the elements r, g, and b. Each color
-- component is in the range [0..1]. -- component is in the range [0..1].

View File

@ -26,7 +26,7 @@ local hwk = require("spec/hwkeys")
describe("Kdenlive keymap", function() describe("Kdenlive keymap", function()
it("...", function() it("initializes", function()
local mb = require("snippets/multibow") local mb = require("snippets/multibow")
local k = require("layouts/kdenlive") local k = require("layouts/kdenlive")
assert.is.equal(k.keymap.name, mb.current_keymap.name) assert.is.equal(k.keymap.name, mb.current_keymap.name)
@ -46,26 +46,55 @@ describe("Kdenlive keymap", function()
_G.setup() _G.setup()
end) end)
it("colors its keys", function()
for _, keymap in pairs(mb.registered_keymaps()) do
if string.sub(keymap.name, 1, #"kdenlive") == "kdenlive" then
for keyno = 0, 11 do
local keydef = keymap[keyno]
if keydef then
assert.is_truthy(keydef.c)
end
end
end
end
end)
inslit("automatically un-shifts after key press", function() inslit("automatically un-shifts after key press", function()
local some_key = shift.KEY_SHIFT ~= 0 and 0 or 1 local some_key = shift.KEY_SHIFT ~= 0 and 0 or 1
for round = 1, 2 do for round = 1, 2 do
for round = 1, 2 do for round = 1, 2 do
assert.is.equal(k.keymap.name, mb.current_keymap.name) assert.equals(k.keymap.name, mb.current_keymap.name)
hwk.tap(shift.KEY_SHIFT) hwk.tap(shift.KEY_SHIFT)
assert.is.equal(k.keymap_shifted.name, mb.current_keymap.name) assert.equals(k.keymap_shifted.name, mb.current_keymap.name)
hwk.tap(some_key) hwk.tap(some_key)
assert.is.equal(k.keymap.name, mb.current_keymap.name) assert.equals(k.keymap.name, mb.current_keymap.name)
end end
for round = 1, 2 do for round = 1, 2 do
hwk.tap(shift.KEY_SHIFT) hwk.tap(shift.KEY_SHIFT)
assert.is.equal(k.keymap_shifted.name, mb.current_keymap.name) assert.equals(k.keymap_shifted.name, mb.current_keymap.name)
hwk.tap(shift.KEY_SHIFT) hwk.tap(shift.KEY_SHIFT)
assert.is.equal(k.keymap.name, mb.current_keymap.name) assert.equals(k.keymap.name, mb.current_keymap.name)
end end
end end
end) end)
inslit("taps unshifted", function()
local s = spy.on(mb, "tap")
local sm = spy.on(keybow, "set_modifier")
hwk.tap(k.KEY_PROJECT_BEGIN)
assert.spy(s).was.called(1)
assert.spy(sm).was_not.called()
s:clear()
hwk.tap(shift.KEY_SHIFT)
assert.equals(k.keymap_shifted.name, mb.current_keymap.name)
hwk.tap(k.KEY_CLIP_BEGIN)
assert.spy(s).was.called(1)
assert.spy(sm).was.called()
end)
end) end)
end) end)

View File

@ -0,0 +1,48 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
require "mocked-keybow"
local hwk = require("spec/hwkeys")
describe("VSC golang keymap", function()
local mb, go
it("initializes", function()
mb = require("snippets/multibow")
go = require("layouts/vsc-golang")
assert.is.equal(go.keymap.name, mb.current_keymap.name)
assert.is.equal(1, #mb.registered_keymaps())
end)
it("colors its keys", function()
for _, keymap in pairs({go.keymap}) do
for keyno = 0, 11 do
local keydef = keymap[keyno]
if keydef then
assert.is_truthy(keydef.c)
end
end
end
end)
end)

View File

@ -0,0 +1,69 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
require "mocked-keybow"
local mb = require("snippets/multibow")
describe("multibow keys", function()
local tap = spy.on(keybow, "tap_key")
local mod = spy.on(keybow, "set_modifier")
before_each(function()
tap:clear()
mod:clear()
end)
it("taps a plain honest key", function()
mb.tap("x")
assert.spy(tap).was.called(1)
assert.spy(tap).was.called_with("x")
assert.spy(mod).was_not.called()
end)
it("taps a plain honest key", function()
mb.tap("x", keybow.LEFT_CTRL, keybow.LEFT_SHIFT)
assert.spy(tap).was.called(1)
assert.spy(mod).was.called(4)
for _, ud in pairs({keybow.KEY_DOWN, keybow.KEY_UP}) do
assert.spy(mod).was.called_with(keybow.LEFT_CTRL, ud)
assert.spy(mod).was.called_with(keybow.LEFT_SHIFT, ud)
end
end)
it("taps the same key repeatedly", function()
mb.tap_times("x", 3)
assert.spy(tap).was.called(3)
assert.spy(tap).was.called_with("x")
end)
it("taps the same key repeatedly with modifiers", function()
mb.tap_times("x", 3, keybow.LEFT_CTRL)
assert.spy(tap).was.called(3)
assert.spy(tap).was.called_with("x")
assert.spy(mod).was.called(2)
for _, ud in pairs({keybow.KEY_DOWN, keybow.KEY_UP}) do
assert.spy(mod).was.called_with(keybow.LEFT_CTRL, ud)
end
end)
end)

View File

@ -0,0 +1,39 @@
--[[
Copyright 2019 Harald Albrecht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]--
require "mocked-keybow"
local mb = require("snippets/multibow")
describe("multibow LEDs", function()
it("controls brightness", function()
mb.set_brightness(0.5)
assert.equals(0.5, mb.brightness)
mb.set_brightness(1.1)
assert.equals(1.0, mb.brightness)
mb.set_brightness(0)
assert.equals(0.1, mb.brightness)
end)
end)

View File

@ -23,7 +23,7 @@ SOFTWARE.
require "mocked-keybow" require "mocked-keybow"
local hwk = require("spec/hwkeys") local hwk = require("spec/hwkeys")
describe("routehandlers", function() describe("multibow routehandlers", function()
-- ensure to get a fresh multibow module instance each time we run -- ensure to get a fresh multibow module instance each time we run
-- an isolated test... -- an isolated test...