diff options
Diffstat (limited to 'lisp/dawn.el')
-rw-r--r-- | lisp/dawn.el | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lisp/dawn.el b/lisp/dawn.el new file mode 100644 index 0000000..806c422 --- /dev/null +++ b/lisp/dawn.el | |||
@@ -0,0 +1,84 @@ | |||
1 | ;;; dawn.el --- Do things at dawn (and dusk) -*- lexical-binding: t; -*- | ||
2 | |||
3 | ;;; Commentary: | ||
4 | |||
5 | ;; There is also circadian.el, but it doesn't quite work for me. | ||
6 | ;; This code comes mostly from https://gnu.xyz/auto_theme.html, but also | ||
7 | ;; somewhere else (which I've forgotten) and my own brain :) | ||
8 | |||
9 | ;;; Code: | ||
10 | |||
11 | (require 'calendar) | ||
12 | (require 'cl-lib) | ||
13 | (require 'solar) | ||
14 | |||
15 | (defvar dawn--dawn-timer nil | ||
16 | "Timer for dawn-command.") | ||
17 | |||
18 | (defvar dawn--dusk-timer nil | ||
19 | "Timer for dusk-command.") | ||
20 | |||
21 | (defvar dawn--reset-timer nil | ||
22 | "Timer to reset dawn at midnight.") | ||
23 | |||
24 | (defun dawn-encode-time (f) | ||
25 | "Encode fractional time F." | ||
26 | (let ((hhmm (cl-floor f)) | ||
27 | (date (cdddr (decode-time)))) | ||
28 | (encode-time | ||
29 | (append (list 0 | ||
30 | (round (* 60 (cadr hhmm))) | ||
31 | (car hhmm) | ||
32 | ) | ||
33 | date)))) | ||
34 | |||
35 | (defun dawn-midnight () | ||
36 | "Return the time of the /next/ midnight." | ||
37 | (let ((date (cdddr (decode-time)))) | ||
38 | (encode-time | ||
39 | (append (list 0 0 0 (1+ (car date))) (cdr date))))) | ||
40 | |||
41 | (defun dawn-sunrise () | ||
42 | "Return the time of today's sunrise." | ||
43 | (dawn-encode-time (caar (solar-sunrise-sunset (calendar-current-date))))) | ||
44 | |||
45 | (defun dawn-sunset () | ||
46 | "Return the time of today's sunset." | ||
47 | (dawn-encode-time (caadr (solar-sunrise-sunset (calendar-current-date))))) | ||
48 | |||
49 | (defun dawn-schedule (dawn-command dusk-command) | ||
50 | "Run DAWN-COMMAND at sunrise, and DUSK-COMMAND at dusk. | ||
51 | RESET is an argument for internal use." | ||
52 | (when (or (null calendar-longitude) | ||
53 | (null calendar-latitude)) | ||
54 | (user-error "`dawn' won't work without setting %s!" | ||
55 | (cond ((and (null calendar-longitude) | ||
56 | (null calendar-latitude)) | ||
57 | "`calendar-longitude' and `calendar-latitude'") | ||
58 | ((null calendar-longitude) | ||
59 | "`calendar-longitude'") | ||
60 | ((null calendar-latitude) | ||
61 | "`calendar-latitude'")))) | ||
62 | (let ((dawn (dawn-sunrise)) | ||
63 | (dusk (dawn-sunset))) | ||
64 | (cond | ||
65 | ((time-less-p nil dawn) | ||
66 | ;; If it isn't dawn yet, it's still dark. Run DUSK-COMMAND and schedule | ||
67 | ;; DAWN-COMMAND and DUSK-COMMAND for later. | ||
68 | (funcall dusk-command) | ||
69 | (run-at-time dawn nil dawn-command) | ||
70 | (run-at-time dusk nil dusk-command)) | ||
71 | ((time-less-p nil dusk) | ||
72 | ;; If it isn't dusk yet, it's still light. Run DAWN-COMMAND and schedule | ||
73 | ;; DUSK-COMMAND. | ||
74 | (funcall dawn-command) | ||
75 | (run-at-time dusk nil dusk-command)) | ||
76 | (t ;; Otherwise, it's past dusk, so run DUSK-COMMAND. | ||
77 | (funcall dusk-command))) | ||
78 | ;; Schedule a reset at midnight, to re-calculate dawn/dusk times. | ||
79 | ;(unless reset) | ||
80 | (run-at-time (dawn-midnight) nil | ||
81 | #'dawn-schedule dawn-command dusk-command))) | ||
82 | |||
83 | (provide 'dawn) | ||
84 | ;;; dawn.el ends here | ||