Skip to content

Instantly share code, notes, and snippets.

@drm00
Created April 19, 2023 18:26
Show Gist options
  • Save drm00/7a07fab05afcf2429d03eae0cb643605 to your computer and use it in GitHub Desktop.
Save drm00/7a07fab05afcf2429d03eae0cb643605 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
#
# Script to transform the latest NEO2-layout for macos to a similar layout,
# such as KOY. It swaps the keycodes to the corresponding ones and leaves
# the rest of the file as it is. I use it to generate a KOY layout from
# the latest NEO2 upstream at
#
# https://git.neo-layout.org/neo/neo-layout/src/branch/master/mac_osx/neo-layouts.bundle/Contents/Resources/Deutsch%20%28Neo%202%29.keylayout
#
# Other layouts such as bone, mine etc. could be generated as well.
# Layers 4, 6, 8 and 9 are left untouched.
#
import re
import sys
neo2koy = {
'0': '5',
'5': '14',
'14': '31',
'31': '39',
'39': '17',
'17': '43',
'43': '15',
'15': '34',
'34': '32',
'32': '0',
'1': '3',
'3': '2',
'2': '1',
'4': '41',
'41': '4',
'6': '9',
'9': '46',
'46': '47',
'47': '13',
'13': '16',
'16': '12',
'12': '6',
'7': '11',
'11': '33',
'33': '35',
'35': '7',
'37': '38',
'38': '37',
}
def transform(input, output, target, debug=False):
layers = {}
current_layer = None
buffer = []
with open(input) as f:
for n, line in enumerate(f):
original_line = line
line = line.strip()
if line.startswith('<keyboard group="'):
new_line = re.sub(r'Deutsch \(Neo 2\)', r'Deutsch (KOY)', original_line, count=1)
buffer.append(new_line)
continue
elif line.startswith('<keyMap index="'):
m = re.search(r'<keyMap index="(\d+)"', line)
if m:
layer = m.group(1)
if debug: print(f"layer {layer} starts at line {n}: {line}")
if layer in ['4', '6', '8', '9']:
# skip layers that should remain the same
if debug: print(f"leaving layer {layer} as it is")
else:
layers[layer] = {}
current_layer = layer
else:
print(f"ERROR: no layer index found at line {n}: {line}!", file=sys.stderr)
sys.exit(1)
buffer.append(original_line)
continue
elif line.startswith('</keyMap>'):
if current_layer is not None:
# write collected and modified keymaps for layer
s = sorted(layers[current_layer], key=int)
for i in s:
if debug: print(f"i: {i}, line: {layers[current_layer][i].strip()}")
buffer.append(layers[current_layer][i])
buffer.append(original_line)
current_layer = None
continue
if current_layer is not None:
m = re.search(r'<key code="(\d+)"', line)
if m:
code = m.group(1)
else:
print(f"ERROR: no code found at line {n}: {line}!", file=sys.stderr)
sys.exit(1)
if code in target:
if debug: print(f"substituting code '{code}' to '{target[code]}' in line {n}: {line}")
new_line = re.sub(code, target[code], original_line, count=1)
if debug: print(f"result: {new_line.strip()}")
layers[current_layer][target[code]] = new_line
else:
layers[current_layer][code] = original_line
else:
buffer.append(original_line)
with open(output, 'w') as f:
f.writelines(buffer)
if __name__ == '__main__':
transform('Deutsch (Neo 2).keylayout', 'koy.keylayout', neo2koy, debug=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment