Receive warnings and alerts via alert.el
for upcoming events in your day.
Ever look at your clock 10 minutes before a scheduled phone call, keep working on something else, and then not look at your clock until 2 minutes after the phone call was supposed to begin?
I do it all the time. It must stop.
org-timed-alerts
scans your agenda files, finds any timestamps (active, deadline, or scheduled) with a time-of-day specification, and sends event warnings via alert.el
according to whatever intervals you specify with custom alert messages.
WARNING: This package is under development. It is close to complete and stable for my daily use.
Test alert
by evaluating: (alert "test")
. Did you see a notification? If so, proceed.
- dash.el
- https://github.com/magnars/dash.el
- org-ql
- https://github.com/alphapapa/org-ql
- ts.el
- https://github.com/alphapapa/ts.el
Clone this repository into your load path.
git clone https://github.com/legalnonsense/org-timed-alerts.git
Use-package declaration with all custom variables set to the default values:
(use-package org-timed-alerts
:after (org)
:custom
(org-timed-alerts-alert-function # 'alert)
(org-timed-alerts-tag-exclusions nil)
(org-timed-alerts-default-alert-props nil)
(org-timed-alerts-warning-times '(-10 -5))
(org-timed-alerts-agenda-hook-p t)
(org-timed-alert-final-alert-string "IT IS %alert-time\n\n%todo %headline")
(org-timed-alert-warning-string (concat "%todo %headline\n at %alert-time\n "
"it is now %current-time\n "
"*THIS IS YOUR %warning-time MINUTE WARNING*"))
:config
(add-hook 'org-mode-hook #'org-timed-alerts-mode))
There is no reason not to use use-package
, but if you refuse, you can minimally use:
(require 'org-timed-alerts)
(add-hook 'org-mode-hook #'org-timed-alerts-mode)
Adding (org-timed-alerts-mode)
to org-mode-hook
will activate the alert timers the next time you run org-agenda
. It will not add timers until you run org-agenda
.
Custom variables | Description | Default value |
---|---|---|
org-timed-alerts-todo-exclusions | List of TODO states to ignore when generating the alert list. E.g., ‘(“DONE”) | nilb |
org-timed-alerts-warning-times | List of integers representing the intervals of warnings preceding the event. E.g., ‘(-10 -5) means you want to be warned 10 minutes, 5 minutes, and 2 minutes before the event. nil means no warning. There is no difference between positive and negative numbers, i.e., 10 and -10 both mean to send an alert 10 minutes before the event. A final notification is automatically sent at the time the event begins. | ’(-10 -5) |
org-timed-alert-final-alert-string | Message to display in the alert shown at the time event begins (see below) | “IT IS %alert-time\n\nTIME FOR:\n%todo %headline” |
org-timed-alert-warning-string | Message to be displayed for warnings that precede the event (see below) | “%todo %headline\n at %alert-time\n it is now %current-time\n * THIS IS YOUR %warning-time MINUTE WARNING *” |
Less frequently needed custom variables | Description | Default value |
---|---|---|
org-timed-alerts-agenda-hook-p | Automatically add org-timed-alerts-set-all-timers to org-agenda-hook ? If you turn this off, the minor mode is effectively meaningless and you’ll need to find another suitable way to call org-timed-alerts-set-all-timers . | t |
org-timed-alerts-default-alert-props | See the documentation for the function alert . This plist will be used to set the default for any of those properties. Any value of this list can be a function which will be called with the point at the org-heading. See description below. | nil |
org-timed-alerts-alert-command | Function to call when invoking the alert. See alert.el for other possibilities, e.g., #'alert-libnotify-notify , #'alert-growl-notify . Use these specific functions only if you don’t want to use the default alert specified in alert-default-style . | #’alert |
org-timed-alert-final-alert-string
and org-timed-alert-warning-string
are strings that allow the following substitutions:
string | substitution |
---|---|
%todo | the TODO state of the the heading, if any |
%headline | the headline text of the heading |
%alert-time | the time of the event |
%warning-time | the current number of minutes before the event |
%current-time | the time the alert is actually sent to the user |
%category | the category property of the org heading, or the name of the file if none |
For example, consider the heading:
* TODO phone conference I don't want to have
:PROPERTIES:
:CATEGORY: annoying-client
:END:
<2020-11-23 Mon 15:45>
The following string:
%todo %headline\n at %alert-time\n it is now %current-time\n * THIS IS YOUR %warning-time MINUTE WARNING *
Will use these substitutions when it send a 5 minute warning:
string | substitution |
---|---|
%todo | “TODO” |
%headline | “phone conference I don’t want to have” |
%alert-time | “20:05” |
%warning-time | “5” |
%current-time | “20:00” |
%category | “annoying-client” |
And will display a warning that looks like this:
Unless the :title
property is overridden by org-timed-alerts-default-alert-props
, the title of an alert defaults to the category
property of the org heading.
Any heading can set custom alert intervals by setting the property :ORG-TIMED-ALERTS:
For example:
* Lunch meeting
:PROPERTIES:
:ORG-TIMED-ALERTS: 5 4 3 2 1
:END:
<2020-11-29 Sun 11:36>
Will override org-timed-alerts-warning-times
and send alert notifications 5, 4, 3, 2, and 1 minute before the appointment time.
As stated above, the value of any property can be a function that is run at the underlying org heading. If you want more advanced customization of the alert properties, you can take advantage of this. For example, suppose you wanted the title of each alert to show the text of the root heading in the tree:
(setq org-timed-alerts-default-alert-props
'(:title
(lambda () (save-excursion
;; Move to the root heading
(while (org-up-heading-safe))
;; Return its headline, without tags, todo, etc.
(org-get-heading t t t t)))))
Or suppose you wanted to customize the icon for an alert depending on the priority of the heading:
(setq org-timed-alerts-default-alert-props
'(:icon
(lambda ()
(if (string= "A" (org-entry-get (point) "PRIORITY"))
"/path/to/some/icon"
"/path/to/some/other/icon"))))
org-timed-alerts
updates itself via org-agenda-hook
. This is fast enough that I don’t notice much speed difference when generating an agenda. You can turn this off by setting org-timed-alerts-agenda-hook-p
to nil. If you do that, you can update manually with org-timed-alerts-set-all-timers
or find another suitable hook (the package only schedules timers for the current day, so you’ll need to update at least daily and after any relevant timestamp changes).
- Run an org-ql query to get all active timestamps, scheduled timestamps, and deadlines on the current date.
- For each of these events which has an associated time:
- Create a timer to send an alert at that time via alert.el. This alert will use the string
org-timed-alert-final-alert-string
- Create warning timers according to the intervals specified in
org-timed-alerts-warning-times
and using the stringorg-timed-alert-warning-string
- Create a timer to send an alert at that time via alert.el. This alert will use the string
- Update all timers any time the user runs
org-agenda
. You can update manually withorg-timed-alerts-set-all-timers
. You can disable all timers withorg-timed-alerts-cancel-all-timers
or by disabling the minor mode.
This pacakge is meant to do what I want and and nothing more; I tried to abstract a bit so others might find it useful. I have included my notes on other similar packages. Apologies to the authors if they are not accurate.
org-alert
. See https://github.com/spegoraro/org-alert. Org-alert checks for items which are scheduled or with deadlines for the current date, and then sends notification of those items immediately and simultaneously. It will resend notifications if you run org-alert-check
. It serves a different purpose than this package.
org-notify
. See https://code.orgmode.org/bzg/org-mode/raw/master/contrib/lisp/org-notify.el. Org-notify allows notifications to be scheduled and customized, but requires a special property to be set for each org heading for which an alert is desired. It also does not seem to use alert.el
by default but appears it could be customized to do so. There are a lot of nice customization options here, but it asks a lot of the user with regard to setting special properties. By contrast, the goal of org-timed-alerts
is to stay out of the way of the user by not requiring setting any special properties. In short, I feared getting this package set up for my purposes would be less enjoyable than writing a custom solution.
org-wild-notifier
. See https://github.com/akhramov/org-wild-notifier.el. Org-wild-notifier is the closest to org-timed-alerts
. The biggest drawback I saw was the inability to customize the alert message. See /akhramov/org-wild-notifier.el#43. Otherwise, this package may serve your purposes.
- [2020-12-03 Thu] Add support for repeating timestamps
- [2020-12-04 Fri] Add support for excluding TODO states in
org-timed-alerts-todo-exclusions