changes due to linting; refactors keybow mock stuff to go inside spec/
This commit is contained in:
parent
7328db8666
commit
6fd78c1bf1
4
.busted
4
.busted
|
@ -1,4 +1,4 @@
|
||||||
-- Configuration for "busted" TDD tool
|
-- Configuration for "busted" TDD tool to unit test Multibow
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -24,7 +24,7 @@ SOFTWARE.
|
||||||
|
|
||||||
return {
|
return {
|
||||||
default = {
|
default = {
|
||||||
lpath = "./sdcard/?.lua;./mock/?.lua",
|
lpath = "./sdcard/?.lua;./spec/mock/?.lua",
|
||||||
-- Provides an "insl" convenience replacement for busted's insulate() using
|
-- Provides an "insl" convenience replacement for busted's insulate() using
|
||||||
-- a fixed descriptive text ... or rather, icon. Please not that "insl"
|
-- a fixed descriptive text ... or rather, icon. Please not that "insl"
|
||||||
-- not only rhymes with "insulation", but even more so with the German
|
-- not only rhymes with "insulation", but even more so with the German
|
||||||
|
|
36
.luacheckrc
36
.luacheckrc
|
@ -1,5 +1,37 @@
|
||||||
std = {
|
-- Configuration for "luacheck"ing 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.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
stds.multibow = {
|
||||||
read_globals = {
|
read_globals = {
|
||||||
"insl", "require"
|
-- 3rd party stuff that doesn't exactly play by the new Lua module rules...
|
||||||
|
"keybow",
|
||||||
|
|
||||||
|
-- our unit testing setup
|
||||||
|
"insl", "inslit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std = "max+multibow"
|
||||||
|
|
||||||
|
exclude_files = { "spec/mock/keybow.lua" }
|
||||||
|
|
66
README.md
66
README.md
|
@ -18,6 +18,34 @@ And yes, this is probably a New Year's project slightly gone overboard ...
|
||||||
what sane reason is there to end up with a Lua-scripted multi-layout keyboard
|
what sane reason is there to end up with a Lua-scripted multi-layout keyboard
|
||||||
"operating" system and a bunch of automated unit test cases?
|
"operating" system and a bunch of automated unit test cases?
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Download the [Pibow
|
||||||
|
firmware](https://github.com/pimoroni/keybow-firmware/releases) and copy
|
||||||
|
all files inside its `sdcard/` subdirectory onto an empty, FAT32 formatted
|
||||||
|
microSD card. Copy only the files **inside** `sdcard/`, but do **not**
|
||||||
|
place them into a ~~`sdcard`~~ directory on your microSD card.
|
||||||
|
|
||||||
|
2. Download all files from the `sdcard/` subdirectory of this repository and
|
||||||
|
then copy them onto the microSD card. This will overwrite but one file
|
||||||
|
`key.lua`, all other files are new.
|
||||||
|
|
||||||
|
## Multiple Keyboard Layouts
|
||||||
|
|
||||||
|
To enable one or more multibow keyboard layouts, edit `sdcard/keys.lua`
|
||||||
|
accordingly in order to "`require`" them. The default configuration looks as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require "layouts/shift" -- for cycling between layouts.
|
||||||
|
require "layouts/vsc-golang" -- debugging Go programs in VisualStudio Code.
|
||||||
|
require "layouts/kdenlive" -- editing video using Kdenlive.
|
||||||
|
require "layouts/empty" -- empty, do-nothing layout.
|
||||||
|
```
|
||||||
|
|
||||||
|
> You can disable a specific keyboard layout by simply putting two dashes `--`
|
||||||
|
> in front of the `require "..."`, making it look like `--require "..."`.
|
||||||
|
|
||||||
## Layouts
|
## Layouts
|
||||||
|
|
||||||
The default setup activates the following macro keyboard layouts shown below.
|
The default setup activates the following macro keyboard layouts shown below.
|
||||||
|
@ -56,13 +84,19 @@ Debug Go programs and packages in VisualStudio Code with its Go extension.
|
||||||
|
|
||||||
_coming soon..._
|
_coming soon..._
|
||||||
|
|
||||||
### SHIFT
|
### SHIFT Overlay
|
||||||
|
|
||||||
A SHIFT key, with Keybow LED brightness and keyboard layout cycle control.
|
This layout provides a SHIFT key. Only when pressed and held, two additional
|
||||||
|
keys become active for controlling the brightness of the Keybow LEDs and for
|
||||||
|
switching between multiple keyboard layouts.
|
||||||
|
|
||||||
|
Simply pressing and then immediately releasing the SHIFT key without pressing
|
||||||
|
any of the other keys activates the SHIFT layer in other Multibow keyboard
|
||||||
|
layouts that are SHIFT-aware.
|
||||||
|
|
||||||
> **NOTE:** press and hold SHIFT, then use →LAYOUT and 🔆BRIGHT. The SHIFT key
|
> **NOTE:** press and hold SHIFT, then use →LAYOUT and 🔆BRIGHT. The SHIFT key
|
||||||
> is always active, regardless of keyboard layout. The other keys in this layout
|
> is always active, regardless of keyboard layout. The other keys in this
|
||||||
> only become active _while_ holding SHIFT.
|
> layout become only active _while_ holding SHIFT.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
╔════╗ ╔╌╌╌╌╗ ╔╌╌╌╌╗ ┌╌╌╌╌┐
|
╔════╗ ╔╌╌╌╌╗ ╔╌╌╌╌╗ ┌╌╌╌╌┐
|
||||||
|
@ -169,30 +203,6 @@ The file `keybow.lua` included from
|
||||||
testing purposes is licensed under the MIT license, as declared by Pimoroni's
|
testing purposes is licensed under the MIT license, as declared by Pimoroni's
|
||||||
keybow-firmware GitHub repository.
|
keybow-firmware GitHub repository.
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
1. Download the [Pibow
|
|
||||||
firmware](https://github.com/pimoroni/keybow-firmware/releases) and copy
|
|
||||||
all files inside its `sdcard/` subdirectory onto an empty, FAT32 formatted
|
|
||||||
microSD card. Copy only the files **inside** `sdcard/`, but do **not**
|
|
||||||
place them into a ~~`sdcard`~~ directory on your microSD card.
|
|
||||||
|
|
||||||
2. Download all files from the `sdcard/` subdirectory of this repository and
|
|
||||||
then copy them onto the microSD card. This will overwrite but one file
|
|
||||||
`key.lua`, all other files are new.
|
|
||||||
|
|
||||||
## Multiple Keyboard Layouts
|
|
||||||
|
|
||||||
To enable one or more multibow keyboard layouts, edit `sdcard/keys.lua`
|
|
||||||
accordingly to require them. The default configuration is as follows:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
require "layouts/shift" -- for cycling between layouts.
|
|
||||||
require "layouts/vsc-golang" -- debugging Go programs in VisualStudio Code.
|
|
||||||
require "layouts/kdenlive" -- editing video using Kdenlive.
|
|
||||||
require "layouts/empty" -- empty, do-nothing layout.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
Whether you want to dry-run your own keyboard layout or to hack Multibow: use
|
Whether you want to dry-run your own keyboard layout or to hack Multibow: use
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
hascmd() {
|
||||||
|
command -v "$1" >/dev/null
|
||||||
|
}
|
||||||
|
if ! hascmd busted || ! hascmd luacheck ; then
|
||||||
|
echo "missing busted TDD library and luacheck Lua static source code checker; trying to install..."
|
||||||
|
bash ./setup-tests.sh
|
||||||
|
fi
|
||||||
|
echo "testing..."
|
||||||
|
busted
|
||||||
|
echo "linting..."
|
||||||
|
luacheck -q ./sdcard ./spec
|
|
@ -1,16 +0,0 @@
|
||||||
local busted=require "busted"
|
|
||||||
|
|
||||||
require "keybow"
|
|
||||||
busted.stub(keybow, "auto_lights")
|
|
||||||
busted.stub(keybow, "clear_lights")
|
|
||||||
busted.stub(keybow, "load_pattern")
|
|
||||||
busted.stub(keybow, "set_pixel")
|
|
||||||
-- keybow.set_pixel = function(led, r, g, b) print("LED #"..led..", "..r..", "..g..", "..b) end
|
|
||||||
busted.stub(keybow, "set_key")
|
|
||||||
busted.stub(keybow, "set_modifier")
|
|
||||||
busted.stub(keybow, "tap_key")
|
|
||||||
|
|
||||||
busted.stub(keybow, "sleep") -- FIXME
|
|
||||||
busted.stub(keybow, "usleep") -- FIXME
|
|
||||||
|
|
||||||
return keybow
|
|
|
@ -1,5 +1,5 @@
|
||||||
-- An empty Multibow Keybow layout. Useful for "switching off" any active
|
-- An empty Multibow layout. Useful for "switching off" any active keymaps,
|
||||||
-- keymaps, with only the permanent keymaps (SHIFT, etc) being still in place.
|
-- with only the permanent keymaps (SHIFT, etc) being still in place.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
-- A Multibow keyboard layout for the Kdenlive (https://kdenlive.org/) open
|
||||||
|
-- source non-linear video editor.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
|
||||||
|
@ -20,15 +23,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
|
||||||
-- allow users to set their own configuration before req'ing this
|
-- allow users to set their own configuration before req'ing this
|
||||||
-- module, in order to control the key layout. For defaults, please see
|
-- module, in order to control the key layout. For defaults, please see
|
||||||
-- below.
|
-- below.
|
||||||
local k = _G.kdenlive or {} -- module
|
local k = _G.kdenlive or {} -- module
|
||||||
|
|
||||||
require("keybow")
|
|
||||||
local mk = require("snippets/morekeys")
|
|
||||||
local mb = require("snippets/multibow")
|
local mb = require("snippets/multibow")
|
||||||
|
|
||||||
|
-- luacheck: ignore 614
|
||||||
--[[
|
--[[
|
||||||
The Keybow layout is as follows when in landscape orientation, with the USB
|
The Keybow layout is as follows when in landscape orientation, with the USB
|
||||||
cable going off "northwards":
|
cable going off "northwards":
|
||||||
|
@ -77,7 +80,7 @@ end
|
||||||
|
|
||||||
-- 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(_)
|
||||||
mb.activate_keymap(k.keymap.name)
|
mb.activate_keymap(k.keymap.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -97,15 +100,15 @@ k.keymap = k.init_color({
|
||||||
name="kdenlive",
|
name="kdenlive",
|
||||||
[k.KEY_ZONE_BEGIN] = {press=function() mb.tap("I") end},
|
[k.KEY_ZONE_BEGIN] = {press=function() mb.tap("I") end},
|
||||||
[k.KEY_ZONE_END] = {press=function() mb.tap("O") end},
|
[k.KEY_ZONE_END] = {press=function() mb.tap("O") end},
|
||||||
[k.KEY_CLIP_BEGIN] = {press=function() mb.tap(mk.HOME) end},
|
[k.KEY_CLIP_BEGIN] = {press=function() mb.tap(keybow.HOME) end},
|
||||||
[k.KEY_CLIP_END] = {press=function() mb.tap(mk.END) end},
|
[k.KEY_CLIP_END] = {press=function() mb.tap(keybow.END) end},
|
||||||
[k.KEY_PLAY_AROUND_MOUSE] = {press=function() k.play_around_mouse(keybow.SPACE, keybow.LEFT_CTRL) end},
|
[k.KEY_PLAY_AROUND_MOUSE] = {press=function() k.play_around_mouse(keybow.SPACE, keybow.LEFT_CTRL) end},
|
||||||
}, k.COLOR_UNSHIFTED)
|
}, k.COLOR_UNSHIFTED)
|
||||||
k.keymap_shifted = k.init_color({
|
k.keymap_shifted = k.init_color({
|
||||||
name="kdenlive-shifted",
|
name="kdenlive-shifted",
|
||||||
secondary=true,
|
secondary=true,
|
||||||
[k.KEY_PROJECT_BEGIN] = {press=function() mb.tap(mk.HOME, keybow.LEFT_CTRL) end},
|
[k.KEY_PROJECT_BEGIN] = {press=function() mb.tap(keybow.HOME, keybow.LEFT_CTRL) end},
|
||||||
[k.KEY_PROJECT_END] = {press=function() mb.tap(mk.END, keybow.LEFT_CTRL) end},
|
[k.KEY_PROJECT_END] = {press=function() mb.tap(keybow.END, keybow.LEFT_CTRL) end},
|
||||||
[k.KEY_PLAY_AROUND_MOUSE] = {press=function() k.play_around_mouse(keybow.SPACE, keybow.LEFT_ALT) end},
|
[k.KEY_PLAY_AROUND_MOUSE] = {press=function() k.play_around_mouse(keybow.SPACE, keybow.LEFT_ALT) end},
|
||||||
[-1] = {release=k.unshift},
|
[-1] = {release=k.unshift},
|
||||||
}, k.COLOR_SHIFTED)
|
}, k.COLOR_SHIFTED)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
-- An empty Multibow Keybow layout. Useful for "switching off" any active
|
-- A Multibow template layout, useful for starting your own keymap layouts.
|
||||||
-- keymaps, with only the permanent keymaps (SHIFT, etc) being still in place.
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -45,11 +44,11 @@ cable going off "northwards":
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
-- Some action on a certain key press...
|
-- Some action on a certain key press...
|
||||||
function km.mypress(keyno)
|
function km.mypress(keyno) -- luacheck: ignore 212
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Some action on a certain key release...
|
-- Some action on a certain key release...
|
||||||
function km.myrelease(keyno)
|
function km.myrelease(keyno) -- luacheck: ignore 212
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The keymap layout...
|
-- The keymap layout...
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
-- A permanent "SHIFT" keymap for cycling keymaps and LED brightness control.
|
-- A permanent "SHIFT" Multibow keymap layout for cycling keymaps, LED
|
||||||
|
-- brightness control, and adding SHIFT layers to other Multibow keyboard
|
||||||
|
-- (multi) layouts.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -29,6 +31,7 @@ local shift = _G.shift or {} -- module
|
||||||
|
|
||||||
local mb = require "snippets/multibow"
|
local mb = require "snippets/multibow"
|
||||||
|
|
||||||
|
-- luacheck: ignore 614
|
||||||
--[[
|
--[[
|
||||||
The Keybow layout is as follows when in landscape orientation, with the USB
|
The Keybow layout is as follows when in landscape orientation, with the USB
|
||||||
cable going off "northwards":
|
cable going off "northwards":
|
||||||
|
@ -79,12 +82,12 @@ end
|
||||||
|
|
||||||
-- Remember how many grabbed keys are pressed, so we won't ungrab later until
|
-- Remember how many grabbed keys are pressed, so we won't ungrab later until
|
||||||
-- all keys have been released.
|
-- all keys have been released.
|
||||||
function shift.any_press(keyno)
|
function shift.any_press(_)
|
||||||
grabbed_key_count = grabbed_key_count + 1
|
grabbed_key_count = grabbed_key_count + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Only ungrab after last key has been released
|
-- Only ungrab after last key has been released
|
||||||
function shift.any_release(keyno)
|
function shift.any_release(_)
|
||||||
if grabbed_key_count > 0 then
|
if grabbed_key_count > 0 then
|
||||||
grabbed_key_count = grabbed_key_count - 1
|
grabbed_key_count = grabbed_key_count - 1
|
||||||
if grabbed_key_count == 0 then
|
if grabbed_key_count == 0 then
|
||||||
|
@ -101,16 +104,13 @@ end
|
||||||
-- SHIFT press: switches into grabbed SHIFT mode, activating the in-SHIFT keys
|
-- SHIFT press: switches into grabbed SHIFT mode, activating the in-SHIFT keys
|
||||||
-- for brightness change, keymap cycling, et cetera.
|
-- for brightness change, keymap cycling, et cetera.
|
||||||
function shift.shift(key)
|
function shift.shift(key)
|
||||||
grabbed_keys = 1 -- includes myself; this is necessary as the grab "any"
|
|
||||||
-- handler will not register the SHIFT press, because it
|
|
||||||
-- wasn't grabbed yet.
|
|
||||||
shift_only = true
|
shift_only = true
|
||||||
shift.any_press(key)
|
shift.any_press(key)
|
||||||
mb.grab(shift.keymap_shifted.name)
|
mb.grab(shift.keymap_shifted.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cycles to the next primary keyboard layout (keymap)
|
-- Cycles to the next primary keyboard layout (keymap)
|
||||||
function shift.cycle(key)
|
function shift.cycle(_)
|
||||||
shift_only = false
|
shift_only = false
|
||||||
mb.cycle_primary_keymaps()
|
mb.cycle_primary_keymaps()
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,27 @@
|
||||||
-- VSC Go extension debug Keybow layout
|
-- A Multibow keyboard layout for the VisualStudio Go extension
|
||||||
|
-- (https://github.com/Microsoft/vscode-go).
|
||||||
|
|
||||||
|
--[[
|
||||||
|
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.
|
||||||
|
]]--
|
||||||
|
|
||||||
local vscgo = _G.vscgo or {} -- module
|
local vscgo = _G.vscgo or {} -- module
|
||||||
|
|
||||||
|
@ -52,31 +75,31 @@ 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 --
|
||||||
|
|
||||||
function vscgo.debug_stop(key)
|
function vscgo.debug_stop(_)
|
||||||
mb.tap(keybow.F5, keybow.LEFT_SHIFT)
|
mb.tap(keybow.F5, keybow.LEFT_SHIFT)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.debug_restart(key)
|
function vscgo.debug_restart(_)
|
||||||
mb.tap(keybow.F5, keybow.LEFT_SHIFT, keybow.LEFT_CTRL)
|
mb.tap(keybow.F5, keybow.LEFT_SHIFT, keybow.LEFT_CTRL)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.debug_continue(key)
|
function vscgo.debug_continue(_)
|
||||||
mb.tap(keybow.F5)
|
mb.tap(keybow.F5)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.debug_stepover(key)
|
function vscgo.debug_stepover(_)
|
||||||
mb.tap(keybow.F10)
|
mb.tap(keybow.F10)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.debug_stepinto(key)
|
function vscgo.debug_stepinto(_)
|
||||||
mb.tap(keybow.F11)
|
mb.tap(keybow.F11)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.debug_stepout(key)
|
function vscgo.debug_stepout(_)
|
||||||
mb.tap(keybow.F11, keybow.LEFT_SHIFT)
|
mb.tap(keybow.F11, keybow.LEFT_SHIFT)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vscgo.go_test_package(key)
|
function vscgo.go_test_package(_)
|
||||||
mb.tap("P", keybow.LEFT_SHIFT, keybow.LEFT_CTRL)
|
mb.tap("P", keybow.LEFT_SHIFT, keybow.LEFT_CTRL)
|
||||||
keybow.sleep(250)
|
keybow.sleep(250)
|
||||||
keybow.text("go test package")
|
keybow.text("go test package")
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
-- Multibow internal "module" implementing keymap-related management and
|
||||||
|
-- handling.
|
||||||
|
|
||||||
|
--[[
|
||||||
|
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.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
-- luacheck: globals mb
|
||||||
|
|
||||||
|
-- Internal variables for housekeeping...
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
-- A primary keymap is any keymap without either a "permanent" or "secondary"
|
||||||
|
-- table element. Users can cycle through primary keymaps using the "shift"
|
||||||
|
-- permanent keyboard layout.
|
||||||
|
--
|
||||||
|
-- permanent keymaps (marked by table element "permanent=true") are always
|
||||||
|
-- active, thus they don't need to be activated.
|
||||||
|
--
|
||||||
|
-- Secondary keymaps (marked by table element "secondary=true") are intended
|
||||||
|
-- as SHIFT/modifier layers. As such the get ignored by cycling, but instead
|
||||||
|
-- need to be activated explicitly. The "shift" permanent keyboard layout
|
||||||
|
-- automates this.
|
||||||
|
--
|
||||||
|
-- If this is the first keymap getting registered, then it will also made
|
||||||
|
-- activated.
|
||||||
|
function mb.register_keymap(keymap)
|
||||||
|
local name = keymap.name
|
||||||
|
-- register
|
||||||
|
mb.keymaps[name] = keymap
|
||||||
|
-- ensure that first registered keymap also automatically gets activated
|
||||||
|
-- (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()
|
||||||
|
local keymaps = {}
|
||||||
|
for _, keymap in pairs(mb.keymaps) do
|
||||||
|
table.insert(keymaps, keymap)
|
||||||
|
end
|
||||||
|
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 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 _, 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
|
||||||
|
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)
|
||||||
|
name = type(name) == "table" and name.name or name
|
||||||
|
local keymap = mb.keymaps[name]
|
||||||
|
if keymap and not keymap.permanent then
|
||||||
|
mb.current_keymap = keymap
|
||||||
|
mb.activate_leds()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sets a "grabbing" keymap that takes (temporarily) grabs all keys. While a
|
||||||
|
-- grab keymap is in place, key presses and releases will only be routed to
|
||||||
|
-- the grab keymap, but never to the permanent keymaps, nor the previously
|
||||||
|
-- "active" primary keymap.
|
||||||
|
function mb.grab(name)
|
||||||
|
name = type(name) == "table" and name.name or name
|
||||||
|
mb.grab_keymap = mb.keymaps[name]
|
||||||
|
mb.activate_leds()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Removes a "grabbing" keymap, thus reactivating the permanent keymaps, as
|
||||||
|
-- well as the previously active primary keymap.
|
||||||
|
function mb.ungrab()
|
||||||
|
mb.grab_keymap = nil
|
||||||
|
mb.activate_leds()
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
-- Part of Multibow
|
-- Multibow internal "module" implementing convenience functions for sending
|
||||||
|
-- key presses to the USB host to which the Keybow device is connected to.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -22,6 +23,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
-- luacheck: globals mb
|
||||||
|
|
||||||
|
-- Default delay between rapidly (repeated) key presses, can be overridden.
|
||||||
|
mb.KEY_DELAY_MS = mb.KEY_DELAY_MS or 100
|
||||||
|
|
||||||
|
-- Delay between key presses
|
||||||
|
function mb.delay()
|
||||||
|
keybow.sleep(mb.KEY_DELAY_MS)
|
||||||
|
end
|
||||||
|
|
||||||
-- Sends a single key tap to the USB host, optionally with modifier keys, such
|
-- 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"
|
-- 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
|
-- parameter can be a string or a Keybow key code, such as keybow.HOME, et
|
||||||
|
@ -36,15 +47,14 @@ end
|
||||||
function mb.tap_times(key, times, ...)
|
function mb.tap_times(key, times, ...)
|
||||||
for modifier_argno = 1, select("#", ...) do
|
for modifier_argno = 1, select("#", ...) do
|
||||||
local modifier = select(modifier_argno, ...)
|
local modifier = select(modifier_argno, ...)
|
||||||
if modifier then; keybow.set_modifier(modifier, keybow.KEY_DOWN); end
|
if modifier then keybow.set_modifier(modifier, keybow.KEY_DOWN) end
|
||||||
end
|
end
|
||||||
for tap = 1, times do
|
for _ = 1, times do
|
||||||
keybow.tap_key(key)
|
keybow.tap_key(key)
|
||||||
keybow.sleep(100)
|
mb.delay()
|
||||||
end
|
end
|
||||||
for modifier_argno = 1, select("#", ...) do
|
for modifier_argno = 1, select("#", ...) do
|
||||||
local modifier = select(modifier_argno, ...)
|
local modifier = select(modifier_argno, ...)
|
||||||
if modifier then; keybow.set_modifier(modifier, keybow.KEY_UP); end
|
if modifier then keybow.set_modifier(modifier, keybow.KEY_UP) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
-- Part of Multibow
|
-- Multibow internal "module" implementing Keybow LED-related functionality,
|
||||||
|
-- such as brightness control and "lighting up" a (multibow) keymap.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -23,6 +24,8 @@ SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
|
||||||
|
-- luacheck: globals mb
|
||||||
|
|
||||||
mb.MIN_BRIGHTNESS = mb.MIN_BRIGHTNESS or 0.1
|
mb.MIN_BRIGHTNESS = mb.MIN_BRIGHTNESS or 0.1
|
||||||
|
|
||||||
-- Default LED brightness in the [0.1..1] range.
|
-- Default LED brightness in the [0.1..1] range.
|
||||||
|
@ -74,7 +77,7 @@ function mb.activate_leds()
|
||||||
end
|
end
|
||||||
-- ...then update LEDs from permanent keymap(s), as this ensures that
|
-- ...then update LEDs from permanent keymap(s), as this ensures that
|
||||||
-- the permanent keymaps take precedence.
|
-- the permanent keymaps take precedence.
|
||||||
for name, keymap in pairs(mb.keymaps) do
|
for _, keymap in pairs(mb.keymaps) do
|
||||||
if keymap.permanent then
|
if keymap.permanent then
|
||||||
mb.activate_keymap_leds(keymap)
|
mb.activate_keymap_leds(keymap)
|
||||||
end
|
end
|
||||||
|
@ -93,4 +96,3 @@ function mb.activate_keymap_leds(keymap)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
-- Multibow module providing additional USB HID keycode definitions to augment
|
||||||
|
-- the existing keybow definitions. For more information about USB HID
|
||||||
|
-- keyboard scan codes, for instance, see:
|
||||||
|
-- https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Provide additional keybow USB HID key definitions.
|
|
||||||
|
|
||||||
For more information about USB HID keyboard scan codes, for instance,
|
|
||||||
see: https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2
|
|
||||||
|
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
@ -27,6 +27,11 @@ SOFTWARE.
|
||||||
|
|
||||||
require("keybow")
|
require("keybow")
|
||||||
|
|
||||||
|
-- Tell luacheck that it is okay in this specific case to change the keybow
|
||||||
|
-- global.
|
||||||
|
|
||||||
|
-- luacheck: globals keybow
|
||||||
|
|
||||||
keybow.SYSRQ = 0x46
|
keybow.SYSRQ = 0x46
|
||||||
keybow.SCROLLLOCK = 0x47
|
keybow.SCROLLLOCK = 0x47
|
||||||
keybow.PAUSE = 0x48
|
keybow.PAUSE = 0x48
|
|
@ -1,4 +1,6 @@
|
||||||
-- Part of Multibow
|
-- Multibow internal "module" implementing routing Keybow hardware key presses
|
||||||
|
-- and releases from the Keybow Lua firmware to our keymaps with their own key
|
||||||
|
-- handlers.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
@ -22,6 +24,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]] --
|
]] --
|
||||||
|
|
||||||
|
|
||||||
|
-- luacheck: globals mb
|
||||||
|
|
||||||
-- This all-key, central key router forwards Keybow key events to their
|
-- This all-key, central key router forwards Keybow key events to their
|
||||||
-- correct handlers, depending on which keyboard layout currently is active.
|
-- correct handlers, depending on which keyboard layout currently is active.
|
||||||
--
|
--
|
||||||
|
@ -47,7 +52,7 @@ function mb.route(keyno, pressed)
|
||||||
-- No grab in place, so continue checking for a matching key in the
|
-- No grab in place, so continue checking for a matching key in the
|
||||||
-- permanent keymaps first. Remember, there cannot be "any" handlers
|
-- permanent keymaps first. Remember, there cannot be "any" handlers
|
||||||
-- with permanent keymaps.
|
-- with permanent keymaps.
|
||||||
for name, keymap in pairs(mb.keymaps) do
|
for _, keymap in pairs(mb.keymaps) do
|
||||||
if keymap.permanent then
|
if keymap.permanent then
|
||||||
keydef = keymap[keyno]
|
keydef = keymap[keyno]
|
||||||
if keydef then
|
if keydef then
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
-- "Multibow" is a Lua module for Pimoroni's Keybow firmware that offers and
|
||||||
|
-- manages multiple keyboard layouts.
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Copyright 2019 Harald Albrecht
|
Copyright 2019 Harald Albrecht
|
||||||
|
|
||||||
|
@ -20,149 +23,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
mb = {} -- module
|
-- luacheck: globals mb
|
||||||
|
mb = mb or {} -- module
|
||||||
|
|
||||||
require "keybow"
|
require "keybow"
|
||||||
|
|
||||||
|
-- Pulls in the individual modules that make up Multibow.
|
||||||
mb.path = (...):match("^(.-)[^%/]+$")
|
mb.path = (...):match("^(.-)[^%/]+$")
|
||||||
|
|
||||||
require(mb.path .. "morekeys")
|
require(mb.path .. "mb/morekeys")
|
||||||
|
require(mb.path .. "mb/keymaps")
|
||||||
require(mb.path .. "mb/keys")
|
require(mb.path .. "mb/keys")
|
||||||
require(mb.path .. "mb/routehandlers")
|
require(mb.path .. "mb/routehandlers")
|
||||||
require(mb.path .. "mb/leds")
|
require(mb.path .. "mb/leds")
|
||||||
|
|
||||||
|
|
||||||
-- Internal variables for housekeeping...
|
|
||||||
|
|
||||||
-- 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
|
|
||||||
|
|
||||||
|
|
||||||
-- 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.
|
|
||||||
--
|
|
||||||
-- A primary keymap is any keymap without either a "permanent" or "secondary"
|
|
||||||
-- table element. Users can cycle through primary keymaps using the "shift"
|
|
||||||
-- permanent keyboard layout.
|
|
||||||
--
|
|
||||||
-- permanent keymaps (marked by table element "permanent=true") are always
|
|
||||||
-- active, thus they don't need to be activated.
|
|
||||||
--
|
|
||||||
-- Secondary keymaps (marked by table element "secondary=true") are intended
|
|
||||||
-- as SHIFT/modifier layers. As such the get ignored by cycling, but instead
|
|
||||||
-- need to be activated explicitly. The "shift" permanent keyboard layout
|
|
||||||
-- automates this.
|
|
||||||
--
|
|
||||||
-- If this is the first keymap getting registered, then it will also made
|
|
||||||
-- activated.
|
|
||||||
function mb.register_keymap(keymap)
|
|
||||||
local name = keymap.name
|
|
||||||
-- register
|
|
||||||
mb.keymaps[name] = keymap
|
|
||||||
-- ensure that first registered keymap also automatically gets activated
|
|
||||||
-- (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()
|
|
||||||
local keymaps = {}
|
|
||||||
for name, keymap in pairs(mb.keymaps) do
|
|
||||||
table.insert(keymaps, keymap)
|
|
||||||
end
|
|
||||||
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 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
|
|
||||||
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)
|
|
||||||
local keymap = mb.keymaps[name]
|
|
||||||
if keymap and not keymap.permanent then
|
|
||||||
mb.current_keymap = keymap
|
|
||||||
mb.activate_leds()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
function mb.grab(name)
|
|
||||||
mb.grab_keymap = mb.keymaps[name]
|
|
||||||
mb.activate_leds()
|
|
||||||
end
|
|
||||||
|
|
||||||
function mb.ungrab()
|
|
||||||
mb.grab_keymap = nil
|
|
||||||
mb.activate_leds()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Disables the automatic Keybow lightshow and sets the key LED colors. This
|
-- 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
|
-- is a well-known (hook) function that gets called by the Keybow firmware
|
||||||
-- after initialization immediately before waiting for key events.
|
-- after initialization immediately before waiting for key events.
|
||||||
|
-- luacheck: globals setup
|
||||||
function setup()
|
function setup()
|
||||||
-- Disables the automatic keybow lightshow and switches all key LEDs off
|
-- Disables the automatic keybow lightshow and switches all key LEDs off
|
||||||
-- because the LEDs might be in a random state after power on.
|
-- because the LEDs might be in a random state after power on.
|
||||||
|
|
|
@ -6,3 +6,5 @@ sudo apt-get install --yes lua5.3 liblua5.3-dev
|
||||||
sudo update-alternatives --install /usr/bin/lua lua /usr/bin/lua5.3 10
|
sudo update-alternatives --install /usr/bin/lua lua /usr/bin/lua5.3 10
|
||||||
sudo apt-get install --yes luarocks
|
sudo apt-get install --yes luarocks
|
||||||
sudo luarocks install busted
|
sudo luarocks install busted
|
||||||
|
sudo luarocks install luasocket
|
||||||
|
sudo luarocks install luacheck
|
||||||
|
|
|
@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
hwk = {} -- module
|
local hwk = {} -- module
|
||||||
|
|
||||||
-- Convenience: returns the name of a Keybow key handler function for the
|
-- Convenience: returns the name of a Keybow key handler function for the
|
||||||
-- given key number.
|
-- given key number.
|
||||||
|
|
|
@ -20,6 +20,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
-- luacheck: globals handle_key_00 handle_key_01
|
||||||
|
|
||||||
local hwk = require("spec/hwkeys")
|
local hwk = require("spec/hwkeys")
|
||||||
|
|
||||||
describe("Keybow hardware key handler module", function()
|
describe("Keybow hardware key handler module", function()
|
||||||
|
|
|
@ -62,15 +62,15 @@ describe("Kdenlive keymap", function()
|
||||||
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 -- luacheck: ignore 213
|
||||||
for round = 1, 2 do
|
for round = 1, 2 do -- luacheck: ignore 213 423
|
||||||
assert.equals(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.equals(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.equals(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 -- luacheck: ignore 213 423
|
||||||
hwk.tap(shift.KEY_SHIFT)
|
hwk.tap(shift.KEY_SHIFT)
|
||||||
assert.equals(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)
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe("SHIFT multibow keymap", function()
|
||||||
-- SHIFT must register exactly two keymaps, a primary and a secondary one.
|
-- SHIFT must register exactly two keymaps, a primary and a secondary one.
|
||||||
local kms = mb.registered_keymaps()
|
local kms = mb.registered_keymaps()
|
||||||
assert.is.equal(#kms, 2)
|
assert.is.equal(#kms, 2)
|
||||||
for idx, keymap in ipairs(kms) do
|
for _, keymap in ipairs(kms) do
|
||||||
if keymap == "shift" then
|
if keymap == "shift" then
|
||||||
assert.is_falsy(keymap.permanent)
|
assert.is_falsy(keymap.permanent)
|
||||||
assert.is_falsy(keymap.secondary)
|
assert.is_falsy(keymap.secondary)
|
||||||
|
@ -47,8 +47,6 @@ describe("SHIFT multibow keymap", function()
|
||||||
assert.is_true(keymap.secondary)
|
assert.is_true(keymap.secondary)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
default_key_shift = shift.KEY_SHIFT
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
inslit("accepts changes form default", function()
|
inslit("accepts changes form default", function()
|
||||||
|
@ -99,7 +97,7 @@ describe("SHIFT multibow keymap", function()
|
||||||
|
|
||||||
-- but that SHIFT followed by another function doesn't shift.
|
-- but that SHIFT followed by another function doesn't shift.
|
||||||
shift.shift_secondary_keymap:clear()
|
shift.shift_secondary_keymap:clear()
|
||||||
for idx, key in ipairs({
|
for _, key in ipairs({
|
||||||
shift.KEY_LAYOUT,
|
shift.KEY_LAYOUT,
|
||||||
shift.KEY_BRIGHTNESS
|
shift.KEY_BRIGHTNESS
|
||||||
}) do
|
}) do
|
||||||
|
@ -117,7 +115,7 @@ describe("SHIFT multibow keymap", function()
|
||||||
}
|
}
|
||||||
local keymap_shifted = {
|
local keymap_shifted = {
|
||||||
name="test-shifted",
|
name="test-shifted",
|
||||||
[0]={press=function(key) end}
|
[0]={press=function(_) end}
|
||||||
}
|
}
|
||||||
keymap.shift_to = keymap_shifted
|
keymap.shift_to = keymap_shifted
|
||||||
keymap_shifted.shift_to = keymap
|
keymap_shifted.shift_to = keymap
|
||||||
|
|
|
@ -21,7 +21,7 @@ SOFTWARE.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
require "mocked-keybow"
|
require "mocked-keybow"
|
||||||
local hwk = require("spec/hwkeys")
|
require("spec/hwkeys")
|
||||||
|
|
||||||
describe("VSC golang keymap", function()
|
describe("VSC golang keymap", function()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
-- Mocks some parts of the Keybow Lua module during unit tests, so we can run
|
||||||
|
-- the tests outside the Keybow firmware on a standard (full-blown) Lua host
|
||||||
|
-- system.
|
||||||
|
|
||||||
|
--[[
|
||||||
|
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.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local busted=require("busted")
|
||||||
|
local sock=require("socket")
|
||||||
|
|
||||||
|
require "keybow"
|
||||||
|
-- luacheck: globals keybow.no_delay
|
||||||
|
keybow.no_delay = keybow.no_delay or true
|
||||||
|
|
||||||
|
busted.stub(keybow, "auto_lights")
|
||||||
|
busted.stub(keybow, "clear_lights")
|
||||||
|
busted.stub(keybow, "load_pattern")
|
||||||
|
busted.stub(keybow, "set_pixel")
|
||||||
|
busted.stub(keybow, "set_key")
|
||||||
|
busted.stub(keybow, "set_modifier")
|
||||||
|
busted.stub(keybow, "tap_key")
|
||||||
|
|
||||||
|
-- luacheck: globals keybow.sleep
|
||||||
|
function keybow.sleep(ms)
|
||||||
|
if not keybow.no_delay then
|
||||||
|
sock.sleep(ms / 1000)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- luacheck: globals keybow.usleep
|
||||||
|
function keybow.usleep(us)
|
||||||
|
keybow.sleep(us / 1000)
|
||||||
|
end
|
||||||
|
|
||||||
|
return keybow -- adhere to Lua's (new) module rules
|
|
@ -0,0 +1,50 @@
|
||||||
|
--[[
|
||||||
|
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.
|
||||||
|
]]--
|
||||||
|
|
||||||
|
-- luacheck: globals keybow.no_delay
|
||||||
|
require("mocked-keybow")
|
||||||
|
|
||||||
|
describe("Mocked Keybow API", function()
|
||||||
|
|
||||||
|
local sock=require("socket")
|
||||||
|
|
||||||
|
local sleep = function(time, factor, sf, on)
|
||||||
|
local old = keybow.no_delay
|
||||||
|
keybow.no_delay = not on
|
||||||
|
local start = sock.gettime()
|
||||||
|
sf(time)
|
||||||
|
local delay = (sock.gettime() - start) * factor
|
||||||
|
keybow.no_delay = old
|
||||||
|
return delay
|
||||||
|
end
|
||||||
|
|
||||||
|
it("delays ms or not", function()
|
||||||
|
assert.is_true(sleep(10, 1000, keybow.sleep, true) >= 10)
|
||||||
|
assert.is_true(sleep(10, 1000, keybow.sleep, false) < 10)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("delays us or not", function()
|
||||||
|
assert.is_true(sleep(10, 1000*1000, keybow.usleep, true) >= 10)
|
||||||
|
assert.is_true(sleep(10, 1000*1000, keybow.usleep, false) < 10)
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
|
@ -40,7 +40,7 @@ describe("multibow LEDs", function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("cycles brightness", function()
|
it("cycles brightness", function()
|
||||||
function f(b, scale)
|
local f = function(b, scale)
|
||||||
local copy = table.pack(table.unpack(b))
|
local copy = table.pack(table.unpack(b))
|
||||||
local len = #b
|
local len = #b
|
||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
|
|
|
@ -109,8 +109,8 @@ describe("multibow", function()
|
||||||
-- on purpose, the names of the primary keymaps are in reverse lexical order,
|
-- 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
|
-- to make sure that cycling follows the registration order, but not the
|
||||||
-- name order.
|
-- name order.
|
||||||
local prim1km = { name= "last" }
|
local prim1km = { name= "last", shift_to=nil }
|
||||||
local sec1km = { name="last-shift", secondary=true, shift_to }
|
local sec1km = { name="last-shift", secondary=true, shift_to=nil }
|
||||||
prim1km.shift_to = sec1km
|
prim1km.shift_to = sec1km
|
||||||
local prim2km = { name= "first" }
|
local prim2km = { name= "first" }
|
||||||
mb.register_keymap(prim1km)
|
mb.register_keymap(prim1km)
|
||||||
|
|
|
@ -23,26 +23,26 @@ SOFTWARE.
|
||||||
require "mocked-keybow"
|
require "mocked-keybow"
|
||||||
local hwk = require("spec/hwkeys")
|
local hwk = require("spec/hwkeys")
|
||||||
|
|
||||||
describe("multibow routehandlers", function()
|
describe("Multibow route handlers", 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...
|
||||||
local mb
|
local mb
|
||||||
|
|
||||||
local spies = mock({
|
local spies = mock({
|
||||||
prim_key_press=function(key) end,
|
prim_key_press=function(_) end,
|
||||||
prim_key_release=function(key) end,
|
prim_key_release=function(_) end,
|
||||||
prim_otherkey_press=function(key) end,
|
prim_otherkey_press=function(_) end,
|
||||||
prim_otherkey_release=function(key) end,
|
prim_otherkey_release=function(_) end,
|
||||||
|
|
||||||
sec_key_press=function(key) end,
|
sec_key_press=function(_) end,
|
||||||
sec_key_release=function(key) end,
|
sec_key_release=function(_) end,
|
||||||
|
|
||||||
perm_key_press=function(key) end,
|
perm_key_press=function(_) end,
|
||||||
perm_key_release=function(key) end,
|
perm_key_release=function(_) end,
|
||||||
|
|
||||||
grab_key_press=function(key) end,
|
grab_key_press=function(_) end,
|
||||||
grab_key_release=function(key) end,
|
grab_key_release=function(_) end,
|
||||||
})
|
})
|
||||||
|
|
||||||
local primary_keymap = {
|
local primary_keymap = {
|
||||||
|
@ -67,10 +67,9 @@ describe("multibow routehandlers", function()
|
||||||
}
|
}
|
||||||
|
|
||||||
before_each(function()
|
before_each(function()
|
||||||
require("keybow")
|
|
||||||
mb = require("snippets/multibow")
|
mb = require("snippets/multibow")
|
||||||
-- make sure to clear our spies
|
-- make sure to clear our spies
|
||||||
for name, schlapphut in pairs(spies) do
|
for _, schlapphut in pairs(spies) do
|
||||||
schlapphut:clear()
|
schlapphut:clear()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
Loading…
Reference in New Issue