abouttreesummaryrefslogcommitdiff
path: root/srcs/compose
diff options
context:
space:
mode:
authorJules Aguillon2024-02-11 20:46:36 +0100
committerJules Aguillon2024-02-17 23:28:31 +0100
commit8c290732607692cd94247f7e3e9c80fad1dfe516 (patch)
tree1903ef13cc72626d0b12c712f9d15aede6fc67b4 /srcs/compose
parent38deb810f94d0e2fea91add4cd53fdd615d19d64 (diff)
downloadunexpected-keyboard-8c290732607692cd94247f7e3e9c80fad1dfe516.tar.gz
unexpected-keyboard-8c290732607692cd94247f7e3e9c80fad1dfe516.zip
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.
Diffstat (limited to 'srcs/compose')
-rw-r--r--srcs/compose/compile.py80
-rw-r--r--srcs/compose/sequences.txt4
2 files changed, 84 insertions, 0 deletions
diff --git a/srcs/compose/compile.py b/srcs/compose/compile.py
new file mode 100644
index 0000000..214d4b8
--- /dev/null
+++ b/srcs/compose/compile.py
@@ -0,0 +1,80 @@
+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)
diff --git a/srcs/compose/sequences.txt b/srcs/compose/sequences.txt
new file mode 100644
index 0000000..31063b7
--- /dev/null
+++ b/srcs/compose/sequences.txt
@@ -0,0 +1,4 @@
+=e€
+`eè
+`aà
+`uù