Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify non qwerty layout use #431

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 38 additions & 29 deletions docs/international.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
# International Keycodes
International extension adds keys for non US layouts. It can simply be added to
the extensions list.
# Non QWERTY layout
If your computer is not configured (at the OS level) to use the QWERTY layout, you will have a hard time making your layers as `KC.Q` will for example output an `a` on an azerty layout.

To not have to deal yourself with all those translation we provide the `KeyMapConverter` class. It is intented to be subclassed for your layout, you then only have to define your mapping.

Note: There is no consensus on this (and currently not many user of that feature). Keep in mind that this might evolve, so keep an eyes on this when you update KMK.

The mapping is a relation:
- from what you want to use in the keymap (= what you see on your keyboard key)
- to what it should send as qwerty (= what your computer will print for this key if you set it up to use a QWERTY layout)


## Example use
For a french AZERTY layout you would have something like:

file: /kmk/extensions/keymap_extras/keymap_french.py
```python
from kmk.extensions.international import International
keyboard.extensions.append(International())
from kmk.keys import KC
from kmk.extensions.keymap_extras.base import KeyMapConverter

class AZERTY(KeyMapConverter):
MAPPING = {
'A': KC.Q,
'Z': KC.W,
'E': KC.E,
'R': KC.R,
'T': KC.T,
'Y': KC.Y,
...
}
```

## Keycodes

|Key |Aliases |Description |
|-----------------------|--------------------|-----------------------------------------------|
|`KC.NONUS_HASH` |`KC.NUHS` |Non-US `#` and `~` |
|`KC.NONUS_BSLASH` |`KC.NUBS` |Non-US `\` and <code>&#124;</code> |
|`KC.INT1` |`KC.RO` |JIS `\` and <code>&#124;</code> |
|`KC.INT2` |`KC.KANA` |JIS Katakana/Hiragana |
|`KC.INT3` |`KC.JYEN` |JIS `¥` |
|`KC.INT4` |`KC.HENK` |JIS Henkan |
|`KC.INT5` |`KC.MHEN` |JIS Muhenkan |
|`KC.INT6` | |JIS Numpad `,` |
|`KC.INT7` | |International 7 |
|`KC.INT8` | |International 8 |
|`KC.INT9` | |International 9 |
|`KC.LANG1` |`KC.HAEN` |Hangul/English |
|`KC.LANG2` |`KC.HANJ` |Hanja |
|`KC.LANG3` | |JIS Katakana |
|`KC.LANG4` | |JIS Hiragana |
|`KC.LANG5` | |JIS Zenkaku/Hankaku |
|`KC.LANG6` | |Language 6 |
|`KC.LANG7` | |Language 7 |
|`KC.LANG8` | |Language 8 |
|`KC.LANG9` | |Language 9 |
file: /code.py
```python
from kmk.extensions.keymap_extras.keymap_french import AZERTY

FR = AZERTY()
keyboard.keymap = [[FR.A, FR.Z, FR.E, FR.R, FR.T, FR.Y, ...]]
```

## Generating a missing layout
Making such mapping is very tedious. But a script to generate it from the equivlaent files from QMK can be found [here](https://github.com/crazyiop/kmk_keymap_extras)

Warning: The generated layout **need to be tested** and might need to be refined but that should save you quite some work.
11 changes: 11 additions & 0 deletions kmk/extensions/keymap_extras/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from kmk.keys import KC


class KeyMapConverter:
'''Class to allow easy definition of alternative layout'''

def __getattr__(self, key):
try:
return self.MAPPING[key]
except KeyError:
return getattr(KC, key)
172 changes: 172 additions & 0 deletions kmk/extensions/keymap_extras/keymap_bepo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
from kmk.extensions.keymap_extras.base import KeyMapConverter
from kmk.keys import KC


class BEPO(KeyMapConverter):
MAPPING = {
# Row 1
'DOLLAR': KC.GRV, # $
'DQUOTE': KC.N1, # "
'LDAQ': KC.N2, # «
'RDAQ': KC.N3, # »
'LPRN': KC.N4, # (
'RPRN': KC.N5, # )
'AT': KC.N6, # @
'PLUS': KC.N7, # +
'MINUS': KC.N8, # -
'SLASH': KC.N9, # /
'ASTERISK': KC.N0, # *
'EQUAL': KC.MINS, # =
'PERCENT': KC.EQL, # %
# Row 2
'B': KC.Q, # B
'EACUTE': KC.W, # É
'P': KC.E, # P
'O': KC.R, # O
'EGRAVE': KC.T, # È
'DCIR': KC.Y, # ^ (dead)
'V': KC.U, # V
'D': KC.I, # D
'L': KC.O, # L
'J': KC.P, # J
'Z': KC.LBRC, # Z
'W': KC.RBRC, # W
# Row 3
'A': KC.A, # A
'U': KC.S, # U
'I': KC.D, # I
'E': KC.F, # E
'COMM': KC.G, # ,
'COMMA': KC.G, # ,
'C': KC.H, # C
'T': KC.J, # T
'S': KC.K, # S
'R': KC.L, # R
'N': KC.SCLN, # N
'M': KC.QUOT, # M
'CCED': KC.BSLS, # Ç
# Row 4
'ECIR': KC.NUBS, # Ê
'AGRAVE': KC.Z, # À
'Y': KC.X, # Y
'X': KC.C, # X
'DOT': KC.V, # .
'K': KC.B, # K
'QUOTE': KC.N, # '
'Q': KC.M, # Q
'G': KC.COMM, # G
'H': KC.DOT, # H
'F': KC.SLSH, # F
# Shifted symbols
# Row 1
'HASH': KC.LSFT(KC.GRV), # #
'N1': KC.LSFT(KC.N1), # 1
'N2': KC.LSFT(KC.N2), # 2
'N3': KC.LSFT(KC.N3), # 3
'N4': KC.LSFT(KC.N4), # 4
'N5': KC.LSFT(KC.N5), # 5
'N6': KC.LSFT(KC.N6), # 6
'N7': KC.LSFT(KC.N7), # 7
'N8': KC.LSFT(KC.N8), # 8
'N9': KC.LSFT(KC.N9), # 9
'N0': KC.LSFT(KC.N0), # 0
'DEG': KC.LSFT(KC.MINS), # °
'GRAVE': KC.LSFT(KC.EQL), # `
# Row 2
'EXLM': KC.LSFT(KC.Y), # !
# Row 3
'SCLN': KC.LSFT(KC.G), # ;
# Row 4
'COLN': KC.LSFT(KC.V), # :
'QUES': KC.LSFT(KC.N), # ?
# Row 5
'NBSP': KC.LSFT(KC.SPC), # (non-breaking space)
# AltGr symbols
# Row 1
'NDSH': KC.RALT(KC.GRV), # –
'MDSH': KC.RALT(KC.N1), # —
'LESS': KC.RALT(KC.N2), # <
'GRTR': KC.RALT(KC.N3), # >
'LBRC': KC.RALT(KC.N4), # [
'RBRC': KC.RALT(KC.N5), # ]
'CIRC': KC.RALT(KC.N6), # ^
'PLMN': KC.RALT(KC.N7), # ±
'MMNS': KC.RALT(KC.N8), # −
'DIV': KC.RALT(KC.N9), # ÷
'MUL': KC.RALT(KC.N0), # ×
'NEQL': KC.RALT(KC.MINS), # ≠
'PERM': KC.RALT(KC.EQL), # ‰
# Row 2
'PIPE': KC.RALT(KC.Q), # |
'DACUTE': KC.RALT(KC.W), # ´ (dead)
'AMPR': KC.RALT(KC.E), # &
'OE': KC.RALT(KC.R), # Œ
'DGRAVE': KC.RALT(KC.T), # ` (dead)
'IEXL': KC.RALT(KC.Y), # ¡
'CARN': KC.RALT(KC.U), # ˇ (dead)
'ETH': KC.RALT(KC.I), # Ð
'DSLS': KC.RALT(KC.O), # / (dead)
'IJ': KC.RALT(KC.P), # IJ
'SCHW': KC.RALT(KC.LBRC), # Ə
'BREV': KC.RALT(KC.RBRC), # ˘ (dead)
# Row 3
'AE': KC.RALT(KC.A), # Æ
'UGRAVE': KC.RALT(KC.S), # Ù
'DTREMA': KC.RALT(KC.D), # ¨ (dead)
'EURO': KC.RALT(KC.F), # €
'COPY': KC.RALT(KC.H), # ©
'THRN': KC.RALT(KC.J), # Þ
'SS': KC.RALT(KC.K), # ẞ
'REGD': KC.RALT(KC.L), # ®
'DTIL': KC.RALT(KC.SCLN), # ~ (dead)
'MACR': KC.RALT(KC.QUOTE), # ¯ (dead)
'CEDL': KC.RALT(KC.BSLS), # ¸ (dead)
# Row 4
'BSLS': KC.RALT(KC.Z), # (backslash)
'LCBR': KC.RALT(KC.X), # {
'RCBR': KC.RALT(KC.C), # }
'ELLP': KC.RALT(KC.V), # …
'TILD': KC.RALT(KC.B), # ~
'IQUE': KC.RALT(KC.LSFT(KC.N)), # ¿
'RNGA': KC.RALT(KC.M), # ° (dead)
'DGRK': KC.RALT(KC.COMM), # µ (dead Greek key)
'DAGG': KC.RALT(KC.DOT), # †
'OGON': KC.RALT(KC.SLSH), # ˛ (dead)
# Row 5
'UNDS': KC.RALT(KC.SPC), # _
# Shift+AltGr symbols
# Row 1
'PARA': KC.LSFT(KC.RALT(KC.GRV)), # ¶
'DLQU': KC.LSFT(KC.RALT(KC.N1)), # „
'LDQU': KC.LSFT(KC.RALT(KC.N2)), # “
'RDQU': KC.LSFT(KC.RALT(KC.N3)), # ”
'LEQL': KC.LSFT(KC.RALT(KC.N4)), # ≤
'GEQL': KC.LSFT(KC.RALT(KC.N5)), # ≥
'NOT': KC.LSFT(KC.RALT(KC.N7)), # ¬
'QRTR': KC.LSFT(KC.RALT(KC.N8)), # ¼
'HALF': KC.LSFT(KC.RALT(KC.N9)), # ½
'TQTR': KC.LSFT(KC.RALT(KC.N0)), # ¾
'PRIM': KC.LSFT(KC.RALT(KC.MINS)), # ′
'DPRM': KC.LSFT(KC.RALT(KC.EQL)), # ″
# Row 2
'BRKP': KC.LSFT(KC.RALT(KC.Q)), # ¦
'DACU': KC.LSFT(KC.RALT(KC.W)), # ˝ (dead)
'SECT': KC.LSFT(KC.RALT(KC.E)), # §
# Row 3
'DOTA': KC.LSFT(KC.RALT(KC.D)), # ˙ (dead)
'CURR': KC.LSFT(KC.RALT(KC.F)), # ¤ (dead)
'HORN': KC.LSFT(KC.RALT(KC.G)), # ̛ (dead)
'LNGS': KC.LSFT(KC.RALT(KC.H)), # ſ
'TM': KC.LSFT(KC.RALT(KC.L)), # ™
'MORD': KC.LSFT(KC.RALT(KC.QUOTE)), # º
'DCMM': KC.LSFT(KC.RALT(KC.BSLS)), # , (dead)
# Row 4
'LSQU': KC.LSFT(KC.RALT(KC.X)), # ‘
'TAPO': KC.LSFT(KC.RALT(KC.C)), # ’
'MDDT': KC.LSFT(KC.RALT(KC.V)), # ·
'KEYB': KC.LSFT(KC.RALT(KC.B)), # ⌨
'HOKA': KC.LSFT(KC.RALT(KC.N)), # ̉ (dead)
'DOTB': KC.LSFT(KC.RALT(KC.M)), # ̣ (dead)
'DDAG': KC.LSFT(KC.RALT(KC.DOT)), # ‡
'FORD': KC.LSFT(KC.RALT(KC.SLSH)), # ª
}