Add Dunst adapter to Sithego for theme generation and configuration

This commit is contained in:
2026-02-17 22:49:14 +01:00
parent a3c9ccbf6f
commit ed6dc1d54b
5 changed files with 246 additions and 327 deletions
+5
View File
@@ -2,6 +2,7 @@ package main
import (
"Sithego/themer"
"Sithego/themer/adapters/dunst"
"Sithego/themer/adapters/gtk"
"Sithego/themer/adapters/intellij"
"Sithego/themer/adapters/qt"
@@ -30,4 +31,8 @@ func main() {
panic(err)
}
if err := dunst.New(dunst.WithOutputDir("../dotfiles/.config/dunst/")).Generate(theme); err != nil {
panic(err)
}
}
+127
View File
@@ -0,0 +1,127 @@
package dunst
import (
"Sithego/themer"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"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: filepath.Join(home, ".config", "dunst"),
}
for _, o := range opt {
o(a)
}
return a
}
func (a *Adapter) Name() string { return "Dunst" }
type tmplData struct {
Theme themer.Theme
Padding struct {
V int
H int
}
Radius struct {
Small int
Base int
Large int
}
}
func (a *Adapter) Generate(t themer.Theme) error {
templatePath := filepath.Join("themer", "adapters", "dunst", "dunstrc")
templ, err := template.ParseFiles(templatePath)
if err != nil {
return err
}
if err := os.MkdirAll(a.OutputDir, 0o755); err != nil {
return err
}
outputPath := filepath.Join(a.OutputDir, "dunstrc")
f, err := os.Create(outputPath)
if err != nil {
return err
}
defer f.Close()
data := tmplData{Theme: t}
vp, hp := parsePaddingPair(t.Spacing.Padding)
data.Padding.V = vp
data.Padding.H = hp
data.Radius.Small = parsePx(t.Spacing.RadiusSmall)
if data.Radius.Small == 0 {
data.Radius.Small = 4
}
data.Radius.Base = parsePx(t.Spacing.Radius)
if data.Radius.Base == 0 {
data.Radius.Base = data.Radius.Small
}
data.Radius.Large = parsePx(t.Spacing.RadiusLarge)
if data.Radius.Large == 0 {
data.Radius.Base = data.Radius.Large
}
if err := templ.Execute(f, data); err != nil {
return err
}
return nil
}
var rePxPair = regexp.MustCompile(`(?i)\b(\d+)\s*px\b(?:\s+(\d+)\s*px\b)?`)
var rePx = regexp.MustCompile(`(?i)\b(\d+)\s*px\b`)
func parsePaddingPair(s string) (int, int) {
s = strings.TrimSpace(s)
if s == "" {
return 0, 0
}
m := rePxPair.FindStringSubmatch(s)
if len(m) == 3 {
v, _ := strconv.Atoi(m[1])
if m[2] != "" {
h, _ := strconv.Atoi(m[2])
return v, h
}
// single value provided -> use for both
return v, v
}
// fallback: try generic px
m2 := rePx.FindStringSubmatch(s)
if len(m2) == 2 {
v, _ := strconv.Atoi(m2[1])
return v, v
}
return 0, 0
}
func parsePx(s string) int {
s = strings.TrimSpace(s)
m := rePx.FindStringSubmatch(s)
if len(m) == 2 {
v, _ := strconv.Atoi(m[1])
return v
}
return 0
}
+87
View File
@@ -0,0 +1,87 @@
# Generated by Sithego for {{ .Theme.Meta.Name }}
# This file is included from your main dunstrc and sets colors, paddings and radii.
[global]
monitor = 0
follow = keyboard
width = 500
height = (0,500)
origin = top-center
offset = (0,25)
scale = 0
notification_limit = 20
progress_bar = true
progress_bar_height = 15
progress_bar_frame_width = 1
progress_bar_min_width = 150
progress_bar_max_width = 500
indicate_hidden = yes
separator_height = 2
text_icon_padding = 0
frame_width = 5
gap_size = 0
separator_color = frame
sort = yes
idle_threshold = 120
font = "Fira Sans Semibold" 9
line_height = 1
markup = full
format = "<i>%a</i>\n<b>%s</b> %p\n%b"
alignment = center
vertical_alignment = center
show_age_threshold = 60
ellipsize = middle
ignore_newline = no
stack_duplicates = true
hide_duplicate_count = false
show_indicators = yes
enable_recursive_icon_lookup = true
icon_theme = "Silvery-Dark-Icons,Adwaita"
icon_position = left
min_icon_size = 32
max_icon_size = 128
icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
sticky_history = yes
history_length = 20
browser = /usr/bin/xdg-open
always_run_script = true
title = Dunst
class = Dunst
corner_radius = {{ .Radius.Large }}
ignore_dbusclose = false
force_xwayland = false
force_xinerama = false
mouse_left_click = close_current
mouse_middle_click = do_action, close_current
mouse_right_click = close_all
# Global color accents
frame_color = "{{ .Theme.Colors.Semantic.Border.Value }}"
highlight = "{{ .Theme.Colors.Semantic.Accent.Value }}"
# Spacing derived from theme spacing (Padding: vertical horizontal)
padding = {{ .Padding.V }}
horizontal_padding = {{ .Padding.H }}
# Radii
progress_bar_corner_radius = {{ .Radius.Small }}
icon_corner_radius = {{ .Radius.Small }}
# Urgency styles mapped from semantic palette
[urgency_low]
background = "{{ .Theme.Colors.Semantic.Background.Value }}69"
foreground = "{{ .Theme.Colors.Semantic.Text.Value }}"
frame_color = "{{ .Theme.Colors.Semantic.Accent.Value }}"
timeout = 6
[urgency_normal]
background = "{{ .Theme.Colors.Semantic.Background.Value }}69"
foreground = "{{ .Theme.Colors.Semantic.Text.Value }}"
frame_color = "{{ .Theme.Colors.Semantic.Accent.Value }}"
timeout = 6
[urgency_critical]
background = "{{ .Theme.Colors.Semantic.Warn.Value }}69"
foreground = "{{ .Theme.Colors.Semantic.Surface.Value }}"
frame_color = "{{ .Theme.Colors.Semantic.Warn.Value }}"
timeout = 12