Skip to content

Commit

Permalink
Merge pull request #8 from guidoschmidt/v0.3.0
Browse files Browse the repository at this point in the history
V0.3.0
  • Loading branch information
guidoschmidt committed Oct 22, 2017
2 parents 6412eca + 315b5af commit feec308
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 79 deletions.
7 changes: 4 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ matrix:
allow_failures:
- env: EMACS_VERSION=snapshot
env:
- EMACS_VERSION=24.3
- EMACS_VERSION=24.4
- EMACS_VERSION=24.5
- EMACS_VERSION=25.1
- EMACS_VERSION=25.2
- EMACS_VERSION=25.3
- EMACS_VERSION=snapshot
before_install:
# Configure $PATH: Executables are installed to $HOME/bin
Expand All @@ -30,7 +31,7 @@ install:
# Install your dependencies
- cask install
script:
# Run your tests
# Run tests
- cask exec ert-runner
# Byte-compile
- emacs -Q -batch -f batch-byte-compile circadian.el
- cask build
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Change Log:

### 0.3.0
- Implement configuration with keywords `:sunrise` and `:sunset`
- Rename `circadian-mapcar` to `circadian-mapc`
- Fixed time-comparison bug in
in `circadian-compare-time-strings`
- Renamed `circadian-compare-time-strings` to more appropriate name:
`circadian-a-earlier-b-p`

### 0.2.3
- Use -*- lexical-binding: t -*-
- Requiring cl-lib
- Prefixed cl function like `cl-first', `cl-remove-if'
- `mapcar' -> `mapc'
- Swapped argument order for `circadian-filter-inactivate-themes'
- Bugfix: load the last theme from `circadian-themes', when the first
time slot lies in the future

### 0.2.2
- Added testing (+ configuration for travis CI)
- Changed arguments of `circadian-filter-inactivate-themes' to accept
the current time string + themes asoc list due to gain testability
of that function with various time strings (see `tests/').

### 0.2.1
- Add function to load the latest overdue theme to `circadian-setup'

### 0.2.0
- nyx-theme and hemera-theme live in their own repos from now on:
nyx: https://github.com/GuidoSchmidt/emacs-nyx-theme
hemera: https://github.com/GuidoSchmidt/emacs-hemera-theme
- Use default themes for default configuration of `circadian-themes'
- Re-implemented configuration using associated list and timers
(thanks to Steve Purcell for pointing me into this direction)

### 0.1.0
- Initial release
- Variables for day/night hour
- Themes included: hemera-theme, nyx-theme
3 changes: 2 additions & 1 deletion Cask
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(source gnu)
(source melpa)

(package "circadian" "" "automatic theme-switching based on daytime")
(package "circadian" "0.3.0" "automatic theme-switching based on daytime")

(depends-on "ert-runner")
(depends-on "el-mock")
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,28 @@ and [nyx-theme](https://github.com/GuidoSchmidt/emacs-nyx-theme) (with use-packa
(circadian-setup))
```

### Switch themes on sunrise & sunset
Be sure to set your latitude and longitude (Get them e.g. at [latlong.net](https://www.latlong.net/)):
```elisp
(use-package circadian
:load-path "~/.emacs.d/config/circadian/"
:ensure t
:config
(setq calendar-latitude 49.0)
(setq calendar-longitude 8.5)
(setq circadian-themes '((:sunrise . apropospriate-light)
("10:00" . hemera)
("19:30" . nyx)
(:sunset . nord)))
(circadian-setup))
```

**:warning: The preceding example features the following themes - make sure to have them
installed, before using them in circadian**
- [Apropospriate Theme](https://github.com/waymondo/apropospriate-theme)
- [Nord Theme](https://github.com/arcticicestudio/nord-emacs)

---

### Themes
Expand Down
135 changes: 82 additions & 53 deletions circadian.el
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
;; Author: Guido Schmidt
;; Maintainer: Guido Schmidt <guido.schmidt.2912@gmail.com>
;; URL: https://github.com/GuidoSchmidt/circadian
;; Version: 0.2.3
;; Version: 0.3.0
;; Keywords: circadian, themes
;; Package-Requires: ((emacs "24.4"))

Expand All @@ -27,64 +27,37 @@
;;; Commentary:
;; Circadian provides automated theme switching based on daytime.
;;
;; Example usage (with `use-package') featuring `nyx-theme' and `hemera-theme':
;; Example usage (with `use-package') - make sure to properly set your
;; latitude & longitude:
;;
;; (use-package circadian
;; :config
;; (setq circadian-themes '(("8:00" . hemera)
;; ("19:30" . nyx)))
;; (setq calendar-latitude 49.0)
;; (setq calendar-longitude 8.5)
;; (setq circadian-themes '((:sunrise . wombat)
;; ("8:00" . tango)
;; (:sunset . adwaita)
;; ("23:30" . tango)))
;; (circadian-setup))

;;; Change Log:
;; 0.2.3
;; - Use -*- lexical-binding: t -*-
;; - Requiring cl-lib
;; - Prefixed cl function like `cl-first', `cl-remove-if'
;; - `mapcar' -> `mapc'
;; - Swapped argument order for `circadian-filter-inactivate-themes'
;; - Bugfix: load the last theme from `circadian-themes', when the first
;; time slot lies in the future
;;
;; 0.2.2
;; - Added testing (+ configuration for travis CI)
;; - Changed arguments of `circadian-filter-inactivate-themes' to accept
;; the current time string + themes asoc list due to gain testability
;; of that function with various time strings (see `tests/').
;;
;; 0.2.1
;; - Add function to load the latest overdue theme to `circadian-setup'
;;
;; 0.2.0
;; - nyx-theme and hemera-theme live in their own repos from now on:
;; nyx: https://github.com/GuidoSchmidt/emacs-nyx-theme
;; hemera: https://github.com/GuidoSchmidt/emacs-hemera-theme
;; - Use default themes for default configuration of `circadian-themes'
;; - Re-implemented configuration using associated list and timers
;; (thanks to Steve Purcell for pointing me into this direction)
;;
;; 0.1.0
;; - Initial release
;; - Variables for day/night hour
;; - Themes included: hemera-theme, nyx-theme

;;; Code:
(require 'cl-lib)

(defcustom circadian-themes '(("7:30" . leuven)
(defcustom circadian-themes '(("7:30" . tango)
("19:30" . wombat))
"List of themes mapped to the time they should be loaded."
:type 'alist
:group 'circadian)

(defun circadian-enable-theme (theme)
"Clear previous `custom-enabled-themes' and load THEME."
(mapc 'disable-theme custom-enabled-themes)
(mapc #'disable-theme custom-enabled-themes)
(load-theme theme t))

(defun circadian-mapcar (entry)
(defun circadian-mapc (entry)
"Map over `circadian-themes' to run a timer for each ENTRY."
(let ((time (cl-first entry)))
(let ((theme (cdr (assoc time circadian-themes)))
(let ((time (circadian-match-sun (cl-first entry))))
(let ((theme (cdr entry))
(repeat-after 86400))
(run-at-time time repeat-after 'circadian-enable-theme theme))))

Expand All @@ -100,24 +73,30 @@

(defun circadian-compare-hours (hour-a hour-b)
"Compare two hours HOUR-A and HOUR-B."
(>= hour-a hour-b))
(> hour-a hour-b))

(defun circadian-compare-minutes (min-a min-b)
"Compare two minutes MIN-A and MIN-B."
(>= min-a min-b))

(defun circadian-compare-time-strings (time-a time-b)
(defun circadian-a-earlier-b-p (time-a time-b)
"Compare to time strings TIME-A and TIME-B by hour and minutes."
(let ((parsed-time-a (parse-time-string time-a))
(parsed-time-b (parse-time-string time-b)))
(and (circadian-compare-hours (cl-third parsed-time-b) (cl-third parsed-time-a))
(circadian-compare-minutes (cl-second parsed-time-b) (cl-second parsed-time-a)))))
(let ((hour-a (cl-third parsed-time-a))
(hour-b (cl-third parsed-time-b))
(minute-a (cl-second parsed-time-a))
(minute-b (cl-second parsed-time-b)))
(cond ((cl-equalp hour-b hour-a)
(circadian-compare-minutes minute-b minute-a))
(t (circadian-compare-hours hour-b hour-a))))))


(defun circadian-filter-inactivate-themes (theme-list now-time)
"Filter THEME-LIST to consist of themes that are due NOW-TIME."
(cl-remove-if (lambda (entry)
(let ((theme-time (cl-first entry)))
(not (circadian-compare-time-strings theme-time now-time))))
(let ((theme-time (circadian-match-sun (cl-first entry))))
(not (circadian-a-earlier-b-p theme-time now-time))))
theme-list))

(defun circadian-activate-latest-theme ()
Expand All @@ -126,16 +105,66 @@
(let ((entry (cl-first (last (circadian-filter-inactivate-themes
circadian-themes
(circadian-now-time-string))))))
(let ((time (cl-first entry)))
(let ((theme (cdr (assoc time circadian-themes))))
(if (equal theme nil)
(circadian-enable-theme (cdr (cl-first (last circadian-themes))))
(circadian-enable-theme theme))))))
(let ((theme (cdr entry)))
(if (equal theme nil)
(circadian-enable-theme (cdr (cl-first (last circadian-themes))))
(circadian-enable-theme theme)))))

;; --- Sunset-sunrise
(defun clean-string (string)
"Clean Emacs' STRING derived from `sunset-sunrise' result."
(replace-regexp-in-string " " "" (replace-regexp-in-string
"sun.[A-za-z]+" ""
(replace-regexp-in-string
"(CEST)" ""
string))))

(defun circadian-sunrise ()
"Get clean sunrise time string from Emacs' `sunset-sunrise'`."
(clean-string
(cl-first (split-string (sunrise-sunset) ","))))

(defun circadian-sunset ()
"Get clean sunset time string from Emacs' `sunset-sunrise'`."
(let ((sunset-string (clean-string (cl-second (split-string (sunrise-sunset) ",")))))
(replace-regexp-in-string " " "" (replace-regexp-in-string
"at.+" ""
sunset-string))))

(defun circadian-12-to-24h-offset (string)
"Match STRING for am/am and return the offset to 24h system."
(cond ((string-match-p "am" string)
0)
((string-match-p "pm" string)
12)
;; default
(t 0)))

(defun circadian-clear-12h-postfix (input)
"Remove am/pm post-fix from INPUT."
(replace-regexp-in-string ".m" "" input))

(defun circadian-parse-time-string (input)
"Parse INPUT and return corrected 24h time string."
(let ((splitted (split-string input ":"))
(add-hour (circadian-12-to-24h-offset input)))
(let ((hours (string-to-number (cl-first splitted)))
(minutes (circadian-clear-12h-postfix (cl-second splitted))))
(concat (number-to-string (+ hours add-hour)) ":" minutes))))

(defun circadian-match-sun (input)
"Match INPUT to a case for setting up timers."
(cond ((cl-equalp input :sunrise)
(circadian-parse-time-string (circadian-sunrise)))
((cl-equalp input :sunset)
(circadian-parse-time-string (circadian-sunset)))
((stringp input)
input)))

;;;###autoload
(defun circadian-setup ()
"Setup circadian based on `circadian-themes'."
(mapc 'circadian-mapcar circadian-themes)
(mapc 'circadian-mapc circadian-themes)
(circadian-activate-latest-theme))

(provide 'circadian)
Expand Down

0 comments on commit feec308

Please sign in to comment.