summaryrefslogtreecommitdiff
path: root/emacs/.config/emacs/lisp/kj-timer.el
blob: 204116e06871ffdfd0717267e7a72aba1832c779 (plain)
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
;;; kj-timer.el -- countdown timer -*- lexical-binding: t -*-

(defvar kj/current-timer nil)
(defvar kj/roster nil)
(defvar kj/timer-seconds)

(defun kj/display-timer (seconds current &optional next)
  (with-current-buffer (get-buffer-create "*timer*")
    (let* ((stopped (< seconds 0))
           (seconds (if stopped 0 (truncate seconds))))
      (erase-buffer)
      (insert
       (propertize (format "%02d:%02d" (/ seconds 60)
                           (% seconds 60))
                   'face
                   (append '(:height 1000)
                           (when stopped
                             '(:inherit 'org-imminent-deadline))))
       "\n" (propertize (concat current " · " (if next next "done"))
                        'face '(:foreground "gray" :height 500)))
      (set-left-margin (point-min) (point-max) 10))))

(defun kj/run-single-timer (seconds current next)
  (let* ((stop-time (+ (float-time) seconds))
         (display-fn (lambda ()
                       (kj/display-timer
                        (- stop-time (float-time))
                        current next))))
    (setq kj/current-timer (run-at-time t 0.5 display-fn))))

(defun kj/timer (seconds &rest roster)
  (with-current-buffer (get-buffer-create "*timer*")
    (display-buffer (current-buffer))
    (setq cursor-type nil)
    (use-local-map (define-keymap "SPC" 'kj/timer-next))
    (setq kj/roster roster)
    (setq kj/timer-seconds seconds)
    (kj/timer-next)))

(defun kj/timer-next ()
  (interactive)
  (unless kj/roster
    (error "The timers are done."))
  (when kj/current-timer
    (cancel-timer kj/current-timer))
  (kj/run-single-timer kj/timer-seconds (nth 0 kj/roster) (nth 1 kj/roster))
  (setq kj/roster (cdr kj/roster)))