mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
feat/matugen3 (#771)
* added matugen 3 terminal templates and logic fixed version check and light terminal check refactored json generation fixed syntax keep tmp debug fixed file outputs fixed syntax issues and implicit passing added debug stderr output * moved calls to matugen after template is built correctly added --json hex disabled debug message cleaned up code into modular functions, re-added second full matugen call fixed args added shift commented vs code section debug changes * arg format fixes fixed json import flag fixed string quotation fix arg order * cleaned up fix cfg naming * removed mt2.0 templates and refactored worker removed/replaced matugen 2 templates fix formatter diffs + consistent styling * fixed last json output * fixed syntax error * vs code templates * matugen: inject all stock/custom theme colors as overrides - also some general architectural changes * dank16: remove vscode enrich option --------- Co-authored-by: bbedward
This commit is contained in:
@@ -46,3 +46,9 @@ packages:
|
||||
outpkg: mocks_evdev
|
||||
interfaces:
|
||||
EvdevDevice:
|
||||
github.com/AvengeMedia/DankMaterialShell/core/internal/version:
|
||||
config:
|
||||
dir: "internal/mocks/version"
|
||||
outpkg: mocks_version
|
||||
interfaces:
|
||||
VersionFetcher:
|
||||
|
||||
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/dank16"
|
||||
@@ -26,7 +25,6 @@ func init() {
|
||||
dank16Cmd.Flags().Bool("alacritty", false, "Output in Alacritty terminal format")
|
||||
dank16Cmd.Flags().Bool("ghostty", false, "Output in Ghostty terminal format")
|
||||
dank16Cmd.Flags().Bool("wezterm", false, "Output in Wezterm terminal format")
|
||||
dank16Cmd.Flags().String("vscode-enrich", "", "Enrich existing VSCode theme file with terminal colors")
|
||||
dank16Cmd.Flags().String("background", "", "Custom background color")
|
||||
dank16Cmd.Flags().String("contrast", "dps", "Contrast algorithm: dps (Delta Phi Star, default) or wcag")
|
||||
}
|
||||
@@ -44,7 +42,6 @@ func runDank16(cmd *cobra.Command, args []string) {
|
||||
isAlacritty, _ := cmd.Flags().GetBool("alacritty")
|
||||
isGhostty, _ := cmd.Flags().GetBool("ghostty")
|
||||
isWezterm, _ := cmd.Flags().GetBool("wezterm")
|
||||
vscodeEnrich, _ := cmd.Flags().GetString("vscode-enrich")
|
||||
background, _ := cmd.Flags().GetString("background")
|
||||
contrastAlgo, _ := cmd.Flags().GetString("contrast")
|
||||
|
||||
@@ -65,18 +62,7 @@ func runDank16(cmd *cobra.Command, args []string) {
|
||||
|
||||
colors := dank16.GeneratePalette(primaryColor, opts)
|
||||
|
||||
if vscodeEnrich != "" {
|
||||
data, err := os.ReadFile(vscodeEnrich)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file: %v", err)
|
||||
}
|
||||
|
||||
enriched, err := dank16.EnrichVSCodeTheme(data, colors)
|
||||
if err != nil {
|
||||
log.Fatalf("Error enriching theme: %v", err)
|
||||
}
|
||||
fmt.Println(string(enriched))
|
||||
} else if isJson {
|
||||
if isJson {
|
||||
fmt.Print(dank16.GenerateJSON(colors))
|
||||
} else if isKitty {
|
||||
fmt.Print(dank16.GenerateKittyTheme(colors))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dank16
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
@@ -373,79 +372,6 @@ func TestGeneratePalette(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnrichVSCodeTheme(t *testing.T) {
|
||||
colors := GeneratePalette("#625690", PaletteOptions{IsLight: false})
|
||||
|
||||
baseTheme := map[string]interface{}{
|
||||
"name": "Test Theme",
|
||||
"type": "dark",
|
||||
"colors": map[string]interface{}{
|
||||
"editor.background": "#000000",
|
||||
},
|
||||
}
|
||||
|
||||
themeJSON, err := json.Marshal(baseTheme)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal base theme: %v", err)
|
||||
}
|
||||
|
||||
result, err := EnrichVSCodeTheme(themeJSON, colors)
|
||||
if err != nil {
|
||||
t.Fatalf("EnrichVSCodeTheme failed: %v", err)
|
||||
}
|
||||
|
||||
var enriched map[string]interface{}
|
||||
if err := json.Unmarshal(result, &enriched); err != nil {
|
||||
t.Fatalf("Failed to unmarshal result: %v", err)
|
||||
}
|
||||
|
||||
colorsMap, ok := enriched["colors"].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatal("colors is not a map")
|
||||
}
|
||||
|
||||
terminalColors := []string{
|
||||
"terminal.ansiBlack",
|
||||
"terminal.ansiRed",
|
||||
"terminal.ansiGreen",
|
||||
"terminal.ansiYellow",
|
||||
"terminal.ansiBlue",
|
||||
"terminal.ansiMagenta",
|
||||
"terminal.ansiCyan",
|
||||
"terminal.ansiWhite",
|
||||
"terminal.ansiBrightBlack",
|
||||
"terminal.ansiBrightRed",
|
||||
"terminal.ansiBrightGreen",
|
||||
"terminal.ansiBrightYellow",
|
||||
"terminal.ansiBrightBlue",
|
||||
"terminal.ansiBrightMagenta",
|
||||
"terminal.ansiBrightCyan",
|
||||
"terminal.ansiBrightWhite",
|
||||
}
|
||||
|
||||
for i, key := range terminalColors {
|
||||
if val, ok := colorsMap[key]; !ok {
|
||||
t.Errorf("Missing terminal color: %s", key)
|
||||
} else if val != colors[i] {
|
||||
t.Errorf("%s = %s, expected %s", key, val, colors[i])
|
||||
}
|
||||
}
|
||||
|
||||
if colorsMap["editor.background"] != "#000000" {
|
||||
t.Error("Original theme colors should be preserved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnrichVSCodeThemeInvalidJSON(t *testing.T) {
|
||||
colors := GeneratePalette("#625690", PaletteOptions{IsLight: false})
|
||||
invalidJSON := []byte("{invalid json")
|
||||
|
||||
_, err := EnrichVSCodeTheme(invalidJSON, colors)
|
||||
if err == nil {
|
||||
t.Error("Expected error for invalid JSON, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundTripConversion(t *testing.T) {
|
||||
testColors := []string{"#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff", "#625690", "#808080"}
|
||||
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
package dank16
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type VSCodeTheme struct {
|
||||
Schema string `json:"$schema"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Colors map[string]string `json:"colors"`
|
||||
TokenColors []VSCodeTokenColor `json:"tokenColors"`
|
||||
SemanticHighlighting bool `json:"semanticHighlighting"`
|
||||
SemanticTokenColors map[string]VSCodeTokenSetting `json:"semanticTokenColors"`
|
||||
}
|
||||
|
||||
type VSCodeTokenColor struct {
|
||||
Scope interface{} `json:"scope"`
|
||||
Settings VSCodeTokenSetting `json:"settings"`
|
||||
}
|
||||
|
||||
type VSCodeTokenSetting struct {
|
||||
Foreground string `json:"foreground,omitempty"`
|
||||
FontStyle string `json:"fontStyle,omitempty"`
|
||||
}
|
||||
|
||||
func updateTokenColor(tc interface{}, scopeToColor map[string]string) {
|
||||
tcMap, ok := tc.(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
scopes, ok := tcMap["scope"].([]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
settings, ok := tcMap["settings"].(map[string]interface{})
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
isYaml := hasScopeContaining(scopes, "yaml")
|
||||
|
||||
for _, scope := range scopes {
|
||||
scopeStr, ok := scope.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if scopeStr == "string" && isYaml {
|
||||
continue
|
||||
}
|
||||
|
||||
if applyColorToScope(settings, scope, scopeToColor) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyColorToScope(settings map[string]interface{}, scope interface{}, scopeToColor map[string]string) bool {
|
||||
scopeStr, ok := scope.(string)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
newColor, exists := scopeToColor[scopeStr]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
settings["foreground"] = newColor
|
||||
return true
|
||||
}
|
||||
|
||||
func hasScopeContaining(scopes []interface{}, substring string) bool {
|
||||
for _, scope := range scopes {
|
||||
scopeStr, ok := scope.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for i := 0; i <= len(scopeStr)-len(substring); i++ {
|
||||
if scopeStr[i:i+len(substring)] == substring {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func EnrichVSCodeTheme(themeData []byte, colors []string) ([]byte, error) {
|
||||
var theme map[string]interface{}
|
||||
if err := json.Unmarshal(themeData, &theme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
colorsMap, ok := theme["colors"].(map[string]interface{})
|
||||
if !ok {
|
||||
colorsMap = make(map[string]interface{})
|
||||
theme["colors"] = colorsMap
|
||||
}
|
||||
|
||||
bg := colors[0]
|
||||
isLight := false
|
||||
if len(bg) == 7 && bg[0] == '#' {
|
||||
r, g, b := 0, 0, 0
|
||||
fmt.Sscanf(bg[1:], "%02x%02x%02x", &r, &g, &b)
|
||||
luminance := (0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)) / 255.0
|
||||
isLight = luminance > 0.5
|
||||
}
|
||||
|
||||
if isLight {
|
||||
theme["type"] = "light"
|
||||
} else {
|
||||
theme["type"] = "dark"
|
||||
}
|
||||
|
||||
colorsMap["terminal.ansiBlack"] = colors[0]
|
||||
colorsMap["terminal.ansiRed"] = colors[1]
|
||||
colorsMap["terminal.ansiGreen"] = colors[2]
|
||||
colorsMap["terminal.ansiYellow"] = colors[3]
|
||||
colorsMap["terminal.ansiBlue"] = colors[4]
|
||||
colorsMap["terminal.ansiMagenta"] = colors[5]
|
||||
colorsMap["terminal.ansiCyan"] = colors[6]
|
||||
colorsMap["terminal.ansiWhite"] = colors[7]
|
||||
colorsMap["terminal.ansiBrightBlack"] = colors[8]
|
||||
colorsMap["terminal.ansiBrightRed"] = colors[9]
|
||||
colorsMap["terminal.ansiBrightGreen"] = colors[10]
|
||||
colorsMap["terminal.ansiBrightYellow"] = colors[11]
|
||||
colorsMap["terminal.ansiBrightBlue"] = colors[12]
|
||||
colorsMap["terminal.ansiBrightMagenta"] = colors[13]
|
||||
colorsMap["terminal.ansiBrightCyan"] = colors[14]
|
||||
colorsMap["terminal.ansiBrightWhite"] = colors[15]
|
||||
|
||||
tokenColors, ok := theme["tokenColors"].([]interface{})
|
||||
if ok {
|
||||
scopeToColor := map[string]string{
|
||||
"comment": colors[8],
|
||||
"punctuation.definition.comment": colors[8],
|
||||
"keyword": colors[5],
|
||||
"storage.type": colors[13],
|
||||
"storage.modifier": colors[5],
|
||||
"variable": colors[15],
|
||||
"variable.parameter": colors[7],
|
||||
"meta.object-literal.key": colors[4],
|
||||
"meta.property.object": colors[4],
|
||||
"variable.other.property": colors[4],
|
||||
"constant.other.symbol": colors[12],
|
||||
"constant.numeric": colors[12],
|
||||
"constant.language": colors[12],
|
||||
"constant.character": colors[3],
|
||||
"entity.name.type": colors[12],
|
||||
"support.type": colors[13],
|
||||
"entity.name.class": colors[12],
|
||||
"entity.name.function": colors[2],
|
||||
"support.function": colors[2],
|
||||
"support.class": colors[15],
|
||||
"support.variable": colors[15],
|
||||
"variable.language": colors[12],
|
||||
"entity.name.tag.yaml": colors[12],
|
||||
"string.unquoted.plain.out.yaml": colors[15],
|
||||
"string.unquoted.yaml": colors[15],
|
||||
"string": colors[3],
|
||||
}
|
||||
|
||||
for i, tc := range tokenColors {
|
||||
updateTokenColor(tc, scopeToColor)
|
||||
tokenColors[i] = tc
|
||||
}
|
||||
|
||||
yamlRules := []VSCodeTokenColor{
|
||||
{
|
||||
Scope: "entity.name.tag.yaml",
|
||||
Settings: VSCodeTokenSetting{Foreground: colors[12]},
|
||||
},
|
||||
{
|
||||
Scope: []string{"string.unquoted.plain.out.yaml", "string.unquoted.yaml"},
|
||||
Settings: VSCodeTokenSetting{Foreground: colors[15]},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rule := range yamlRules {
|
||||
tokenColors = append(tokenColors, rule)
|
||||
}
|
||||
|
||||
theme["tokenColors"] = tokenColors
|
||||
}
|
||||
|
||||
if semanticTokenColors, ok := theme["semanticTokenColors"].(map[string]interface{}); ok {
|
||||
updates := map[string]string{
|
||||
"variable": colors[15],
|
||||
"variable.readonly": colors[12],
|
||||
"property": colors[4],
|
||||
"function": colors[2],
|
||||
"method": colors[2],
|
||||
"type": colors[12],
|
||||
"class": colors[12],
|
||||
"typeParameter": colors[13],
|
||||
"enumMember": colors[12],
|
||||
"string": colors[3],
|
||||
"number": colors[12],
|
||||
"comment": colors[8],
|
||||
"keyword": colors[5],
|
||||
"operator": colors[15],
|
||||
"parameter": colors[7],
|
||||
"namespace": colors[15],
|
||||
}
|
||||
|
||||
for key, color := range updates {
|
||||
if existing, ok := semanticTokenColors[key].(map[string]interface{}); ok {
|
||||
existing["foreground"] = color
|
||||
} else {
|
||||
semanticTokenColors[key] = map[string]interface{}{
|
||||
"foreground": color,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
semanticTokenColors := make(map[string]interface{})
|
||||
updates := map[string]string{
|
||||
"variable": colors[7],
|
||||
"variable.readonly": colors[12],
|
||||
"property": colors[4],
|
||||
"function": colors[2],
|
||||
"method": colors[2],
|
||||
"type": colors[12],
|
||||
"class": colors[12],
|
||||
"typeParameter": colors[13],
|
||||
"enumMember": colors[12],
|
||||
"string": colors[3],
|
||||
"number": colors[12],
|
||||
"comment": colors[8],
|
||||
"keyword": colors[5],
|
||||
"operator": colors[15],
|
||||
"parameter": colors[7],
|
||||
"namespace": colors[15],
|
||||
}
|
||||
|
||||
for key, color := range updates {
|
||||
semanticTokenColors[key] = map[string]interface{}{
|
||||
"foreground": color,
|
||||
}
|
||||
}
|
||||
theme["semanticTokenColors"] = semanticTokenColors
|
||||
}
|
||||
|
||||
return json.MarshalIndent(theme, "", " ")
|
||||
}
|
||||
144
core/internal/mocks/version/mock_VersionFetcher.go
Normal file
144
core/internal/mocks/version/mock_VersionFetcher.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Code generated by mockery v2.53.5. DO NOT EDIT.
|
||||
|
||||
package mocks_version
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// MockVersionFetcher is an autogenerated mock type for the VersionFetcher type
|
||||
type MockVersionFetcher struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockVersionFetcher_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockVersionFetcher) EXPECT() *MockVersionFetcher_Expecter {
|
||||
return &MockVersionFetcher_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetCurrentVersion provides a mock function with given fields: dmsPath
|
||||
func (_m *MockVersionFetcher) GetCurrentVersion(dmsPath string) (string, error) {
|
||||
ret := _m.Called(dmsPath)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetCurrentVersion")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
|
||||
return rf(dmsPath)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||
r0 = rf(dmsPath)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(dmsPath)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockVersionFetcher_GetCurrentVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCurrentVersion'
|
||||
type MockVersionFetcher_GetCurrentVersion_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetCurrentVersion is a helper method to define mock.On call
|
||||
// - dmsPath string
|
||||
func (_e *MockVersionFetcher_Expecter) GetCurrentVersion(dmsPath interface{}) *MockVersionFetcher_GetCurrentVersion_Call {
|
||||
return &MockVersionFetcher_GetCurrentVersion_Call{Call: _e.mock.On("GetCurrentVersion", dmsPath)}
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetCurrentVersion_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetCurrentVersion_Call) Return(_a0 string, _a1 error) *MockVersionFetcher_GetCurrentVersion_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetCurrentVersion_Call) RunAndReturn(run func(string) (string, error)) *MockVersionFetcher_GetCurrentVersion_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetLatestVersion provides a mock function with given fields: dmsPath
|
||||
func (_m *MockVersionFetcher) GetLatestVersion(dmsPath string) (string, error) {
|
||||
ret := _m.Called(dmsPath)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetLatestVersion")
|
||||
}
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string) (string, error)); ok {
|
||||
return rf(dmsPath)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string) string); ok {
|
||||
r0 = rf(dmsPath)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||
r1 = rf(dmsPath)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockVersionFetcher_GetLatestVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestVersion'
|
||||
type MockVersionFetcher_GetLatestVersion_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetLatestVersion is a helper method to define mock.On call
|
||||
// - dmsPath string
|
||||
func (_e *MockVersionFetcher_Expecter) GetLatestVersion(dmsPath interface{}) *MockVersionFetcher_GetLatestVersion_Call {
|
||||
return &MockVersionFetcher_GetLatestVersion_Call{Call: _e.mock.On("GetLatestVersion", dmsPath)}
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetLatestVersion_Call) Run(run func(dmsPath string)) *MockVersionFetcher_GetLatestVersion_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetLatestVersion_Call) Return(_a0 string, _a1 error) *MockVersionFetcher_GetLatestVersion_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockVersionFetcher_GetLatestVersion_Call) RunAndReturn(run func(string) (string, error)) *MockVersionFetcher_GetLatestVersion_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewMockVersionFetcher creates a new instance of MockVersionFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewMockVersionFetcher(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *MockVersionFetcher {
|
||||
mock := &MockVersionFetcher{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -18,28 +18,27 @@ type VersionInfo struct {
|
||||
HasUpdate bool
|
||||
}
|
||||
|
||||
func GetCurrentDMSVersion() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get home directory: %w", err)
|
||||
}
|
||||
// VersionFetcher is an interface for fetching version information
|
||||
type VersionFetcher interface {
|
||||
GetCurrentVersion(dmsPath string) (string, error)
|
||||
GetLatestVersion(dmsPath string) (string, error)
|
||||
}
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
if _, err := os.Stat(dmsPath); os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("DMS not installed")
|
||||
}
|
||||
|
||||
originalDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Chdir(originalDir)
|
||||
|
||||
if err := os.Chdir(dmsPath); err != nil {
|
||||
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
||||
}
|
||||
// DefaultVersionFetcher is the default implementation that uses git/curl
|
||||
type DefaultVersionFetcher struct{}
|
||||
|
||||
func (d *DefaultVersionFetcher) GetCurrentVersion(dmsPath string) (string, error) {
|
||||
if _, err := os.Stat(filepath.Join(dmsPath, ".git")); err == nil {
|
||||
originalDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Chdir(originalDir)
|
||||
|
||||
if err := os.Chdir(dmsPath); err != nil {
|
||||
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
||||
}
|
||||
|
||||
tagCmd := exec.Command("git", "describe", "--exact-match", "--tags", "HEAD")
|
||||
if tagOutput, err := tagCmd.Output(); err == nil {
|
||||
return strings.TrimSpace(string(tagOutput)), nil
|
||||
@@ -65,21 +64,14 @@ func GetCurrentDMSVersion() (string, error) {
|
||||
return "unknown", nil
|
||||
}
|
||||
|
||||
func GetLatestDMSVersion() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get home directory: %w", err)
|
||||
}
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
|
||||
originalDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Chdir(originalDir)
|
||||
|
||||
func (d *DefaultVersionFetcher) GetLatestVersion(dmsPath string) (string, error) {
|
||||
if _, err := os.Stat(filepath.Join(dmsPath, ".git")); err == nil {
|
||||
originalDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Chdir(originalDir)
|
||||
|
||||
if err := os.Chdir(dmsPath); err != nil {
|
||||
return "", fmt.Errorf("failed to change to DMS directory: %w", err)
|
||||
}
|
||||
@@ -154,13 +146,54 @@ func GetLatestDMSVersion() (string, error) {
|
||||
return result.TagName, nil
|
||||
}
|
||||
|
||||
// defaultFetcher is used by the public functions
|
||||
var defaultFetcher VersionFetcher = &DefaultVersionFetcher{}
|
||||
|
||||
func GetCurrentDMSVersion() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get home directory: %w", err)
|
||||
}
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
if _, err := os.Stat(dmsPath); os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("DMS not installed")
|
||||
}
|
||||
|
||||
return defaultFetcher.GetCurrentVersion(dmsPath)
|
||||
}
|
||||
|
||||
func GetLatestDMSVersion() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get home directory: %w", err)
|
||||
}
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
return defaultFetcher.GetLatestVersion(dmsPath)
|
||||
}
|
||||
|
||||
func GetDMSVersionInfo() (*VersionInfo, error) {
|
||||
current, err := GetCurrentDMSVersion()
|
||||
return GetDMSVersionInfoWithFetcher(defaultFetcher)
|
||||
}
|
||||
|
||||
func GetDMSVersionInfoWithFetcher(fetcher VersionFetcher) (*VersionInfo, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get home directory: %w", err)
|
||||
}
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
if _, err := os.Stat(dmsPath); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("DMS not installed")
|
||||
}
|
||||
|
||||
current, err := fetcher.GetCurrentVersion(dmsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
latest, err := GetLatestDMSVersion()
|
||||
latest, err := fetcher.GetLatestVersion(dmsPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get latest version: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
mocks_version "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/version"
|
||||
)
|
||||
|
||||
func TestCompareVersions(t *testing.T) {
|
||||
@@ -33,36 +35,107 @@ func TestCompareVersions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDMSVersionInfo_Structure(t *testing.T) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("Cannot get home directory")
|
||||
}
|
||||
// Create a temp directory with a fake DMS installation
|
||||
tempDir := t.TempDir()
|
||||
dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms")
|
||||
os.MkdirAll(dmsPath, 0755)
|
||||
|
||||
dmsPath := filepath.Join(homeDir, ".config", "quickshell", "dms")
|
||||
if _, err := os.Stat(dmsPath); os.IsNotExist(err) {
|
||||
t.Skip("DMS not installed, skipping version info test")
|
||||
}
|
||||
// Create a .git directory to simulate git installation
|
||||
os.MkdirAll(filepath.Join(dmsPath, ".git"), 0755)
|
||||
|
||||
info, err := GetDMSVersionInfo()
|
||||
originalHome := os.Getenv("HOME")
|
||||
defer os.Setenv("HOME", originalHome)
|
||||
os.Setenv("HOME", tempDir)
|
||||
|
||||
// Create mock fetcher
|
||||
mockFetcher := mocks_version.NewMockVersionFetcher(t)
|
||||
mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("v0.1.0", nil)
|
||||
mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("v0.1.1", nil)
|
||||
|
||||
info, err := GetDMSVersionInfoWithFetcher(mockFetcher)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDMSVersionInfo() failed: %v", err)
|
||||
t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err)
|
||||
}
|
||||
|
||||
if info == nil {
|
||||
t.Fatal("GetDMSVersionInfo() returned nil")
|
||||
t.Fatal("GetDMSVersionInfoWithFetcher() returned nil")
|
||||
}
|
||||
|
||||
if info.Current == "" {
|
||||
t.Error("Current version is empty")
|
||||
if info.Current != "v0.1.0" {
|
||||
t.Errorf("Current version = %s, expected v0.1.0", info.Current)
|
||||
}
|
||||
|
||||
if info.Latest == "" {
|
||||
t.Error("Latest version is empty")
|
||||
if info.Latest != "v0.1.1" {
|
||||
t.Errorf("Latest version = %s, expected v0.1.1", info.Latest)
|
||||
}
|
||||
|
||||
if !info.HasUpdate {
|
||||
t.Error("HasUpdate should be true when current != latest")
|
||||
}
|
||||
|
||||
if !info.IsTag {
|
||||
t.Error("IsTag should be true for v0.1.0")
|
||||
}
|
||||
|
||||
t.Logf("Current: %s, Latest: %s, HasUpdate: %v", info.Current, info.Latest, info.HasUpdate)
|
||||
}
|
||||
|
||||
func TestGetDMSVersionInfo_BranchVersion(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms")
|
||||
os.MkdirAll(dmsPath, 0755)
|
||||
os.MkdirAll(filepath.Join(dmsPath, ".git"), 0755)
|
||||
|
||||
originalHome := os.Getenv("HOME")
|
||||
defer os.Setenv("HOME", originalHome)
|
||||
os.Setenv("HOME", tempDir)
|
||||
|
||||
mockFetcher := mocks_version.NewMockVersionFetcher(t)
|
||||
mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("master@abc1234", nil)
|
||||
mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("master@def5678", nil)
|
||||
|
||||
info, err := GetDMSVersionInfoWithFetcher(mockFetcher)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err)
|
||||
}
|
||||
|
||||
if !info.IsBranch {
|
||||
t.Error("IsBranch should be true for branch@commit format")
|
||||
}
|
||||
|
||||
if !info.IsGit {
|
||||
t.Error("IsGit should be true for branch@commit format")
|
||||
}
|
||||
|
||||
if !info.HasUpdate {
|
||||
t.Error("HasUpdate should be true when commits differ")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDMSVersionInfo_NoUpdate(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
dmsPath := filepath.Join(tempDir, ".config", "quickshell", "dms")
|
||||
os.MkdirAll(dmsPath, 0755)
|
||||
os.MkdirAll(filepath.Join(dmsPath, ".git"), 0755)
|
||||
|
||||
originalHome := os.Getenv("HOME")
|
||||
defer os.Setenv("HOME", originalHome)
|
||||
os.Setenv("HOME", tempDir)
|
||||
|
||||
mockFetcher := mocks_version.NewMockVersionFetcher(t)
|
||||
mockFetcher.EXPECT().GetCurrentVersion(dmsPath).Return("v0.1.0", nil)
|
||||
mockFetcher.EXPECT().GetLatestVersion(dmsPath).Return("v0.1.0", nil)
|
||||
|
||||
info, err := GetDMSVersionInfoWithFetcher(mockFetcher)
|
||||
if err != nil {
|
||||
t.Fatalf("GetDMSVersionInfoWithFetcher() failed: %v", err)
|
||||
}
|
||||
|
||||
if info.HasUpdate {
|
||||
t.Error("HasUpdate should be false when current == latest")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentDMSVersion_NotInstalled(t *testing.T) {
|
||||
originalHome := os.Getenv("HOME")
|
||||
defer os.Setenv("HOME", originalHome)
|
||||
|
||||
@@ -88,7 +88,9 @@ Singleton {
|
||||
property bool gtkThemingEnabled: typeof SettingsData !== "undefined" ? SettingsData.gtkAvailable : false
|
||||
property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false
|
||||
property var workerRunning: false
|
||||
property var pendingThemeRequest: null
|
||||
property var matugenColors: ({})
|
||||
property var _pendingGenerateParams: null
|
||||
property var customThemeData: null
|
||||
|
||||
Component.onCompleted: {
|
||||
@@ -784,13 +786,26 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function setDesiredTheme(kind, value, isLight, iconTheme, matugenType) {
|
||||
function setDesiredTheme(kind, value, isLight, iconTheme, matugenType, stockColors) {
|
||||
if (!matugenAvailable) {
|
||||
console.warn("Theme: matugen not available or disabled - cannot set system theme");
|
||||
return;
|
||||
}
|
||||
|
||||
console.info("Theme: Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", "type:", matugenType);
|
||||
if (workerRunning) {
|
||||
console.info("Theme: Worker already running, queueing request");
|
||||
pendingThemeRequest = {
|
||||
kind,
|
||||
value,
|
||||
isLight,
|
||||
iconTheme,
|
||||
matugenType,
|
||||
stockColors
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
console.info("Theme: Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)");
|
||||
|
||||
if (typeof NiriService !== "undefined" && CompositorService.isNiri) {
|
||||
NiriService.suppressNextToast();
|
||||
@@ -805,15 +820,18 @@ Singleton {
|
||||
"runUserTemplates": (typeof SettingsData !== "undefined") ? SettingsData.runUserMatugenTemplates : true
|
||||
};
|
||||
|
||||
if (stockColors) {
|
||||
desired.stockColors = JSON.stringify(stockColors);
|
||||
}
|
||||
|
||||
const json = JSON.stringify(desired);
|
||||
const desiredPath = stateDir + "/matugen.desired.json";
|
||||
|
||||
Quickshell.execDetached(["sh", "-c", `mkdir -p '${stateDir}' && cat > '${desiredPath}' << 'EOF'\n${json}\nEOF`]);
|
||||
workerRunning = true;
|
||||
const syncModeWithPortal = (typeof SettingsData !== "undefined" && SettingsData.syncModeWithPortal) ? "true" : "false";
|
||||
const terminalsAlwaysDark = (typeof SettingsData !== "undefined" && SettingsData.terminalsAlwaysDark) ? "true" : "false";
|
||||
|
||||
console.log("Theme: Starting matugen worker");
|
||||
systemThemeGenerator.command = [shellDir + "/scripts/matugen-worker.sh", stateDir, shellDir, configDir, syncModeWithPortal, terminalsAlwaysDark, "--run"];
|
||||
workerRunning = true;
|
||||
systemThemeGenerator.command = ["sh", "-c", `mkdir -p '${stateDir}' && cat > '${desiredPath}' << 'EOF'\n${json}\nEOF\nexec '${shellDir}/scripts/matugen-worker.sh' '${stateDir}' '${shellDir}' '${configDir}' '${syncModeWithPortal}' '${terminalsAlwaysDark}' --run`];
|
||||
systemThemeGenerator.running = true;
|
||||
}
|
||||
|
||||
@@ -821,40 +839,122 @@ Singleton {
|
||||
const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode);
|
||||
if (!matugenAvailable || isGreeterMode)
|
||||
return;
|
||||
|
||||
_pendingGenerateParams = true;
|
||||
_themeGenerateDebounce.restart();
|
||||
}
|
||||
|
||||
function _executeThemeGeneration() {
|
||||
if (!_pendingGenerateParams)
|
||||
return;
|
||||
_pendingGenerateParams = null;
|
||||
|
||||
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode);
|
||||
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default";
|
||||
|
||||
if (currentTheme === dynamic) {
|
||||
if (!rawWallpaperPath) {
|
||||
if (!rawWallpaperPath)
|
||||
return;
|
||||
}
|
||||
const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot";
|
||||
if (rawWallpaperPath.startsWith("#")) {
|
||||
setDesiredTheme("hex", rawWallpaperPath, isLight, iconTheme, selectedMatugenType);
|
||||
} else {
|
||||
setDesiredTheme("image", rawWallpaperPath, isLight, iconTheme, selectedMatugenType);
|
||||
}
|
||||
} else {
|
||||
let primaryColor;
|
||||
let matugenType;
|
||||
if (currentTheme === "custom") {
|
||||
if (!customThemeData || !customThemeData.primary) {
|
||||
console.warn("Custom theme data not available for system theme generation");
|
||||
return;
|
||||
}
|
||||
primaryColor = customThemeData.primary;
|
||||
matugenType = customThemeData.matugen_type;
|
||||
} else {
|
||||
primaryColor = currentThemeData.primary;
|
||||
matugenType = currentThemeData.matugen_type;
|
||||
}
|
||||
|
||||
if (!primaryColor) {
|
||||
console.warn("No primary color available for theme:", currentTheme);
|
||||
return;
|
||||
}
|
||||
setDesiredTheme("hex", primaryColor, isLight, iconTheme, matugenType);
|
||||
const kind = rawWallpaperPath.startsWith("#") ? "hex" : "image";
|
||||
setDesiredTheme(kind, rawWallpaperPath, isLight, iconTheme, selectedMatugenType, null);
|
||||
return;
|
||||
}
|
||||
|
||||
let darkTheme, lightTheme;
|
||||
if (currentTheme === "custom") {
|
||||
darkTheme = customThemeData;
|
||||
lightTheme = customThemeData;
|
||||
} else {
|
||||
darkTheme = StockThemes.getThemeByName(currentTheme, false);
|
||||
lightTheme = StockThemes.getThemeByName(currentTheme, true);
|
||||
}
|
||||
|
||||
if (!darkTheme || !darkTheme.primary) {
|
||||
console.warn("Theme data not available for:", currentTheme);
|
||||
return;
|
||||
}
|
||||
|
||||
const stockColors = buildMatugenColorsFromTheme(darkTheme, lightTheme);
|
||||
const themeData = isLight ? lightTheme : darkTheme;
|
||||
setDesiredTheme("hex", themeData.primary, isLight, iconTheme, themeData.matugen_type, stockColors);
|
||||
}
|
||||
|
||||
function buildMatugenColorsFromTheme(darkTheme, lightTheme) {
|
||||
const colors = {};
|
||||
|
||||
function addColor(matugenKey, darkVal, lightVal) {
|
||||
if (!darkVal && !lightVal)
|
||||
return;
|
||||
colors[matugenKey] = {
|
||||
"dark": {
|
||||
"color": String(darkVal || lightVal)
|
||||
},
|
||||
"light": {
|
||||
"color": String(lightVal || darkVal)
|
||||
},
|
||||
"default": {
|
||||
"color": String(darkVal || lightVal)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function get(theme, key, fallback) {
|
||||
return theme[key] || fallback;
|
||||
}
|
||||
|
||||
addColor("primary", darkTheme.primary, lightTheme.primary);
|
||||
addColor("on_primary", darkTheme.primaryText, lightTheme.primaryText);
|
||||
addColor("primary_container", darkTheme.primaryContainer, lightTheme.primaryContainer);
|
||||
addColor("on_primary_container", darkTheme.primaryContainerText || darkTheme.surfaceText, lightTheme.primaryContainerText || lightTheme.surfaceText);
|
||||
addColor("secondary", darkTheme.secondary, lightTheme.secondary);
|
||||
addColor("on_secondary", darkTheme.secondaryText || darkTheme.primaryText, lightTheme.secondaryText || lightTheme.primaryText);
|
||||
addColor("secondary_container", darkTheme.secondaryContainer || darkTheme.surfaceContainerHigh, lightTheme.secondaryContainer || lightTheme.surfaceContainerHigh);
|
||||
addColor("on_secondary_container", darkTheme.secondaryContainerText || darkTheme.surfaceText, lightTheme.secondaryContainerText || lightTheme.surfaceText);
|
||||
addColor("tertiary", darkTheme.tertiary || darkTheme.secondary, lightTheme.tertiary || lightTheme.secondary);
|
||||
addColor("on_tertiary", darkTheme.tertiaryText || darkTheme.secondaryText || darkTheme.primaryText, lightTheme.tertiaryText || lightTheme.secondaryText || lightTheme.primaryText);
|
||||
addColor("tertiary_container", darkTheme.tertiaryContainer || darkTheme.secondaryContainer || darkTheme.surfaceContainerHigh, lightTheme.tertiaryContainer || lightTheme.secondaryContainer || lightTheme.surfaceContainerHigh);
|
||||
addColor("on_tertiary_container", darkTheme.tertiaryContainerText || darkTheme.surfaceText, lightTheme.tertiaryContainerText || lightTheme.surfaceText);
|
||||
addColor("error", darkTheme.error || "#F2B8B5", lightTheme.error || "#B3261E");
|
||||
addColor("on_error", darkTheme.errorText || "#601410", lightTheme.errorText || "#FFFFFF");
|
||||
addColor("error_container", darkTheme.errorContainer || "#8C1D18", lightTheme.errorContainer || "#F9DEDC");
|
||||
addColor("on_error_container", darkTheme.errorContainerText || "#F9DEDC", lightTheme.errorContainerText || "#410E0B");
|
||||
addColor("surface", darkTheme.surface, lightTheme.surface);
|
||||
addColor("on_surface", darkTheme.surfaceText, lightTheme.surfaceText);
|
||||
addColor("surface_variant", darkTheme.surfaceVariant, lightTheme.surfaceVariant);
|
||||
addColor("on_surface_variant", darkTheme.surfaceVariantText, lightTheme.surfaceVariantText);
|
||||
addColor("surface_tint", darkTheme.surfaceTint, lightTheme.surfaceTint);
|
||||
addColor("background", darkTheme.background, lightTheme.background);
|
||||
addColor("on_background", darkTheme.backgroundText, lightTheme.backgroundText);
|
||||
addColor("outline", darkTheme.outline, lightTheme.outline);
|
||||
addColor("outline_variant", darkTheme.outlineVariant || darkTheme.surfaceVariant, lightTheme.outlineVariant || lightTheme.surfaceVariant);
|
||||
addColor("surface_container", darkTheme.surfaceContainer, lightTheme.surfaceContainer);
|
||||
addColor("surface_container_high", darkTheme.surfaceContainerHigh, lightTheme.surfaceContainerHigh);
|
||||
addColor("surface_container_highest", darkTheme.surfaceContainerHighest || darkTheme.surfaceContainerHigh, lightTheme.surfaceContainerHighest || lightTheme.surfaceContainerHigh);
|
||||
addColor("surface_container_low", darkTheme.surfaceContainerLow || darkTheme.surface, lightTheme.surfaceContainerLow || lightTheme.surface);
|
||||
addColor("surface_container_lowest", darkTheme.surfaceContainerLowest || darkTheme.background, lightTheme.surfaceContainerLowest || lightTheme.background);
|
||||
addColor("surface_bright", darkTheme.surfaceBright || darkTheme.surfaceContainerHighest || darkTheme.surfaceContainerHigh, lightTheme.surfaceBright || lightTheme.surface);
|
||||
addColor("surface_dim", darkTheme.surfaceDim || darkTheme.background, lightTheme.surfaceDim || lightTheme.surfaceContainer);
|
||||
addColor("inverse_surface", darkTheme.inverseSurface || lightTheme.surface, lightTheme.inverseSurface || darkTheme.surface);
|
||||
addColor("inverse_on_surface", darkTheme.inverseOnSurface || lightTheme.surfaceText, lightTheme.inverseOnSurface || darkTheme.surfaceText);
|
||||
addColor("inverse_primary", darkTheme.inversePrimary || lightTheme.primary, lightTheme.inversePrimary || darkTheme.primary);
|
||||
addColor("scrim", darkTheme.scrim || "#000000", lightTheme.scrim || "#000000");
|
||||
addColor("shadow", darkTheme.shadow || "#000000", lightTheme.shadow || "#000000");
|
||||
addColor("source_color", darkTheme.primary, lightTheme.primary);
|
||||
addColor("primary_fixed", darkTheme.primaryFixed || darkTheme.primaryContainer, lightTheme.primaryFixed || lightTheme.primaryContainer);
|
||||
addColor("primary_fixed_dim", darkTheme.primaryFixedDim || darkTheme.primary, lightTheme.primaryFixedDim || lightTheme.primary);
|
||||
addColor("on_primary_fixed", darkTheme.onPrimaryFixed || darkTheme.primaryText, lightTheme.onPrimaryFixed || lightTheme.primaryText);
|
||||
addColor("on_primary_fixed_variant", darkTheme.onPrimaryFixedVariant || darkTheme.primaryText, lightTheme.onPrimaryFixedVariant || lightTheme.primaryText);
|
||||
addColor("secondary_fixed", darkTheme.secondaryFixed || darkTheme.secondary, lightTheme.secondaryFixed || lightTheme.secondary);
|
||||
addColor("secondary_fixed_dim", darkTheme.secondaryFixedDim || darkTheme.secondary, lightTheme.secondaryFixedDim || lightTheme.secondary);
|
||||
addColor("on_secondary_fixed", darkTheme.onSecondaryFixed || darkTheme.primaryText, lightTheme.onSecondaryFixed || lightTheme.primaryText);
|
||||
addColor("on_secondary_fixed_variant", darkTheme.onSecondaryFixedVariant || darkTheme.primaryText, lightTheme.onSecondaryFixedVariant || lightTheme.primaryText);
|
||||
addColor("tertiary_fixed", darkTheme.tertiaryFixed || darkTheme.tertiary || darkTheme.secondary, lightTheme.tertiaryFixed || lightTheme.tertiary || lightTheme.secondary);
|
||||
addColor("tertiary_fixed_dim", darkTheme.tertiaryFixedDim || darkTheme.tertiary || darkTheme.secondary, lightTheme.tertiaryFixedDim || lightTheme.tertiary || lightTheme.secondary);
|
||||
addColor("on_tertiary_fixed", darkTheme.onTertiaryFixed || darkTheme.primaryText, lightTheme.onTertiaryFixed || lightTheme.primaryText);
|
||||
addColor("on_tertiary_fixed_variant", darkTheme.onTertiaryFixedVariant || darkTheme.primaryText, lightTheme.onTertiaryFixedVariant || lightTheme.primaryText);
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
function applyGtkColors() {
|
||||
@@ -1005,10 +1105,6 @@ Singleton {
|
||||
|
||||
if (exitCode === 0) {
|
||||
console.info("Theme: Matugen worker completed successfully");
|
||||
if (currentTheme === dynamic) {
|
||||
console.log("Theme: Reloading dynamic colors file");
|
||||
dynamicColorsFileView.reload();
|
||||
}
|
||||
} else if (exitCode === 2) {
|
||||
console.log("Theme: Matugen worker completed with code 2 (no changes needed)");
|
||||
} else {
|
||||
@@ -1017,6 +1113,13 @@ Singleton {
|
||||
}
|
||||
console.warn("Theme: Matugen worker failed with exit code:", exitCode);
|
||||
}
|
||||
|
||||
if (pendingThemeRequest) {
|
||||
const req = pendingThemeRequest;
|
||||
pendingThemeRequest = null;
|
||||
console.info("Theme: Processing queued theme request");
|
||||
setDesiredTheme(req.kind, req.value, req.isLight, req.iconTheme, req.matugenType, req.stockColors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,6 +1232,13 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: _themeGenerateDebounce
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: root._executeThemeGeneration()
|
||||
}
|
||||
|
||||
// These timers are for screen transitions, since sometimes QML still beats the niri call
|
||||
Timer {
|
||||
id: themeTransitionTimer
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[templates.dmscodiumdefault]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-default.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-default-base.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-default.json'
|
||||
|
||||
[templates.dmscodiumdark]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-dark.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-dark-base.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-dark.json'
|
||||
|
||||
[templates.dmscodiumlight]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-light.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-light-base.json'
|
||||
output_path = '~/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-light.json'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[templates.dmsvscodedefault]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-default.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-default-base.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-default.json'
|
||||
|
||||
[templates.dmsvscodedark]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-dark.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-dark-base.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-dark.json'
|
||||
|
||||
[templates.dmsvscodelight]
|
||||
input_path = 'SHELL_DIR/matugen/templates/vscode-color-theme-light.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-light-base.json'
|
||||
output_path = '~/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1/themes/dankshell-light.json'
|
||||
|
||||
@@ -9,3 +9,23 @@ background = '{{colors.primary_container.default.hex}}'
|
||||
[colors.cursor]
|
||||
text = '{{colors.background.default.hex}}'
|
||||
cursor = '{{colors.primary.default.hex}}'
|
||||
|
||||
[colors.normal]
|
||||
black = '{{dank16.color0}}'
|
||||
red = '{{dank16.color1}}'
|
||||
green = '{{dank16.color2}}'
|
||||
yellow = '{{dank16.color3}}'
|
||||
blue = '{{dank16.color4}}'
|
||||
magenta = '{{dank16.color5}}'
|
||||
cyan = '{{dank16.color6}}'
|
||||
white = '{{dank16.color7}}'
|
||||
|
||||
[colors.bright]
|
||||
black = '{{dank16.color8}}'
|
||||
red = '{{dank16.color9}}'
|
||||
green = '{{dank16.color10}}'
|
||||
yellow = '{{dank16.color11}}'
|
||||
blue = '{{dank16.color12}}'
|
||||
magenta = '{{dank16.color13}}'
|
||||
cyan = '{{dank16.color14}}'
|
||||
white = '{{dank16.color15}}'
|
||||
|
||||
@@ -3,3 +3,20 @@ foreground={{colors.on_surface.default.hex_stripped}}
|
||||
background={{colors.background.default.hex_stripped}}
|
||||
selection-foreground={{colors.on_surface.default.hex_stripped}}
|
||||
selection-background={{colors.primary_container.default.hex_stripped}}
|
||||
|
||||
regular0={{dank16.color0 | remove_prefix: '#'}}
|
||||
regular1={{dank16.color1 | remove_prefix: '#'}}
|
||||
regular2={{dank16.color2 | remove_prefix: '#'}}
|
||||
regular3={{dank16.color3 | remove_prefix: '#'}}
|
||||
regular4={{dank16.color4 | remove_prefix: '#'}}
|
||||
regular5={{dank16.color5 | remove_prefix: '#'}}
|
||||
regular6={{dank16.color6 | remove_prefix: '#'}}
|
||||
regular7={{dank16.color7 | remove_prefix: '#'}}
|
||||
bright0={{dank16.color8 | remove_prefix: '#'}}
|
||||
bright1={{dank16.color9 | remove_prefix: '#'}}
|
||||
bright2={{dank16.color10 | remove_prefix: '#'}}
|
||||
bright3={{dank16.color11 | remove_prefix: '#'}}
|
||||
bright4={{dank16.color12 | remove_prefix: '#'}}
|
||||
bright5={{dank16.color13 | remove_prefix: '#'}}
|
||||
bright6={{dank16.color14 | remove_prefix: '#'}}
|
||||
bright7={{dank16.color15 | remove_prefix: '#'}}
|
||||
|
||||
@@ -2,4 +2,21 @@ background = {{colors.background.default.hex}}
|
||||
foreground = {{colors.on_surface.default.hex}}
|
||||
cursor-color = {{colors.primary.default.hex}}
|
||||
selection-background = {{colors.primary_container.default.hex}}
|
||||
selection-foreground = {{colors.on_surface.default.hex}}
|
||||
selection-foreground = {{colors.on_surface.default.hex}}
|
||||
|
||||
palette = 0={{dank16.color0}}
|
||||
palette = 1={{dank16.color1}}
|
||||
palette = 2={{dank16.color2}}
|
||||
palette = 3={{dank16.color3}}
|
||||
palette = 4={{dank16.color4}}
|
||||
palette = 5={{dank16.color5}}
|
||||
palette = 6={{dank16.color6}}
|
||||
palette = 7={{dank16.color7}}
|
||||
palette = 8={{dank16.color8}}
|
||||
palette = 9={{dank16.color9}}
|
||||
palette = 10={{dank16.color10}}
|
||||
palette = 11={{dank16.color11}}
|
||||
palette = 12={{dank16.color12}}
|
||||
palette = 13={{dank16.color13}}
|
||||
palette = 14={{dank16.color14}}
|
||||
palette = 15={{dank16.color15}}
|
||||
@@ -5,4 +5,21 @@ foreground {{colors.on_surface.default.hex}}
|
||||
background {{colors.background.default.hex}}
|
||||
selection_foreground {{colors.on_secondary.default.hex}}
|
||||
selection_background {{colors.secondary_fixed_dim.default.hex}}
|
||||
url_color {{colors.primary.default.hex}}
|
||||
url_color {{colors.primary.default.hex}}
|
||||
|
||||
color0 {{dank16.color0}}
|
||||
color1 {{dank16.color1}}
|
||||
color2 {{dank16.color2}}
|
||||
color3 {{dank16.color3}}
|
||||
color4 {{dank16.color4}}
|
||||
color5 {{dank16.color5}}
|
||||
color6 {{dank16.color6}}
|
||||
color7 {{dank16.color7}}
|
||||
color8 {{dank16.color8}}
|
||||
color9 {{dank16.color9}}
|
||||
color10 {{dank16.color10}}
|
||||
color11 {{dank16.color11}}
|
||||
color12 {{dank16.color12}}
|
||||
color13 {{dank16.color13}}
|
||||
color14 {{dank16.color14}}
|
||||
color15 {{dank16.color15}}
|
||||
@@ -97,6 +97,22 @@
|
||||
|
||||
"terminal.background": "{{colors.background.dark.hex}}",
|
||||
"terminal.foreground": "{{colors.on_surface.dark.hex}}",
|
||||
"terminal.ansiBlack": "{{dank16.color0}}",
|
||||
"terminal.ansiRed": "{{dank16.color1}}",
|
||||
"terminal.ansiGreen": "{{dank16.color2}}",
|
||||
"terminal.ansiYellow": "{{dank16.color3}}",
|
||||
"terminal.ansiBlue": "{{dank16.color4}}",
|
||||
"terminal.ansiMagenta": "{{dank16.color5}}",
|
||||
"terminal.ansiCyan": "{{dank16.color6}}",
|
||||
"terminal.ansiWhite": "{{dank16.color7}}",
|
||||
"terminal.ansiBrightBlack": "{{dank16.color8}}",
|
||||
"terminal.ansiBrightRed": "{{dank16.color9}}",
|
||||
"terminal.ansiBrightGreen": "{{dank16.color10}}",
|
||||
"terminal.ansiBrightYellow": "{{dank16.color11}}",
|
||||
"terminal.ansiBrightBlue": "{{dank16.color12}}",
|
||||
"terminal.ansiBrightMagenta": "{{dank16.color13}}",
|
||||
"terminal.ansiBrightCyan": "{{dank16.color14}}",
|
||||
"terminal.ansiBrightWhite": "{{dank16.color15}}",
|
||||
|
||||
"gitDecoration.modifiedResourceForeground": "{{colors.primary.dark.hex}}",
|
||||
"gitDecoration.addedResourceForeground": "{{colors.primary.dark.hex}}",
|
||||
@@ -158,19 +174,6 @@
|
||||
},
|
||||
|
||||
"tokenColors": [
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.outline.dark.hex}}",
|
||||
"fontStyle": "italic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["keyword", "storage.type", "storage.modifier"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.primary.dark.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["variable", "meta.object-literal.key"],
|
||||
"settings": {
|
||||
@@ -263,53 +266,166 @@
|
||||
"settings": {
|
||||
"foreground": "{{colors.secondary.dark.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color8}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.modifier",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.parameter",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color7}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.object-literal.key", "meta.property.object", "variable.other.property"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color4}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.other.symbol",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["constant.numeric", "constant.language"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.character",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.type", "entity.name.class"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "support.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.function", "support.function"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color2}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["support.class", "support.variable"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.language",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.tag.yaml",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["string.unquoted.plain.out.yaml", "string.unquoted.yaml"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "string",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"semanticHighlighting": true,
|
||||
"semanticTokenColors": {
|
||||
"variable": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"variable.readonly": {
|
||||
"foreground": "{{colors.tertiary.dark.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"property": {
|
||||
"foreground": "{{colors.on_surface.dark.hex}}"
|
||||
"foreground": "{{dank16.color4}}"
|
||||
},
|
||||
"function": {
|
||||
"foreground": "{{colors.primary.dark.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"method": {
|
||||
"foreground": "{{colors.primary.dark.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"type": {
|
||||
"foreground": "{{colors.tertiary.dark.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"class": {
|
||||
"foreground": "{{colors.tertiary.dark.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"typeParameter": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
},
|
||||
"enumMember": {
|
||||
"foreground": "{{colors.tertiary.dark.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"string": {
|
||||
"foreground": "{{colors.secondary.dark.hex}}"
|
||||
"foreground": "{{dank16.color3}}"
|
||||
},
|
||||
"number": {
|
||||
"foreground": "{{colors.tertiary.dark.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"comment": {
|
||||
"foreground": "{{colors.outline.dark.hex}}",
|
||||
"fontStyle": "italic"
|
||||
"foreground": "{{dank16.color8}}"
|
||||
},
|
||||
"keyword": {
|
||||
"foreground": "{{colors.primary.dark.hex}}"
|
||||
"foreground": "{{dank16.color5}}"
|
||||
},
|
||||
"operator": {
|
||||
"foreground": "{{colors.on_surface.dark.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"parameter": {
|
||||
"foreground": "{{colors.on_surface.dark.hex}}"
|
||||
"foreground": "{{dank16.color7}}"
|
||||
},
|
||||
"namespace": {
|
||||
"foreground": "{{colors.secondary.dark.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,22 @@
|
||||
|
||||
"terminal.background": "{{colors.background.default.hex}}",
|
||||
"terminal.foreground": "{{colors.on_surface.default.hex}}",
|
||||
"terminal.ansiBlack": "{{dank16.color0}}",
|
||||
"terminal.ansiRed": "{{dank16.color1}}",
|
||||
"terminal.ansiGreen": "{{dank16.color2}}",
|
||||
"terminal.ansiYellow": "{{dank16.color3}}",
|
||||
"terminal.ansiBlue": "{{dank16.color4}}",
|
||||
"terminal.ansiMagenta": "{{dank16.color5}}",
|
||||
"terminal.ansiCyan": "{{dank16.color6}}",
|
||||
"terminal.ansiWhite": "{{dank16.color7}}",
|
||||
"terminal.ansiBrightBlack": "{{dank16.color8}}",
|
||||
"terminal.ansiBrightRed": "{{dank16.color9}}",
|
||||
"terminal.ansiBrightGreen": "{{dank16.color10}}",
|
||||
"terminal.ansiBrightYellow": "{{dank16.color11}}",
|
||||
"terminal.ansiBrightBlue": "{{dank16.color12}}",
|
||||
"terminal.ansiBrightMagenta": "{{dank16.color13}}",
|
||||
"terminal.ansiBrightCyan": "{{dank16.color14}}",
|
||||
"terminal.ansiBrightWhite": "{{dank16.color15}}",
|
||||
|
||||
"gitDecoration.modifiedResourceForeground": "{{colors.primary.default.hex}}",
|
||||
"gitDecoration.addedResourceForeground": "{{colors.primary.default.hex}}",
|
||||
@@ -158,19 +174,6 @@
|
||||
},
|
||||
|
||||
"tokenColors": [
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.outline.default.hex}}",
|
||||
"fontStyle": "italic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["keyword", "storage.type", "storage.modifier"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.primary.default.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["variable", "meta.object-literal.key"],
|
||||
"settings": {
|
||||
@@ -263,53 +266,166 @@
|
||||
"settings": {
|
||||
"foreground": "{{colors.secondary.default.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color8}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.modifier",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.parameter",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color7}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.object-literal.key", "meta.property.object", "variable.other.property"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color4}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.other.symbol",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["constant.numeric", "constant.language"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.character",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.type", "entity.name.class"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "support.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.function", "support.function"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color2}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["support.class", "support.variable"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.language",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.tag.yaml",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["string.unquoted.plain.out.yaml", "string.unquoted.yaml"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "string",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"semanticHighlighting": true,
|
||||
"semanticTokenColors": {
|
||||
"variable": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"variable.readonly": {
|
||||
"foreground": "{{colors.tertiary.default.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"property": {
|
||||
"foreground": "{{colors.on_surface.default.hex}}"
|
||||
"foreground": "{{dank16.color4}}"
|
||||
},
|
||||
"function": {
|
||||
"foreground": "{{colors.primary.default.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"method": {
|
||||
"foreground": "{{colors.primary.default.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"type": {
|
||||
"foreground": "{{colors.tertiary.default.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"class": {
|
||||
"foreground": "{{colors.tertiary.default.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"typeParameter": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
},
|
||||
"enumMember": {
|
||||
"foreground": "{{colors.tertiary.default.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"string": {
|
||||
"foreground": "{{colors.secondary.default.hex}}"
|
||||
"foreground": "{{dank16.color3}}"
|
||||
},
|
||||
"number": {
|
||||
"foreground": "{{colors.tertiary.default.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"comment": {
|
||||
"foreground": "{{colors.outline.default.hex}}",
|
||||
"fontStyle": "italic"
|
||||
"foreground": "{{dank16.color8}}"
|
||||
},
|
||||
"keyword": {
|
||||
"foreground": "{{colors.primary.default.hex}}"
|
||||
"foreground": "{{dank16.color5}}"
|
||||
},
|
||||
"operator": {
|
||||
"foreground": "{{colors.on_surface.default.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"parameter": {
|
||||
"foreground": "{{colors.on_surface.default.hex}}"
|
||||
"foreground": "{{dank16.color7}}"
|
||||
},
|
||||
"namespace": {
|
||||
"foreground": "{{colors.secondary.default.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,22 @@
|
||||
|
||||
"terminal.background": "{{colors.background.light.hex}}",
|
||||
"terminal.foreground": "{{colors.on_surface.light.hex}}",
|
||||
"terminal.ansiBlack": "{{dank16.color0}}",
|
||||
"terminal.ansiRed": "{{dank16.color1}}",
|
||||
"terminal.ansiGreen": "{{dank16.color2}}",
|
||||
"terminal.ansiYellow": "{{dank16.color3}}",
|
||||
"terminal.ansiBlue": "{{dank16.color4}}",
|
||||
"terminal.ansiMagenta": "{{dank16.color5}}",
|
||||
"terminal.ansiCyan": "{{dank16.color6}}",
|
||||
"terminal.ansiWhite": "{{dank16.color7}}",
|
||||
"terminal.ansiBrightBlack": "{{dank16.color8}}",
|
||||
"terminal.ansiBrightRed": "{{dank16.color9}}",
|
||||
"terminal.ansiBrightGreen": "{{dank16.color10}}",
|
||||
"terminal.ansiBrightYellow": "{{dank16.color11}}",
|
||||
"terminal.ansiBrightBlue": "{{dank16.color12}}",
|
||||
"terminal.ansiBrightMagenta": "{{dank16.color13}}",
|
||||
"terminal.ansiBrightCyan": "{{dank16.color14}}",
|
||||
"terminal.ansiBrightWhite": "{{dank16.color15}}",
|
||||
|
||||
"gitDecoration.modifiedResourceForeground": "{{colors.primary.light.hex}}",
|
||||
"gitDecoration.addedResourceForeground": "{{colors.primary.light.hex}}",
|
||||
@@ -158,19 +174,6 @@
|
||||
},
|
||||
|
||||
"tokenColors": [
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.outline.light.hex}}",
|
||||
"fontStyle": "italic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["keyword", "storage.type", "storage.modifier"],
|
||||
"settings": {
|
||||
"foreground": "{{colors.primary.light.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["variable", "meta.object-literal.key"],
|
||||
"settings": {
|
||||
@@ -263,53 +266,166 @@
|
||||
"settings": {
|
||||
"foreground": "{{colors.secondary.light.hex}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["comment", "punctuation.definition.comment"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color8}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "storage.modifier",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color5}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.parameter",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color7}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["meta.object-literal.key", "meta.property.object", "variable.other.property"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color4}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.other.symbol",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["constant.numeric", "constant.language"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.character",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.type", "entity.name.class"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "support.type",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["entity.name.function", "support.function"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color2}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["support.class", "support.variable"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.language",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.tag.yaml",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color12}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": ["string.unquoted.plain.out.yaml", "string.unquoted.yaml"],
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "string",
|
||||
"settings": {
|
||||
"foreground": "{{dank16.color3}}"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"semanticHighlighting": true,
|
||||
"semanticTokenColors": {
|
||||
"variable": {
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"variable.readonly": {
|
||||
"foreground": "{{colors.tertiary.light.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"property": {
|
||||
"foreground": "{{colors.on_surface.light.hex}}"
|
||||
"foreground": "{{dank16.color4}}"
|
||||
},
|
||||
"function": {
|
||||
"foreground": "{{colors.primary.light.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"method": {
|
||||
"foreground": "{{colors.primary.light.hex}}"
|
||||
"foreground": "{{dank16.color2}}"
|
||||
},
|
||||
"type": {
|
||||
"foreground": "{{colors.tertiary.light.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"class": {
|
||||
"foreground": "{{colors.tertiary.light.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"typeParameter": {
|
||||
"foreground": "{{dank16.color13}}"
|
||||
},
|
||||
"enumMember": {
|
||||
"foreground": "{{colors.tertiary.light.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"string": {
|
||||
"foreground": "{{colors.secondary.light.hex}}"
|
||||
"foreground": "{{dank16.color3}}"
|
||||
},
|
||||
"number": {
|
||||
"foreground": "{{colors.tertiary.light.hex}}"
|
||||
"foreground": "{{dank16.color12}}"
|
||||
},
|
||||
"comment": {
|
||||
"foreground": "{{colors.outline.light.hex}}",
|
||||
"fontStyle": "italic"
|
||||
"foreground": "{{dank16.color8}}"
|
||||
},
|
||||
"keyword": {
|
||||
"foreground": "{{colors.primary.light.hex}}"
|
||||
"foreground": "{{dank16.color5}}"
|
||||
},
|
||||
"operator": {
|
||||
"foreground": "{{colors.on_surface.light.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
},
|
||||
"parameter": {
|
||||
"foreground": "{{colors.on_surface.light.hex}}"
|
||||
"foreground": "{{dank16.color7}}"
|
||||
},
|
||||
"namespace": {
|
||||
"foreground": "{{colors.secondary.light.hex}}"
|
||||
"foreground": "{{dank16.color15}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,6 @@ cursor_border = '{{colors.primary.default.hex}}'
|
||||
|
||||
selection_bg = '{{colors.primary_container.default.hex}}'
|
||||
selection_fg = '{{colors.on_surface.default.hex}}'
|
||||
|
||||
ansi = ['{{dank16.color0}}', '{{dank16.color1}}', '{{dank16.color2}}', '{{dank16.color3}}', '{{dank16.color4}}', '{{dank16.color5}}', '{{dank16.color6}}', '{{dank16.color7}}']
|
||||
brights = ['{{dank16.color8}}', '{{dank16.color9}}', '{{dank16.color10}}', '{{dank16.color11}}', '{{dank16.color12}}', '{{dank16.color13}}', '{{dank16.color14}}', '{{dank16.color15}}']
|
||||
|
||||
@@ -1,467 +1,275 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -uo pipefail
|
||||
|
||||
if [ $# -lt 5 ]; then
|
||||
echo "Usage: $0 STATE_DIR SHELL_DIR CONFIG_DIR SYNC_MODE_WITH_PORTAL TERMINALS_ALWAYS_DARK --run" >&2
|
||||
exit 1
|
||||
fi
|
||||
log() { echo "[matugen-worker] $*" >&2; }
|
||||
err() { echo "[matugen-worker] ERROR: $*" >&2; }
|
||||
|
||||
[[ $# -lt 6 ]] && { echo "Usage: $0 STATE_DIR SHELL_DIR CONFIG_DIR SYNC_MODE_WITH_PORTAL TERMINALS_ALWAYS_DARK --run" >&2; exit 1; }
|
||||
|
||||
STATE_DIR="$1"
|
||||
SHELL_DIR="$2"
|
||||
CONFIG_DIR="$3"
|
||||
SYNC_MODE_WITH_PORTAL="$4"
|
||||
TERMINALS_ALWAYS_DARK="$5"
|
||||
|
||||
if [ ! -d "$STATE_DIR" ]; then
|
||||
echo "Error: STATE_DIR '$STATE_DIR' does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$SHELL_DIR" ]; then
|
||||
echo "Error: SHELL_DIR '$SHELL_DIR' does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$CONFIG_DIR" ]; then
|
||||
echo "Error: CONFIG_DIR '$CONFIG_DIR' does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift 5
|
||||
[[ "${1:-}" != "--run" ]] && { echo "Usage: $0 ... --run" >&2; exit 1; }
|
||||
|
||||
if [[ "${1:-}" != "--run" ]]; then
|
||||
echo "usage: $0 STATE_DIR SHELL_DIR CONFIG_DIR SYNC_MODE_WITH_PORTAL TERMINALS_ALWAYS_DARK --run" >&2
|
||||
exit 1
|
||||
fi
|
||||
[[ ! -d "$STATE_DIR" ]] && { err "STATE_DIR '$STATE_DIR' does not exist"; exit 1; }
|
||||
[[ ! -d "$SHELL_DIR" ]] && { err "SHELL_DIR '$SHELL_DIR' does not exist"; exit 1; }
|
||||
[[ ! -d "$CONFIG_DIR" ]] && { err "CONFIG_DIR '$CONFIG_DIR' does not exist"; exit 1; }
|
||||
|
||||
DESIRED_JSON="$STATE_DIR/matugen.desired.json"
|
||||
BUILT_KEY="$STATE_DIR/matugen.key"
|
||||
LAST_JSON="$STATE_DIR/last.json"
|
||||
LOCK="$STATE_DIR/matugen-worker.lock"
|
||||
COLORS_OUTPUT="$STATE_DIR/dms-colors.json"
|
||||
|
||||
exec 9>"$LOCK"
|
||||
flock 9
|
||||
|
||||
rm -f "$BUILT_KEY"
|
||||
|
||||
get_matugen_major_version() {
|
||||
local version_output=$(matugen --version 2>&1)
|
||||
local version=$(echo "$version_output" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
|
||||
local major=$(echo "$version" | cut -d. -f1)
|
||||
echo "$major"
|
||||
read_json_field() {
|
||||
local json="$1" field="$2"
|
||||
echo "$json" | sed -n "s/.*\"$field\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -1
|
||||
}
|
||||
|
||||
MATUGEN_VERSION=$(get_matugen_major_version)
|
||||
|
||||
read_desired() {
|
||||
[[ ! -f "$DESIRED_JSON" ]] && { echo "no desired state" >&2; exit 0; }
|
||||
cat "$DESIRED_JSON"
|
||||
read_json_escaped_field() {
|
||||
local json="$1" field="$2"
|
||||
local after="${json#*\"$field\":\"}"
|
||||
[[ "$after" == "$json" ]] && return
|
||||
local result=""
|
||||
while [[ -n "$after" ]]; do
|
||||
local char="${after:0:1}"
|
||||
after="${after:1}"
|
||||
[[ "$char" == '"' ]] && break
|
||||
[[ "$char" == '\' ]] && { result+="${after:0:1}"; after="${after:1}"; continue; }
|
||||
result+="$char"
|
||||
done
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
key_of() {
|
||||
read_json_bool() {
|
||||
local json="$1" field="$2"
|
||||
echo "$json" | sed -n "s/.*\"$field\"[[:space:]]*:[[:space:]]*\([^,}]*\).*/\1/p" | head -1 | tr -d ' '
|
||||
}
|
||||
|
||||
compute_key() {
|
||||
local json="$1"
|
||||
local kind=$(echo "$json" | sed 's/.*"kind": *"\([^"]*\)".*/\1/')
|
||||
local value=$(echo "$json" | sed 's/.*"value": *"\([^"]*\)".*/\1/')
|
||||
local mode=$(echo "$json" | sed 's/.*"mode": *"\([^"]*\)".*/\1/')
|
||||
local icon=$(echo "$json" | sed 's/.*"iconTheme": *"\([^"]*\)".*/\1/')
|
||||
local matugen_type=$(echo "$json" | sed 's/.*"matugenType": *"\([^"]*\)".*/\1/')
|
||||
local run_user_templates=$(echo "$json" | sed 's/.*"runUserTemplates": *\([^,}]*\).*/\1/')
|
||||
[[ -z "$icon" ]] && icon="System Default"
|
||||
[[ -z "$matugen_type" ]] && matugen_type="scheme-tonal-spot"
|
||||
[[ -z "$run_user_templates" ]] && run_user_templates="true"
|
||||
echo "${kind}|${value}|${mode}|${icon}|${matugen_type}|${run_user_templates}" | sha256sum | cut -d' ' -f1
|
||||
local kind=$(read_json_field "$json" "kind")
|
||||
local value=$(read_json_field "$json" "value")
|
||||
local mode=$(read_json_field "$json" "mode")
|
||||
local icon=$(read_json_field "$json" "iconTheme")
|
||||
local mtype=$(read_json_field "$json" "matugenType")
|
||||
local run_user=$(read_json_bool "$json" "runUserTemplates")
|
||||
local stock_colors=$(read_json_escaped_field "$json" "stockColors")
|
||||
echo "${kind}|${value}|${mode}|${icon:-default}|${mtype:-scheme-tonal-spot}|${run_user:-true}|${stock_colors:-}" | sha256sum | cut -d' ' -f1
|
||||
}
|
||||
|
||||
append_config() {
|
||||
local check_cmd="$1" file_name="$2" cfg_file="$3"
|
||||
local target="$SHELL_DIR/matugen/configs/$file_name"
|
||||
[[ ! -f "$target" ]] && return
|
||||
[[ "$check_cmd" != "skip" ]] && ! command -v "$check_cmd" >/dev/null 2>&1 && return
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$target" >> "$cfg_file"
|
||||
echo "" >> "$cfg_file"
|
||||
}
|
||||
|
||||
build_merged_config() {
|
||||
local mode="$1" run_user="$2" cfg_file="$3"
|
||||
|
||||
if [[ "$run_user" == "true" && -f "$CONFIG_DIR/matugen/config.toml" ]]; then
|
||||
awk '/^\[config\]/{p=1} /^\[templates\]/{p=0} p' "$CONFIG_DIR/matugen/config.toml" >> "$cfg_file"
|
||||
else
|
||||
echo "[config]" >> "$cfg_file"
|
||||
fi
|
||||
echo "" >> "$cfg_file"
|
||||
|
||||
grep -v '^\[config\]' "$SHELL_DIR/matugen/configs/base.toml" | sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" >> "$cfg_file"
|
||||
echo "" >> "$cfg_file"
|
||||
|
||||
cat >> "$cfg_file" << EOF
|
||||
[templates.dank]
|
||||
input_path = '$SHELL_DIR/matugen/templates/dank.json'
|
||||
output_path = '$COLORS_OUTPUT'
|
||||
|
||||
EOF
|
||||
|
||||
[[ "$mode" == "light" ]] && append_config "skip" "gtk3-light.toml" "$cfg_file" || append_config "skip" "gtk3-dark.toml" "$cfg_file"
|
||||
|
||||
append_config "niri" "niri.toml" "$cfg_file"
|
||||
append_config "qt5ct" "qt5ct.toml" "$cfg_file"
|
||||
append_config "qt6ct" "qt6ct.toml" "$cfg_file"
|
||||
append_config "firefox" "firefox.toml" "$cfg_file"
|
||||
append_config "pywalfox" "pywalfox.toml" "$cfg_file"
|
||||
append_config "vesktop" "vesktop.toml" "$cfg_file"
|
||||
append_config "ghostty" "ghostty.toml" "$cfg_file"
|
||||
append_config "kitty" "kitty.toml" "$cfg_file"
|
||||
append_config "foot" "foot.toml" "$cfg_file"
|
||||
append_config "alacritty" "alacritty.toml" "$cfg_file"
|
||||
append_config "wezterm" "wezterm.toml" "$cfg_file"
|
||||
append_config "dgop" "dgop.toml" "$cfg_file"
|
||||
append_config "code" "vscode.toml" "$cfg_file"
|
||||
append_config "codium" "codium.toml" "$cfg_file"
|
||||
|
||||
if [[ "$run_user" == "true" && -f "$CONFIG_DIR/matugen/config.toml" ]]; then
|
||||
awk '/^\[templates\]/{p=1} p' "$CONFIG_DIR/matugen/config.toml" >> "$cfg_file"
|
||||
echo "" >> "$cfg_file"
|
||||
fi
|
||||
|
||||
if [[ -d "$CONFIG_DIR/matugen/dms/configs" ]]; then
|
||||
for config in "$CONFIG_DIR/matugen/dms/configs"/*.toml; do
|
||||
[[ -f "$config" ]] || continue
|
||||
cat "$config" >> "$cfg_file"
|
||||
echo "" >> "$cfg_file"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
generate_dank16() {
|
||||
local primary="$1" surface="$2" light_flag="$3"
|
||||
local args=("$primary" --json)
|
||||
[[ -n "$light_flag" ]] && args+=("$light_flag")
|
||||
[[ -n "$surface" ]] && args+=(--background "$surface")
|
||||
dms dank16 "${args[@]}" 2>/dev/null || echo '{}'
|
||||
}
|
||||
|
||||
set_system_color_scheme() {
|
||||
[[ "$SYNC_MODE_WITH_PORTAL" != "true" ]] && return
|
||||
local mode="$1"
|
||||
local scheme="prefer-dark"
|
||||
[[ "$mode" == "light" ]] && scheme="default"
|
||||
gsettings set org.gnome.desktop.interface color-scheme "$scheme" 2>/dev/null || \
|
||||
dconf write /org/gnome/desktop/interface/color-scheme "'$scheme'" 2>/dev/null || true
|
||||
}
|
||||
|
||||
if [[ "$SYNC_MODE_WITH_PORTAL" != "true" ]]; then
|
||||
return 0
|
||||
refresh_gtk() {
|
||||
local mode="$1"
|
||||
local gtk_css="$CONFIG_DIR/gtk-3.0/gtk.css"
|
||||
[[ ! -e "$gtk_css" ]] && return
|
||||
local should_run=false
|
||||
if [[ -L "$gtk_css" ]]; then
|
||||
[[ "$(readlink "$gtk_css")" == *"dank-colors.css"* ]] && should_run=true
|
||||
elif grep -q "dank-colors.css" "$gtk_css" 2>/dev/null; then
|
||||
should_run=true
|
||||
fi
|
||||
[[ "$should_run" != "true" ]] && return
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "" 2>/dev/null || true
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "adw-gtk3-${mode}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
local target_scheme
|
||||
if [[ "$mode" == "light" ]]; then
|
||||
target_scheme="default"
|
||||
else
|
||||
target_scheme="prefer-dark"
|
||||
fi
|
||||
setup_vscode_extension() {
|
||||
local cmd="$1" ext_dir="$2" config_dir="$3"
|
||||
command -v "$cmd" >/dev/null 2>&1 || return
|
||||
[[ ! -d "$config_dir" ]] && return
|
||||
local theme_dir="$ext_dir/themes"
|
||||
mkdir -p "$theme_dir"
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-package.json" "$ext_dir/package.json" 2>/dev/null || true
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-vsixmanifest.xml" "$ext_dir/.vsixmanifest" 2>/dev/null || true
|
||||
}
|
||||
|
||||
if command -v gsettings >/dev/null 2>&1; then
|
||||
gsettings set org.gnome.desktop.interface color-scheme "$target_scheme" >/dev/null 2>&1 || true
|
||||
elif command -v dconf >/dev/null 2>&1; then
|
||||
dconf write /org/gnome/desktop/interface/color-scheme "'$target_scheme'" >/dev/null 2>&1 || true
|
||||
fi
|
||||
signal_terminals() {
|
||||
pgrep -x kitty >/dev/null 2>&1 && pkill -USR1 kitty
|
||||
pgrep -x ghostty >/dev/null 2>&1 && pkill -USR2 ghostty
|
||||
}
|
||||
|
||||
build_once() {
|
||||
local json="$1"
|
||||
local kind value mode icon matugen_type run_user_templates
|
||||
kind=$(echo "$json" | sed 's/.*"kind": *"\([^"]*\)".*/\1/')
|
||||
value=$(echo "$json" | sed 's/.*"value": *"\([^"]*\)".*/\1/')
|
||||
mode=$(echo "$json" | sed 's/.*"mode": *"\([^"]*\)".*/\1/')
|
||||
icon=$(echo "$json" | sed 's/.*"iconTheme": *"\([^"]*\)".*/\1/')
|
||||
matugen_type=$(echo "$json" | sed 's/.*"matugenType": *"\([^"]*\)".*/\1/')
|
||||
run_user_templates=$(echo "$json" | sed 's/.*"runUserTemplates": *\([^,}]*\).*/\1/')
|
||||
[[ -z "$icon" ]] && icon="System Default"
|
||||
[[ -z "$matugen_type" ]] && matugen_type="scheme-tonal-spot"
|
||||
[[ -z "$run_user_templates" ]] && run_user_templates="true"
|
||||
local kind=$(read_json_field "$json" "kind")
|
||||
local value=$(read_json_field "$json" "value")
|
||||
local mode=$(read_json_field "$json" "mode")
|
||||
local mtype=$(read_json_field "$json" "matugenType")
|
||||
local run_user=$(read_json_bool "$json" "runUserTemplates")
|
||||
local stock_colors=$(read_json_escaped_field "$json" "stockColors")
|
||||
|
||||
USER_MATUGEN_DIR="$CONFIG_DIR/matugen/dms"
|
||||
|
||||
TMP_CFG="$(mktemp)"
|
||||
trap 'rm -f "$TMP_CFG"' RETURN
|
||||
[[ -z "$mtype" ]] && mtype="scheme-tonal-spot"
|
||||
[[ -z "$run_user" ]] && run_user="true"
|
||||
|
||||
if [[ "$run_user_templates" == "true" ]] && [[ -f "$CONFIG_DIR/matugen/config.toml" ]]; then
|
||||
awk '/^\[config/{p=1} /^\[templates/{p=0} p' "$CONFIG_DIR/matugen/config.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
local TMP_CFG=$(mktemp)
|
||||
trap "rm -f '$TMP_CFG'" RETURN
|
||||
|
||||
build_merged_config "$mode" "$run_user" "$TMP_CFG"
|
||||
|
||||
local light_flag=""
|
||||
[[ "$mode" == "light" ]] && light_flag="--light"
|
||||
|
||||
local primary surface dank16_dark dank16_light import_args=()
|
||||
|
||||
if [[ -n "$stock_colors" ]]; then
|
||||
log "Using stock/custom theme colors with matugen base"
|
||||
primary=$(echo "$stock_colors" | sed -n 's/.*"primary"[^{]*{[^}]*"dark"[^{]*{[^}]*"color"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
||||
surface=$(echo "$stock_colors" | sed -n 's/.*"surface"[^{]*{[^}]*"dark"[^{]*{[^}]*"color"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
||||
|
||||
[[ -z "$primary" ]] && { err "Failed to extract primary from stock colors"; return 1; }
|
||||
|
||||
dank16_dark=$(generate_dank16 "$primary" "$surface" "")
|
||||
dank16_light=$(generate_dank16 "$primary" "$surface" "--light")
|
||||
|
||||
local dank16_current
|
||||
[[ "$mode" == "light" ]] && dank16_current="$dank16_light" || dank16_current="$dank16_dark"
|
||||
[[ "$TERMINALS_ALWAYS_DARK" == "true" && "$mode" == "light" ]] && dank16_current="$dank16_dark"
|
||||
|
||||
import_args+=(--import-json-string "{\"colors\": $stock_colors, \"dank16\": $dank16_current}")
|
||||
|
||||
log "Running matugen color hex with stock color overrides"
|
||||
if ! matugen color hex "$primary" -m "$mode" -t "${mtype:-scheme-tonal-spot}" -c "$TMP_CFG" "${import_args[@]}"; then
|
||||
err "matugen failed"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo "[config]" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
log "Using dynamic theme from $kind: $value"
|
||||
|
||||
grep -v '^\[config\]' "$SHELL_DIR/matugen/configs/base.toml" | \
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
local matugen_cmd=("matugen")
|
||||
[[ "$kind" == "hex" ]] && matugen_cmd+=("color" "hex") || matugen_cmd+=("$kind")
|
||||
matugen_cmd+=("$value")
|
||||
|
||||
cat >> "$TMP_CFG" << EOF
|
||||
[templates.dank]
|
||||
input_path = '$SHELL_DIR/matugen/templates/dank.json'
|
||||
output_path = '$STATE_DIR/dms-colors.json'
|
||||
local mat_json
|
||||
mat_json=$("${matugen_cmd[@]}" -m dark -t "$mtype" --json hex --dry-run 2>/dev/null | tr -d '\n')
|
||||
[[ -z "$mat_json" ]] && { err "matugen dry-run failed"; return 1; }
|
||||
|
||||
EOF
|
||||
primary=$(echo "$mat_json" | sed -n 's/.*"primary"[[:space:]]*:[[:space:]]*{[^}]*"dark"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
|
||||
surface=$(echo "$mat_json" | sed -n 's/.*"surface"[[:space:]]*:[[:space:]]*{[^}]*"dark"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
|
||||
|
||||
# If light mode, use gtk3 light config
|
||||
if [[ "$mode" == "light" ]]; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/gtk3-light.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
else
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/gtk3-dark.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
[[ -z "$primary" ]] && { err "Failed to extract primary color"; return 1; }
|
||||
|
||||
if command -v niri >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/niri.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
dank16_dark=$(generate_dank16 "$primary" "$surface" "")
|
||||
dank16_light=$(generate_dank16 "$primary" "$surface" "--light")
|
||||
|
||||
if command -v qt5ct >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/qt5ct.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
local dank16_current
|
||||
[[ "$mode" == "light" ]] && dank16_current="$dank16_light" || dank16_current="$dank16_dark"
|
||||
[[ "$TERMINALS_ALWAYS_DARK" == "true" && "$mode" == "light" ]] && dank16_current="$dank16_dark"
|
||||
|
||||
if command -v qt6ct >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/qt6ct.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
import_args+=(--import-json-string "{\"dank16\": $dank16_current}")
|
||||
|
||||
if command -v firefox >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/firefox.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
|
||||
if command -v pywalfox >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/pywalfox.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
|
||||
if command -v vesktop >/dev/null 2>&1 && [[ -d "$CONFIG_DIR/vesktop" ]]; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/vesktop.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
|
||||
if [[ "$run_user_templates" == "true" ]] && [[ -f "$CONFIG_DIR/matugen/config.toml" ]]; then
|
||||
awk '/^\[templates/{p=1} p' "$CONFIG_DIR/matugen/config.toml" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
fi
|
||||
|
||||
for config in "$USER_MATUGEN_DIR/configs"/*.toml; do
|
||||
[[ -f "$config" ]] || continue
|
||||
cat "$config" >> "$TMP_CFG"
|
||||
echo "" >> "$TMP_CFG"
|
||||
done
|
||||
|
||||
pushd "$SHELL_DIR" >/dev/null
|
||||
MAT_MODE=(-m "$mode")
|
||||
MAT_TYPE=(-t "$matugen_type")
|
||||
|
||||
case "$kind" in
|
||||
image)
|
||||
[[ -f "$value" ]] || { echo "wallpaper not found: $value" >&2; popd >/dev/null; return 2; }
|
||||
JSON=$(matugen -c "$TMP_CFG" --json hex image "$value" "${MAT_MODE[@]}" "${MAT_TYPE[@]}")
|
||||
matugen -c "$TMP_CFG" image "$value" "${MAT_MODE[@]}" "${MAT_TYPE[@]}" >/dev/null
|
||||
;;
|
||||
hex)
|
||||
[[ "$value" =~ ^#[0-9A-Fa-f]{6}$ ]] || { echo "invalid hex: $value" >&2; popd >/dev/null; return 2; }
|
||||
JSON=$(matugen -c "$TMP_CFG" --json hex color hex "$value" "${MAT_MODE[@]}" "${MAT_TYPE[@]}")
|
||||
matugen -c "$TMP_CFG" color hex "$value" "${MAT_MODE[@]}" "${MAT_TYPE[@]}" >/dev/null
|
||||
;;
|
||||
*)
|
||||
echo "unknown kind: $kind" >&2; popd >/dev/null; return 2;;
|
||||
esac
|
||||
|
||||
TMP_CONTENT_CFG="$(mktemp)"
|
||||
echo "[config]" > "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
|
||||
TERMINAL_MODE="$mode"
|
||||
if [[ "$TERMINALS_ALWAYS_DARK" == "true" ]]; then
|
||||
TERMINAL_MODE="dark"
|
||||
fi
|
||||
|
||||
if command -v ghostty >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/ghostty.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v kitty >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/kitty.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v foot >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/foot.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v alacritty >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/alacritty.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v wezterm >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/wezterm.toml" >>"$TMP_CONTENT_CFG"
|
||||
echo "" >>"$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v dgop >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/dgop.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v code >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/vscode.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if command -v codium >/dev/null 2>&1; then
|
||||
sed "s|'SHELL_DIR/|'$SHELL_DIR/|g" "$SHELL_DIR/matugen/configs/codium.toml" >> "$TMP_CONTENT_CFG"
|
||||
echo "" >> "$TMP_CONTENT_CFG"
|
||||
fi
|
||||
|
||||
if [[ -s "$TMP_CONTENT_CFG" ]] && grep -q '\[templates\.' "$TMP_CONTENT_CFG"; then
|
||||
MAT_TERMINAL_MODE=(-m "$TERMINAL_MODE")
|
||||
case "$kind" in
|
||||
image)
|
||||
matugen -c "$TMP_CONTENT_CFG" image "$value" "${MAT_TERMINAL_MODE[@]}" "${MAT_TYPE[@]}" >/dev/null
|
||||
;;
|
||||
hex)
|
||||
matugen -c "$TMP_CONTENT_CFG" color hex "$value" "${MAT_TERMINAL_MODE[@]}" "${MAT_TYPE[@]}" >/dev/null
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
rm -f "$TMP_CONTENT_CFG"
|
||||
popd >/dev/null
|
||||
|
||||
echo "$JSON" | grep -q '"primary"' || { echo "matugen JSON missing primary" >&2; set_system_color_scheme "$mode"; return 2; }
|
||||
printf "%s" "$JSON" > "$LAST_JSON"
|
||||
|
||||
GTK_CSS="$CONFIG_DIR/gtk-3.0/gtk.css"
|
||||
SHOULD_RUN_HOOK=false
|
||||
|
||||
if [[ -L "$GTK_CSS" ]]; then
|
||||
LINK_TARGET=$(readlink "$GTK_CSS")
|
||||
if [[ "$LINK_TARGET" == *"dank-colors.css"* ]]; then
|
||||
SHOULD_RUN_HOOK=true
|
||||
fi
|
||||
elif [[ -f "$GTK_CSS" ]] && grep -q "dank-colors.css" "$GTK_CSS"; then
|
||||
SHOULD_RUN_HOOK=true
|
||||
fi
|
||||
|
||||
if [[ "$SHOULD_RUN_HOOK" == "true" ]]; then
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "" >/dev/null 2>&1 || true
|
||||
gsettings set org.gnome.desktop.interface gtk-theme "adw-gtk3-${mode}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
COLOR_EXTRACT_MODE="$mode"
|
||||
if [[ "$TERMINALS_ALWAYS_DARK" == "true" ]]; then
|
||||
COLOR_EXTRACT_MODE="dark"
|
||||
fi
|
||||
|
||||
if [[ "$MATUGEN_VERSION" == "2" ]]; then
|
||||
PRIMARY=$(echo "$JSON" | sed -n "s/.*\"$COLOR_EXTRACT_MODE\":{[^}]*\"primary\":\"\\(#[0-9a-fA-F]\\{6\\}\\)\".*/\\1/p")
|
||||
SURFACE=$(echo "$JSON" | sed -n "s/.*\"$COLOR_EXTRACT_MODE\":{[^}]*\"surface\":\"\\(#[0-9a-fA-F]\\{6\\}\\)\".*/\\1/p")
|
||||
else
|
||||
JSON_FLAT=$(echo "$JSON" | tr -d '\n')
|
||||
PRIMARY=$(echo "$JSON_FLAT" | sed -n "s/.*\"primary\" *: *{ *[^}]*\"$COLOR_EXTRACT_MODE\" *: *\"\\(#[0-9a-fA-F]\\{6\\}\\)\".*/\\1/p")
|
||||
SURFACE=$(echo "$JSON_FLAT" | sed -n "s/.*\"surface\" *: *{ *[^}]*\"$COLOR_EXTRACT_MODE\" *: *\"\\(#[0-9a-fA-F]\\{6\\}\\)\".*/\\1/p")
|
||||
fi
|
||||
|
||||
if [[ -z "$PRIMARY" ]]; then
|
||||
echo "Error: Failed to extract PRIMARY color from matugen JSON (mode: $mode)" >&2
|
||||
echo "This may indicate an incompatible matugen JSON format" >&2
|
||||
set_system_color_scheme "$mode"
|
||||
return 2
|
||||
fi
|
||||
|
||||
TERMINAL_LIGHT_FLAG=""
|
||||
if [[ "$TERMINALS_ALWAYS_DARK" != "true" ]] && [[ "$mode" == "light" ]]; then
|
||||
TERMINAL_LIGHT_FLAG="--light"
|
||||
fi
|
||||
|
||||
if command -v ghostty >/dev/null 2>&1 && [[ -f "$CONFIG_DIR/ghostty/config-dankcolors" ]]; then
|
||||
OUT=$(dms dank16 "$PRIMARY" $TERMINAL_LIGHT_FLAG ${SURFACE:+--background "$SURFACE"} --ghostty 2>/dev/null || true)
|
||||
if [[ -n "${OUT:-}" ]]; then
|
||||
printf "\n%s\n" "$OUT" >> "$CONFIG_DIR/ghostty/config-dankcolors"
|
||||
if [[ -f "$CONFIG_DIR/ghostty/config" ]] && grep -q "^[^#]*config-dankcolors" "$CONFIG_DIR/ghostty/config" 2>/dev/null; then
|
||||
pkill -USR2 -x 'ghostty|.ghostty-wrappe' >/dev/null 2>&1 || true
|
||||
fi
|
||||
log "Running matugen $kind with dank16 injection"
|
||||
if ! "${matugen_cmd[@]}" -m "$mode" -t "$mtype" -c "$TMP_CFG" "${import_args[@]}"; then
|
||||
err "matugen failed"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v kitty >/dev/null 2>&1 && [[ -f "$CONFIG_DIR/kitty/dank-theme.conf" ]]; then
|
||||
OUT=$(dms dank16 "$PRIMARY" $TERMINAL_LIGHT_FLAG ${SURFACE:+--background "$SURFACE"} --kitty 2>/dev/null || true)
|
||||
if [[ -n "${OUT:-}" ]]; then
|
||||
printf "\n%s\n" "$OUT" >> "$CONFIG_DIR/kitty/dank-theme.conf"
|
||||
if [[ -f "$CONFIG_DIR/kitty/kitty.conf" ]] && grep -q "^[^#]*dank-theme.conf" "$CONFIG_DIR/kitty/kitty.conf" 2>/dev/null; then
|
||||
pkill -USR1 -x kitty >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v foot >/dev/null 2>&1; then
|
||||
FOOT_CONFIG="$CONFIG_DIR/foot/dank-colors.ini"
|
||||
|
||||
if [[ ! -f "$FOOT_CONFIG" ]]; then
|
||||
mkdir -p "$(dirname "$FOOT_CONFIG")"
|
||||
echo "[colors]" > "$FOOT_CONFIG"
|
||||
fi
|
||||
|
||||
OUT=$(dms dank16 "$PRIMARY" $TERMINAL_LIGHT_FLAG ${SURFACE:+--background "$SURFACE"} --foot 2>/dev/null || true)
|
||||
if [[ -n "${OUT:-}" ]]; then
|
||||
printf "\n%s\n" "$OUT" >> "$FOOT_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v wezterm >/dev/null 2>&1; then
|
||||
WEZTERM_CONFIG="$CONFIG_DIR/wezterm/colors/dank-theme.toml"
|
||||
|
||||
if [[ ! -f "$WEZTERM_CONFIG" ]]; then
|
||||
mkdir -p "$(dirname "$WEZTERM_CONFIG")"
|
||||
touch "$WEZTERM_CONFIG"
|
||||
fi
|
||||
|
||||
OUT=$(dms dank16 "$PRIMARY" $TERMINAL_LIGHT_FLAG ${SURFACE:+--background "$SURFACE"} --wezterm 2>/dev/null || true)
|
||||
if [[ -n "${OUT:-}" ]]; then
|
||||
printf "\n%s\n" "$OUT" >>"$WEZTERM_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v alacritty >/dev/null 2>&1; then
|
||||
ALACRITTY_CONFIG="$CONFIG_DIR/alacritty/dank-theme.toml"
|
||||
|
||||
if [[ ! -f "$ALACRITTY_CONFIG" ]]; then
|
||||
mkdir -p "$(dirname "$ALACRITTY_CONFIG")"
|
||||
touch "$ALACRITTY_CONFIG"
|
||||
fi
|
||||
|
||||
OUT=$(dms dank16 "$PRIMARY" $TERMINAL_LIGHT_FLAG ${SURFACE:+--background "$SURFACE"} --alacritty 2>/dev/null || true)
|
||||
if [[ -n "${OUT:-}" ]]; then
|
||||
printf "\n%s\n" "$OUT" >> "$ALACRITTY_CONFIG"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v code >/dev/null 2>&1; then
|
||||
VSCODE_EXT_DIR="$HOME/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1"
|
||||
VSCODE_THEME_DIR="$VSCODE_EXT_DIR/themes"
|
||||
VSCODE_BASE_THEME="$VSCODE_THEME_DIR/dankshell-color-theme-base.json"
|
||||
VSCODE_FINAL_THEME="$VSCODE_THEME_DIR/dankshell-color-theme.json"
|
||||
|
||||
mkdir -p "$VSCODE_THEME_DIR"
|
||||
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-package.json" "$VSCODE_EXT_DIR/package.json"
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-vsixmanifest.xml" "$VSCODE_EXT_DIR/.vsixmanifest"
|
||||
|
||||
for variant in default dark light; do
|
||||
VSCODE_BASE="$VSCODE_THEME_DIR/dankshell-${variant}-base.json"
|
||||
VSCODE_FINAL="$VSCODE_THEME_DIR/dankshell-${variant}.json"
|
||||
|
||||
if [[ -f "$VSCODE_BASE" ]]; then
|
||||
VARIANT_FLAG=""
|
||||
if [[ "$variant" == "light" ]]; then
|
||||
VARIANT_FLAG="--light"
|
||||
elif [[ "$variant" == "default" && "$mode" == "light" ]]; then
|
||||
VARIANT_FLAG="--light"
|
||||
fi
|
||||
|
||||
dms dank16 "$PRIMARY" $VARIANT_FLAG ${SURFACE:+--background "$SURFACE"} --vscode-enrich "$VSCODE_BASE" > "$VSCODE_FINAL" 2>/dev/null || cp "$VSCODE_BASE" "$VSCODE_FINAL"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if command -v codium >/dev/null 2>&1; then
|
||||
CODIUM_EXT_DIR="$HOME/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1"
|
||||
CODIUM_THEME_DIR="$CODIUM_EXT_DIR/themes"
|
||||
CODIUM_BASE_THEME="$CODIUM_THEME_DIR/dankshell-color-theme-base.json"
|
||||
CODIUM_FINAL_THEME="$CODIUM_THEME_DIR/dankshell-color-theme.json"
|
||||
CODIUM_EXTENSIONS_JSON="$HOME/.vscode-oss/extensions/extensions.json"
|
||||
|
||||
mkdir -p "$CODIUM_THEME_DIR"
|
||||
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-package.json" "$CODIUM_EXT_DIR/package.json"
|
||||
cp "$SHELL_DIR/matugen/templates/vscode-vsixmanifest.xml" "$CODIUM_EXT_DIR/.vsixmanifest"
|
||||
|
||||
if [[ -f "$CODIUM_EXTENSIONS_JSON" ]]; then
|
||||
if ! grep -q "local.dynamic-base16-dankshell" "$CODIUM_EXTENSIONS_JSON" 2>/dev/null; then
|
||||
cp "$CODIUM_EXTENSIONS_JSON" "$CODIUM_EXTENSIONS_JSON.backup-$(date +%s)" 2>/dev/null || true
|
||||
|
||||
CODIUM_ENTRY='{"identifier":{"id":"local.dynamic-base16-dankshell"},"version":"0.0.1","location":{"$mid":1,"path":"'"$CODIUM_EXT_DIR"'","scheme":"file"},"relativeLocation":"local.dynamic-base16-dankshell-0.0.1","metadata":{"id":"local.dynamic-base16-dankshell","publisherId":"local","publisherDisplayName":"local","targetPlatform":"undefined","isApplicationScoped":false,"updated":false,"isPreReleaseVersion":false,"installedTimestamp":'"$(date +%s)000"',"preRelease":false}}'
|
||||
|
||||
if [[ "$(cat "$CODIUM_EXTENSIONS_JSON")" == "[]" ]]; then
|
||||
echo "[$CODIUM_ENTRY]" > "$CODIUM_EXTENSIONS_JSON"
|
||||
else
|
||||
TMP_JSON="$(mktemp)"
|
||||
sed 's/]$/,'"$CODIUM_ENTRY"']/' "$CODIUM_EXTENSIONS_JSON" > "$TMP_JSON"
|
||||
mv "$TMP_JSON" "$CODIUM_EXTENSIONS_JSON"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
for variant in default dark light; do
|
||||
CODIUM_BASE="$CODIUM_THEME_DIR/dankshell-${variant}-base.json"
|
||||
CODIUM_FINAL="$CODIUM_THEME_DIR/dankshell-${variant}.json"
|
||||
|
||||
if [[ -f "$CODIUM_BASE" ]]; then
|
||||
VARIANT_FLAG=""
|
||||
if [[ "$variant" == "light" ]]; then
|
||||
VARIANT_FLAG="--light"
|
||||
elif [[ "$variant" == "default" && "$mode" == "light" ]]; then
|
||||
VARIANT_FLAG="--light"
|
||||
fi
|
||||
|
||||
dms dank16 "$PRIMARY" $VARIANT_FLAG ${SURFACE:+--background "$SURFACE"} --vscode-enrich "$CODIUM_BASE" > "$CODIUM_FINAL" 2>/dev/null || cp "$CODIUM_BASE" "$CODIUM_FINAL"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
refresh_gtk "$mode"
|
||||
setup_vscode_extension "code" "$HOME/.vscode/extensions/local.dynamic-base16-dankshell-0.0.1" "$HOME/.vscode"
|
||||
setup_vscode_extension "codium" "$HOME/.vscode-oss/extensions/local.dynamic-base16-dankshell-0.0.1" "$HOME/.vscode-oss"
|
||||
set_system_color_scheme "$mode"
|
||||
signal_terminals
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
while :; do
|
||||
DESIRED="$(read_desired)"
|
||||
WANT_KEY="$(key_of "$DESIRED")"
|
||||
HAVE_KEY=""
|
||||
[[ -f "$BUILT_KEY" ]] && HAVE_KEY="$(cat "$BUILT_KEY" 2>/dev/null || true)"
|
||||
[[ ! -f "$DESIRED_JSON" ]] && { log "No desired state file"; exit 0; }
|
||||
|
||||
if [[ "$WANT_KEY" == "$HAVE_KEY" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
DESIRED=$(cat "$DESIRED_JSON")
|
||||
WANT_KEY=$(compute_key "$DESIRED")
|
||||
HAVE_KEY=""
|
||||
[[ -f "$BUILT_KEY" ]] && HAVE_KEY=$(cat "$BUILT_KEY" 2>/dev/null || true)
|
||||
|
||||
if build_once "$DESIRED"; then
|
||||
echo "$WANT_KEY" > "$BUILT_KEY"
|
||||
else
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
[[ "$WANT_KEY" == "$HAVE_KEY" ]] && { log "Already up to date"; exit 0; }
|
||||
|
||||
exit 0
|
||||
log "Building theme (key: ${WANT_KEY:0:12}...)"
|
||||
if build_once "$DESIRED"; then
|
||||
echo "$WANT_KEY" > "$BUILT_KEY"
|
||||
log "Done"
|
||||
exit 0
|
||||
else
|
||||
err "Build failed"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user