mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 19:27:16 +01:00
Merge branch 'main' of https://github.com/kuhyx/utils
Some checks failed
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
sickdays pre-commit / pre-commit (push) Has been cancelled
sickdays tests / test (push) Has been cancelled
Some checks failed
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
sickdays pre-commit / pre-commit (push) Has been cancelled
sickdays tests / test (push) Has been cancelled
This commit is contained in:
commit
35569a6335
@ -122,7 +122,10 @@ def desktop_problems(repo: Path) -> list[str]:
|
||||
if not names:
|
||||
out.append(f"{rel}: no Name= in [Desktop Entry]")
|
||||
for name in names:
|
||||
out += [f"{rel}: Name={p}" for p in launcher_label.label_problems(name)]
|
||||
out += [
|
||||
f"{rel}: Name={p}"
|
||||
for p in launcher_label.label_problems(name, words=True)
|
||||
]
|
||||
return out
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,8 @@ the launcher font is capped too (`label_widths.py`): FocusOwner, 10
|
||||
characters, was still cut. The same rules live
|
||||
in `~/src/testsAndMisc/python_pkg/app_icons/labels.py` (`label_problems`);
|
||||
the messages are mirrored here, not imported, because utils must not depend
|
||||
on another repo.
|
||||
on another repo. A desktop entry's `Name=` (rule 2) may hold single spaces
|
||||
between words (`words=True`); the phone launcher may not.
|
||||
|
||||
The name is `<application android:label>` of the main manifest, plus the
|
||||
`android:label` of any activity (or alias) whose intent-filter holds MAIN +
|
||||
@ -38,27 +39,39 @@ from repo_contract.label_widths import MAX_WIDTH, label_width
|
||||
MAX_LENGTH = 10
|
||||
STRINGS = Path("android/app/src/main/res/values/strings.xml")
|
||||
_ASCII_LETTERS = re.compile(r"[A-Za-z]+")
|
||||
_ASCII_WORDS = re.compile(r"[A-Za-z]+( [A-Za-z]+)*")
|
||||
_STRING_REF = re.compile(r"@string/(\w+)")
|
||||
_PLACEHOLDER = re.compile(r"\$\{(\w+)\}")
|
||||
_UNRESOLVED = "cannot resolve the launcher name"
|
||||
|
||||
|
||||
def label_problems(name: str) -> list[str]:
|
||||
"""Every launcher-name rule `name` breaks (app_icons labels.py wording)."""
|
||||
def label_problems(name: str, *, words: bool = False) -> list[str]:
|
||||
"""Every launcher-name rule `name` breaks (app_icons labels.py wording).
|
||||
|
||||
`words=True` is for a desktop entry's `Name=` (rule 2), shown in a menu or
|
||||
dmenu where "Sick days" reads better than "Sickdays": one space between
|
||||
words is fine. The phone launcher (rule 1) never passes it.
|
||||
"""
|
||||
if not name:
|
||||
return ["label is empty"]
|
||||
problems: list[str] = []
|
||||
letters_only = _ASCII_LETTERS.fullmatch(name) is not None
|
||||
if not letters_only:
|
||||
problems.append(
|
||||
f"{name!r} must contain only ASCII letters (no spaces, _ or symbols)"
|
||||
if words:
|
||||
valid = _ASCII_WORDS.fullmatch(name) is not None
|
||||
message = (
|
||||
f"{name!r} must be ASCII letters, one space between words (no _ or symbols)"
|
||||
)
|
||||
else:
|
||||
valid = _ASCII_LETTERS.fullmatch(name) is not None
|
||||
message = f"{name!r} must contain only ASCII letters (no spaces, _ or symbols)"
|
||||
if not valid:
|
||||
problems.append(message)
|
||||
if not name[0].isupper():
|
||||
problems.append(f"{name!r} must start with a capital letter")
|
||||
# The width table only knows ASCII letters; other names already failed.
|
||||
if letters_only and label_width(name) > MAX_WIDTH:
|
||||
letters = name.replace(" ", "")
|
||||
if valid and label_width(letters) > MAX_WIDTH:
|
||||
problems.append(
|
||||
f"{name!r} is {label_width(name)} wide in the launcher font; "
|
||||
f"{name!r} is {label_width(letters)} wide in the launcher font; "
|
||||
f"at most {MAX_WIDTH} fit"
|
||||
)
|
||||
if len(name) > MAX_LENGTH:
|
||||
|
||||
@ -98,6 +98,7 @@ def test_no_flutter_app_no_rules(repo: Path) -> None:
|
||||
def test_desktop_names_checked(repo: Path) -> None:
|
||||
flutter_app(repo)
|
||||
write(repo, "linux/good.desktop", DESKTOP.format(name="Todo"))
|
||||
write(repo, "linux/spaced.desktop", DESKTOP.format(name="Sick days"))
|
||||
write(repo, "linux/bad.desktop", DESKTOP.format(name="todo app"))
|
||||
write(
|
||||
repo,
|
||||
@ -108,10 +109,6 @@ def test_desktop_names_checked(repo: Path) -> None:
|
||||
track(repo)
|
||||
write(repo, "linux/untracked.desktop", DESKTOP.format(name="bad name"))
|
||||
assert launcher.problems(repo) == [
|
||||
(
|
||||
"launcher: linux/bad.desktop: Name='todo app' must contain only ASCII"
|
||||
" letters (no spaces, _ or symbols)"
|
||||
),
|
||||
"launcher: linux/bad.desktop: Name='todo app' must start with a capital letter",
|
||||
"launcher: linux/none.desktop: no Name= in [Desktop Entry]",
|
||||
]
|
||||
|
||||
@ -177,3 +177,45 @@ def test_manifest_without_application(tmp_path: Path) -> None:
|
||||
assert ll.problems(app) == [
|
||||
f"{MAIN}: <application> has no android:label; cannot resolve the launcher name"
|
||||
]
|
||||
|
||||
|
||||
WORDS_RULE = "must be ASCII letters, one space between words (no _ or symbols)"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("name", "expected"),
|
||||
[
|
||||
("Sick days", []),
|
||||
("Todo", []),
|
||||
("sick days", ["'sick days' must start with a capital letter"]),
|
||||
(
|
||||
"Sick days",
|
||||
[f"'Sick days' {WORDS_RULE}"],
|
||||
),
|
||||
(
|
||||
"Sick days ",
|
||||
[f"'Sick days ' {WORDS_RULE}"],
|
||||
),
|
||||
(
|
||||
"Sick_days",
|
||||
[f"'Sick_days' {WORDS_RULE}"],
|
||||
),
|
||||
(
|
||||
"Focus owner x",
|
||||
[
|
||||
"'Focus owner x' is 607 wide in the launcher font; at most 522 fit",
|
||||
"'Focus owner x' has 13 characters; at most 10 fit",
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_desktop_names_may_have_spaces_between_words(
|
||||
name: str, expected: list[str]
|
||||
) -> None:
|
||||
assert ll.label_problems(name, words=True) == expected
|
||||
|
||||
|
||||
def test_the_phone_label_still_refuses_a_space() -> None:
|
||||
assert ll.label_problems("Sick days") == [
|
||||
"'Sick days' must contain only ASCII letters (no spaces, _ or symbols)"
|
||||
]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Sickdays
|
||||
Name=Sick days
|
||||
Comment=Mark sick days and choose which lockers still apply
|
||||
Exec=sickdays gui
|
||||
Icon=face-sick
|
||||
|
||||
Loading…
Reference in New Issue
Block a user