From cac380cf2a2960c97274c6ce3cc8b4ae3feb62d8 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 18 Jun 2026 20:42:29 -0500 Subject: feat(theme-studio): bucket unrecognized faces by their defface source A newly-loaded package (or a new built-in face) used to fall into emacs-core because grouping is by name-prefix and an unknown prefix matched nothing. Now the fallback routes by where the defface lives: an elpa face becomes its own package bucket, a built-in face a new emacs-general child. So loading a package and running make face-coverage surfaces it as a fresh TODO bucket instead of an orphan in core. Recognized faces still match their family first, and faces.el/frame.el faces stay in emacs-core. --- scripts/theme-studio/face_coverage.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'scripts/theme-studio') diff --git a/scripts/theme-studio/face_coverage.py b/scripts/theme-studio/face_coverage.py index 99a4e01fc..ba761230b 100644 --- a/scripts/theme-studio/face_coverage.py +++ b/scripts/theme-studio/face_coverage.py @@ -109,7 +109,31 @@ def load_managed(): return managed, fontlock, ui, pkg, inv -def make_group_of(families): +# Built-in source files whose faces are core display faces, not a subsystem; +# an unrecognized face from one of these stays in emacs-core rather than +# spawning an odd subsystem bucket under emacs-general. +CORE_FILES = {'faces', 'frame'} + + +def bucket_from_source(path): + """Derive a bucket name from a face's defface file, for faces that match no + known family. elpa -> the package dir name (version stripped); built-in -> + the source file basename; otherwise emacs-core (can't tell).""" + if not path: + return 'emacs-core' + if '/elpa/' in path: + pkgdir = path.split('/elpa/', 1)[1].split('/', 1)[0] + return re.sub(r'-[0-9].*$', '', pkgdir) or 'emacs-core' + if '/.emacs.d/modules' in path: + return 'user-config' + if path.startswith('/usr/share/emacs') or path.startswith('/usr/lib/emacs'): + base = os.path.basename(path) + base = base[:-3] if base.endswith('.el') else base + return 'emacs-core' if base in CORE_FILES else base + return 'emacs-core' + + +def make_group_of(families, src): fams = sorted(families, key=len, reverse=True) def group_of(f): @@ -124,7 +148,9 @@ def make_group_of(families): return p if f.lower().startswith('info-'): return 'info' - return 'emacs-core' + # Unrecognized: route by where the defface lives so a newly-loaded + # package buckets itself instead of falling into emacs-core. + return bucket_from_source(src.get(f, '')) return group_of @@ -189,7 +215,7 @@ def build(data, today): universe = sorted(set(docs.keys()) | managed) families = set(inv.keys()) | EXTRA_FAMILIES - group_of = make_group_of(families) + group_of = make_group_of(families, src) groups = collections.defaultdict(list) for f in universe: groups[group_of(f)].append(f) -- cgit v1.2.3