Add automated checks on layouts

The script `check_layout.py` checks some properties about layouts.
No check is an error.

The result of running this script on every layouts is stored in the file
`check_layout.output`, which is useful to track changes.

Add make rules to run this script as well as `sync_translations`.
This commit is contained in:
Jules Aguillon 2023-06-03 21:03:05 +02:00
parent f451902efa
commit e5ae4816df
5 changed files with 201 additions and 8 deletions

View File

@ -88,6 +88,9 @@ An entry must be added to the layout option in `res/values/arrays.xml`, to both
The layout must also be referenced in `srcs/juloo.keyboard2/Config.java` in The layout must also be referenced in `srcs/juloo.keyboard2/Config.java` in
`layout_of_string`. `layout_of_string`.
Run `make check_layouts` to check some properties about your layout. This will
change the file `check_layout.output`, which you should commit.
#### Adding a programming layout #### Adding a programming layout
A programming layout must contains every ASCII characters. A programming layout must contains every ASCII characters.
@ -135,10 +138,12 @@ The app can be translated by writing `res/values-<language code>/strings.xml`
(for example `values-fr`, `values-lv`), based on the default: (for example `values-fr`, `values-lv`), based on the default:
`res/values/strings.xml` (English). `res/values/strings.xml` (English).
To check that `strings.xml` is formatted correctly, run
`python sync_translations.py`. This will modify your files.
The store description is found in `metadata/android/<locale>/`, The store description is found in `metadata/android/<locale>/`,
`short_description.txt` and `full_description.txt`. `short_description.txt` and `full_description.txt`.
Translating changelogs is not useful. Changelogs are written quickly just Translating changelogs is not useful.
before a release and older ones are never shown to anyone currently.
The app name might be partially translated, the "unexpected" word should remain The app name might be partially translated, the "unexpected" word should remain
untranslated. untranslated.

View File

@ -22,10 +22,19 @@ clean:
rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \ rm -rf _build/*.dex _build/class _build/gen _build/*.apk _build/*.unsigned-apk \
_build/*.idsig _build/assets _build/*.idsig _build/assets
rebuild_special_font: rebuild_special_font: _build/special_font.ttf
cd srcs/special_font && fontforge -lang=ff -script build.pe *.svg cp "$<" srcs/special_font/result.ttf
.PHONY: release debug installd clean rebuild_special_font sync_translations:
python sync_translations.py
check_layouts:
python check_layout.py $(wildcard res/xml/*.xml) > check_layout.output
# Will modify the source tree.
runtest: rebuild_special_font sync_translations check_layouts
.PHONY: release debug installd clean rebuild_special_font check_layouts sync_translations runtest
$(shell mkdir -p _build) $(shell mkdir -p _build)
@ -117,3 +126,10 @@ _build/classes.dex: $(JAVA_FILES) $(R_FILE)
-sourcepath $(SRC_DIR):$(GEN_DIR) \ -sourcepath $(SRC_DIR):$(GEN_DIR) \
$^ $^
$(ANDROID_BUILD_TOOLS)/d8 --output $(@D) $(OBJ_DIR)/*/*/* $(subst :, ,$(EXTRA_JARS)) $(ANDROID_BUILD_TOOLS)/d8 --output $(@D) $(OBJ_DIR)/*/*/* $(subst :, ,$(EXTRA_JARS))
# Font file
FONT_GLYPHS = $(wildcard srcs/special_font/*.svg)
_build/special_font.ttf: srcs/special_font/build.pe $(FONT_GLYPHS)
fontforge -lang=ff -script $< "$@" $(FONT_GLYPHS)

100
check_layout.output Normal file
View File

@ -0,0 +1,100 @@
# res/xml/ar_alt.xml
Layout includes some ASCII punctuation but not all, missing: !, ", ', +, -, /, :, ;, <, =, >, ?, [, \, ], _, |, ~
1 warnings
# res/xml/ar_pc.xml
Layout includes some ASCII punctuation but not all, missing: !, ', +, ;, ?, \, |
1 warnings
# res/xml/azerty.xml
0 warnings
# res/xml/bangla.xml
Layout includes some ASCII punctuation but not all, missing: $
1 warnings
# res/xml/bone.xml
Layout includes some ASCII punctuation but not all, missing: $
1 warnings
Not a layout file: res/xml/bottom_row.xml
# res/xml/colemak.xml
0 warnings
# res/xml/devanagari_1.xml
Layout includes some ASCII punctuation but not all, missing: ", $, ', ^, _, `, |
1 warnings
# res/xml/devanagari_2.xml
Layout includes some ASCII punctuation but not all, missing: #, $, %, &, ', (, ), *, +, ., /, :, <, =, >, @, [, \, ], ^, _, `, {, |, }, ~
1 warnings
# res/xml/dvorak.xml
0 warnings
# res/xml/greekmath.xml
Layout includes some ASCII punctuation but not all, missing: !, ", #, $, %, &, ', (, ), *, +, ,, -, /, :, ;, <, >, ?, @, [, \, ], _, `, {, |, }, ~
Layout redefines the bottom row but some important keys are missing, missing: change_method, config, ctrl, switch_emoji, switch_second
2 warnings
# res/xml/he_il_1452_1.xml
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# res/xml/he_il_1452_2.xml
Layout includes some ASCII punctuation but not all, missing: (, ), <, >, [, ], {, }
1 warnings
# res/xml/jcuken_ua.xml
0 warnings
# res/xml/local_bgph1.xml
Layout includes some ASCII punctuation but not all, missing: ~
1 warnings
# res/xml/local_ru_jcuken.xml
0 warnings
Not a layout file: res/xml/method.xml
# res/xml/neo2.xml
0 warnings
Not a layout file: res/xml/number_row.xml
# res/xml/numeric.xml
Layout includes some ASCII punctuation but not all, missing: &, ?, @, `
Layout redefines the bottom row but some important keys are missing, missing: change_method, config, switch_emoji, switch_numeric, switch_second
2 warnings
# res/xml/numpad.xml
Layout includes some ASCII punctuation but not all, missing: !, ", #, $, %, &, ', (, ), ,, :, ;, <, >, ?, @, [, \, ], ^, _, `, {, |, }, ~
Layout doesn't define some important keys, missing: backspace, delete
Layout redefines the bottom row but some important keys are missing, missing: action, change_method, config, ctrl, down, enter, fn, left, right, space, switch_emoji, switch_numeric, switch_second, up
3 warnings
# res/xml/persian.xml
Layout includes some ASCII punctuation but not all, missing: ", $, %, ', *, ,, /, ;, <, =, >, ?, [, \, ], ^, _, `, {, |, }, ~
1 warnings
# res/xml/pin.xml
Layout includes some ASCII punctuation but not all, missing: !, ", $, %, &, ', ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, ~
Layout redefines the bottom row but some important keys are missing, missing: change_method, config, ctrl, fn, switch_emoji, switch_second
2 warnings
# res/xml/qwerty_el.xml
0 warnings
# res/xml/qwerty_es.xml
0 warnings
# res/xml/qwerty_hu.xml
0 warnings
# res/xml/qwerty_ko.xml
0 warnings
# res/xml/qwerty_lv.xml
0 warnings
# res/xml/qwerty_no.xml
0 warnings
# res/xml/qwerty_pl.xml
0 warnings
# res/xml/qwerty_pt.xml
0 warnings
# res/xml/qwerty_sv_se.xml
0 warnings
# res/xml/qwerty_tr.xml
0 warnings
# res/xml/qwerty_vi.xml
Layout includes some ASCII punctuation but not all, missing: \
1 warnings
# res/xml/qwerty.xml
0 warnings
# res/xml/qwertz_cs.xml
Layout includes some ASCII punctuation but not all, missing: `
1 warnings
# res/xml/qwertz_de.xml
0 warnings
# res/xml/qwertz_hu.xml
0 warnings
# res/xml/qwertz_sk.xml
Layout includes some ASCII punctuation but not all, missing: \, `
1 warnings
# res/xml/qwertz.xml
0 warnings
Not a layout file: res/xml/settings.xml

72
check_layout.py Normal file
View File

@ -0,0 +1,72 @@
import xml.etree.ElementTree as ET
import sys
warning_count = 0
def warn(msg):
global warning_count
print(msg)
warning_count += 1
def key_list_str(keys):
return ", ".join(sorted(list(keys)))
def missing_some_of(keys, symbols, class_name=None):
if class_name is None:
class_name = "of [" + ", ".join(symbols) + "]"
missing = set(symbols).difference(keys)
if len(missing) > 0 and len(missing) != len(symbols):
warn("Layout includes some %s but not all, missing: %s" % (
class_name, key_list_str(missing)))
def missing_required(keys, symbols, msg):
missing = set(symbols).difference(keys)
if len(missing) > 0:
warn("%s, missing: %s" % (msg, key_list_str(missing)))
def unexpected_keys(keys, symbols, msg):
unexpected = set(symbols).intersection(keys)
if len(unexpected) > 0:
warn("%s, unexpected: %s" % (msg, key_list_str(unexpected)))
def parse_layout(fname):
keys = set()
root = ET.parse(fname).getroot()
if root.tag != "keyboard":
return None
for row in root:
for key in row:
for attr in key.keys():
keys.add(key.get(attr).removeprefix("\\"))
return root, keys
def check_layout(layout):
root, keys = layout
missing_some_of(keys, "~!@#$%^&*(){}`[]=\\-_;:/.,?<>'\"+|", "ASCII punctuation")
missing_some_of(keys, "0123456789", "digits")
missing_some_of(keys, ["f11_placeholder", "f12_placeholder"])
missing_some_of(keys, ["esc", "tab"])
missing_required(keys, ["backspace", "delete"], "Layout doesn't define some important keys")
bottom_row_keys = [
"ctrl", "fn", "switch_numeric", "change_method", "switch_emoji",
"config", "switch_second", "enter", "action", "left", "up", "right",
"down", "space"
]
if root.get("bottom_row") == "false":
missing_required(keys, bottom_row_keys,
"Layout redefines the bottom row but some important keys are missing")
else:
unexpected_keys(keys, bottom_row_keys,
"Layout contains keys present in the bottom row")
for fname in sys.argv[1:]:
layout = parse_layout(fname)
if layout == None:
print("Not a layout file: %s" % fname)
else:
print("# %s" % fname)
warning_count = 0
check_layout(layout)
print("%d warnings" % warning_count)

View File

@ -2,8 +2,8 @@
# files, one for each glyph. # files, one for each glyph.
New() New()
# Imports glyphs, file name is position in the font. # Imports glyphs, first argument is file name for the generated font
i = 1 i = 2
while (i < $argc) while (i < $argc)
Select(Strtol($argv[i]:t:r, 16)) Select(Strtol($argv[i]:t:r, 16))
Import($argv[i], 0, 0, 4.0, 0.1) Import($argv[i], 0, 0, 4.0, 0.1)
@ -11,4 +11,4 @@ while (i < $argc)
i++ i++
endloop endloop
Generate("result.ttf") Generate($argv[1])