Skip to content

Commit 6adb6be

Browse files
committed
Add keys for uc mode selection to macros + missing docs
1 parent 07b8dad commit 6adb6be

File tree

4 files changed

+281
-8
lines changed

4 files changed

+281
-8
lines changed

docs/en/macros.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# Macros
2+
3+
Macros are used for sending multiple keystrokes in a single action, and can
4+
be used for things like Unicode characters (even emojis! 🇨🇦), _Lorem ipsum_
5+
generators, triggering side effects (think lighting, speakers,
6+
microcontroller-optimized cryptocurrency miners, whatever).
7+
8+
## Setup
9+
10+
```python
11+
from kmk.modules.macros import Macros
12+
13+
macros = Macros()
14+
keyboard.modules.append(macros)
15+
```
16+
17+
This will enable a new type of keycode: `KC.MACRO()`
18+
19+
## Keycodes
20+
21+
|Key |Description |
22+
|-------------------|------------------------------------------|
23+
|`KC.MACRO(macro)` |Create a key that will play back a macro. |
24+
|`KC.UC_MODE_IBUS` |Switch Unicode mode to IBus. |
25+
|`KC.UC_MODE_MACOS` |Switch Unicode mode to macOS. |
26+
|`KC.UC_MODE_WINC` |Switch Unicode mode to Windows Compose. |
27+
28+
## Sending strings
29+
30+
The most basic sequence is an ASCII string. It can be used to send any standard
31+
English alphabet character, and an assortment of other "standard" keyboard keys
32+
(return, space, exclamation points, etc.).
33+
Keep in mind that some characters from shifted keys are i18n dependent.
34+
35+
```python
36+
WOW = KC.MACRO("Wow, KMK is awesome!")
37+
38+
keyboard.keymap = [<other keycodes>, WOW, <other keycodes>]
39+
```
40+
41+
## Key sequences
42+
43+
If you need to add modifier keys to your sequence or you need more granular control.
44+
You can use it to add things like copying/pasting, tabbing between fields, etc.
45+
46+
```python
47+
from kmk.modules.macros import Press, Release, Tap
48+
49+
PASTE_WITH_COMMENTARY = KC.MACRO(
50+
"look at this: ",
51+
Press(KC.LCTL),
52+
Tap(KC.V),
53+
Release(KC.LCTL)
54+
)
55+
56+
keyboard.keymap = [<other keycodes>, PASTE_WITH_COMMENTARY, <other keycodes>]
57+
```
58+
59+
The above example will type out "look at this: " and then paste the contents of your
60+
clipboard.
61+
62+
63+
### Sleeping within a sequence
64+
65+
If you need to wait during a sequence, you can use `Delay(ms)` to wait a
66+
length of time, in milliseconds.
67+
68+
```python
69+
from kmk.modules.macros import Tap, Delay
70+
71+
COUNTDOWN_TO_PASTE = KC.MACRO(
72+
Tap(KC.N3),
73+
Tap(KC.ENTER),
74+
Delay(1000),
75+
Tap(KC.N2),
76+
Tap(KC.ENTER),
77+
Delay(1000),
78+
Tap(KC.N1),
79+
Tap(KC.ENTER),
80+
Delay(1000),
81+
Tap(KC.LCTL(KC.V)),
82+
)
83+
84+
keyboard.keymap = [<other keycodes>, COUNTDOWN_TO_PASTE, <other keycodes>]
85+
```
86+
87+
This example will type out the following, waiting one second (1000 ms) between numbers:
88+
89+
3
90+
2
91+
1
92+
93+
and then paste the contents of your clipboard.
94+
95+
### Alt Tab with delay
96+
97+
If alt tab isn't working because it requires a delay, adding a delay and triggering
98+
down and up on ALT manually may fix the issue.
99+
100+
``` python
101+
from kmk.modules.macros import Delay, Press, Release, Tap
102+
103+
NEXT = KC.MACRO(
104+
Press(KC.LALT),
105+
Delay(30),
106+
Tap(KC.TAB),
107+
Delay(30),
108+
Release(KC.LALT),
109+
)
110+
```
111+
112+
## Unicode
113+
114+
### Unicode Modes
115+
116+
On Linux, Unicode uses `Ctrl-Shift-U`, which is supported by `ibus` and GTK+3.
117+
`ibus` users will need to add `IBUS_ENABLE_CTRL_SHIFT_U=1` to their environment
118+
(`~/profile`, `~/.bashrc`, `~/.zshrc`, or through your desktop environment's
119+
configurator).
120+
121+
On Windows, [WinCompose](https://github.com/samhocevar/wincompose) is required.
122+
123+
- Linux : `UnicodeModeIBus`, the default
124+
- MacOS: `UnicodeModeMacOS`
125+
- Windows: `UnicodeModeWinC`
126+
127+
### Unicode Examples
128+
129+
Initialize `Macros` to use `UnicodeModeMac` and make a key to cycle between modes
130+
at runtime.
131+
132+
```python
133+
from kmk.keys import Key
134+
from kmk.modules.macros import Macros, UnicodeModeIBus, UnicodeModeMacOS, UnicodeModeWinC
135+
136+
macros = Macros(unicode_mode=UnicodeModeMacOS)
137+
keyboard.modules.append(macros)
138+
139+
def switch_um(keyboard):
140+
if macros.unicode_mode == UnicodeModeIBus:
141+
macros.unicode_mode = UnicodeModeMacOS
142+
elif macros.unicode_mode == UnicodeModeMacOS:
143+
macros.unicode_mode = UnicodeModeWinC
144+
else:
145+
macros.Unicode_mode = UnicodeModeIBus
146+
147+
UCCYCLE = Key(code=None, on_press=switch_um)
148+
149+
FLIP = KC.MACRO('(ノಠ痊ಠ)ノ彡┻━┻')
150+
151+
keyboard.keymap = [<other keycodes>, UCCYCLE, FLIP, <other keycodes>]
152+
```
153+
154+
## Arbitrary Actions
155+
156+
As it happens, macros accept any callable object (even generators) as arguments.
157+
The `KMKKeyboard` object is passed as argument to that callable.
158+
159+
### Example 1
160+
161+
Change the RGB animation mode to "SWIRL" for five seconds and print an ASCII
162+
spinner
163+
164+
```python
165+
# ... boilerplate omitted for brevity.
166+
167+
prev_animation = None
168+
169+
def start_spinning(keyboard):
170+
global prev_animation
171+
prev_animation = rgb.animation_mode
172+
rgb.animation_mode = AnimationModes.SWIRL
173+
rgb.effect_init = True
174+
175+
def stop_spinning(keyboard):
176+
rgb.animation_mode = prev_animation
177+
rgb.effect_init = True
178+
179+
DISCO = KC.MACRO(
180+
"disco time!",
181+
start_color_wheel,
182+
"-",
183+
DELAY(1000),
184+
KC.BSPC,
185+
"\\",
186+
DELAY(1000),
187+
KC.BSPC,
188+
"|",
189+
DELAY(1000),
190+
KC.BSPC,
191+
"/",
192+
DELAY(1000),
193+
KC.BSPC,
194+
"-",
195+
DELAY(1000),
196+
KC.BSPC,
197+
stop_color_wheel,
198+
" disco time over.",
199+
)
200+
```
201+
202+
### Example 2
203+
204+
Here's a programmatic version of the earlier countdown-to-paste example, using a
205+
generator.
206+
Any return value that is not `None` is interpreted as a delay instruction in
207+
milliseconds.
208+
209+
```python
210+
def countdown(count, delay_ms):
211+
def generator(keyboard):
212+
for n in range(count, 0, -1):
213+
KC[n].on_press(keyboard)
214+
yield
215+
KC[n].on_release(keyboard)
216+
yield
217+
KC.ENTER.on_press(keyboard)
218+
yield
219+
KC.ENTER.on_release(keyboard)
220+
yield delay_ms
221+
return generator
222+
223+
COUNTDOWN_TO_PASTE = KC.MACRO(
224+
countdown(3, 1000),
225+
Tap(KC.LCTL(KC.V)),
226+
)

kmk/modules/macros.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from kmk.keys import KC, make_argumented_key
1+
from kmk.keys import KC, make_argumented_key, make_key
22
from kmk.modules import Module
33
from kmk.scheduler import create_task
44
from kmk.utils import Debug
@@ -49,7 +49,7 @@ def post(keyboard):
4949
KC.ENTER.on_release(keyboard)
5050

5151

52-
class UnicodeModeMac:
52+
class UnicodeModeMacOS:
5353
@staticmethod
5454
def pre(keyboard):
5555
KC.LALT.on_press(keyboard)
@@ -135,7 +135,22 @@ def __init__(self, unicode_mode=UnicodeModeIBus, delay=10):
135135
make_argumented_key(
136136
validator=MacroMeta,
137137
names=('MACRO',),
138-
on_press=self.macro_pressed,
138+
on_press=self.on_press_macro,
139+
)
140+
make_key(
141+
names=('UC_MODE_IBUS',),
142+
meta=UnicodeModeIBus,
143+
on_press=self.on_press_unicode_mode,
144+
)
145+
make_key(
146+
names=('UC_MODE_MACOS',),
147+
meta=UnicodeModeMacOS,
148+
on_press=self.on_press_unicode_mode,
149+
)
150+
make_key(
151+
names=('UC_MODE_WINC',),
152+
meta=UnicodeModeWinC,
153+
on_press=self.on_press_unicode_mode,
139154
)
140155

141156
def during_bootup(self, keyboard):
@@ -165,7 +180,10 @@ def on_powersave_enable(self, keyboard):
165180
def on_powersave_disable(self, keyboard):
166181
return
167182

168-
def macro_pressed(self, key, keyboard, *args, **kwargs):
183+
def on_press_unicode_mode(self, key, keyboard, *args, **kwargs):
184+
self.unicode_mode = key.meta
185+
186+
def on_press_macro(self, key, keyboard, *args, **kwargs):
169187
self._active = True
170188

171189
_iter = MacroIter(keyboard, key.meta.macro, self.unicode_mode)

tests/test_macros.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
Release,
99
Tap,
1010
UnicodeModeIBus,
11-
UnicodeModeMac,
11+
UnicodeModeMacOS,
1212
UnicodeModeWinC,
1313
)
1414
from tests.keyboard_test import KeyboardTest
@@ -31,7 +31,7 @@ def setUp(self):
3131
KC.MACRO('🍺!'),
3232
]
3333
],
34-
debug_enabled=True,
34+
debug_enabled=False,
3535
)
3636

3737
def test_0(self):
@@ -144,7 +144,7 @@ def test_7_ibus_explicit(self):
144144
)
145145

146146
def test_7_ralt(self):
147-
self.macros.unicode_mode = UnicodeModeMac
147+
self.macros.unicode_mode = UnicodeModeMacOS
148148
self.kb.test(
149149
'',
150150
[(7, True), (7, False)],
@@ -192,5 +192,33 @@ def test_8_winc(self):
192192
)
193193

194194

195+
class TestUnicodeModeKeys(unittest.TestCase):
196+
def setUp(self):
197+
self.macros = Macros()
198+
self.kb = KeyboardTest(
199+
[self.macros],
200+
[
201+
[
202+
KC.UC_MODE_IBUS,
203+
KC.UC_MODE_MACOS,
204+
KC.UC_MODE_WINC,
205+
]
206+
],
207+
debug_enabled=False,
208+
)
209+
210+
def test_ibus(self):
211+
self.kb.test('', [(0, True), (0, False)], [{}])
212+
self.assertEqual(self.macros.unicode_mode, UnicodeModeIBus)
213+
214+
def test_mac(self):
215+
self.kb.test('', [(1, True), (1, False)], [{}])
216+
self.assertEqual(self.macros.unicode_mode, UnicodeModeMacOS)
217+
218+
def test_winc(self):
219+
self.kb.test('', [(2, True), (2, False)], [{}])
220+
self.assertEqual(self.macros.unicode_mode, UnicodeModeWinC)
221+
222+
195223
if __name__ == '__main__':
196224
unittest.main()

util/aspell.en.pws

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
personal_ws-1.1 en 354
1+
personal_ws-1.1 en 355
22
ADNS
33
AMS
44
ANAVI
@@ -69,6 +69,7 @@ Hanja
6969
Hankaku
7070
Henkan
7171
HoldTap
72+
IBus
7273
InternalState
7374
ItsyBitsy
7475
JIS

0 commit comments

Comments
 (0)