aboutsummaryrefslogtreecommitdiff
path: root/gnus-desktop-notify.el
diff options
context:
space:
mode:
Diffstat (limited to 'gnus-desktop-notify.el')
-rw-r--r--gnus-desktop-notify.el202
1 files changed, 101 insertions, 101 deletions
diff --git a/gnus-desktop-notify.el b/gnus-desktop-notify.el
index 271d7f5..7c5dbd9 100644
--- a/gnus-desktop-notify.el
+++ b/gnus-desktop-notify.el
@@ -81,48 +81,20 @@
(require 'format-spec)
(require 'gnus-group)
+
(unless (require 'alert nil t)
(require 'notifications nil t))
-(eval-when-compile
- (require 'cl))
+
+;;; Custom variables
(defgroup gnus-desktop-notify nil
"Gnus external notification framework"
:group 'gnus)
-;;;###autoload
-(define-minor-mode gnus-desktop-notify-mode
- "Gnus Desktop Notification mode uses libnotify's 'notify-send'
-program to generate popup messages or call external executables
-whenever a group receives new messages through gnus-demon (see
-`gnus-demon-add-handler').
-
- You can actually call any program by changing the
-`gnus-desktop-notify-exec-program' variable, or change the
-behavior entirely by setting a different
-`gnus-desktop-notify-function' function.
-
- See the `gnus-desktop-notify' customization group for more
-details."
- :init-value nil
- :group 'gnus-desktop-notify
- :require 'gnus
- :global t
- (cond
- (gnus-desktop-notify-mode
- (add-hook 'gnus-after-getting-new-news-hook 'gnus-desktop-notify-check)
- (add-hook 'gnus-started-hook 'gnus-desktop-notify-check))
- (t
- (remove-hook 'gnus-after-getting-new-news-hook 'gnus-desktop-notify-check)
- (remove-hook 'gnus-started-hook 'gnus-desktop-notify-check))))
-
-
-;;; Custom variables
-
(defcustom gnus-desktop-notify-function
- (cond ((featurep 'alert) 'gnus-desktop-notify-alert)
- ((featurep 'notifications) 'gnus-desktop-notify-dbus)
- (t 'gnus-desktop-notify-send))
+ (cond ((featurep 'alert) 'gnus-desktop-notify-alert)
+ ((featurep 'notifications) 'gnus-desktop-notify-dbus)
+ (t 'gnus-desktop-notify-send))
"Function called when a group receives new messages. The first
argument will be an alist containing the groups and the number of
new messages. The default is to use `gnus-desktop-notify-alert'
@@ -159,10 +131,11 @@ See `gnus-desktop-notify-send-program'."
(defcustom gnus-desktop-notify-behavior 'gnus-desktop-notify-multi
"Desktop notification behavior. Can be either:
-'gnus-desktop-notify-single: display a single notification for
- each group.
-'gnus-desktop-notify-multi: display a multi-line notification for
- all groups at once."
+`gnus-desktop-notify-single': display a single notification for
+ each group.
+
+`gnus-desktop-notify-multi': display a multi-line notification
+ for all groups at once."
:type 'symbol)
(defcustom gnus-desktop-notify-send-subject "New mail"
@@ -193,14 +166,15 @@ deactivate shortening completely."
(defcustom gnus-desktop-notify-groups 'gnus-desktop-notify-all-except
"Gnus group notification mode. Can be either:
-'gnus-desktop-notify-all-except: monitor all groups by
- default except excluded ones,
-'gnus-desktop-notify-explicit: monitor only requested groups.
+`gnus-desktop-notify-all-except': monitor all groups by default
+ except excluded ones,
- Groups can be included or excluded by setting the
-'group-notify' group parameter to 't'. This can be set either in
-the `gnus-parameters' variable, or interactively by pressing 'G
-c' in the group buffer."
+`gnus-desktop-notify-explicit': monitor only requested groups.
+
+Groups can be included or excluded by setting the `group-notify'
+group parameter to `t'. This can be set either in the
+`gnus-parameters' variable, or interactively by pressing `G c' in
+the group buffer."
:type 'symbol)
;;; Group parameters
@@ -223,6 +197,7 @@ the notification of new messages (depending on the value of
(">" . ">" ))
"Map special characters to their HTML entities.")
+;; FIXME: Do not reinvent the wheel if possible
(defun gnus-desktop-notify-escape-html-entities (str)
"Escape HTML character entity references."
(let* ((lut gnus-desktop-notify-html-lut)
@@ -230,12 +205,6 @@ the notification of new messages (depending on the value of
(replace-regexp-in-string
chars (lambda (s) (cdr (assoc-string s lut))) str)))
-(defun gnus-desktop-notify-arg (group)
- (format-spec gnus-desktop-notify-format
- (format-spec-make
- ?n (cdr group)
- ?G (gnus-desktop-notify-escape-html-entities (car group)))))
-
(defun gnus-desktop-notify-read-count (group)
(let* ((range (gnus-range-normalize (gnus-info-read group)))
(count (gnus-last-element range)))
@@ -249,7 +218,36 @@ collapsing."
(gnus-short-group-name group gnus-desktop-notify-uncollapsed-levels)
group))
+(defun gnus-desktop-notify-format-1 (group)
+ "Convert GROUP to its printed representation.
+GROUP should have the form (NAME . COUNT), where NAME is the
+group name to display and COUNT is the corresponding number of
+articles."
+ (let ((name (gnus-desktop-notify-escape-html-entities (car group)))
+ (count (cdr group)))
+ (format-spec gnus-desktop-notify-format
+ (format-spec-make ?n count
+ ?G name))))
+
+(defun gnus-desktop-notify-format-n (groups)
+ "Return a list of the printed representations of GROUPS.
+
+GROUPS should be a list of cons cells accepted by
+`gnus-desktop-notify-format-1', which see.
+
+Depending on the value of `gnus-desktop-notify-behavior', the
+returned list will comprise either a single multiline string or
+multiple uniline strings."
+ (mapcar (lambda (body) (mapconcat #'identity body "\n"))
+ ;; Iterate over the groups either individually or as a whole
+ (let ((bodies (mapcar #'gnus-desktop-notify-format-1 groups)))
+ (cond ((eq gnus-desktop-notify-behavior 'gnus-desktop-notify-single)
+ (mapcar #'list bodies))
+ ((eq gnus-desktop-notify-behavior 'gnus-desktop-notify-multi)
+ `(,bodies))))))
+
(defun gnus-desktop-notify-check (&rest _ignored)
+ "Check all groups for and notify of new articles."
(interactive)
(let ((updated-groups ()))
(dolist (g gnus-newsrc-alist)
@@ -271,70 +269,72 @@ collapsing."
(push (cons (gnus-desktop-short-group-name name) delta)
updated-groups)))))))
(when (and updated-groups (not (called-interactively-p 'any)))
- (funcall gnus-desktop-notify-function updated-groups))))
+ (mapc gnus-desktop-notify-function
+ (gnus-desktop-notify-format-n updated-groups)))))
+
+(defun gnus-desktop-shell-command (&rest args)
+ "Execute ARGS as a synchronous shell command without I/O."
+ (call-process-shell-command
+ (mapconcat #'shell-quote-argument args " ") nil 0 nil))
-;;; Notification functions
+;;; Notification backends
-(defun gnus-desktop-notify-exec (groups)
+(defun gnus-desktop-notify-exec (body)
"Call a program defined by `gnus-desktop-notify-exec-program'.
with each argument being a group formatted according to
`gnus-desktop-notify-format' and calling behavior is defined by
`gnus-desktop-notify-behavior'."
- (let ((groups (mapcar 'gnus-desktop-notify-arg groups)))
- (case gnus-desktop-notify-behavior
- ('gnus-desktop-notify-single
- (dolist (g groups)
- (call-process-shell-command gnus-desktop-notify-exec-program nil 0 nil
- (shell-quote-argument g))))
- ('gnus-desktop-notify-multi
- (call-process-shell-command gnus-desktop-notify-exec-program nil 0 nil
- (mapconcat 'shell-quote-argument groups " "))))))
-
-(defun gnus-desktop-notify-send (groups)
+ (funcall #'gnus-desktop-shell-command gnus-desktop-notify-exec-program body))
+
+(defun gnus-desktop-notify-send (body)
"Invoke the configured `notify-send' program.
See `gnus-desktop-notify-send-program',
`gnus-desktop-notify-send-switches' and
`gnus-desktop-notify-behavior' for configuration options."
- (let ((args `(,gnus-desktop-notify-send-program
- ,@gnus-desktop-notify-send-switches
- "--"
- ,gnus-desktop-notify-send-subject))
- (groups (mapcar #'gnus-desktop-notify-arg groups)))
- ;; Iterate over the groups either individually or as a whole
- (dolist (group (case gnus-desktop-notify-behavior
- (gnus-desktop-notify-single groups)
- (gnus-desktop-notify-multi `(,groups))))
- ;; Join the groups when viewing as a whole
- (let* ((lines (if (listp group) group `(,group)))
- (body (mapconcat #'identity lines "\n")))
- ;; Actually perform the work
- (call-process-shell-command
- (mapconcat #'shell-quote-argument `(,@args ,body) " ")
- nil 0 nil)))))
-
-(defun gnus-desktop-notify-dbus (groups)
+ (apply #'gnus-desktop-shell-command
+ `(,gnus-desktop-notify-send-program
+ ,@gnus-desktop-notify-send-switches
+ "--"
+ ,gnus-desktop-notify-send-subject
+ ,body)))
+
+(defun gnus-desktop-notify-dbus (body)
"Generate a notification directly using `notifications' with
the behavior defined by `gnus-desktop-notify-behavior'."
- (let ((groups (mapcar 'gnus-desktop-notify-arg groups)))
- (case gnus-desktop-notify-behavior
- ('gnus-desktop-notify-single
- (dolist (g groups)
- (notifications-notify :title gnus-desktop-notify-send-subject :body g)))
- ('gnus-desktop-notify-multi
- (notifications-notify :title gnus-desktop-notify-send-subject
- :body (mapconcat 'identity groups "\n"))))))
-
-(defun gnus-desktop-notify-alert (groups)
+ (notifications-notify :title gnus-desktop-notify-send-subject :body body))
+
+(defun gnus-desktop-notify-alert (body)
"Generate a notification directly using `alert' with
the behavior defined by `gnus-desktop-notify-behavior'."
- (let ((groups (mapcar 'gnus-desktop-notify-arg groups)))
- (case gnus-desktop-notify-behavior
- ('gnus-desktop-notify-single
- (dolist (g groups)
- (alert g :title gnus-desktop-notify-send-subject)))
- ('gnus-desktop-notify-multi
- (alert (mapconcat 'identity groups "\n")
- :title gnus-desktop-notify-send-subject)))))
+ (alert body :title gnus-desktop-notify-send-subject))
+
+;;; Minor mode
+
+;;;###autoload
+(define-minor-mode gnus-desktop-notify-mode
+ "Gnus Desktop Notification mode uses libnotify's 'notify-send'
+program to generate popup messages or call external executables
+whenever a group receives new messages through gnus-demon (see
+`gnus-demon-add-handler').
+
+ You can actually call any program by changing the
+`gnus-desktop-notify-exec-program' variable, or change the
+behavior entirely by setting a different
+`gnus-desktop-notify-function' function.
+
+ See the `gnus-desktop-notify' customization group for more
+details."
+ :init-value nil
+ :group 'gnus-desktop-notify
+ :require 'gnus
+ :global t
+ (cond
+ (gnus-desktop-notify-mode
+ (add-hook 'gnus-after-getting-new-news-hook #'gnus-desktop-notify-check)
+ (add-hook 'gnus-started-hook #'gnus-desktop-notify-check))
+ (t
+ (remove-hook 'gnus-after-getting-new-news-hook #'gnus-desktop-notify-check)
+ (remove-hook 'gnus-started-hook #'gnus-desktop-notify-check))))
(provide 'gnus-desktop-notify)
;;; gnus-desktop-notify.el ends here