blob: 46dbb719741c1aa71f80a995d2776347bbe1781b [file] [log] [blame]
#!/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)