Skip to content

Commit

Permalink
Add keys for uc mode selection to macros
Browse files Browse the repository at this point in the history
  • Loading branch information
xs5871 committed May 20, 2024
1 parent 07b8dad commit b811ec3
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 4 deletions.
152 changes: 152 additions & 0 deletions docs/en/macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Macros

Macros are used for sending multiple keystrokes in a single action, and can
be used for things like Unicode characters (even emojis! 🇨🇦), _Lorem ipsum_
generators, triggering side effects (think lighting, speakers,
microcontroller-optimized cryptocurrency miners, whatever).

## Setup

```python
from kmk.modules.macros import Macros

macros = Macros()
keyboard.modules.append(macros)
```

This will enable a new type of keycode: `KC.MACRO()`

## Keycodes

|Key |Description |
|------------------|------------------------------------------|
|`KC.MACRO(macro)` |Create a key that will play back a macro. |
|`KC.UC_MODE_IBUS` |Switch unicode mode to IBus. |
|`KC.UC_MODE_MAC` |Switch unicode mode to Mac/OSX. |
|`KC.UC_MODE_WINC` |Switch unicode mode to Windows Compose. |

## Sending strings

The most basic sequence is an ASCII string. It can be used to send any standard
English alphabet character, and an assortment of other "standard" keyboard keys
(return, space, exclamation points, etc.).
Keep in mind that some characters from shifted keys are i18n dependend.

```python
WOW = KC.MACRO("Wow, KMK is awesome!")

keyboard.keymap = [<other keycodes>, WOW, <other keycodes>]
```

## Key sequences

If you need to add modifier keys to your sequence or you need more granular control.
You can use it to add things like copying/pasting, tabbing between fields, etc.

```python
from kmk.modules.macros import Press, Release, Tap

PASTE_WITH_COMMENTARY = KC.MACRO(
"look at this: ",
Press(KC.LCTL),
Tap(KC.V),
Release(KC.LCTL)
)

keyboard.keymap = [<other keycodes>, PASTE_WITH_COMMENTARY, <other keycodes>]
```

The above example will type out "look at this: " and then paste the contents of your
clipboard.


### Sleeping within a sequence

If you need to wait during a sequence, you can use `Delay(ms)` to wait a
length of time, in milliseconds.

```python
from kmk.modules.macros import Tap, Delay

COUNTDOWN_TO_PASTE = KC.MACRO(
Tap(KC.N3),
Tap(KC.ENTER),
Delay(1000),
Tap(KC.N2),
Tap(KC.ENTER),
Delay(1000),
Tap(KC.N1),
Tap(KC.ENTER),
Delay(1000),
Tap(KC.LCTL(KC.V)),
)

keyboard.keymap = [<other keycodes>, COUNTDOWN_TO_PASTE, <other keycodes>]
```

This example will type out the following, waiting one second (1000 ms) between numbers:

3
2
1

and then paste the contents of your clipboard.

### Alt Tab with delay

If alt tab isn't working because it requires a delay, adding a delay and triggering
down and up on ALT manually may fix the issue.

``` python
from kmk.modules.macros import Delay, Press, Release, Tap

NEXT = KC.MACRO(
Press(KC.LALT),
Delay(30),
Tap(KC.TAB),
Delay(30),
Release(KC.LALT),
)
```

## Unicode

### Unicode Modes

On Linux, Unicode uses `Ctrl-Shift-U`, which is supported by `ibus` and GTK+3.
`ibus` users will need to add `IBUS_ENABLE_CTRL_SHIFT_U=1` to their environment
(`~/profile`, `~/.bashrc`, `~/.zshrc`, or through your desktop environment's
configurator).

On Windows, [WinCompose](https://github.com/samhocevar/wincompose) is required.

- Linux : `UnicodeModeIBus`, the default
- Mac: `UnicodeModeMac`
- Windows: `UnicodeModeWinC`

### Unicode Examples

Initialize `Macros` to use `UnicodeModeMac` and make a key to cycle between modes
at runtime.

```python
from kmk.keys import Key
from kmk.modules.macros import Macros, UnicodeModeIBus, UnicodeModeMac, UnicodeModeWinC

macros = Macros(unicode_mode=UnicodeModeMac)
keyboard.modules.append(macros)

def switch_um(keyboard):
if macros.unicode_mode == UnicodeModeIBus:
macros.unicode_mode = UnicodeModeMac
elif macros.unicode_mode == UnicodeModeMac:
macros.unicode_mode = UnicodeModeWinC
else:
macros.Unicode_mode = UnicodeModeIBus

UCCYCLE = Key(code=None, on_press=switch_um)

FLIP = KC.MACRO('(ノಠ痊ಠ)ノ彡┻━┻')

keyboard.keymap = [<other keycodes>, UCCYCLE, FLIP, <other keycodes>]
```
24 changes: 21 additions & 3 deletions kmk/modules/macros.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from kmk.keys import KC, make_argumented_key
from kmk.keys import KC, make_argumented_key, make_key
from kmk.modules import Module
from kmk.scheduler import create_task
from kmk.utils import Debug
Expand Down Expand Up @@ -135,7 +135,22 @@ def __init__(self, unicode_mode=UnicodeModeIBus, delay=10):
make_argumented_key(
validator=MacroMeta,
names=('MACRO',),
on_press=self.macro_pressed,
on_press=self.on_press_macro,
)
make_key(
names=('UC_MODE_IBUS',),
meta=UnicodeModeIBus,
on_press=self.on_press_unicode_mode,
)
make_key(
names=('UC_MODE_MAC',),
meta=UnicodeModeMac,
on_press=self.on_press_unicode_mode,
)
make_key(
names=('UC_MODE_WINC',),
meta=UnicodeModeWinC,
on_press=self.on_press_unicode_mode,
)

def during_bootup(self, keyboard):
Expand Down Expand Up @@ -165,7 +180,10 @@ def on_powersave_enable(self, keyboard):
def on_powersave_disable(self, keyboard):
return

def macro_pressed(self, key, keyboard, *args, **kwargs):
def on_press_unicode_mode(self, key, keyboard, *args, **kwargs):
self.unicode_mode = key.meta

def on_press_macro(self, key, keyboard, *args, **kwargs):
self._active = True

_iter = MacroIter(keyboard, key.meta.macro, self.unicode_mode)
Expand Down
30 changes: 29 additions & 1 deletion tests/test_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def setUp(self):
KC.MACRO('🍺!'),
]
],
debug_enabled=True,
debug_enabled=False,
)

def test_0(self):
Expand Down Expand Up @@ -192,5 +192,33 @@ def test_8_winc(self):
)


class TestUnicodeModeKeys(unittest.TestCase):
def setUp(self):
self.macros = Macros()
self.kb = KeyboardTest(
[self.macros],
[
[
KC.UC_MODE_IBUS,
KC.UC_MODE_MAC,
KC.UC_MODE_WINC,
]
],
debug_enabled=False,
)

def test_ibus(self):
self.kb.test('', [(0, True), (0, False)], [{}])
self.assertEqual(self.macros.unicode_mode, UnicodeModeIBus)

def test_mac(self):
self.kb.test('', [(1, True), (1, False)], [{}])
self.assertEqual(self.macros.unicode_mode, UnicodeModeMac)

def test_winc(self):
self.kb.test('', [(2, True), (2, False)], [{}])
self.assertEqual(self.macros.unicode_mode, UnicodeModeWinC)


if __name__ == '__main__':
unittest.main()

0 comments on commit b811ec3

Please sign in to comment.