feat: include Conjure palette appearance

This commit is contained in:
hl-valdemar
2026-10-22 16:49:08 +02:00
parent b42e789f29
commit 92200c76ec
3 changed files with 58 additions and 7 deletions
+1 -1
View File
@@ -121,7 +121,7 @@ Configure OMP to use `tinty-current` where required.
### Conjure ### Conjure
The `apply-apps` flow writes `$XDG_CONFIG_HOME/conjure/theme.json`, falling back to `~/.config/conjure/theme.json` when `XDG_CONFIG_HOME` is unset, empty, or relative. The generated JSON contains seven opaque colors: `background`, `text`, `secondaryText`, `accent`, `glow`, `keyBackground`, and `error`, using Tinty semantic UI colors with Base16/Base24 or tinted8 palette fallbacks. The `apply-apps` flow writes `$XDG_CONFIG_HOME/conjure/theme.json`, falling back to `~/.config/conjure/theme.json` when `XDG_CONFIG_HOME` is unset, empty, or relative. The generated JSON contains the selected scheme's `variant` (`light` or `dark`) and seven opaque colors: `background`, `text`, `secondaryText`, `accent`, `glow`, `keyBackground`, and `error`, using Tinty semantic UI colors with Base16/Base24 or tinted8 palette fallbacks. Conjure uses the variant to match its native window appearance to the palette without an additional user setting.
Opt in by adding this to `conjure/config.toml` in the same configuration directory: Opt in by adding this to `conjure/config.toml` in the same configuration directory:
+6 -3
View File
@@ -40,7 +40,7 @@ func applyApps(zedSource string) error {
if err := writeHerdrTheme(colors, ui, syntax); err != nil { if err := writeHerdrTheme(colors, ui, syntax); err != nil {
return err return err
} }
if err := writeConjureTheme(colors, ui); err != nil { if err := writeConjureTheme(scheme.Variant, colors, ui); err != nil {
return err return err
} }
return writeZedTheme(zedSource) return writeZedTheme(zedSource)
@@ -189,7 +189,10 @@ func semanticTheme(colors, ui, syntax map[string]string) (map[string]string, map
return omp, herdr return omp, herdr
} }
func writeConjureTheme(colors, ui map[string]string) error { func writeConjureTheme(variant string, colors, ui map[string]string) error {
if variant != "light" && variant != "dark" {
return fmt.Errorf("invalid Conjure variant: %q", variant)
}
mapping := map[string]string{ mapping := map[string]string{
"background": pick(ui, "global.background.normal", colors, "base00"), "background": pick(ui, "global.background.normal", colors, "base00"),
"text": pick(ui, "global.foreground.normal", colors, "base05"), "text": pick(ui, "global.foreground.normal", colors, "base05"),
@@ -209,7 +212,7 @@ func writeConjureTheme(colors, ui map[string]string) error {
if !filepath.IsAbs(configHome) { if !filepath.IsAbs(configHome) {
configHome = filepath.Join(homeDir(), ".config") configHome = filepath.Join(homeDir(), ".config")
} }
return writeJSON(filepath.Join(configHome, "conjure", "theme.json"), map[string]any{"colors": mapping}) return writeJSON(filepath.Join(configHome, "conjure", "theme.json"), map[string]any{"variant": variant, "colors": mapping})
} }
func writeOMPTheme(colors, ui, syntax map[string]string) error { func writeOMPTheme(colors, ui, syntax map[string]string) error {
+50 -2
View File
@@ -138,6 +138,7 @@ func TestApplyAppsUsesTinted8Semantics(t *testing.T) {
"black-normal": {Hex: "#000000"}, "black-bright": {Hex: "#111111"}, "black-normal": {Hex: "#000000"}, "black-bright": {Hex: "#111111"},
"gray-dim": {Hex: "#222222"}, "gray-normal": {Hex: "#333333"}, "gray-bright": {Hex: "#444444"}, "gray-dim": {Hex: "#222222"}, "gray-normal": {Hex: "#333333"}, "gray-bright": {Hex: "#444444"},
"white-normal": {Hex: "#eeeeee"}, "white-bright": {Hex: "#ffffff"}, "white-normal": {Hex: "#eeeeee"}, "white-bright": {Hex: "#ffffff"},
"black-dim": {Hex: "#111111"}, "white-dim": {Hex: "#dddddd"},
"red-normal": {Hex: "#aa0000"}, "orange-normal": {Hex: "#bb5500"}, "red-normal": {Hex: "#aa0000"}, "orange-normal": {Hex: "#bb5500"},
"yellow-normal": {Hex: "#aaaa00"}, "green-normal": {Hex: "#00aa00"}, "yellow-normal": {Hex: "#aaaa00"}, "green-normal": {Hex: "#00aa00"},
"cyan-normal": {Hex: "#00aaaa"}, "blue-normal": {Hex: "#0000aa"}, "cyan-normal": {Hex: "#00aaaa"}, "blue-normal": {Hex: "#0000aa"},
@@ -211,11 +212,15 @@ esac
t.Fatalf("Zed theme was not renamed:\n%s", zedOutput) t.Fatalf("Zed theme was not renamed:\n%s", zedOutput)
} }
var conjure struct { var conjure struct {
Variant string `json:"variant"`
Colors map[string]string `json:"colors"` Colors map[string]string `json:"colors"`
} }
if err := json.Unmarshal([]byte(readFile(t, filepath.Join(filepath.Dir(conjureConfig), "theme.json"))), &conjure); err != nil { if err := json.Unmarshal([]byte(readFile(t, filepath.Join(filepath.Dir(conjureConfig), "theme.json"))), &conjure); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if conjure.Variant != "dark" {
t.Fatalf("Conjure variant = %q, want dark", conjure.Variant)
}
expected := map[string]string{ expected := map[string]string{
"background": "#010101", "text": "#fefefe", "secondaryText": "#444444", "background": "#010101", "text": "#fefefe", "secondaryText": "#444444",
"accent": "#123456", "glow": "#aa0000", "keyBackground": "#111111", "error": "#aa0000", "accent": "#123456", "glow": "#aa0000", "keyBackground": "#111111", "error": "#aa0000",
@@ -231,6 +236,33 @@ esac
if readFile(t, conjureConfig) != userConfig { if readFile(t, conjureConfig) != userConfig {
t.Fatal("Conjure user configuration changed") t.Fatal("Conjure user configuration changed")
} }
scheme.Variant = "light"
expected["secondaryText"] = "#222222"
expected["keyBackground"] = "#dddddd"
data, err = json.Marshal([]tintyScheme{scheme})
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(listPath, data, 0o644); err != nil {
t.Fatal(err)
}
if err := applyApps(zed); err != nil {
t.Fatal(err)
}
if err := json.Unmarshal([]byte(readFile(t, filepath.Join(filepath.Dir(conjureConfig), "theme.json"))), &conjure); err != nil {
t.Fatal(err)
}
if conjure.Variant != "light" {
t.Fatalf("Conjure variant = %q, want light", conjure.Variant)
}
for key, value := range expected {
if conjure.Colors[key] != value {
t.Errorf("light Conjure %s = %q, want %q", key, conjure.Colors[key], value)
}
}
if readFile(t, conjureConfig) != userConfig {
t.Fatal("Conjure user configuration changed")
}
} }
func TestBase16SemanticFallback(t *testing.T) { func TestBase16SemanticFallback(t *testing.T) {
@@ -277,7 +309,7 @@ func TestConjureThemeFallbacks(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := writeConjureTheme(colors, nil); err != nil { if err := writeConjureTheme("dark", colors, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
var theme struct { var theme struct {
@@ -308,13 +340,29 @@ func TestConjureThemeRejectsInvalidColors(t *testing.T) {
"base00": "#000000", "base01": "#111111", "base04": "#444444", "base00": "#000000", "base01": "#111111", "base04": "#444444",
"base05": "#555555", "base08": "#880000", "base0D": value, "base05": "#555555", "base08": "#880000", "base0D": value,
} }
if err := writeConjureTheme(colors, nil); err == nil { if err := writeConjureTheme("dark", colors, nil); err == nil {
t.Fatalf("accepted invalid accent %q", value) t.Fatalf("accepted invalid accent %q", value)
} }
}) })
} }
} }
func TestConjureThemeRejectsInvalidVariants(t *testing.T) {
t.Setenv("HOME", t.TempDir())
t.Setenv("XDG_CONFIG_HOME", "")
colors := map[string]string{
"base00": "#000000", "base01": "#111111", "base04": "#444444",
"base05": "#555555", "base08": "#880000", "base0D": "#0000dd",
}
for _, variant := range []string{"", "auto", "Light", "DARK"} {
t.Run(variant, func(t *testing.T) {
if err := writeConjureTheme(variant, colors, nil); err == nil {
t.Fatalf("accepted invalid variant %q", variant)
}
})
}
}
func writeExecutable(t *testing.T, path, content string) { func writeExecutable(t *testing.T, path, content string) {
t.Helper() t.Helper()
if err := os.WriteFile(path, []byte(content), 0o755); err != nil { if err := os.WriteFile(path, []byte(content), 0o755); err != nil {