From 47e64b5dff7e820619d4d60cf97a0fe027a4bcbd Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Mon, 15 Jun 2026 02:38:40 -0500 Subject: feat(theme-studio): add org-faces app for agenda keyword and priority colors Surface the org-faces-config.el header-row faces as their own theme-studio app, placed beside elfeed and mu4e so it reads as a custom layer rather than built-in org. The seed mirrors the module defaults exactly across all 28 faces (10 keywords, 4 priorities, and their dim variants), so the editor opens on the live colors. The preview shows a focused agenda block and an auto-dim block covering every face. --- scripts/theme-studio/app.js | 29 ++++++++++++++++++++++++++++- scripts/theme-studio/app_inventory.py | 1 + scripts/theme-studio/face_data.py | 16 ++++++++++++++++ scripts/theme-studio/generate.py | 1 + scripts/theme-studio/theme-studio.html | 31 +++++++++++++++++++++++++++++-- 5 files changed, 75 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js index 964ec2b2c..8803bec48 100644 --- a/scripts/theme-studio/app.js +++ b/scripts/theme-studio/app.js @@ -685,6 +685,33 @@ function renderMu4ePreview(){const a='mu4e',L=[]; L.push(os(a,'mu4e-compose-header-face','Subject:')+' new mail'); L.push(os(a,'mu4e-compose-separator-face','--text follows this line--')); return previewLines(L);} +function renderOrgFacesPreview(){const a='org-faces',L=[]; + L.push('Agenda header row -- one face per keyword and priority (this config, not built-in org):'); + L.push(''); + L.push(os(a,'org-faces-todo','TODO')+' Draft the spec '+os(a,'org-faces-priority-a','[#A]')); + L.push(os(a,'org-faces-project','PROJECT')+' Theme studio overhaul '+os(a,'org-faces-priority-b','[#B]')); + L.push(os(a,'org-faces-doing','DOING')+' Wire the faces '+os(a,'org-faces-priority-c','[#C]')); + L.push(os(a,'org-faces-waiting','WAITING')+' On review '+os(a,'org-faces-priority-d','[#D]')); + L.push(os(a,'org-faces-verify','VERIFY')+' Confirm the round-trip'); + L.push(os(a,'org-faces-stalled','STALLED')+' Blocked on upstream'); + L.push(os(a,'org-faces-delegated','DELEGATED')+' Handed to Kostya'); + L.push(os(a,'org-faces-failed','FAILED')+' Could not reproduce'); + L.push(os(a,'org-faces-done','DONE')+' Shipped the module'); + L.push(os(a,'org-faces-cancelled','CANCELLED')+' Dropped the approach'); + L.push(''); + L.push('Unfocused (auto-dim) -- the -dim variants auto-dim remaps onto in non-selected windows:'); + L.push(''); + L.push(os(a,'org-faces-todo-dim','TODO')+' Draft the spec '+os(a,'org-faces-priority-a-dim','[#A]')); + L.push(os(a,'org-faces-project-dim','PROJECT')+' Theme studio overhaul '+os(a,'org-faces-priority-b-dim','[#B]')); + L.push(os(a,'org-faces-doing-dim','DOING')+' Wire the faces '+os(a,'org-faces-priority-c-dim','[#C]')); + L.push(os(a,'org-faces-waiting-dim','WAITING')+' On review '+os(a,'org-faces-priority-d-dim','[#D]')); + L.push(os(a,'org-faces-verify-dim','VERIFY')+' Confirm the round-trip'); + L.push(os(a,'org-faces-stalled-dim','STALLED')+' Blocked on upstream'); + L.push(os(a,'org-faces-delegated-dim','DELEGATED')+' Handed to Kostya'); + L.push(os(a,'org-faces-failed-dim','FAILED')+' Could not reproduce'); + L.push(os(a,'org-faces-done-dim','DONE')+' Shipped the module'); + L.push(os(a,'org-faces-cancelled-dim','CANCELLED')+' Dropped the approach'); + return previewLines(L);} function renderLspPreview(){const a='lsp-mode',L=[]; L.push(os(a,'lsp-signature-face','process(')+os(a,'lsp-signature-highlight-function-argument','items: list')+os(a,'lsp-signature-face',') -> None')); L.push(os(a,'lsp-signature-posframe',' docs: iterate over items and process each one ')); @@ -873,7 +900,7 @@ function renderAutodimPreview(){ const PACKAGE_PREVIEWS={ autodim:renderAutodimPreview, org:renderOrgPreview,magit:renderMagitPreview,elfeed:renderElfeedPreview,ghostel:renderGhostelPreview, - dashboard:renderDashboardPreview,mu4e:renderMu4ePreview,lsp:renderLspPreview,gitgutter:renderGitGutterPreview, + dashboard:renderDashboardPreview,mu4e:renderMu4ePreview,orgfaces:renderOrgFacesPreview,lsp:renderLspPreview,gitgutter:renderGitGutterPreview, flycheck:renderFlycheckPreview,dired:renderDiredPreview,dirvish:renderDirvishPreview,calibredb:renderCalibredbPreview, erc:renderErcPreview,orgdrill:renderOrgdrillPreview,orgnoter:renderOrgnoterPreview,signel:renderSignelPreview, pearl:renderPearlPreview,slack:renderSlackPreview,telega:renderTelegaPreview,shr:renderShrPreview diff --git a/scripts/theme-studio/app_inventory.py b/scripts/theme-studio/app_inventory.py index 26044d359..01dcb7db7 100644 --- a/scripts/theme-studio/app_inventory.py +++ b/scripts/theme-studio/app_inventory.py @@ -14,6 +14,7 @@ BESPOKE_APPS = { "org", "org-mode", "mu4e", + "org-faces", "ghostel", "auto-dim-other-buffers", "dashboard", diff --git a/scripts/theme-studio/face_data.py b/scripts/theme-studio/face_data.py index d9b129150..bfce31cdd 100644 --- a/scripts/theme-studio/face_data.py +++ b/scripts/theme-studio/face_data.py @@ -149,6 +149,22 @@ AUTODIM_FACES=("auto-dim-other-buffers auto-dim-other-buffers-hide").split() AUTODIM_SEED={ "auto-dim-other-buffers":{"fg":"#5e6770","bg":"#000000"}, "auto-dim-other-buffers-hide":{"fg":"#000000","bg":"#000000"}} +# org-faces-config.el: custom, clearly-not-builtin faces for the agenda header +# row -- one face per TODO keyword and per priority cookie, plus a -dim variant +# auto-dim remaps to in non-selected windows. Seed mirrors the module defaults. +ORGFACES_FACES=("org-faces-todo org-faces-project org-faces-doing org-faces-waiting org-faces-verify " + "org-faces-stalled org-faces-delegated org-faces-failed org-faces-done org-faces-cancelled " + "org-faces-priority-a org-faces-priority-b org-faces-priority-c org-faces-priority-d " + "org-faces-todo-dim org-faces-project-dim org-faces-doing-dim org-faces-waiting-dim org-faces-verify-dim " + "org-faces-stalled-dim org-faces-delegated-dim org-faces-failed-dim org-faces-done-dim org-faces-cancelled-dim " + "org-faces-priority-a-dim org-faces-priority-b-dim org-faces-priority-c-dim org-faces-priority-d-dim").split() +ORGFACES_SEED={ + "org-faces-todo":{"fg":"#8fbf73","bold":True},"org-faces-project":{"fg":"#7a9abe","bold":True},"org-faces-doing":{"fg":"#e8c668","bold":True},"org-faces-waiting":{"fg":"#c9b08a","bold":True},"org-faces-verify":{"fg":"#d98a5a","bold":True}, + "org-faces-stalled":{"fg":"#9a8fb0","bold":True},"org-faces-delegated":{"fg":"#7fc0a8","bold":True},"org-faces-failed":{"fg":"#d05a5a","bold":True},"org-faces-done":{"fg":"#6f7a82","bold":True},"org-faces-cancelled":{"fg":"#6f7a82","bold":True,"strike":True}, + "org-faces-priority-a":{"fg":"#7aa0d0","bold":True},"org-faces-priority-b":{"fg":"#e8c668"},"org-faces-priority-c":{"fg":"#8fbf73"},"org-faces-priority-d":{"fg":"#8a8a8a"}, + "org-faces-todo-dim":{"fg":"#5f7a4d","bold":True},"org-faces-project-dim":{"fg":"#4f6680","bold":True},"org-faces-doing-dim":{"fg":"#9a8544","bold":True},"org-faces-waiting-dim":{"fg":"#87745c","bold":True},"org-faces-verify-dim":{"fg":"#8f5a3c","bold":True}, + "org-faces-stalled-dim":{"fg":"#665e75","bold":True},"org-faces-delegated-dim":{"fg":"#547d6c","bold":True},"org-faces-failed-dim":{"fg":"#8a3c3c","bold":True},"org-faces-done-dim":{"fg":"#4a5158","bold":True},"org-faces-cancelled-dim":{"fg":"#4a5158","bold":True,"strike":True}, + "org-faces-priority-a-dim":{"fg":"#4f6a8a","bold":True},"org-faces-priority-b-dim":{"fg":"#9a8544"},"org-faces-priority-c-dim":{"fg":"#5f7a4d"},"org-faces-priority-d-dim":{"fg":"#5a5a5a"}} DASHBOARD_FACES=("dashboard-banner-logo-title dashboard-text-banner dashboard-heading " "dashboard-items-face dashboard-navigator dashboard-no-items-face dashboard-footer-face dashboard-footer-icon-face").split() DASHBOARD_SEED={ diff --git a/scripts/theme-studio/generate.py b/scripts/theme-studio/generate.py index cc6a26f89..632bbc23a 100644 --- a/scripts/theme-studio/generate.py +++ b/scripts/theme-studio/generate.py @@ -228,6 +228,7 @@ _BESPOKE_APPS=[ ("magit","magit","magit",MAGIT_FACES,"magit-",MAGIT_SEED), ("elfeed","elfeed","elfeed",ELFEED_FACES,"elfeed-",ELFEED_SEED), ("mu4e","mu4e","mu4e",MU4E_FACES,"mu4e-",MU4E_SEED), + ("org-faces","org-faces","orgfaces",ORGFACES_FACES,"org-faces-",ORGFACES_SEED), ("ghostel","ghostel","ghostel",GHOSTEL_FACES,"ghostel-",GHOSTEL_SEED), ("auto-dim-other-buffers","auto-dim","autodim",AUTODIM_FACES,"auto-dim-other-buffers-",AUTODIM_SEED), ("dashboard","dashboard","dashboard",DASHBOARD_FACES,"dashboard-",DASHBOARD_SEED), diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html index 58a00de0c..09823f3f4 100644 --- a/scripts/theme-studio/theme-studio.html +++ b/scripts/theme-studio/theme-studio.html @@ -240,7 +240,7 @@