fixes primary keymap cycling
This commit is contained in:
parent
f2682864fb
commit
9848f34d27
|
@ -31,8 +31,15 @@ require(mb.path .. "routehandlers")
|
|||
|
||||
|
||||
mb.brightness = 0.4
|
||||
-- The registered keymaps, indexed by their names (.name field).
|
||||
mb.keymaps = {}
|
||||
-- The ordered sequence of primary keymap, in the sequence they were
|
||||
-- registered.
|
||||
mb.primary_keymaps = {}
|
||||
-- The currently activated keymap.
|
||||
mb.current_keymap = nil
|
||||
|
||||
-- A temporary keymap while grabbing.
|
||||
mb.grab_keymap = nil
|
||||
|
||||
|
||||
|
@ -49,7 +56,6 @@ function mb.tap(keyno, key, ...)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- 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
|
||||
-- default, or permanent or secondary keymaps.
|
||||
|
@ -73,13 +79,14 @@ function mb.register_keymap(keymap)
|
|||
-- register
|
||||
mb.keymaps[name] = keymap
|
||||
-- ensure that first registered keymap also automatically gets activated
|
||||
-- (albeit the LEDs will only update later).
|
||||
-- (albeit the LEDs will only update later). Also maintain the (ordered)
|
||||
-- sequence of registered primary keymaps.
|
||||
if not (keymap.permanent or keymap.secondary) then
|
||||
mb.current_keymap = mb.current_keymap or keymap
|
||||
table.insert(mb.primary_keymaps, keymap)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Returns the list of currently registered keymaps; this list is a table,
|
||||
-- with its registered keymaps at indices 1, 2, ...
|
||||
function mb.registered_keymaps()
|
||||
|
@ -90,35 +97,57 @@ function mb.registered_keymaps()
|
|||
return keymaps
|
||||
end
|
||||
|
||||
-- Returns the list of currently registered primary keymaps, in the same order
|
||||
-- as they were registered. First primary is at index 1, second at 2, ...
|
||||
function mb.registered_primary_keymaps()
|
||||
return mb.primary_keymaps
|
||||
end
|
||||
|
||||
-- Cycles through the available (primary) keymaps, ignoring secondary and
|
||||
-- permanent keymaps. This is convenient for assigning primary keymap switching
|
||||
-- using a key on the Keybow device itself.
|
||||
function mb.cycle_primary_keymaps()
|
||||
local first_name
|
||||
local next = false
|
||||
local next_name
|
||||
for name, keymap in pairs(mb.keymaps) do
|
||||
if not (keymap.permanent or keymap.secondary) then
|
||||
-- Remembers the first "primary" keymap.
|
||||
first_name = first_name or name
|
||||
-- Notice if we just pass the current keymap and then make sure to pick
|
||||
-- up the following primary keymap.
|
||||
if keymap == mb.current_keymap then
|
||||
next = true
|
||||
elseif next then
|
||||
next_name = name
|
||||
next = false
|
||||
local km = mb.current_keymap
|
||||
if km == nil then return end
|
||||
-- If this is a secondary keymap, locate its corresponding primary keymap.
|
||||
if km.secondary then
|
||||
if not km.shift_to then
|
||||
-- No SHIFT's shift_to cyclic chain available, so rely on the naming
|
||||
-- schema instead and try to locate the primary keymap with the first
|
||||
-- match instead. This assumes that the name of the secondary keymaps
|
||||
-- have some suffix and thus are longer than the name of their
|
||||
-- corresponding primary keymap.
|
||||
for idx, pkm in ipairs(mb.primary_keymaps) do
|
||||
if string.sub(km.name, 1, #pkm.name) == pkm.name then
|
||||
km = pkm
|
||||
break
|
||||
end
|
||||
end
|
||||
-- Checks if locating the primary keymap failed and then bails out
|
||||
-- immediately.
|
||||
if km.secondary then return end
|
||||
else
|
||||
-- Follows the cyclic chain of SHIFT's shift_to keymaps, until we get
|
||||
-- to the primary keymap in the cycle, or until we have completed one
|
||||
-- cycle.
|
||||
repeat
|
||||
km = km.shift_to
|
||||
if not km or km == mb.current_keymap then
|
||||
return
|
||||
end
|
||||
until not(km.secondary)
|
||||
end
|
||||
end
|
||||
-- Move on to the next primary keymap, rolling over at the end of our list.
|
||||
for idx, pkm in ipairs(mb.primary_keymaps) do
|
||||
if pkm == km then
|
||||
idx = idx + 1
|
||||
if idx > #mb.primary_keymaps then idx = 1 end
|
||||
mb.activate_keymap(mb.primary_keymaps[idx].name)
|
||||
end
|
||||
next_name = next_name or first_name
|
||||
if first_name then
|
||||
mb.activate_keymap(next_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Activates a specific keymap by name. Please note that it isn't necessary
|
||||
-- to "activate" permanent keymaps at all (and thus this deed cannot be done).
|
||||
function mb.activate_keymap(name)
|
||||
|
@ -150,7 +179,6 @@ function mb.set_brightness(brightness)
|
|||
mb.activate_leds()
|
||||
end
|
||||
|
||||
|
||||
-- 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
|
||||
-- component is in the range [0..1].
|
||||
|
@ -163,7 +191,6 @@ function mb.led(keyno, color)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Restores Keybow LEDs according to current keymap and the permanent keymaps.
|
||||
function mb.activate_leds()
|
||||
keybow.clear_lights()
|
||||
|
@ -185,7 +212,6 @@ function mb.activate_leds()
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Helper function that iterates over all keymap elements but skipping non-key
|
||||
-- bindings.
|
||||
function mb.activate_keymap_leds(keymap)
|
||||
|
@ -197,7 +223,6 @@ function mb.activate_keymap_leds(keymap)
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Disables the automatic Keybow lightshow and sets the key LED colors. This
|
||||
-- is a well-known (hook) function that gets called by the Keybow firmware
|
||||
-- after initialization immediately before waiting for key events.
|
||||
|
@ -209,4 +234,5 @@ function setup()
|
|||
mb.activate_leds()
|
||||
end
|
||||
|
||||
|
||||
return mb -- module
|
||||
|
|
|
@ -33,8 +33,7 @@ describe("multibow", function()
|
|||
mb = require("snippets/multibow")
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("adds permanent keyboard layout, but doesn't activate it", function()
|
||||
inslit("adds permanent keyboard layout, but doesn't activate it", function()
|
||||
local permkm = {
|
||||
name="permanent",
|
||||
permanent=true
|
||||
|
@ -44,16 +43,12 @@ describe("multibow", function()
|
|||
assert.is.equal(mb.keymaps["permanent"], permkm)
|
||||
assert.is_nil(mb.current_keymap)
|
||||
end)
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("checks multibow module is fresh again", function()
|
||||
inslit("checks multibow module is fresh again", function()
|
||||
assert.is_nil(mb.keymaps["permanent"])
|
||||
end)
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("adds permanent, then two primary layouts, activates only first primary layout", function()
|
||||
inslit("adds permanent, then two primary layouts, activates only first primary layout", function()
|
||||
local permkm = {
|
||||
name="permanent",
|
||||
permanent=true
|
||||
|
@ -63,22 +58,76 @@ describe("multibow", function()
|
|||
local prim2km = { name="primary-two" }
|
||||
mb.register_keymap(prim1km)
|
||||
mb.register_keymap(prim2km)
|
||||
assert.is.equal(mb.current_keymap, prim1km)
|
||||
end)
|
||||
assert.is.equal(prim1km, mb.current_keymap)
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("adds secondary, then primary layout, activates only primary layout", function()
|
||||
inslit("sequence of primary keymaps is in registration order", function()
|
||||
local prim1km = { name="last" }
|
||||
local prim2km = { name="first" }
|
||||
mb.register_keymap(prim1km)
|
||||
mb.register_keymap(prim2km)
|
||||
assert.is.same(mb.registered_primary_keymaps(), {prim1km, prim2km})
|
||||
end)
|
||||
|
||||
inslit("adds secondary, then primary layout, activates only primary layout", function()
|
||||
local primkm = { name="berlin" }
|
||||
local seckm = { name="munich", secondary=true }
|
||||
mb.register_keymap(seckm)
|
||||
mb.register_keymap(primkm)
|
||||
assert.is.equal(mb.current_keymap, primkm)
|
||||
end)
|
||||
assert.is.equal(primkm, mb.current_keymap)
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("sets up multibow, activates lights", function()
|
||||
inslit("cycles primary keymaps based on primary-secondary names substring match", function()
|
||||
-- on purpose, the names of the primary keymaps are in reverse lexical order,
|
||||
-- to make sure that cycling follows the registration order, but not the
|
||||
-- name order.
|
||||
local prim1km = { name= "last" }
|
||||
local sec1km = { name="last-shift", secondary=true }
|
||||
local sec2km = { name="xlast-shift", secondary=true}
|
||||
local prim2km = { name= "first" }
|
||||
mb.register_keymap(prim1km)
|
||||
mb.register_keymap(prim2km)
|
||||
mb.register_keymap(sec1km)
|
||||
mb.register_keymap(sec2km)
|
||||
assert.is.equal(4, #mb.registered_keymaps())
|
||||
assert.is.same(mb.registered_primary_keymaps(), {prim1km, prim2km})
|
||||
|
||||
-- cycles from secondary to next primary
|
||||
mb.activate_keymap(sec1km.name)
|
||||
mb.cycle_primary_keymaps()
|
||||
assert.is.equal(prim2km.name, mb.current_keymap.name)
|
||||
-- cycles from last primary to first primary
|
||||
mb.cycle_primary_keymaps()
|
||||
assert.is.equal(prim1km.name, mb.current_keymap.name)
|
||||
-- cannot cycle from misnamed secondary without shift_to
|
||||
mb.activate_keymap(sec2km.name)
|
||||
mb.cycle_primary_keymaps()
|
||||
assert.is.equal(sec2km.name, mb.current_keymap.name)
|
||||
end)
|
||||
|
||||
inslit("cycles primary keymaps based on shift_to", function()
|
||||
-- on purpose, the names of the primary keymaps are in reverse lexical order,
|
||||
-- to make sure that cycling follows the registration order, but not the
|
||||
-- name order.
|
||||
local prim1km = { name= "last" }
|
||||
local sec1km = { name="last-shift", secondary=true, shift_to }
|
||||
prim1km.shift_to = sec1km
|
||||
local prim2km = { name= "first" }
|
||||
mb.register_keymap(prim1km)
|
||||
mb.register_keymap(prim2km)
|
||||
mb.register_keymap(sec1km)
|
||||
assert.is.same(mb.registered_primary_keymaps(), {prim1km, prim2km})
|
||||
|
||||
-- cycles from secondary to next primary
|
||||
mb.activate_keymap(sec1km.name)
|
||||
mb.cycle_primary_keymaps()
|
||||
assert.is.equal(prim2km.name, mb.current_keymap.name)
|
||||
-- cycles from last primary to first primary
|
||||
mb.cycle_primary_keymaps()
|
||||
assert.is.equal(prim1km.name, mb.current_keymap.name)
|
||||
end)
|
||||
|
||||
inslit("sets up multibow, activates lights", function()
|
||||
local s = spy.on(_G, "setup")
|
||||
local al = spy.on(mb, "activate_leds")
|
||||
|
||||
|
@ -89,13 +138,10 @@ describe("multibow", function()
|
|||
s:revert()
|
||||
al:revert()
|
||||
end)
|
||||
end)
|
||||
|
||||
insl(function()
|
||||
it("has more keys", function()
|
||||
inslit("has more keys", function()
|
||||
assert.is_not_nil(keybow.F13)
|
||||
assert.is.equal(keybow.F13, 0x68)
|
||||
end)
|
||||
assert.is.equal(0x68, keybow.F13)
|
||||
end)
|
||||
|
||||
end)
|
||||
|
|
Loading…
Reference in New Issue