Unexpected-Keyboard/srcs/compose/compile.py
Jules Aguillon 8c29073260 Compose key
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.
2024-02-17 23:28:31 +01:00

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)