improves readme; updates kdenlive keymap
This commit is contained in:
parent
9756bacaea
commit
7328db8666
56
README.md
56
README.md
|
@ -103,6 +103,62 @@ layout by courtesy of Margaret Thatcher._)
|
||||||
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Your Own Multikey Keyboard Layout
|
||||||
|
|
||||||
|
You may want to start from our template in `layouts/keymap-template.lua`.
|
||||||
|
|
||||||
|
1. copy and rename the new layout file name to something more meaningful.
|
||||||
|
|
||||||
|
2. edit your new layout file and change its name which is specified in the
|
||||||
|
`kmt.name` element:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
km.keymap = {
|
||||||
|
-- IMPORTANT: Make sure to change the keymap name to make it unique!
|
||||||
|
name="my-cool-layout",
|
||||||
|
-- ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. add key definitions for colors and handlers as necessary, see next for examples.
|
||||||
|
|
||||||
|
* you can specify key handlers either "inline", as you can see from the
|
||||||
|
example mapping for key #0:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
km.keymap = {
|
||||||
|
-- ...
|
||||||
|
[0] = { c={r=1, g=1, b=1}, press=function() mb.tap("a") end},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This sets the key #0's LED color to white, and emits an "a" press everytime
|
||||||
|
you tap key #0.
|
||||||
|
|
||||||
|
* for more complex handling, you may want to use a dedicated function instead:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function km.mypress(keyno)
|
||||||
|
mb.tap("a")
|
||||||
|
end
|
||||||
|
|
||||||
|
km.keymap = {
|
||||||
|
-- ...
|
||||||
|
[1] = { c={r=1, g=1, b=1}, press=km.mypress}
|
||||||
|
}
|
||||||
|
|
||||||
|
* you can also do things on key releases:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
km.keymap = {
|
||||||
|
-- ...
|
||||||
|
[2] = { c={r=1, g=1, b=1}, release=function() mb.tap("x") end},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details and examples, please have a look at the keyboard layouts in
|
||||||
|
`layouts/vsc-golang.lua` and `layouts/kdenlive.lua`.
|
||||||
|
|
||||||
## Licenses
|
## Licenses
|
||||||
|
|
||||||
Multibow is (c) 2019 Harald Albrecht and is licensed under the MIT license, see
|
Multibow is (c) 2019 Harald Albrecht and is licensed under the MIT license, see
|
||||||
|
|
|
@ -44,7 +44,7 @@ cable going off "northwards":
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
empty.keymap = {name="empty"}
|
empty.keymap = { name="empty" }
|
||||||
mb.register_keymap(empty.keymap)
|
mb.register_keymap(empty.keymap)
|
||||||
|
|
||||||
return empty -- module
|
return empty -- module
|
||||||
|
|
|
@ -29,36 +29,86 @@ require("keybow")
|
||||||
local mk = require("snippets/morekeys")
|
local mk = require("snippets/morekeys")
|
||||||
local mb = require("snippets/multibow")
|
local mb = require("snippets/multibow")
|
||||||
|
|
||||||
|
--[[
|
||||||
|
The Keybow layout is as follows when in landscape orientation, with the USB
|
||||||
|
cable going off "northwards":
|
||||||
|
|
||||||
k.KEY_CLIP_BEGIN = k.KEY_CLIP_BEGIN or 9
|
┋┋
|
||||||
k.KEY_PROJECT_BEGIN = k.KEY_PROJECT_BEGIN or 9
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
|
┊ 11 ┊ ┊ 8 ┊ ┊ 5 ┊ ┊ 2 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
|
||||||
k.KEY_CLIP_END = k.KEY_CLIP_END or 0
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
k.KEY_PROJECT_END = k.KEY_PROJECT_END or 0
|
┊ 10 ┊ ┊ 7 ┊ ┊ 4 ┊ ┊ 1 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
|
||||||
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
|
┊ 9 ┊ ┊ 6 ┊ ┊ 3 ┊ ┊ 0 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
⍇ ⍈
|
||||||
|
(⯬) (⯮)
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
k.KEY_PLAY_AROUND_MOUSE = k.KEY_PLAY_AROUND_MOUSE or 10
|
||||||
|
|
||||||
|
k.KEY_ZONE_BEGIN = k.KEY_ZONE_BEGIN or 7
|
||||||
|
k.KEY_ZONE_END = k.KEY_ZONE_END or 4
|
||||||
|
|
||||||
|
k.KEY_CLIP_BEGIN = k.KEY_CLIP_BEGIN or 6
|
||||||
|
k.KEY_CLIP_END = k.KEY_CLIP_END or 3
|
||||||
|
k.KEY_PROJECT_BEGIN = k.KEY_PROJECT_BEGIN or 6
|
||||||
|
k.KEY_PROJECT_END = k.KEY_PROJECT_END or 3
|
||||||
|
|
||||||
-- (Default) key colors for unshifted and shifted keys.
|
-- (Default) key colors for unshifted and shifted keys.
|
||||||
k.COLOR_UNSHIFTED = k.COLOR_UNSHIFTED or {r=0, g=1, b=0}
|
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}
|
k.COLOR_SHIFTED = k.COLOR_SHIFTED or {r=1, g=0, b=0}
|
||||||
|
|
||||||
|
|
||||||
|
function k.play_around_mouse(...)
|
||||||
|
mb.tap("p")
|
||||||
|
mb.tap_times(keybow.LEFT_ARROW, 3, keybow.LEFT_SHIFT)
|
||||||
|
mb.tap("i")
|
||||||
|
mb.tap_times(keybow.RIGHT_ARROW, 3, keybow.LEFT_SHIFT)
|
||||||
|
mb.tap("o")
|
||||||
|
mb.tap(...)
|
||||||
|
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(keyno)
|
||||||
mb.activate_keymap(k.keymap.name)
|
mb.activate_keymap(k.keymap.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
k.keymap = {
|
-- Helps avoiding individual color setting...
|
||||||
|
function k.init_color(keymap, color)
|
||||||
|
for keyno, keydef in pairs(keymap) do
|
||||||
|
if type(keyno) == "number" and keyno >= 0 then
|
||||||
|
if not keydef.c then
|
||||||
|
keydef.c = color
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return keymap
|
||||||
|
end
|
||||||
|
|
||||||
|
k.keymap = k.init_color({
|
||||||
name="kdenlive",
|
name="kdenlive",
|
||||||
[k.KEY_CLIP_BEGIN] = {c=k.COLOR_UNSHIFTED, press=function() mb.tap(mk.HOME) end},
|
[k.KEY_ZONE_BEGIN] = {press=function() mb.tap("I") end},
|
||||||
[k.KEY_CLIP_END] = {c=k.COLOR_UNSHIFTED, press=function() mb.tap(mk.END) end},
|
[k.KEY_ZONE_END] = {press=function() mb.tap("O") end},
|
||||||
}
|
[k.KEY_CLIP_BEGIN] = {press=function() mb.tap(mk.HOME) end},
|
||||||
k.keymap_shifted = {
|
[k.KEY_CLIP_END] = {press=function() mb.tap(mk.END) end},
|
||||||
|
[k.KEY_PLAY_AROUND_MOUSE] = {press=function() k.play_around_mouse(keybow.SPACE, keybow.LEFT_CTRL) end},
|
||||||
|
}, k.COLOR_UNSHIFTED)
|
||||||
|
k.keymap_shifted = k.init_color({
|
||||||
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_BEGIN] = {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},
|
[k.KEY_PROJECT_END] = {press=function() mb.tap(mk.END, keybow.LEFT_CTRL) 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.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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
-- An empty Multibow Keybow layout. Useful for "switching off" any active
|
||||||
|
-- keymaps, with only the permanent keymaps (SHIFT, etc) being still in place.
|
||||||
|
|
||||||
|
--[[
|
||||||
|
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 km = {} -- module
|
||||||
|
|
||||||
|
local mb = require("snippets/multibow")
|
||||||
|
|
||||||
|
--[[
|
||||||
|
The Keybow layout is as follows when in landscape orientation, with the USB
|
||||||
|
cable going off "northwards":
|
||||||
|
|
||||||
|
┋┋
|
||||||
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
|
┊ 11 ┊ ┊ 8 ┊ ┊ 7 ┊ ┊ 6 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
|
┊ 10 ┊ ┊ 7 ┊ ┊ 4 ┊ ┊ 1 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐ ┌╌╌╌╌┐
|
||||||
|
┊ 9 ┊ ┊ 6 ┊ ┊ 3 ┊ ┊ 0 ┊
|
||||||
|
└╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘ └╌╌╌╌┘
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
-- Some action on a certain key press...
|
||||||
|
function km.mypress(keyno)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Some action on a certain key release...
|
||||||
|
function km.myrelease(keyno)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The keymap layout...
|
||||||
|
km.keymap = {
|
||||||
|
-- IMPORTANT: Make sure to change the keymap name to make it unique!
|
||||||
|
name="keymap-template",
|
||||||
|
|
||||||
|
-- The index entries below are defining keys as to their LED color and
|
||||||
|
-- what key taps should be send to the USB host to which your Keybow is
|
||||||
|
-- connected to.
|
||||||
|
[0] = { c={r=1, g=1, b=1}, press=function() mb.tap("a") end},
|
||||||
|
[1] = { c={r=1, g=1, b=1}, press=km.mypress},
|
||||||
|
[2] = { c={r=1, g=1, b=1}, release=km.myrelease},
|
||||||
|
}
|
||||||
|
mb.register_keymap(km.keymap)
|
||||||
|
|
||||||
|
return km -- module
|
|
@ -95,6 +95,16 @@ describe("Kdenlive keymap", function()
|
||||||
assert.spy(sm).was.called()
|
assert.spy(sm).was.called()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
inslit("taps", function()
|
||||||
|
local s = spy.on(mb, "tap")
|
||||||
|
|
||||||
|
hwk.tap(k.KEY_PLAY_AROUND_MOUSE)
|
||||||
|
assert.spy(s).was.called()
|
||||||
|
|
||||||
|
hwk.tap(shift.KEY_SHIFT)
|
||||||
|
hwk.tap(k.KEY_PLAY_AROUND_MOUSE)
|
||||||
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
--[[
|
||||||
|
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"
|
||||||
|
|
||||||
|
describe("template multibow keymap", function()
|
||||||
|
|
||||||
|
local mb = require("snippets/multibow")
|
||||||
|
local hwk = require("spec/hwkeys")
|
||||||
|
local kmt = require("layouts/keymap-template")
|
||||||
|
|
||||||
|
inslit("installs a single primary keymap", function()
|
||||||
|
assert.is_not_nil(kmt) -- we're going over the top here...
|
||||||
|
assert.is_not_nil(kmt.keymap) -- ...even more so.
|
||||||
|
|
||||||
|
-- empty must register exactly one keymap, and it must be
|
||||||
|
-- a primary keymap, not permanent or secondary.
|
||||||
|
local kms = mb.registered_keymaps()
|
||||||
|
assert.is.equal(1, #kms)
|
||||||
|
local keymap = kms[1]
|
||||||
|
assert.is_falsy(keymap.permanent)
|
||||||
|
assert.is_falsy(keymap.secondary)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
inslit("calls press and release handlers", function()
|
||||||
|
local mp = spy.on(kmt.keymap[1], "press")
|
||||||
|
local mr = spy.on(kmt.keymap[2], "release")
|
||||||
|
|
||||||
|
hwk.tap(1)
|
||||||
|
assert.spy(mp).was.called(1)
|
||||||
|
hwk.tap(2)
|
||||||
|
assert.spy(mr).was.called(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
Loading…
Reference in New Issue