diff options
Diffstat (limited to 'bin')
| -rwxr-xr-x | bin/udt-accent | 38 | ||||
| -rwxr-xr-x | bin/udt-palette | 52 |
2 files changed, 90 insertions, 0 deletions
diff --git a/bin/udt-accent b/bin/udt-accent index 75058df..1a542a6 100755 --- a/bin/udt-accent +++ b/bin/udt-accent @@ -32,6 +32,8 @@ MIN_CHROMA = 10.0 OUTPUT = Path.home() / ".cache" / "wal" / "udt-accent.rasi" BORDER_OUTPUT = Path.home() / ".cache" / "wal" / "udt-border.lua" DUNSTRC = Path.home() / ".cache" / "wal" / "dunstrc" +SUBLIME = (Path.home() / ".config" / "sublime-text" / "Packages" / "User" + / "udt.sublime-color-scheme") QML_OUTPUT = Path.home() / ".cache" / "wal" / "udt-palette.qml" # The installed rofi palette, itself generated by udt-palette. Read rather than @@ -280,6 +282,29 @@ def write_dunst(name): stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) +def write_sublime(name): + """Substitute the accent into the Sublime colour scheme install.sh copied. + + In place, like dunst: Sublime colour schemes do not cascade, so the accent + cannot arrive as a second file. Sublime watches Packages/User and reloads a + scheme when its file changes, so no signal is needed. A missing file is not + an error, Sublime simply may not be installed here. + + Unlike dunst, this reads the installed copy and has nowhere to recover + @ACCENT@ from once substituted, so the previous accent is replaced by + matching the variable line rather than a placeholder. + """ + try: + text = SUBLIME.read_text() + except FileNotFoundError: + return + + new, count = re.subn(r'("accent":\s*)"[^"]*"', + lambda m: f'{m.group(1)}"{ACCENTS[name]}"', text, count=1) + if count and new != text: + write_atomic(SUBLIME, new) + + def main(image): try: name = snap(signature_color(image)) @@ -292,6 +317,7 @@ def main(image): write_border(name) write_qml(name) write_dunst(name) + write_sublime(name) write_colors_json(name, image) # Hyprland only rereads its config on request, and may not be running. @@ -316,6 +342,18 @@ def selftest(): delta = min(delta, 2 * math.pi - delta) assert delta < 0.6, f"{probe} snapped to {got}, {delta:.2f} rad away" + # The Sublime accent is replaced by matching its current value, not a + # placeholder, so it has to survive being run twice: once over the freshly + # installed @ACCENT@, and again over the accent it wrote last time. + probe = '{\n "variables":\n {\n "accent": "@ACCENT@",\n' + first, n1 = re.subn(r'("accent":\s*)"[^"]*"', r'\1"#f5a97f"', probe, count=1) + second, n2 = re.subn(r'("accent":\s*)"[^"]*"', r'\1"#8bd5ca"', first, count=1) + third, n3 = re.subn(r'("accent":\s*)"[^"]*"', r'\1"#8bd5ca"', second, count=1) + assert (n1, n2, n3) == (1, 1, 1), (n1, n2, n3) + assert "@ACCENT@" not in first and '"#f5a97f"' in first + assert '"#f5a97f"' not in second and '"#8bd5ca"' in second + assert third == second, "accent substitution is not idempotent" + # A near-grey has an unstable hue angle and must take the fallback. assert snap("#888888") == FALLBACK, snap("#888888") assert FALLBACK in ACCENTS, FALLBACK diff --git a/bin/udt-palette b/bin/udt-palette index a746766..ceed64d 100755 --- a/bin/udt-palette +++ b/bin/udt-palette @@ -106,6 +106,12 @@ def hex8(c): return f"#{r:02x}{g:02x}{b:02x}{round(a * 255 / 100):02x}" +def rgb_array(c): + """[r, g, b], which is how a .sublime-theme writes a colour.""" + r, g, b, _ = c + return f"[{r}, {g}, {b}]" + + def rgba(c): r, g, b, a = c return f"rgb({r},{g},{b})" if a == 100 else f"rgba({r},{g},{b},{a / 100:.2f})" @@ -422,6 +428,48 @@ def gen_dunst(res, scheme, palette, template): return out +def gen_sublime(res, scheme, palette, template): + """Sublime Text: substitute the palette into the colour scheme. + + Scopes map onto the terminal roles rather than onto syntax roles of their + own. A scheme already declares all sixteen ANSI slots, so a syntax theme + costs no new roles and every shipped scheme satisfies it without touching + nine role maps. + + @ACCENT@ is left alone for udt-accent, exactly as in the dunst template: + Sublime colour schemes do not cascade, so the accent cannot arrive as a + second file and has to be substituted into this one. + """ + out = template.replace("@SCHEME@", scheme) + for role in ("bg", "bg_alt", "bg_deep", "surface", "surface_alt", + "fg", "fg_dim", "fg_faint", + "red", "green", "yellow", "blue", "magenta", "cyan", + "critical", "warning", "success", "info"): + out = out.replace(f"@{role.upper()}@", hex6(res[role])) + # The selection has to be translucent or it hides the text under it, and + # selection_bg resolves opaque because the terminal wants it that way. + out = out.replace("@SELECTION_BG@", hex8((*res["selection_bg"][:3], 35))) + return out + + +def gen_sublime_theme(res, scheme, palette, template): + """Sublime Text: the UI chrome, as an override layered over Material Behave. + + A .sublime-theme writes colours as [r, g, b] arrays rather than hex, so this + substitutes a different syntax from the colour scheme next door out of the + same roles. + + The accent is the scheme's fixed one, not the wallpaper's: Sublime reads a + theme once per window, so a moving accent would leave open windows + disagreeing with new ones. Same reasoning as conky, Qt, GTK and waybar. + """ + out = template.replace("@SCHEME@", scheme) + for role in ("bg", "bg_alt", "bg_deep", "fg", "fg_dim", "fg_faint", + "accent"): + out = out.replace(f"@{role.upper()}@", rgb_array(res[role])) + return out + + def gen_conky(res, scheme, palette, template): """conky: substitute into the shipped template. @@ -539,6 +587,10 @@ TARGETS = [ ("templates/typora/udt.css", gen_typora, "templates/typora/udt.css.in"), ("templates/kvantum/theme.kvconfig", gen_kvantum, "templates/kvantum/theme.kvconfig.in"), ("templates/kvantum/theme.svg", gen_kvantum, "templates/kvantum/theme.svg.in"), + ("templates/sublime/udt.sublime-color-scheme", gen_sublime, + "templates/sublime/udt.sublime-color-scheme.in"), + ("templates/sublime/udt.sublime-theme", gen_sublime_theme, + "templates/sublime/udt.sublime-theme.in"), ] |
