1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
#+STARTUP: showall
* The Emacs Desktop Notification Center
The Emacs Desktop Notification Center (EDNC) is
an Emacs package written in pure Lisp that
implements a Desktop Notifications service according to
[[https://people.gnome.org/~mccann/docs/notification-spec/notification-spec-latest.html][the freedesktop.org specification]].
EDNC aspires to be a small, but flexible drop-in replacement
of standalone daemons like [[https://dunst-project.org/][Dunst]].
A global minor mode ~ednc-mode~ tracks active notifications,
which users can access by calling the function ~ednc-notifications~.
They are also free to add their own functions
to the (abnormal) hook ~ednc-notification-amendment-functions~
to amend arbitrary data and
to the (abnormal) hook ~ednc-notification-presentation-functions~
to present notifications as they see fit.
To be useful out of the box,
default hooks record all notifications
in an interactive log buffer ~*ednc-log*~.
** Basic Usage
Either install this package [[https://melpa.org/#/ednc][from MELPA]], or
simply execute the ~package-install-file~ command and
point it to a local copy of this repository.
After installation, ensure that no other notification daemon is active,
execute the ~ednc-mode~ command to activate the global minor mode, and
watch notifications come and go in the interactive log buffer ~*ednc-log*~.
You can create example notifications from Emacs
by evaluating the following expressions:
#+BEGIN_SRC emacs-lisp
(require 'notifications)
(notifications-notify :title "1st test" :body "hello, world" :app-name "EDNC"
:actions '("default" "default"))
#+END_SRC
Some clients (e.g., web browsers) check for a notification server on startup
and thus need to be reopened after enabling EDNC.
By default, you can use the following mouse controls and key bindings
(the latter only in the log buffer):
- @@html:<kbd>@@TAB@@html:</kbd>@@
toggles an expanded view of the notification (~ednc-toggle-expanded-view~),
- @@html:<kbd>@@mouse-1@@html:</kbd>@@ (left click)
or @@html:<kbd>@@RET@@html:</kbd>@@
invokes the notification's default action (~ednc-invoke-action~),
- @@html:<kbd>@@C-down-mouse-1@@html:</kbd>@@
shows a menu of all available actions,
- @@html:<kbd>@@mouse-2@@html:</kbd>@@ (middle click)
pops to the notification in the log buffer
(~ednc-pop-to-notification-in-log-buffer~), and
- @@html:<kbd>@@mouse-3@@html:</kbd>@@ (right click)
or @@html:<kbd>@@d@@html:</kbd>@@
dismisses the notification (~ednc-dismiss-notification~).
This is the log buffer after
creating two test notifications,
dismissing the first one,
and expanding the second one:
[[./screenshot.png]]
** Advanced Usage
You can also
retrieve currently active notifications with the function ~ednc-notifications~
whenever the (abnormal) hook ~ednc-notification-presentation-functions~ runs.
Functions in this hook are given access to
the exact notification that was removed, added, or replaced.
Read on for some suggestions.
*** Show Active Notifications in Mode Line
To simply display all active notifications in the mode line,
first define a function that returns active notifications as a string:
#+NAME: list
#+BEGIN_SRC emacs-lisp :tangle yes
(defun list-notifications ()
(mapconcat #'ednc-format-notification (ednc-notifications) ""))
#+END_SRC
Alternatively, only include the newest notification per application:
#+NAME: stack
#+BEGIN_SRC emacs-lisp :tangle yes
(defun stack-notifications (&optional hide)
(mapconcat (lambda (notification)
(let ((app-name (ednc-notification-app-name notification)))
(unless (member app-name hide)
(push app-name hide)
(ednc-format-notification notification))))
(ednc-notifications) ""))
#+END_SRC
Use the respective function's result as part of your mode line
every time a new notification appears, or an old one is removed:
#+BEGIN_SRC emacs-lisp
(nconc global-mode-string '((:eval (list-notifications)))) ; or stack
(add-hook 'ednc-notification-presentation-functions
(lambda (&rest _) (force-mode-line-update t)))
#+END_SRC
*** Pop to Buffer for Every New Notification
If you want to create a new buffer for every new notification
(instead of or in addition to displaying it in the mode line)
first define a function that uses the abnormal hook's arguments:
#+NAME: buffer
#+BEGIN_SRC emacs-lisp :tangle yes
(defun show-notification-in-buffer (old new)
(let ((name (format "Notification %d" (ednc-notification-id (or old new)))))
(with-current-buffer (get-buffer-create name)
(if new (let ((inhibit-read-only t))
(if old (erase-buffer) (ednc-view-mode))
(insert (ednc-format-notification new t))
(pop-to-buffer (current-buffer)))
(kill-buffer)))))
#+END_SRC
Then ensure the function is called at the appropriate moment:
#+BEGIN_SRC emacs-lisp
(add-hook 'ednc-notification-presentation-functions
#'show-notification-in-buffer)
#+END_SRC
** Questions and Answers
Here you find answers to some real and to some imagined questions from users.
*** How does EDNC differ from [[https://github.com/jwiegley/alert][Alert]]?
These are two different classes of software:
EDNC handles incoming notifications on D-Bus; Alert does not, but
[[https://github.com/jwiegley/alert#builtin-alert-styles][can be configured]]
to /emit/ notifications on D-Bus.
It is possible, and sensible, to use both EDNC and Alert at the same time.
You might configure the packages, for example, so that
- Alert sends a notification on activity in an rcirc buffer,
- Signal sends a notification on receiving a message, and
- EDNC presents both of these uniformly in the mode-line.
Without EDNC, Alert could bypass D-Bus when dealing with rcirc,
but the information from Signal would be inaccessible to Emacs.
*** How does EDNC differ from [[https://dunst-project.org/][Dunst]]?
EDNC is native to Emacs; Dunst is not.
Specifically, you can access and modify received notifications with Emacs Lisp
(a big deal for some users).
Other than that, there should be no fundamental difference.
*** Why do some icons look weird?
Emacs does not support [[http://netpbm.sourceforge.net/doc/pam.html][PAM]],
a newer Netpbm format with optional transparency information.
Until that changes, the icon's alpha channel is simply ignored.
*** Why are some icons not showing up at all?
[[https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html][The Icon Theme Specification]]
has not been implemented yet, so
only file URIs are supported for now.
-----
[[https://github.com/sinic/ednc/actions][https://github.com/sinic/ednc/workflows/CI/badge.svg]]
[[https://www.gnu.org/licenses/gpl-3.0][file:https://img.shields.io/badge/License-GPLv3-blue.svg]]
[[https://melpa.org/#/ednc][file:https://melpa.org/packages/ednc-badge.svg]]
|