dotfiles/oni/home/services/dunst.scm

309 lines
10 KiB
Scheme

(define-module (oni home services dunst)
#:use-module (ice-9 match)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-2)
#:use-module (gnu services configuration)
#:use-module (gnu packages dunst)
#:use-module (gnu home services)
#:use-module (gnu home services shepherd)
#:use-module (gnu home services utils)
#:use-module (guix packages)
#:use-module (guix gexp)
#:export (home-dunst-service-type
home-dunst-configuration
home-dunst-default-service))
(define (color? value)
(and (string? value)
(= 7 (string-length value))
(string-prefix? "#" value)))
(define (hyphen->underscore str)
(string-join (string-split str #\-) "_"))
(define (integer-or-list-of-numbers? value)
(or (integer? value)
(list-of-numbers? value)))
(define (list-of-numbers? value)
(and (list? value)
(every integer? value)))
(define (list-of-strings? value)
(and (list? value)
(every string? value)))
(define (serialize-alist field value)
(apply string-append (map serialize-rule value)))
(define (serialize-boolean field value)
(serialize-string field (if value "true" "false")))
(define (serialize-color field value)
(serialize-string field (string-append "\"" value "\"")))
(define (serialize-integer field value)
(serialize-string field (number->string value)))
(define (serialize-integer-or-list-of-numbers field value)
(match value
((? integer? _) (serialize-integer field value))
((? list? _) (serialize-list-of-numbers field value))
(_ (error "Unknown type of value, not integer or list" value))))
(define (serialize-list-of-numbers field value)
(match field
('offset (serialize-string field (string-join (map number->string value) "x")))
(_ (serialize-string field (string-append "(" (string-join (map number->string value) ", ") ")")))))
(define (serialize-list-of-strings field value)
(serialize-string field (string-join value ":")))
(define (serialize-rule value)
(string-append "[" (car value) "]\n"
(string-join (map serialize-rule-property (cdr value)) "\n")
"\n"))
(define (serialize-rule-property value)
(string-append (hyphen->underscore (symbol->string (car value))) " = " (object->string (cadr value))))
(define (serialize-string field value)
(let ((field-key (hyphen->underscore (symbol->string field))))
(string-append field-key " = " value "\n")))
(define (serialize-symbol field value)
(serialize-string field (symbol->string value)))
(define (serialize-symbol-or-color field value)
(match value
((? symbol? _) (serialize-symbol field value))
((? color? _) (serialize-color field value))
(_ (error "Unknown type of value, not symbol or color" value))))
(define (symbol-or-color? value)
(or (symbol? value)
(color? value)))
(define-maybe color)
(define-maybe integer-or-list-of-numbers)
(define-maybe integer)
(define-maybe list-of-numbers)
(define-maybe list-of-strings)
(define-maybe string)
(define-configuration home-dunst-configuration
(package
(package dunst)
"Package to use for setting Dunst")
(font
maybe-string
"Display font")
(markup
(symbol 'no)
"Allow pango markup")
(format
maybe-string
"Specifies how various attributes of the notification should be formatted on
the notification window.")
(sort
(boolean #t)
"If set to true, display notifications with higher urgency above the others.")
(indicate-hidden
(boolean #t)
"If this is set to true, a notification indicating how many notifications are
not being displayed due to the notification limit will be shown in place of the
last notification slot.")
(alignment
(symbol 'left)
"Defines how the text should be aligned within the notification.")
(show-age-threshold
(integer 60)
"Show age of message if message is older than this time.")
(word-wrap
(boolean #t)
"Specifies whether to wrap the text if the line gets longer than the maximum
notification width.")
(ignore-newline
(boolean #f)
"If set to true, replace newline characters in notifications with whitespace.")
(width
maybe-integer-or-list-of-numbers
"The width of the notification window in height.")
(height
maybe-integer
"The maximum height of a single notification.")
(notification-limit
maybe-integer
"The number of notifications that can appear at one time.")
(origin
(symbol 'top-right)
"The origin of the notification window on the screen.")
(offset
maybe-list-of-numbers
"Respectively the horizontal and vertical offset in pixels from the corner of
the screen specified by define.")
(transparency
maybe-integer
"A 0-100 range on how transparent the notification window should be, with 0
being fully opaque and 100 invisible.")
(idle-threshold
maybe-integer
"Don't timeout notifications if user is idle longer than this time.")
(monitor
maybe-integer
"Specifies on which monitor the notifications should be displayed in, count
starts at 0.")
(follow
(symbol 'none)
"Defines where the notifications should be placed in a multi-monitor setup.")
(sticky-history
(boolean #t)
"If set to true, notifications that have been recalled from history will not
time out automatically.")
(line-height
(integer 0)
"The amount of extra spacing between text lines in pixels.")
(separator-height
(integer 2)
"The height in pixels of the separator between notifications, if set to 0 there
will be no separating line between notifications.")
(padding
(integer 8)
"The distance in pixels from the content to the spearator/border of the window
in the vertical axis.")
(horizontal-padding
(integer 8)
"The distance in pixels from the content to the border of the window in the
horizontal axis.")
(separator-color
(symbol-or-color 'frame)
"Sets the color of the separator line between two notifications.")
(dmenu
maybe-string
"The command that will be run when opening the context menu.")
(browser
maybe-string
"The command that will be run when opening a URL.")
(icon-position
(symbol 'left)
"Defines the position of the icon in the notification window.")
(icon-path
maybe-list-of-strings
"Can be set to a list of paths to search for icons to use with notifications.")
(frame-width
(integer 3)
"Defines width in pixels of frame around the notification window.")
(frame-color
maybe-color
"The frame color of the notifications.")
(max-icon-size
(integer 128)
"Defines the maximum size in pixels for the icons.")
(corner-radius
(integer 0)
"Define the corner radius in pixels.")
(rules
(alist '())
"Rules allow the conditional modification of notifications."))
(define (add-dunst-packages config)
(list (home-dunst-configuration-package config)))
(define (serialize-dunst-configuration config)
#~(string-append
"[global]\n"
#$(serialize-configuration config home-dunst-configuration-fields)))
(define (home-dunst-config-dunstrc config)
(computed-file "dunstrc"
#~(call-with-output-file #$output
(lambda (port)
(display #$(serialize-dunst-configuration config)
port)))))
(define (home-dunst-config-files config)
`(("dunst/dunstrc" ,(home-dunst-config-dunstrc config))))
(define (home-dunst-shepherd-service config)
(list
(shepherd-service
(documentation "Start dunst")
(provision '(dunst))
(auto-start? #t)
(start
#~(make-forkexec-constructor
(list #$(file-append (home-dunst-configuration-package config) "/bin/dunst")
"--config" #$(home-dunst-config-dunstrc config))
#:log-file (format #f "~a/.local/var/log/dunst.log" (getenv "HOME"))))
(stop #~(make-kill-destructor)))))
(define home-dunst-service-type
(service-type (name 'home-dunst)
(extensions
(list (service-extension
home-xdg-configuration-files-service-type
home-dunst-config-files)
(service-extension
home-profile-service-type
add-dunst-packages)
(service-extension
home-shepherd-service-type
home-dunst-shepherd-service)))
(default-value (home-dunst-configuration))
(description "Configure dunst")))
(define home-dunst-default-service
(service home-dunst-service-type
(home-dunst-configuration
(font "Fantasque Sans Mono 15")
(markup 'full)
(format "<u>%s</u>\\n\\n%b")
(width '(0 600))
(origin 'top-center)
(idle-threshold 120)
(padding 15)
(horizontal-padding 15)
(separator-color 'auto)
(dmenu "rofi -dmenu -p dunst:")
(browser "firefox")
(icon-path '("/usr/share/icons/gnome/24x24/status/"
"/usr/share/icons/gnome/24x24/devices/"
"/usr/share/icons/hicolor/24x24/apps/"))
(frame-width 2)
(frame-color "#3d3d3d")
(max-icon-size 24)
(corner-radius 10)
(rules
'(("urgency_low"
(background "#405c2e")
(foreground "#eeeeec")
(timeout 10))
("urgency_normal"
(background "#222224")
(foreground "#eeeeec")
(timeout 10))
("urgency_critical"
(background "#973732")
(foreground "#eeeeec")
(timeout 0))
("Emacs"
(appname "Emacs")
(background "#7f5ab6")
(foreground "#fafafa"))
("Metal Express Radio"
(appname "Metal Express Radio")
(background "#ef4136")
(foreground "#ffffff"))
("Syncthing"
(appname "Syncthing GTK")
(background "#337ab7")
(foreground "#ffffff"))
("Lollypop"
(appname "Lollypop")
(background "#fd3e75")
(foreground "#ffffff"))
("gPodder"
(appname "gPodder")
(background "#7f5785")
(foreground "#ffffff")))))))