| #!/usr/bin/python |
| # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Extract ibus engine information from component XML files and generate a C++ |
| header. |
| |
| This program generate a C++ header file containing the information on available |
| ibus engines. It parses the XML files specified on the command line, and then |
| generates a static array definition from the information extracted. |
| |
| Run it like: |
| gen_engines.py [files] |
| |
| It will produce output that looks like: |
| |
| // This file is automatically generated by gen_engines.py |
| #ifndef IBUS_INPUT_METHODS_H |
| #define IBUS_INPUT_METHODS_H |
| |
| namespace chromeos { |
| |
| struct IBusEngineInfo { |
| const char* name; |
| const char* longname; |
| const char* layout; |
| const char* language; |
| }; |
| const IBusEngineInfo ibus_engines[] = { |
| {"chewing", "Chewing", "us", "zh_TW"}, |
| {"xkb:us::eng", "USA", "us", "eng"}, |
| {"xkb:us:dvorak:eng", "USA - Dvorak", "us(dvorak)", "eng"}, |
| {"xkb:be::fra", "Belgium", "be", "fra"}, |
| {"xkb:br::por", "Brazil", "br", "por"}, |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // IBUS_INPUT_METHODS_H |
| |
| """ |
| |
| __author__ = 'zork (Zachary Kuznia)' |
| |
| import re |
| import sys |
| from xml.etree.ElementTree import ElementTree |
| |
| OUTPUT_HEADER = """ |
| // This file is automatically generated by gen_engines.py |
| #ifndef IBUS_INPUT_METHODS_H |
| #define IBUS_INPUT_METHODS_H |
| |
| namespace chromeos { |
| |
| struct IBusEngineInfo { |
| const char* name; |
| const char* longname; |
| const char* layout; |
| const char* language; |
| }; |
| const IBusEngineInfo ibus_engines[] = { |
| """ |
| |
| ENGINE_FORMAT = """{"%(name)s", "%(longname)s", "%(layout)s", "%(language)s"}, |
| """ |
| |
| OUTPUT_FOOTER = """ |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // IBUS_INPUT_METHODS_H |
| """ |
| |
| def ExtractEngines(filename): |
| """Parse the specified file and extract the engine definitions. |
| |
| Arguments: |
| filename: Full path of the file to parse |
| Returns: |
| List of engines extracted from the file |
| """ |
| engines = [] |
| |
| # Parse the file as XML |
| tree = ElementTree() |
| tree.parse(filename) |
| |
| for engine_list in tree.findall('engines'): |
| for engine in engine_list.findall('engine'): |
| cur_engine = {'name': "", 'longname': "", 'layout': "", 'language': ""} |
| name = engine.findall('name') |
| longname = engine.findall('longname') |
| layout = engine.findall('layout') |
| language = engine.findall('language') |
| |
| # If there's no name, we can't use this entry |
| if not name: |
| continue; |
| |
| cur_engine['name'] = name[0].text |
| if longname: |
| cur_engine['longname'] = longname[0].text |
| if layout: |
| cur_engine['layout'] = layout[0].text |
| if language: |
| cur_engine['language'] = language[0].text |
| |
| engines.append(cur_engine) |
| |
| return engines |
| |
| |
| def GetWhitelist(list_filename): |
| """Get whitelisted IDs. |
| |
| Arguments: |
| list_filename: file name of whitelist. |
| Returns: |
| list of whitelisted input method IDs. |
| """ |
| whitelist = [] |
| whitelist_file = open(list_filename, 'r') |
| for line in whitelist_file: |
| lang = re.sub(r'#.*$', '', line) |
| lang = lang.split() |
| if not lang: continue |
| whitelist.append(lang[0]) |
| whitelist_file.close() |
| return whitelist |
| |
| |
| def SortEnginesWithWhitelist(engines, whitelist): |
| """Sort engines list in the order of appearance in whitelist. |
| |
| Note that any engine in whitelist is supposed to exist in engines list. |
| |
| Arguments: |
| engines: List of engines. |
| whitelist: List of whitelisted input method IDs. |
| Returns: |
| Sorted list of whitelisted input method IDs. |
| """ |
| sorted_engines = [] |
| engine_names_map = {} |
| for engine in engines: |
| engine_names_map[engine['name']] = engine |
| for lang in whitelist: |
| if lang not in engine_names_map: |
| print >> sys.stderr, ( |
| "%s not listed in supported engine, but in whitelist.txt" % lang) |
| sys.exit(1) |
| sorted_engines.append(engine_names_map[lang]) |
| return sorted_engines |
| |
| |
| def CreateEngineHeader(engines): |
| """Create the header file from a list of engines. |
| |
| Arguments: |
| engines: list of ibus engine objects |
| Returns: |
| The text of a C++ header file containing the engine data. |
| """ |
| output = [] |
| output.append(OUTPUT_HEADER) |
| for engine in engines: |
| output.append(ENGINE_FORMAT % engine) |
| output.append(OUTPUT_FOOTER) |
| |
| return "".join(output) |
| |
| |
| def main(argv): |
| if len(argv) < 3: |
| print >> sys.stderr, 'Usage: gen_engines.py [whitelist] [files]' |
| sys.exit(1) |
| engines = [] |
| whitelist = GetWhitelist(argv[1]) |
| for filename in argv[2:]: |
| new_engines = ExtractEngines(filename) |
| if len(new_engines) == 0: |
| print >> sys.stderr, "%s had no engines" % filename |
| sys.exit(2) |
| engines.extend(new_engines) |
| engines = SortEnginesWithWhitelist(engines, whitelist) |
| output = CreateEngineHeader(engines) |
| print output |
| |
| |
| if __name__ == '__main__': |
| main(sys.argv) |