Skip to content

Instantly share code, notes, and snippets.

@tnyeanderson
Created December 9, 2021 07:13
Show Gist options
  • Save tnyeanderson/23057d8286be5a90ce25923f41352dc8 to your computer and use it in GitHub Desktop.
Save tnyeanderson/23057d8286be5a90ce25923f41352dc8 to your computer and use it in GitHub Desktop.
Converts a directory of YAML files to xkeysnail syntax for Kinto.sh
import os
import yaml
outputFilePath = 'kinto.py'
shortcutsDir = 'shortcuts.d'
tabSize = 4
def parseYaml(path):
"""
Parses a yaml file with support for multidoc
"""
with open(path) as file:
try:
return list(yaml.safe_load_all(file))
except yaml.YAMLError as exc:
print(exc)
def parseFiles(path):
"""
Parses all yaml files in a directory and translates their keymaps
"""
for file in sorted(os.listdir(path)):
if file.endswith(".yaml"):
# Might contain multiple yaml docs using ---
confs = parseYaml(f"{path}/{file}")
for conf in confs:
print(f"Loading '{conf['name']}' from {file}")
print(f"Description: {conf['description']}")
translateKeymaps(conf['keymaps'])
print(f"Finished: {file}")
def translateKeymaps(keymaps):
"""
Translate each keymap in the keymaps array of a yaml file
"""
for keymap in keymaps:
translateKeymap(keymap)
output.write('\n')
def translateKeymap(keymap):
"""
Translate a yaml-defined keymap into an xkeysnail definition
"""
if 'raw' in keymap:
out = keymap['raw']
if 'conditional' in keymap:
conditional = translateConditional(keymap['conditional'])
maps = generateMaps(keymap['maps'])
out = defineKeymap(conditional, maps, keymap['name'])
output.write(out)
if 'name' in keymap:
print(f"Created keymap: {keymap['name']}")
def translateConditional(conditional):
"""
Translate a yaml-defined conditional into a string for use in an xkeysnail definition
"""
if 'regex' in conditional:
regex = conditional['regex']
if ('case_sensitive' in conditional) and (conditional['case_sensitive'] == False):
return f're.compile("{regex}", re.IGNORECASE)'
return f're.compile("{regex}")'
elif 'wm_class' in conditional:
wm_class = conditional['wm_class']
inOrNot = 'in'
if 'not' in wm_class:
inOrNot = 'not in'
options = wm_class['not']
else:
options = wm_class['in']
optionsStr = ', '.join(f'"{option}"' for option in options)
return f'lambda wm_class: wm_class {inOrNot} ({optionsStr})'
return 'True'
def generateMaps(maps, indent=0):
"""
Convert a yaml-defined map into a string for insertion into an xkeysnail definition
Uses recursion for nested maps
"""
out = ''
for map in maps:
if 'description' in map:
out += f'# {map["description"]}\n'
fromStr = f'K("{map["from"]}")'
if 'maps' in map:
# We have nested maps. Recurse
toStr = (
f'{{\n'
f'{generateMaps(map["maps"], indent+1)}\n'
f'}}'
)
else:
toStr = f'K("{map["to"]}")'
out += f'{fromStr}: {toStr},\n'
return indentLines(out.rstrip(), indent)
def defineKeymap(conditional, maps, name):
"""
Outputs an xkeysnail definition from a conditional, maps, and name
"""
return (
f'define_keymap({conditional}, {{\n'
f'{indentLines(maps)}\n'
f'}}, "{name}")\n'
)
def indentLines(text, stops=1):
"""
Indent <text> with <tabSize> spaces <stops> times
"""
indent = '\t'.expandtabs(tabSize) * stops
out = []
for line in text.split('\n'):
out.append(f'{indent}{line}')
return '\n'.join(out)
def main():
"""
The main logic of the program
"""
# Make the output file globally accessible
global output
# Remove existing file
if os.path.exists(outputFilePath):
os.remove(outputFilePath)
# Open the file for appending keymaps
output = open(outputFilePath, 'a')
# Parse the yaml files and append translated keymaps to output file
parseFiles(shortcutsDir)
# Close output file
output.close()
# Call main logic
main()
@tnyeanderson
Copy link
Author

tnyeanderson commented Dec 9, 2021

This takes all yaml files in ./shortcuts.d (in order) and converts them into ./kinto.py, a python xkeysnail config for Kinto.

See here for spec and context:
rbreaves/kinto#115 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment