Refactor Hyprland configs, introduce Sithego for theming, and add supporting scripts

This commit is contained in:
2026-02-17 20:42:41 +01:00
parent c57ef06442
commit 8b153d54ac
60 changed files with 1896 additions and 76 deletions
@@ -0,0 +1,25 @@
* {
-GtkHTML-cursor-color: {{ .Theme.Colors.Semantic.Text.Value }};
-GtkIMHtml-cursor-color: {{ .Theme.Colors.Semantic.Text.Value }};
-GtkTextView-error-underline-color: {{ .Theme.Colors.Semantic.Warn.Value }};
-W3C-focus-color: {{ .Theme.Colors.Semantic.Accent.Value }};
outline-color: {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.5 }};
background-clip: padding-box;
-gtk-secondary-caret-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
.background {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
}
:disabled {
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
window,
.window-frame {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border-radius: {{ .Theme.Spacing.RadiusLarge }};
}
@@ -0,0 +1,36 @@
button {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
padding: {{ .Theme.Spacing.Padding }};
transition: all 0.2s ease;
}
button:hover {
background-color: {{ .Theme.Colors.Semantic.Border.Value }};
}
button:active,
button:checked {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
color: {{ .Theme.Colors.Semantic.Background.Value }};
}
button:disabled {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
button.suggested-action {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
color: {{ .Theme.Colors.Semantic.Background.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
button.destructive-action {
background-color: {{ .Theme.Colors.Semantic.Warn.Value }};
color: {{ .Theme.Colors.Semantic.Background.Value }};
border-color: {{ .Theme.Colors.Semantic.Warn.Value }};
}
@@ -0,0 +1,49 @@
check, radio {
margin: 0 {{ .Theme.Spacing.Margin }};
min-height: 18px;
min-width: 18px;
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
color: transparent;
-gtk-icon-source: none;
transition: all 0.2s ease;
}
radio {
border-radius: 50%;
}
check:checked {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
background-image:
linear-gradient(45deg, transparent 45%, {{ .Theme.Colors.Semantic.Accent.Value }} 45%, {{ .Theme.Colors.Semantic.Accent.Value }} 55%, transparent 55%),
linear-gradient(-45deg, transparent 45%, {{ .Theme.Colors.Semantic.Accent.Value }} 45%, {{ .Theme.Colors.Semantic.Accent.Value }} 55%, transparent 55%);
background-size: 70% 70%;
background-repeat: no-repeat;
background-position: center;
}
radio:checked {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
background-image: radial-gradient(circle, {{ .Theme.Colors.Semantic.Accent.Value }} 35%, transparent 40%);
}
check:indeterminate {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
background-image: linear-gradient(to right, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }});
background-size: 60% 2px;
background-repeat: no-repeat;
background-position: center;
}
check:disabled,
radio:disabled {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
color: transparent;
background-image: none;
}
@@ -0,0 +1,19 @@
entry {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
padding: {{ .Theme.Spacing.PaddingSmall }};
caret-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
entry:focus {
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
box-shadow: inset 0 0 0 1px {{ .Theme.Colors.Semantic.Accent.Value }};
}
entry:disabled {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
@@ -0,0 +1,11 @@
headerbar {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border-bottom: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
box-shadow: none;
padding: {{ .Theme.Spacing.PaddingSmall }};
}
headerbar .title {
font-weight: bold;
}
@@ -0,0 +1,53 @@
list,
menu {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
}
menubar {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border-bottom: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
padding: {{ .Theme.Spacing.PaddingSmall }};
}
menubar > menuitem {
padding: {{ .Theme.Spacing.Padding }};
min-height: 24px;
transition: all 0.2s ease;
}
menuitem {
min-height: 24px;
padding: {{ .Theme.Spacing.Padding }};
}
menubar > menuitem:hover {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
border-radius: {{ .Theme.Spacing.RadiusSmall }};
}
list row:selected,
treeview.view:selected,
.view:selected,
iconview.view:selected,
cell:selected,
*:selected {
background-color: {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Accent.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
}
menuitem:hover {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
color: {{ .Theme.Colors.Semantic.Background.Value }};
border-radius: {{ .Theme.Spacing.RadiusSmall }};
}
menuitem:disabled {
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
background-color: transparent;
}
@@ -0,0 +1,32 @@
notebook {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
}
notebook header {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
}
notebook tab {
padding: {{ .Theme.Spacing.PaddingLarge }};
border: 1px solid transparent;
border-radius: {{ .Theme.Spacing.Radius }} {{ .Theme.Spacing.Radius }} 0 0;
transition: all 0.2s ease;
}
notebook tab:hover {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
}
notebook tab:checked {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
border-color: {{ .Theme.Colors.Semantic.Border.Value }};
border-bottom-color: transparent;
border-bottom: 2px solid {{ .Theme.Colors.Semantic.Accent.Value }};
box-shadow: inset 0 -2px 0 {{ .Theme.Colors.Semantic.Accent.Value }};
}
notebook tab label {
font-weight: bold;
color: {{ .Theme.Colors.Semantic.Text.Value }};
}
@@ -0,0 +1,24 @@
scrollbar {
background-color: transparent;
}
scrollbar trough {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
}
scrollbar slider {
background-color: {{ .Theme.Colors.Semantic.Border.Value }};
border: 2px solid transparent;
border-radius: {{ .Theme.Spacing.RadiusLarge }};
min-width: 8px;
min-height: 8px;
}
scrollbar slider:hover {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
scrollbar button {
display: none;
}
@@ -0,0 +1,77 @@
/* Selection */
selection,
row:selected,
iconview:selected,
treeview.view:selected,
.view:selected,
iconview.view:selected,
cell:selected,
*:selected {
background-color: {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Accent.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
}
/* Sliders (Scales) */
scale trough {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
min-height: 4px;
}
scale highlight {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
}
scale slider {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: 50%;
min-height: 16px;
min-width: 16px;
margin: -6px 0;
}
scale slider:hover {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
/* Switches */
switch {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
color: transparent;
}
switch:checked {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
switch slider {
background-color: {{ .Theme.Colors.Semantic.Text.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: 50%;
margin: {{ .Theme.Spacing.MarginSmall }};
min-width: 18px;
min-height: 18px;
}
scale:disabled trough,
scale:disabled highlight,
scale:disabled slider,
switch:disabled {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
switch:disabled slider {
background-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
+93
View File
@@ -0,0 +1,93 @@
package gtk
import (
"Sithego/themer"
"os"
"path/filepath"
"text/template"
)
type Adapter struct {
OutputDir string
}
type Option func(*Adapter)
func WithOutputDir(dir string) Option {
return func(a *Adapter) {
a.OutputDir = dir
}
}
func New(opt ...Option) *Adapter {
home, _ := os.UserHomeDir()
a := &Adapter{
OutputDir: home + "/.themes/",
}
for _, o := range opt {
o(a)
}
return a
}
func (a *Adapter) Name() string {
return "GTK"
}
func (a *Adapter) Generate(t themer.Theme) error {
components := []string{
"template.css",
"components/base.css",
"components/headerbar.css",
"components/buttons.css",
"components/entries.css",
"components/menus.css",
"components/widgets.css",
"components/checks.css",
"components/scrollbars.css",
"components/notebook.css",
}
outputDir := a.OutputDir + t.Meta.Name + "/gtk-3.0"
_ = os.RemoveAll(outputDir)
outputGTK4 := a.OutputDir + t.Meta.Name + "/gtk-4.0"
_ = os.RemoveAll(outputGTK4)
if err := os.MkdirAll(outputDir, 0775); err != nil {
return err
}
for _, component := range components {
templatePath := filepath.Join("themer/adapters/gtk", component)
templ, err := template.ParseFiles(templatePath)
if err != nil {
return err
}
outputName := filepath.Base(component)
if outputName == "template.css" {
outputName = "gtk.css"
}
outputPath := filepath.Join(outputDir, outputName)
file, err := os.Create(outputPath)
if err != nil {
return err
}
err = templ.Execute(file, struct {
Theme themer.Theme
}{
Theme: t,
})
_ = file.Close()
if err != nil {
return err
}
}
if err := os.MkdirAll(outputGTK4, 0775); err != nil {
return err
}
return os.CopyFS(outputGTK4, os.DirFS(outputDir))
}
+11
View File
@@ -0,0 +1,11 @@
[Desktop Entry]
Type=X-GNOME-Metatheme
Name=Serpensortia
Comment=Generated Serpent Theme
Encoding=UTF-8
[X-GNOME-Metatheme]
GtkTheme=Serpensortia
IconTheme=Tela-circle-dark
CursorTheme=Vimix-dark
ButtonLayout=close,maximize:menu
+9
View File
@@ -0,0 +1,9 @@
@import url("base.css");
@import url("headerbar.css");
@import url("buttons.css");
@import url("entries.css");
@import url("menus.css");
@import url("widgets.css");
@import url("checks.css");
@import url("scrollbars.css");
@import url("notebook.css");
@@ -0,0 +1,112 @@
package intellij
import (
"Sithego/themer"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
)
type Adapter struct {
OutputDir string
}
type Option func(*Adapter)
func WithOutputDir(dir string) Option {
abs, err := filepath.Abs(dir)
if err != nil {
panic(err)
}
return func(a *Adapter) {
a.OutputDir = abs
}
}
func New(opt ...Option) *Adapter {
home, _ := os.UserHomeDir()
a := &Adapter{
OutputDir: home + "/.themes/",
}
for _, o := range opt {
o(a)
}
return a
}
func (a *Adapter) Name() string {
return "IntelliJ"
}
func (a *Adapter) Generate(t themer.Theme) error {
// 1. Create temporary directory structure for JAR bundling
tmpDir, err := os.MkdirTemp("", "intellij-theme-*")
if err != nil {
return err
}
defer func(path string) {
err := os.RemoveAll(path)
if err != nil {
}
}(tmpDir)
metaInfDir := filepath.Join(tmpDir, "META-INF")
if err := os.MkdirAll(metaInfDir, 0775); err != nil {
return err
}
funcMap := template.FuncMap{
"lower": strings.ToLower,
}
// 2. Generate plugin.xml
pluginTempl := template.New("template.plugin.xml").Funcs(funcMap)
pluginTempl, err = pluginTempl.ParseFiles("themer/adapters/intellij/template.plugin.xml")
if err != nil {
return err
}
pluginFile, err := os.Create(filepath.Join(metaInfDir, "plugin.xml"))
if err != nil {
return err
}
if err := pluginTempl.Execute(pluginFile, struct{ Theme themer.Theme }{Theme: t}); err != nil {
_ = pluginFile.Close()
return err
}
_ = pluginFile.Close()
// 3. Generate .theme.json
themeTempl, err := template.ParseFiles("themer/adapters/intellij/template.theme.json")
if err != nil {
return err
}
themeName := t.Meta.Name + ".theme.json"
themeFile, err := os.Create(filepath.Join(tmpDir, themeName))
if err != nil {
return err
}
if err := themeTempl.Execute(themeFile, struct{ Theme themer.Theme }{Theme: t}); err != nil {
_ = themeFile.Close()
return err
}
_ = themeFile.Close()
// 4. Bundle everything into a JAR (using zip)
jarName := t.Meta.Name + ".jar"
outputDir := filepath.Join(a.OutputDir, t.Meta.Name, "intellij")
if err := os.MkdirAll(outputDir, 0775); err != nil {
return err
}
jarPath := filepath.Join(outputDir, jarName)
_ = os.Remove(jarPath) // Remove old JAR if exists
cmd := exec.Command("zip", "-r", jarPath, ".")
cmd.Dir = tmpDir
if err := cmd.Run(); err != nil {
return err
}
return nil
}
@@ -0,0 +1,16 @@
<idea-plugin>
<id>de.arindy.{{ .Theme.Meta.Name | lower }}</id>
<name>{{ .Theme.Meta.Name }} Theme</name>
<version>{{ .Theme.Meta.Version }}</version>
<vendor email="support@mail.arindy.de">Arindy</vendor>
<description><![CDATA[
Custom theme generated by Sithego for {{ .Theme.Meta.Name }}.
]]></description>
<depends>com.intellij.modules.platform</depends>
<extensions defaultExtensionNs="com.intellij">
<themeProvider id="de.arindy.{{ .Theme.Meta.Name | lower }}" path="/{{ .Theme.Meta.Name }}.theme.json"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,91 @@
{
"name": "{{ .Theme.Meta.Name }}",
"dark": {{ if eq .Theme.Meta.Type "dark" }}true{{ else }}false{{ end }},
"parentTheme": "Islands Dark",
"author": "Arindy",
"colors": {
"ScrollBar.thumb": "{{ .Theme.Colors.Semantic.Border.Value }}",
"ScrollBar.track": "{{ .Theme.Colors.Semantic.Background.Value }}",
"ScrollBar.hoverThumb": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"ScrollBar.hoverTrack": "{{ .Theme.Colors.Semantic.Surface.Value }}"
},
"ui": {
"*": {
"background": "{{ .Theme.Colors.Semantic.Background.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"selectionBackground": "{{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }}",
"selectionForeground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"focusColor": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"borderColor": "{{ .Theme.Colors.Semantic.Border.Value }}",
"disabledBackground": "{{ .Theme.Colors.Semantic.Background.Value }}",
"disabledForeground": "{{ .Theme.Colors.Semantic.Disabled.Value }}"
},
"Button": {
"startBackground": "{{ .Theme.Colors.Semantic.SurfaceAlt.Value }}",
"endBackground": "{{ .Theme.Colors.Semantic.SurfaceAlt.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"focusedBorderColor": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"default": {
"startBackground": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"endBackground": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Background.Value }}",
"focusedBorderColor": "{{ .Theme.Colors.Semantic.Accent.Value }}"
}
},
"ComboBox": {
"modifiedItemForeground": "{{ .Theme.Colors.Semantic.Accent.Value }}"
},
"List": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"selectionBackground": "{{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }}",
"selectionForeground": "{{ .Theme.Colors.Semantic.Text.Value }}"
},
"Menu": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"selectionBackground": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"selectionForeground": "{{ .Theme.Colors.Semantic.Background.Value }}"
},
"MenuBar": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"selectionBackground": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"selectionForeground": "{{ .Theme.Colors.Semantic.Background.Value }}"
},
"Panel": {
"background": "{{ .Theme.Colors.Semantic.Background.Value }}"
},
"SidePanel": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}"
},
"TabbedPane": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"underlineColor": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"hoverColor": "{{ .Theme.Colors.Semantic.SurfaceAlt.Value }}"
},
"Table": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"gridColor": "{{ .Theme.Colors.Semantic.Border.Value }}"
},
"TextField": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"foreground": "{{ .Theme.Colors.Semantic.Text.Value }}",
"caretColor": "{{ .Theme.Colors.Semantic.Accent.Value }}"
},
"ToolWindow": {
"Header": {
"background": "{{ .Theme.Colors.Semantic.Surface.Value }}",
"inactiveBackground": "{{ .Theme.Colors.Semantic.Background.Value }}"
},
"Button": {
"selectedBackground": "{{ .Theme.Colors.Semantic.Accent.Value }}",
"selectedForeground": "{{ .Theme.Colors.Semantic.Background.Value }}"
}
},
"Tree": {
"rowHeight": 24,
"selectionBackground": "{{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }}",
"selectionForeground": "{{ .Theme.Colors.Semantic.Text.Value }}"
}
}
}
+4
View File
@@ -0,0 +1,4 @@
[ColorScheme]
active_colors={{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.SurfaceAlt.Value }}, {{ .Theme.Colors.Semantic.Surface.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Border.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Warn.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }}
disabled_colors={{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.SurfaceAlt.Value }}, {{ .Theme.Colors.Semantic.Surface.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Border.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Warn.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}
inactive_colors={{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.SurfaceAlt.Value }}, {{ .Theme.Colors.Semantic.Surface.Value }}, {{ .Theme.Colors.Semantic.Disabled.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Border.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Warn.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Text.Value }}, {{ .Theme.Colors.Semantic.Accent.Value }}, {{ .Theme.Colors.Semantic.Background.Value }}, {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }}
+105
View File
@@ -0,0 +1,105 @@
package qt
import (
"Sithego/themer"
"os"
"path/filepath"
"text/template"
)
type Adapter struct {
OutputDir string
}
type Option func(*Adapter)
func WithOutputDir(dir string) Option {
return func(a *Adapter) {
a.OutputDir = dir
}
}
func New(opt ...Option) *Adapter {
home, _ := os.UserHomeDir()
a := &Adapter{
OutputDir: home + "/.config/",
}
for _, o := range opt {
o(a)
}
return a
}
func (a *Adapter) Name() string {
return "Qt"
}
func (a *Adapter) Generate(t themer.Theme) error {
qssComponents := []string{
"template.qss",
}
outputDir := filepath.Join(a.OutputDir, "qt6ct")
if err := os.MkdirAll(outputDir, 0775); err != nil {
return err
}
for _, component := range qssComponents {
templatePath := filepath.Join("themer/adapters/qt", component)
templ, err := template.ParseFiles(templatePath)
if err != nil {
return err
}
qssOutputDir := filepath.Join(outputDir, "qss")
err = os.MkdirAll(qssOutputDir, 0775)
if err != nil {
return err
}
outputPath := filepath.Join(qssOutputDir, t.Meta.Name+".qss")
file, err := os.Create(outputPath)
if err != nil {
return err
}
err = templ.Execute(file, struct {
Theme themer.Theme
}{
Theme: t,
})
_ = file.Close()
if err != nil {
return err
}
}
// 2. Generate qt5ct/qt6ct color scheme (.conf)
confTemplatePath := "themer/adapters/qt/colors.conf"
if _, err := os.Stat(confTemplatePath); err == nil {
templ, err := template.ParseFiles(confTemplatePath)
if err != nil {
return err
}
confOutputDir := filepath.Join(outputDir, "colors")
err = os.MkdirAll(confOutputDir, 0775)
if err != nil {
return err
}
outputPath := filepath.Join(confOutputDir, t.Meta.Name+".conf")
file, err := os.Create(outputPath)
if err != nil {
return err
}
err = templ.Execute(file, struct {
Theme themer.Theme
}{
Theme: t,
})
_ = file.Close()
if err != nil {
return err
}
}
return nil
}
+115
View File
@@ -0,0 +1,115 @@
/* Global Styles */
QWidget {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
selection-background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
selection-color: {{ .Theme.Colors.Semantic.Background.Value }};
}
/* Buttons */
QPushButton {
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
padding: {{ .Theme.Spacing.Padding }};
}
QPushButton:hover {
background-color: {{ .Theme.Colors.Semantic.Border.Value }};
}
QPushButton:pressed {
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
color: {{ .Theme.Colors.Semantic.Background.Value }};
}
QPushButton:disabled {
background-color: {{ .Theme.Colors.Semantic.Background.Value }};
color: {{ .Theme.Colors.Semantic.Disabled.Value }};
border-color: {{ .Theme.Colors.Semantic.Disabled.Value }};
}
/* Input Fields */
QLineEdit, QTextEdit, QPlainTextEdit {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
padding: {{ .Theme.Spacing.PaddingSmall }};
}
QLineEdit:focus {
border: 1px solid {{ .Theme.Colors.Semantic.Accent.Value }};
}
/* Menus and Lists */
QListView, QTreeView, QTableView {
background-color: {{ .Theme.Colors.Semantic.Surface.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
alternate-background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
}
QListView::item:selected, QTreeView::item:selected, QTableView::item:selected {
background-color: {{ .Theme.Colors.Semantic.Accent.Alpha .Theme.Colors.Semantic.Background 0.3 }};
border: 1px solid {{ .Theme.Colors.Semantic.Accent.Value }};
color: {{ .Theme.Colors.Semantic.Text.Value }};
}
/* Scrollbars */
QScrollBar:vertical {
background: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
width: 12px;
margin: 0px;
}
QScrollBar::handle:vertical {
background: {{ .Theme.Colors.Semantic.Border.Value }};
min-height: 20px;
border-radius: {{ .Theme.Spacing.RadiusSmall }};
margin: 2px;
}
QScrollBar::handle:vertical:hover {
background: {{ .Theme.Colors.Semantic.Accent.Value }};
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
height: 0px;
}
/* Tabs */
QTabBar::tab {
background: {{ .Theme.Colors.Semantic.Surface.Value }};
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
padding: {{ .Theme.Spacing.Padding }};
border-top-left-radius: {{ .Theme.Spacing.Radius }};
border-top-right-radius: {{ .Theme.Spacing.Radius }};
}
QTabBar::tab:selected {
background: {{ .Theme.Colors.Semantic.Background.Value }};
border-bottom-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
/* Checkboxes and Radio Buttons */
QCheckBox::indicator, QRadioButton::indicator {
width: 18px;
height: 18px;
border: 1px solid {{ .Theme.Colors.Semantic.Border.Value }};
background-color: {{ .Theme.Colors.Semantic.SurfaceAlt.Value }};
border-radius: {{ .Theme.Spacing.Radius }};
}
QRadioButton::indicator {
border-radius: 9px;
}
QCheckBox::indicator:checked {
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
QRadioButton::indicator:checked {
border-color: {{ .Theme.Colors.Semantic.Accent.Value }};
background-color: {{ .Theme.Colors.Semantic.Accent.Value }};
}
@@ -0,0 +1,60 @@
package starship
import (
"Sithego/themer"
"os"
"path/filepath"
"text/template"
)
type Adapter struct {
OutputDir string
}
type Option func(*Adapter)
func WithOutputDir(dir string) Option {
return func(a *Adapter) {
a.OutputDir = dir
}
}
func New(opt ...Option) *Adapter {
home, _ := os.UserHomeDir()
a := &Adapter{
OutputDir: home + "/.config/",
}
for _, o := range opt {
o(a)
}
return a
}
func (a *Adapter) Name() string {
return "Starship"
}
func (a *Adapter) Generate(t themer.Theme) error {
templatePath := filepath.Join("themer/adapters/starship", "starship.toml")
templ, err := template.ParseFiles(templatePath)
if err != nil {
return err
}
outputPath := filepath.Join(a.OutputDir, "starship.toml")
file, err := os.Create(outputPath)
if err != nil {
return err
}
err = templ.Execute(file, struct {
Theme themer.Theme
}{
Theme: t,
})
_ = file.Close()
if err != nil {
return err
}
return nil
}
@@ -0,0 +1,159 @@
"$schema" = 'https://starship.rs/config-schema.json'
format = """
[](color_bg1)\
[](bg:color_bg1 fg:color_fg0)\
$username\
[](fg:color_bg1)\
$directory\
[](bg:color_bg1 fg:color_black)\
$git_branch\
$git_status\
[](fg:color_bg1 bg:color_blue)\
$c\
$cpp\
$rust\
$golang\
$nodejs\
$php\
$java\
$kotlin\
$haskell\
$python\
[](fg:color_blue bg:color_bg3)\
$docker_context\
$conda\
$pixi\
[](fg:color_bg3 bg:color_bg1)\
$time\
[ ](fg:color_bg1)\
$cmd_duration\
$line_break$character"""
palette = 'serpensortia'
[palettes.serpensortia]
color_black = "#000000"
color_fg0 = "{{ .Theme.Colors.Semantic.Text.Value }}"
color_bg1 = "{{ .Theme.Colors.Semantic.Surface.Value }}"
color_bg3 = "{{ .Theme.Colors.Semantic.SurfaceAlt.Value }}"
color_blue = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_aqua = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_accent = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_orange = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_purple = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_warn = "{{ .Theme.Colors.Semantic.Accent.Value }}"
color_yellow = "{{ .Theme.Colors.Semantic.Accent.Value }}"
[username]
show_always = true
style_user = "bg:color_bg1 fg:color_accent"
style_root = "bg:color_warn fg:color_bg1"
format = '[ $user ]($style)'
[directory]
style = "fg:color_bg0 bg:color_text"
format = "[ $path ]($style)[$read_only]($read_only_style) "
read_only_style = "{{ .Theme.Colors.Semantic.Warn.Value }}"
read_only = "󰌾"
truncation_length = 0
truncation_symbol = "…/"
[directory.substitutions]
"Documents" = "󰈙 "
"Downloads" = " "
"Music" = "󰝚 "
"Pictures" = " "
"workspace" = "󰲋 "
[git_branch]
symbol = ""
style = "bg:color_bg1"
format = '[[ $symbol $branch ](fg:color_accent bg:color_bg1)]($style)'
[git_status]
style = "bg:color_bg1"
format = '[[($all_status$ahead_behind )](fg:color_accent bg:color_bg1)]($style)'
[nodejs]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[c]
symbol = " "
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[cpp]
symbol = " "
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[rust]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[golang]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[php]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[java]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[kotlin]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[haskell]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[python]
symbol = ""
style = "bg:color_blue"
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
[docker_context]
symbol = ""
style = "bg:color_bg3"
format = '[[ $symbol( $context) ](fg:#83a598 bg:color_bg3)]($style)'
[conda]
style = "bg:color_bg3"
format = '[[ $symbol( $environment) ](fg:#83a598 bg:color_bg3)]($style)'
[pixi]
style = "bg:color_bg3"
format = '[[ $symbol( $version)( $environment) ](fg:color_fg0 bg:color_bg3)]($style)'
[time]
disabled = false
time_format = "%R"
style = "bg:color_bg1"
format = '[[  $time ](fg:color_fg0 bg:color_bg1)]($style)'
[line_break]
disabled = false
[character]
disabled = false
success_symbol = '[](bold green)'
error_symbol = '[✖](bold red)'
[cmd_duration]
disabled = false
min_time = 50
show_milliseconds = true
format = '[$duration](bold)'