forked from extern/Unexpected-Keyboard
8c29073260
The COMPOSE_PENDING modifier indicate whether a compose sequence is in progress. The new key of kind Compose_pending sets the current state of the sequence. The compose sequences are compiled into a state machine by a python script into a compact encoding. The state of the pending compose is determined by the index of a state.
81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
import textwrap, sys
|
|
|
|
def parse_sequences_file(fname):
|
|
with open(fname, "r") as inp:
|
|
return [ (s[:-2], s[-2]) for s in inp if len(s) > 1 ]
|
|
|
|
# Turn a list of sequences into a trie.
|
|
def add_sequences_to_trie(seqs, trie):
|
|
for seq, result in seqs:
|
|
t_ = trie
|
|
i = 0
|
|
while i < len(seq) - 1:
|
|
c = seq[i]
|
|
if c not in t_:
|
|
t_[c] = {}
|
|
t_ = t_[c]
|
|
i += 1
|
|
c = seq[i]
|
|
t_[c] = result
|
|
|
|
# Compile the trie into a state machine.
|
|
def make_automata(tree_root):
|
|
states = []
|
|
def add_tree(t):
|
|
# Index and size of the new node
|
|
i = len(states)
|
|
s = len(t.keys())
|
|
# Add node header
|
|
states.append((0, s + 1))
|
|
i += 1
|
|
# Reserve space for the current node in both arrays
|
|
for c in range(s):
|
|
states.append((None, None))
|
|
# Add nested nodes and fill the current node
|
|
for c in sorted(t.keys()):
|
|
node_i = len(states)
|
|
add_node(t[c])
|
|
states[i] = (c, node_i)
|
|
i += 1
|
|
def add_leaf(c):
|
|
states.append((c, 1))
|
|
def add_node(n):
|
|
if type(n) == str:
|
|
add_leaf(n)
|
|
else:
|
|
add_tree(n)
|
|
add_tree(tree_root)
|
|
return states
|
|
|
|
# Print the state machine compiled by make_automata into java code that can be
|
|
# used by [ComposeKeyData.java].
|
|
def gen_java(machine):
|
|
def gen_array(array, indent):
|
|
return textwrap.fill(", ".join(map(str, array)), subsequent_indent=indent)
|
|
print("""package juloo.keyboard2;
|
|
|
|
/** This file is generated, see [srcs/compose/compile.py]. */
|
|
|
|
public final class ComposeKeyData
|
|
{
|
|
public static final char[] states = {
|
|
%s
|
|
};
|
|
|
|
public static final short[] edges = {
|
|
%s
|
|
};
|
|
}""" % (
|
|
gen_array(map(lambda s: repr(s[0]), machine), ' '),
|
|
gen_array(map(lambda s: s[1], machine), ' '),
|
|
))
|
|
|
|
total_sequences = 0
|
|
trie = {}
|
|
for fname in sys.argv[1:]:
|
|
sequences = parse_sequences_file(fname)
|
|
add_sequences_to_trie(sequences, trie)
|
|
total_sequences += len(sequences)
|
|
gen_java(make_automata(trie))
|
|
print("Compiled %d sequences" % total_sequences, file=sys.stderr)
|