Add Dunst adapter to Sithego for theme generation and configuration
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user