diff --git a/oni/home/data/config.scm b/oni/home/data/config.scm index 4c99821..0c89d5b 100644 --- a/oni/home/data/config.scm +++ b/oni/home/data/config.scm @@ -24,6 +24,7 @@ #:use-module (oni home services cmst) #:use-module (oni home services syncthing) #:use-module (oni home services unclutter) + #:use-module (oni home services dunst) #:use-module (oni packages hlwm-run-or-raise) #:use-module (oni packages pick-random-wallpaper)) @@ -390,4 +391,57 @@ LocalForward 2812 localhost:2812")) (openssh-host (name "rincewind") (host-name "192.168.1.135") - (port 4511))))))))) + (port 4511)))))) + + (service home-dunst-service-type + (home-dunst-configuration + (font "Fantasque Sans Mono 15") + (markup 'full) + (format "%s\\n\\n%b") + (width '(0 600)) + (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"))))))))) diff --git a/oni/home/services/dunst.scm b/oni/home/services/dunst.scm new file mode 100644 index 0000000..079f40b --- /dev/null +++ b/oni/home/services/dunst.scm @@ -0,0 +1,250 @@ +(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)) + +(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.") + (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")))