From 661175c3f49d7857aa6c29e43d88766553f39c60 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sat, 17 Jan 2015 11:28:50 +0900 Subject: tools: Add converter from CLDR keyboard data The convert_cldr.py script reads a CLDR keyboard data and produces a Caribou layout file. It can be used as: ./tools/convert_cldr.py fr-t-k0-android-qwertz.xml > fr.xml For simplicity, the script adds only the keys defined in the input file. To make the generated layout really useful, you will need to add 'Caribou_ShiftUp' etc. --- tools/Makefile.am | 1 + tools/convert_cldr.py | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100755 tools/convert_cldr.py diff --git a/tools/Makefile.am b/tools/Makefile.am index ba84708..3a9bcdb 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,6 +1,7 @@ EXTRA_DIST = \ fix_gir.py \ make_schema.py \ + convert_cldr.py \ basic.xsl -include $(top_srcdir)/git.mk diff --git a/tools/convert_cldr.py b/tools/convert_cldr.py new file mode 100755 index 0000000..cd65754 --- /dev/null +++ b/tools/convert_cldr.py @@ -0,0 +1,111 @@ +#!/usr/bin/python + +from gi.repository import Gdk +from xml.etree.ElementTree import ElementTree, Element +import re + +ESCAPE_PATTERN = re.compile(r'\\u\{([0-9A-Fa-f]+?)\}') +ISO_PATTERN = re.compile(r'[A-E]([0-9]+)') + + +def parse_single_key(value): + key = Element('key') + uc = 0 + if hasattr(__builtins__, 'unichr'): + def unescape(m): + return unichr(int(m.group(1), 16)) + else: + def unescape(m): + return chr(int(m.group(1), 16)) + value = ESCAPE_PATTERN.sub(unescape, value) + if len(value) > 1: + key.set('text', value) + uc = ord(value[0]) + keyval = Gdk.unicode_to_keyval(uc) + name = Gdk.keyval_name(keyval) + key.set('name', name) + return key + + +def convert(source, tree): + root = Element('layout') + for index, keymap in enumerate(tree.iter('keyMap')): + level = Element('level') + rows = {} + root.append(level) + level.set('name', 'level%d' % (index+1)) + # FIXME: heuristics here + modifiers = keymap.get('modifiers') + if not modifiers: + mode = 'default' + elif 'shift' in modifiers.split(' ') or 'lock' in modifiers.split(' '): + mode = 'latched' + else: + mode = 'locked' + level.set('mode', mode) + for _map in keymap.iter('map'): + value = _map.get('to') + key = parse_single_key(value) + iso = _map.get('iso') + if not ISO_PATTERN.match(iso): + sys.stderr.write('invalid ISO key name: %s\n' % iso) + continue + if not iso[0] in rows: + rows[iso[0]] = [] + rows[iso[0]].append((int(iso[1:]), key)) + # add attribute to certain keys + name = key.get('name') + if name == 'space': + key.set('align', 'center') + key.set('width', '6.0') + if name in ('space', 'BackSpace'): + key.set('repeatable', 'yes') + # add subkeys + longPress = _map.get('longPress') + if longPress: + for value in longPress.split(' '): + subkey = parse_single_key(value) + key.append(subkey) + for k, v in sorted(rows.items(), key=lambda x: x[0], reverse=True): + row = Element('row') + for key in sorted(v, key=lambda x: x): + row.append(key[1]) + level.append(row) + return root + + +def indent(elem, level=0): + i = "\n" + level*" " + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + " " + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + indent(elem, level+1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + +if __name__ == "__main__": + import sys + + if len(sys.argv) != 2: + print("supply a CLDR keyboard file") + sys.exit(1) + + source = sys.argv[-1] + itree = ElementTree() + itree.parse(source) + + root = convert(source, itree) + indent(root) + + otree = ElementTree(root) + if hasattr(sys.stdout, 'buffer'): + out = sys.stdout.buffer + else: + out = sys.stdout + otree.write(out, xml_declaration=True, encoding='UTF-8') -- cgit v1.2.1