forked from extern/Unexpected-Keyboard
Allow extending the compose key (#713)
This allows adding more compose sequences without modifying en_US_UTF_8_Compose.pre. This is done by grouping sequences files that should be merged together into a directory. This also allows moving keysymdef.h into that directory.
This commit is contained in:
parent
84e10e0470
commit
2696f42144
@ -190,6 +190,12 @@ As translations need to be updated regularly, you can subscribe to this issue
|
||||
to receive a notification when an update is needed:
|
||||
https://github.com/Julow/Unexpected-Keyboard/issues/373
|
||||
|
||||
### Adding Compose key sequences
|
||||
|
||||
New Compose sequences can be added into `srcs/compose/compose/extra.json`.
|
||||
If a entirely new family of sequences were to be added, a new `.json` file can
|
||||
be created in the same directory to host them.
|
||||
|
||||
### Adding key combinations
|
||||
|
||||
Key combinations are defined in `srcs/juloo.keyboard2/KeyModifier.java`.
|
||||
|
@ -151,7 +151,7 @@ tasks.register('compileComposeSequences') {
|
||||
println "\nGenerating ${out}"
|
||||
exec {
|
||||
def sequences = new File(projectDir, "srcs/compose").listFiles().findAll {
|
||||
it.name.endsWith(".pre") || it.name.endsWith(".json")
|
||||
!it.name.endsWith(".py") && !it.name.endsWith(".md")
|
||||
}
|
||||
workingDir = projectDir
|
||||
commandLine("python", "srcs/compose/compile.py", *sequences)
|
||||
|
@ -3,6 +3,8 @@
|
||||
The `compose.py` program parses the compose sequences found in this directory
|
||||
and generates `srcs/juloo.keyboard2/ComposeKeyData.java`.
|
||||
|
||||
## `en_US_UTF_8_Compose.pre`
|
||||
## `compose/en_US_UTF_8_Compose.pre`
|
||||
|
||||
This file is copied from the `xorg` project. Copyright applies.
|
||||
|
||||
## `compose/extra.json`
|
||||
|
@ -12,20 +12,18 @@ from array import array
|
||||
# Parse symbol names from keysymdef.h. Many compose sequences in
|
||||
# en_US_UTF_8_Compose.pre reference theses. For example, all the sequences on
|
||||
# the Greek, Cyrillic and Hebrew scripts need these symbols.
|
||||
def parse_keysymdef_h():
|
||||
with open(os.path.join(os.path.dirname(__file__), "keysymdef.h"), "r") as inp:
|
||||
def parse_keysymdef_h(fname):
|
||||
with open(fname, "r") as inp:
|
||||
keysym_re = re.compile(r'^#define XK_(\S+)\s+\S+\s*/\*.U\+([0-9a-fA-F]+)\s')
|
||||
for line in inp:
|
||||
m = re.match(keysym_re, line)
|
||||
if m != None:
|
||||
yield (m.group(1), chr(int(m.group(2), 16)))
|
||||
|
||||
xkb_char_extra_names = dict(parse_keysymdef_h())
|
||||
|
||||
dropped_sequences = 0
|
||||
|
||||
# Parse XKB's Compose.pre files
|
||||
def parse_sequences_file_xkb(fname):
|
||||
def parse_sequences_file_xkb(fname, xkb_char_extra_names):
|
||||
# Parse a line of the form:
|
||||
# <Multi_key> <minus> <space> : "~" asciitilde # TILDE
|
||||
# Sequences not starting with <Multi_key> are ignored.
|
||||
@ -99,13 +97,30 @@ def parse_sequences_file_json(fname):
|
||||
return list(seqs.items())
|
||||
|
||||
# Format of the sequences file is determined by its extension
|
||||
def parse_sequences_file(fname):
|
||||
def parse_sequences_file(fname, xkb_char_extra_names={}):
|
||||
if fname.endswith(".pre"):
|
||||
return parse_sequences_file_xkb(fname)
|
||||
return parse_sequences_file_xkb(fname, xkb_char_extra_names)
|
||||
if fname.endswith(".json"):
|
||||
return parse_sequences_file_json(fname)
|
||||
raise Exception(fname + ": Unsupported format")
|
||||
|
||||
# A sequence directory can contain several sequence files as well as
|
||||
# 'keysymdef.h'.
|
||||
def parse_sequences_dir(dname):
|
||||
compose_files = []
|
||||
xkb_char_extra_names = {}
|
||||
# Parse keysymdef.h first if present
|
||||
for fbasename in os.listdir(dname):
|
||||
fname = os.path.join(dname, fbasename)
|
||||
if fbasename == "keysymdef.h":
|
||||
xkb_char_extra_names = dict(parse_keysymdef_h(fname))
|
||||
else:
|
||||
compose_files.append(fname)
|
||||
sequences = []
|
||||
for fname in compose_files:
|
||||
sequences.extend(parse_sequences_file(fname, xkb_char_extra_names))
|
||||
return sequences
|
||||
|
||||
# Turn a list of sequences into a trie.
|
||||
def add_sequences_to_trie(seqs, trie):
|
||||
def add_seq_to_trie(t_, seq, result):
|
||||
@ -238,9 +253,12 @@ public final class ComposeKeyData
|
||||
|
||||
total_sequences = 0
|
||||
tries = {} # Orderred dict
|
||||
for fname in sys.argv[1:]:
|
||||
for fname in sorted(sys.argv[1:]):
|
||||
tname, _ = os.path.splitext(os.path.basename(fname))
|
||||
sequences = parse_sequences_file(fname)
|
||||
if os.path.isdir(fname):
|
||||
sequences = parse_sequences_dir(fname)
|
||||
else:
|
||||
sequences = parse_sequences_file(fname)
|
||||
add_sequences_to_trie(sequences, tries.setdefault(tname, {}))
|
||||
total_sequences += len(sequences)
|
||||
entry_states, automata = make_automata(tries)
|
||||
|
5
srcs/compose/compose/extra.json
Normal file
5
srcs/compose/compose/extra.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"V": {
|
||||
"s": "Š"
|
||||
}
|
||||
}
|
Binary file not shown.
@ -570,7 +570,7 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
case "autofill": return editingKey("auto", Editing.AUTOFILL);
|
||||
|
||||
/* The compose key */
|
||||
case "compose": return makeComposePending(0xE016, ComposeKeyData.en_US_UTF_8_Compose, FLAG_SECONDARY | FLAG_SMALLER_FONT | FLAG_SPECIAL);
|
||||
case "compose": return makeComposePending(0xE016, ComposeKeyData.compose, FLAG_SECONDARY | FLAG_SMALLER_FONT | FLAG_SPECIAL);
|
||||
|
||||
/* Placeholder keys */
|
||||
case "removed": return placeholderKey(Placeholder.REMOVED);
|
||||
|
Loading…
Reference in New Issue
Block a user