diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..751a0c4
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,13 @@
+# These are supported funding model platforms
+
+github: guidoschmidt
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
new file mode 100644
index 0000000..3ae82a8
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to report a bug in circadian.el
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Environment (please complete the following information):**
+ - OS: [e.g. macOS 14, Windows 11, Ubuntu etc.]
+ - Emacs: [e.g. emacs-plus 30.0.50]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..bbcbbe7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 172fe48..c4c8ab7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,24 +6,24 @@ jobs:
strategy:
matrix:
emacs-version:
- - 26.3
- 27.2
- 28.2
+ - 29.3
- snapshot
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs-version }}
- - uses: actions/cache@v2
+ - uses: actions/cache@v4
id: cache-cask-packages
with:
path: .cask
key: cache-cask-packages-000
- - uses: actions/cache@v2
+ - uses: actions/cache@v4
id: cache-cask-executable
with:
path: ~/.cask
diff --git a/README.md b/README.md
index 318c242..45eac3a 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
Theme-switching for Emacs based on daytime
-### Conception
+## Conception
Circadian tries to help reducing eye strain that may arise
from difference of your display brightness and the
@@ -31,9 +31,63 @@ adaption software like:
---
-### Example usage
+## Usage & Configuration
+Install circadian.el with
+[use-package](https://www.gnu.org/software/emacs/manual/html_mono/use-package.html)
+or [straight.el](https://github.com/radian-software/straight.el)
-##### Switching themes on time of day
+### Configuration with times
+To auto-switch a theme on a specific time, use time strings:
+
+```elisp
+(use-package circadian
+ :ensure t
+ :config
+ (setq circadian-themes '(("8:00" . wombat)
+ ("19:30" . adwaita)))
+ (circadian-setup))
+```
+
+
+### Configuration with `:sunrise` and `:sunset`
+To auto-switch a theme based on your current locations sunrise and sunset times:
+
+1. Make sure to set your latitude and longitude (Get them e.g. at
+ [latlong.net](https://www.latlong.net/)):
+ ```elisp
+ (setq calendar-latitude 40.712776)
+ (setq calendar-longitude -74.005974)
+ ```
+2. Configure `circadian-themes` using the `:sunset` and `:sunset`
+ ```elisp
+ (use-package circadian
+ :ensure t
+ :config
+ (setq circadian-themes '((:sunrise . adwaita)
+ (:sunset . wombat)))
+ (circadian-setup))
+ ```
+
+
+### Randomly selection from theme list
+Circadian.el can randomly select a theme from a given list, e.g here using [doom-themes](https://github.com/doomemacs/themes) at sunset:
+
+```elisp
+(use-package doom-themes)
+
+(use-package circadian
+ :config
+ (setq circadian-themes '((:sunrise . doom-gruvbox-light)
+ (:sunset . (doom-dracula doom-gruvbox))))
+ (add-hook 'emacs-startup-hook #'circadian-setup)
+ (circadian-setup))
+```
+
+
+### Use with custom themes
+To use custom themes, install them from MELPA using
+e.g. [use-package](https://www.gnu.org/software/emacs/manual/html_mono/use-package.html)
+or [straight.el](https://github.com/radian-software/straight.el).
Example usage featuring [hemera-themes](https://github.com/GuidoSchmidt/emacs-hemera-theme)
and [nyx-theme](https://github.com/GuidoSchmidt/emacs-nyx-theme) (with use-package). Make sure
@@ -45,33 +99,16 @@ to use `:defer` keyword. Omitting it may lead to broken colors
;; make sure to use :defer keyword
(use-package hemera-theme :ensure :defer)
(use-package nyx-theme :ensure :defer)
-
-(use-package circadian
- :ensure t
- :config
- (setq circadian-themes '(("8:00" . hemera)
- ("19:30" . nyx)))
- (circadian-setup))
```
-##### Switching themes on sunrise & sunset
-Be sure to set your latitude and longitude (Get them e.g. at [latlong.net](https://www.latlong.net/)):
+### Verbose messages
+By default circadian will not log any messages. however for development or just
+getting more information, one can enable a more verbose message log:
```elisp
-;; Install additinal themes from melpa
-;; make sure to use :defer keyword
-(use-package apropospriate-theme :ensure :defer)
-(use-package nord-theme :ensure :defer)
+(setq circadian-verbose t)
-(use-package circadian
- :ensure t
- :config
- (setq calendar-latitude 49.0)
- (setq calendar-longitude 8.5)
- (setq circadian-themes '((:sunrise . apropospriate-light)
- (:sunset . nord)))
- (circadian-setup))
```
---
@@ -107,7 +144,7 @@ e.g. I like to override any themes cursor color to a very bright color via:
---
-### Development
+### Development & Testing
Install Emacs [cask](https://github.com/cask/cask) environment. On macOS you
canr use [homebrew](https://brew.sh/) with: `brew install cask`.
diff --git a/circadian.el b/circadian.el
index 6693e0c..4574be6 100644
--- a/circadian.el
+++ b/circadian.el
@@ -5,9 +5,9 @@
;; Author: Guido Schmidt
;; Maintainer: Guido Schmidt
;; URL: https://github.com/GuidoSchmidt/circadian
-;; Version: 0.3.3
+;; Version: 1.0.0
;; Keywords: themes
-;; Package-Requires: ((emacs "24.4"))
+;; Package-Requires: ((emacs "27.2"))
;; This file is part of GNU Emacs.
@@ -44,6 +44,16 @@
(require 'cl-lib)
(require 'solar)
+(defcustom circadian-verbose nil
+ "Timer to execute on next theme switch."
+ :type 'boolean
+ :group 'circadian)
+
+(defcustom circadian-next-timer nil
+ "Timer to execute on next theme switch."
+ :type 'timer
+ :group 'circadian)
+
(defcustom circadian-before-load-theme-hook nil
"Functions to run before the theme is changed."
:type 'hook
@@ -62,36 +72,67 @@
(defun circadian-enable-theme (theme)
"Clear previous `custom-enabled-themes' and load THEME."
- (unless (equal (list theme) custom-enabled-themes)
- ;; Only load the argument theme, when `custom-enabled-themes'
- ;; does not contain it.
- (mapc #'disable-theme custom-enabled-themes)
- (condition-case nil
- (progn
- (run-hook-with-args 'circadian-before-load-theme-hook theme)
- (load-theme theme t)
- (let ((time (circadian-now-time)))
- (message "circadian.el → Enabled %s theme @ %02d:%02d:%02d"
- theme (nth 0 time) (nth 1 time) (nth 2 time)))
- (run-hook-with-args 'circadian-after-load-theme-hook theme))
- (error "ERROR: circadian.el → Problem loading theme %s" theme))))
-
-(defun circadian--encode-time (hour min)
+ ;; Only load the argument theme, when `custom-enabled-themes'
+ ;; does not contain it.
+
+ (condition-case nil
+ (progn
+ (run-hook-with-args 'circadian-before-load-theme-hook theme)
+
+ (if (equal nil (member theme custom-enabled-themes))
+ (progn
+ (mapc #'disable-theme custom-enabled-themes)
+ (load-theme theme t)
+ (if (not (equal nil circadian-next-timer))
+ (cancel-timer circadian-next-timer))
+ (setq circadian-next-timer nil)
+ (if circadian-verbose
+ (message "[circadian.el] → Enabled %s theme @ %s"
+ theme
+ (format-time-string "%H:%M:%S %Z"))))
+ (progn
+ (if circadian-verbose
+ (message "[circadian.el] → %s already enabled"
+ theme))))
+
+ (circadian-schedule)
+
+ (run-hook-with-args 'circadian-after-load-theme-hook theme))
+ (error "[circadian.el/ERROR] → Problem loading theme %s" theme)))
+
+(defun circadian-encode-time (hour min)
"Encode HOUR hours and MIN minutes into a valid format for `run-at-time'."
- (let ((now (decode-time)))
- (let ((day (nth 3 now))
- (month (nth 4 now))
- (year (nth 5 now))
- (zone (current-time-zone)))
- (encode-time 0 min hour day month year zone))))
+ (let* ((now (decode-time))
+ (is-earlier (circadian-a-earlier-b-p (list hour min) (list (nth 2 now) (nth 1 now))))
+ (tomorrow (decode-time (+ (* 24 60 60)
+ (time-to-seconds (current-time)))))
+ (day (if is-earlier
+ (nth 3 tomorrow)
+ (nth 3 now)))
+ (month (if is-earlier
+ (nth 4 now)
+ (nth 4 tomorrow)))
+ (year (if is-earlier
+ (nth 5 now)
+ (nth 5 tomorrow))))
+ (encode-time 0 min hour day month year nil -1 nil)))
(defun circadian-themes-parse ()
- "Parse `circadian-themes' and sort by time."
+ "Parse `circadian-themes', filter the list and sort it by time.
+Uses `circadian-check-calendar' to filter out entries which use `:sunrise'
+or `:sunset' if either `calendar-latitude' or `calendar-longitude' is not
+set and and sort the final list by time."
(sort
- (mapcar
- (lambda (entry)
- (cons (circadian-match-sun (cl-first entry)) (cdr entry)))
- circadian-themes)
+ (mapcar
+ (lambda (entry)
+ (cons (circadian-match-sun (cl-first entry)) (cdr entry)))
+ (seq-filter
+ (lambda (entry)
+ (if (equal nil (circadian-check-calendar))
+ (and (not (equal :sunrise (cl-first entry)))
+ (not (equal :sunset (cl-first entry))))
+ t))
+ circadian-themes))
(lambda (a b) (circadian-a-earlier-b-p (car a) (car b)))))
;;; --- TIME COMPARISONS
@@ -112,51 +153,109 @@
(not (circadian-a-earlier-b-p theme-time now-time))))
theme-list))
-(defun circadian-activate-latest-theme ()
- "Check which themes are overdue to be activated and load the last."
- (interactive)
+(defun circadian-activate-current ()
+ "Check which theme should be active currently and return a time for the next run."
+ (let* ((themes (circadian-themes-parse))
+ (now (circadian-now-time))
+ (past-themes (circadian-filter-inactivate-themes themes now))
+ (entry (car (last (or past-themes themes))))
+ (theme-or-theme-list (cdr entry))
+ (theme (if (listp theme-or-theme-list)
+ (progn
+ (nth (random (length theme-or-theme-list)) theme-or-theme-list))
+ theme-or-theme-list)))
+ (circadian-enable-theme theme)))
+
+(defun circadian-schedule()
+ "Schedule the next timer for circadian."
+ (random (format-time-string "%H:%M" (decode-time)))
(let* ((themes (circadian-themes-parse))
(now (circadian-now-time))
(past-themes (circadian-filter-inactivate-themes themes now))
(entry (car (last (or past-themes themes))))
- (theme (cdr entry))
(next-entry (or (cadr (member entry themes))
(if (circadian-a-earlier-b-p (circadian-now-time) (cl-first entry))
- (car themes))))
- (next-time (if next-entry
- (circadian--encode-time
- (cl-first (cl-first next-entry))
- (cl-second (cl-first next-entry)))
- (+ (* (+ (- 23 (cl-first now)) (cl-first (cl-first (cl-first themes)))) 60 60)
- (* (+ (- 60 (cl-second now)) (cl-second (cl-first (cl-first themes)))) 60)))))
- (circadian-enable-theme theme)
- (cancel-function-timers #'circadian-activate-latest-theme)
- (run-at-time next-time nil #'circadian-activate-latest-theme)))
+ (car themes)
+ (cl-first past-themes))))
+ (next-theme-or-theme-list (cdr next-entry))
+ (next-theme (if (listp next-theme-or-theme-list)
+ (progn
+ (nth (random (length next-theme-or-theme-list)) next-theme-or-theme-list))
+ next-theme-or-theme-list))
+ (next-time (circadian-encode-time
+ (cl-first (cl-first next-entry))
+ (cl-second (cl-first next-entry)))))
+ (if (equal nil circadian-next-timer)
+ (progn (setq circadian-next-timer
+ (run-at-time
+ next-time
+ nil
+ #'circadian-enable-theme next-theme))
+ (if circadian-verbose
+ (message "[circadian.el] → Next theme %s @ %s"
+ (if (listp next-theme)
+ (concat "one of " (format "%s" next-theme))
+ next-theme)
+ (format-time-string "%H:%M:%S %Z" next-time)))))))
;; --- Sunset-sunrise
-(defun circadian--frac-to-time (f)
+(defun circadian-frac-to-time (f)
"Convert fractional time F to (HH MM)."
(let ((l (cl-floor f)))
(list (cl-first l)
(floor (* 60 (cl-second l))))))
+(defun circadian-check-calendar ()
+ "Check if either calendar-latitude or calendar-longitude is not set."
+ ;; 1. Check `calendar-latitude' ond message user if it's not set.
+ (if (and circadian-verbose (equal nil calendar-latitude))
+ (message "calendar-latitude not set. Consider using fixed time strings, e.g.
+
+(setq circadian-themes '((\"9:00\" . wombat)
+ (\"20:00\" . tango))
+
+or set calendar-latitude:
+ (setq calendar-latitude 49.0)"))
+
+ ;; 2. Check `calendar-longitude' ond message user if it's not set.
+ (if (and circadian-verbose (equal nil calendar-longitude))
+ (message "calendar-longitude not set. Consider using fixed time strings, e.g.
+
+(setq circadian-themes '((\"9:00\" . wombat)
+ (\"20:00\" . tango))
+
+or set calendar-longitude:
+ (setq calendar-longitude 8.5)"))
+
+ (cond ((equal nil calendar-latitude)
+ (progn
+ nil))
+
+ ((equal nil calendar-longitude)
+ (progn
+ nil))
+
+ (t)))
+
(defun circadian-sunrise ()
"Get clean sunrise time string from Emacs' `sunset-sunrise'`."
(let ((solar-result (solar-sunrise-sunset (calendar-current-date))))
(let ((sunrise-numeric (cl-first (cl-first solar-result))))
(if (equal nil sunrise-numeric)
- (error "No valid sunrise from solar-sunrise-sunset, consider using fixed time strings, e.g. (setq circadian-themes '((\"9:00\" . wombat) (\"20:00\" . tango)))")
- (circadian--frac-to-time sunrise-numeric)))))
+ (if circadian-verbose
+ (message "[circadian.el/ERROR] No valid sunrise from solar-sunrise-sunset, consider using fixed time strings, e.g. (setq circadian-themes '((\"9:00\" . wombat) (\"20:00\" . tango)))"))
+ (circadian-frac-to-time sunrise-numeric)))))
(defun circadian-sunset ()
"Get clean sunset time string from Emacs' `sunset-sunrise'`."
(let ((solar-result (solar-sunrise-sunset (calendar-current-date))))
(let ((sunset-numeric (cl-first (cl-second solar-result))))
(if (equal nil sunset-numeric)
- (error "No valid sunset from solar-sunrise-sunset, consider using fixed time strings, e.g. (setq circadian-themes '((\"9:00\" . wombat) (\"20:00\" . tango)))")
- (circadian--frac-to-time sunset-numeric)))))
+ (if circadian-verbose
+ (message "[circadian.el/ERROR] No valid sunset from solar-sunrise-sunset, consider using fixed time strings, e.g. (setq circadian-themes '((\"9:00\" . wombat) (\"20:00\" . tango)))"))
+ (circadian-frac-to-time sunset-numeric)))))
-(defun circadian--string-to-time (input)
+(defun circadian-string-to-time (input)
"Parse INPUT string to `(HH MM)'."
(cl-map 'list #'string-to-number (split-string input ":")))
@@ -164,21 +263,34 @@
"Match INPUT to a case for setting up timers."
(cond ((cl-equalp input :sunrise)
(let ((sunrise (circadian-sunrise)))
- (if (equal sunrise "not")
- (error "Could not get valid sunset time — check your time zone settings"))
- (circadian-sunrise)))
+ (if (equal sunrise nil)
+ (if circadian-verbose
+ (message "[circadian.el/ERROR] Could not get valid sunset time — check your time zone settings")))
+ sunrise))
+
((cl-equalp input :sunset)
(let ((sunset (circadian-sunset)))
- (if (equal sunset "on")
- (error "Could not get valid sunset time — check your time zone settings"))
- (circadian-sunset)))
- ((stringp input) (circadian--string-to-time input))))
+ (if (equal sunset nil)
+ (if circadian-verbose
+ (message "[circadian.el/ERROR] Could not get valid sunset time — check your time zone settings")))
+ sunset))
+
+ ((stringp input) (circadian-string-to-time input))))
;;;###autoload
(defun circadian-setup ()
"Setup circadian based on `circadian-themes'."
(interactive)
- (circadian-activate-latest-theme))
+ (circadian-activate-current)
+ (circadian-schedule))
+
+(defun circadian-stop ()
+ "Stop `circadian-next-timer' - To re-schedule, call `circadian-setup' again."
+ (interactive)
+ (if (not (equal nil circadian-next-timer))
+ (progn
+ (cancel-timer circadian-next-timer)
+ (setq circadian-next-timer nil))))
(provide 'circadian)
;;; circadian.el ends here
diff --git a/test.el b/test.el
index f8b2bff..a03cfd4 100644
--- a/test.el
+++ b/test.el
@@ -15,6 +15,7 @@
("23:59" . adwaita)))
(setq circadian-themes-parsed (circadian-themes-parse))
+
;; Before 5:01
(let ((time-now '(4 10)))
(should (equal 0 (length (circadian-filter-inactivate-themes
@@ -22,8 +23,9 @@
time-now)))))
(with-mock
(stub circadian-now-time => '(5 0 0))
- (circadian-activate-latest-theme)
- (should (equal 'adwaita (cl-first custom-enabled-themes))))
+ (circadian-setup)
+
+ (should (equal (list 'adwaita) custom-enabled-themes)))
;; After 5:01, before 14:47
(let ((time-now '(5 2)))
@@ -32,8 +34,8 @@
time-now)))))
(with-mock
(stub circadian-now-time => '(5 2 0))
- (circadian-activate-latest-theme)
- (should (equal 'wombat (cl-first custom-enabled-themes))))
+ (circadian-setup)
+ (should (equal (list 'wombat) custom-enabled-themes)))
;; After 14:47, before 23:59
(let ((time-now '(14 47)))
@@ -42,8 +44,8 @@
time-now)))))
(with-mock
(stub circadian-now-time => '(14 47 1))
- (circadian-activate-latest-theme)
- (should (equal 'tango (cl-first custom-enabled-themes))))
+ (circadian-setup)
+ (should (equal (list 'tango) custom-enabled-themes)))
;; After 23:59
(let ((time-now '(23 59)))
@@ -52,8 +54,8 @@
time-now)))))
(with-mock
(stub circadian-now-time => '(23 59 15))
- (circadian-activate-latest-theme)
- (should (equal 'adwaita (cl-first custom-enabled-themes))))
+ (circadian-setup)
+ (should (equal (list 'adwaita) custom-enabled-themes)))
;; Surpassing midnight
(let ((time-now '(0 2)))
@@ -62,45 +64,41 @@
time-now)))))
(with-mock
(stub circadian-now-time => '(0 2 10))
- (circadian-activate-latest-theme)
- (should (equal 'adwaita (cl-first custom-enabled-themes)))))
+ (circadian-setup)
+ (should (equal (list 'adwaita) custom-enabled-themes))))
-(ert-deftest test-circadian-activate-latest-theme ()
- "Test `circadian-activate-latest-theme' used in `circadian-setup'."
- ;; (print "→ TEST: circadian-activate-latest-theme")
+(ert-deftest test-circadian-setup ()
+ "Test `circadian-setup'."
(setq circadian-themes '(("7:00" . wombat)
("16:00" . tango)))
(with-mock
(stub circadian-now-time => '(7 21 0))
- (circadian-activate-latest-theme)
- (should (equal 'wombat (cl-first custom-enabled-themes))))
+ (circadian-setup)
+ (should (equal (list 'wombat) custom-enabled-themes)))
(with-mock
(stub circadian-now-time => '(17 0 0))
- (circadian-activate-latest-theme)
- (should (equal 'tango (cl-first custom-enabled-themes)))))
+ (circadian-setup)
+ (should (equal (list 'tango) custom-enabled-themes))))
(ert-deftest test-circadian-sunrise-sunset ()
"Test :sunrise and :sunset keywords for theme switching.
@TODO currently failing, needs a fix"
- (setq calendar-latitude 49.329896)
- (setq calendar-longitude 8.570925)
- (setq circadian-themes '((:sunrise . wombat)
- (:sunset . adwaita)))
- (circadian-setup)
-
(with-mock
- (stub circadian-now-time => '(14 21 0))
- (circadian-activate-latest-theme)
- (should (equal 'wombat (cl-first custom-enabled-themes))))
+ (setq calendar-latitude 49.329896)
+ (setq calendar-longitude 8.570925)
+ (setq circadian-themes '((:sunrise . adwaita)
+ (:sunset . wombat)))
+ (stub circadian-now-time => '(14 21 0))
+ (circadian-setup)
+ (should (equal 'adwaita (cl-first custom-enabled-themes)))
- (with-mock
- (stub circadian-now-time-string => '(16 50 0))
- (circadian-activate-latest-theme)
- (should (equal 'adwaita (cl-first custom-enabled-themes)))))
+ (stub circadian-now-time => '(22 30 0))
+ (circadian-setup)
+ (should (equal 'wombat (cl-first custom-enabled-themes)))))
@@ -121,10 +119,38 @@ Time A: 17:59
Time B: 17:58
B should be earlier than A
=> `circadian-a-earlier-b-p' should return t."
- ;; (print "→ TEST: time comparisons")
+ ;; (
(should (equal t (circadian-a-earlier-b-p '(7 50) '(7 51))))
(should (equal nil (circadian-a-earlier-b-p '(19 20) '(19 19))))
- (should (equal t (circadian-a-earlier-b-p '(20 20) '(20 20)))))
+ (should (equal t (circadian-a-earlier-b-p '(20 20) '(20 20))))
+
+ (with-mock
+ ;; tomorrow
+ (stub decode-time => '(0 30 16 28 4 2024 nil -1 nil))
+ (let* ((next-time (decode-time (circadian-encode-time 0 0)))
+ (next-day (nth 3 next-time))
+ (next-hour (nth 2 next-time)))
+ ;; today
+ (stub decode-time => '(0 30 14 28 4 2024 nil -1 nil))
+ (let* ((now (decode-time))
+ (day (nth 3 now))
+ (hour (nth 2 now)))
+ (should (> next-hour hour))
+ (should (equal day next-day)))))
+
+ (with-mock
+ ;; tomorrow
+ (stub decode-time => '(0 30 7 29 4 2024 nil -1 nil))
+ (let* ((next-time (decode-time (circadian-encode-time 0 0)))
+ (next-day (nth 3 next-time))
+ (next-hour (nth 2 next-time)))
+ ;; today
+ (stub decode-time => '(0 30 14 28 4 2024 nil -1 nil))
+ (let* ((now (decode-time))
+ (day (nth 3 now))
+ (hour (nth 2 now)))
+ (should (< next-hour hour))
+ (should (equal (+ 1 day) next-day))))))
@@ -146,7 +172,7 @@ B should be earlier than A
https://github.com/guidoschmidt/circadian.el/issues/27"
(setq calendar-latitude 79.482623)
(setq calendar-longitude 5.318703)
- (setq circadian-themes '((:sunrise . wombat)
+ (setq circadian-themes '((:sunrise . adwaita)
(:sunset . tango)))
(circadian-setup))
@@ -154,12 +180,12 @@ https://github.com/guidoschmidt/circadian.el/issues/27"
(defvar test-order '(member
test-circadian-filter-and-activate-themes
- test-circadian-activate-latest-theme
+ test-circadian-setup
test-circadian-sunrise-sunset
- test-circadian-sunrise-sunset-timezones
test-circadian-time-comparisons
test-circadian-setup-benchmark
- test-circadian-invalid-solar-sunrise-sunset))
+ test-circadian-invalid-solar-sunrise-sunset
+ test-circadian-sunrise-sunset-timezones))
(provide 'circadian.el-test)
;;; circadian.el-test.el ends here