Compare commits

...

3 Commits

3
.gitignore vendored

@ -1,6 +1,7 @@
# emacs buffers and backup files
**/*~
**/*#
**/#*#
**/.#*
# target and buildfiles
tacc-*.tar

@ -0,0 +1,31 @@
# tacc.el
## A pomidoro timer for emacs
tacc implements a slightly modified pomidoro timer with a focus on customizability. Sometimes all you need is a timer to make the pomidoro method work. By default this is just that, a 30 minute timer with a 5 minute break and the option to tag you work session. It can also be easily modified to add or subtract time from each successive work and break cycle and with slightly more effort can be made to process and record your timer stats.
## Customization
In `M-x customize` both the timer's appearence and behavior can be customized in `Applications` under the group `Tacc`. These can also all be set in your `init.el`, just be aware that `customize` renders a lisp symbol name like `tacc-work-seconds` as "Tacc Work Seconds"
The root customization dictates the timer length and can be used to set the increment in seconds. As a small bonus to readability, if you set these values in your `init.el` a function `(m:s 1 30)` can for example be used instead of `90`.
Under the `tacc-behavior` group there are a number of hook and function customizations. These are best to set in your `init.el`, since you can define your functions next to where you `(add-hook)`.
## Serialization and Record Keeping
If you want to keep a record of your work and break times you can! The catch is that you need to code it yourself.
Here's a simple example. It doesn't do much, but hopefully it's instructive.
```lisp
(tacc-register-serialization "json" json-serialize)
(add-hooks 'tacc-json-output-functions (lambda (m) (message "%s" m)))
```
The first call generates a binding for a set of output functions, in this case named `tacc-json-output-functions`. All functions in that hook will be fed the result of calling `json-serialize` on a list of time records.
Time records are laid out in an alist format as follows:
```lisp
(:ts . <unix timestamp>)
(:end . <unix timestamp>)
(:state . <'break | 'work>)
(:tag . <an assigned tag name>)
```

@ -1,3 +1,4 @@
;;; -*- lexical-binding: t -*-
;;; tacc.el --- A pomidoro timer supporting tags and customizable export
;; Author: Brady McDonough <me@bradymcd.ca>
@ -47,16 +48,13 @@
;; 10 Provides
;;; Code:
;;; -*- lexical-binding: t -*-
;; TODOS:
;; ERROR: mapconcat doesn't seem to respect lexical binding which leaves me unable to use a closure for a ticker
;; For now the code which relies on this will be noop'd
;; BUG : Countdown was ??? because 0 doesn't default to zero but "now".
;; That does leave an edgecase in the countdown display I'll need to explicitly check for
;; ERROR: timer shutdown seems to leave things in a wrong state and buffer doesn't die properly
;; Check on the logic of push-current, needs predicates rather than lazy if conditions
;; I'm not calling anything to destroy the buffer on desched
;; BUG: The buffer is immortal?
;;
;; Optional
(require 'icicles nil t)
@ -94,15 +92,15 @@
"The length of a base pomodoro round"
:type 'integer :group 'tacc)
(defcustom tacc-work-seconds-increment (m:s 5 0)
(defcustom tacc-work-seconds-increment 0
"The time to add to each successive work cycle"
:type 'integer :group 'tacc)
(defcustom tacc-break-seconds (m:s 7 0)
(defcustom tacc-break-seconds (m:s 5 0)
"The length of a base break round"
:type 'integer :group 'tacc)
(defcustom tacc-break-seconds-increment (m:s 1 30)
(defcustom tacc-break-seconds-increment 0
"The time to add to each successive break cycle"
:type 'integer :group 'tacc)
@ -209,19 +207,17 @@ Each function must have no required arguments and return a list of strings"
:group 'tacc-behavior)
(defun tacc-play-sound-file-emacs (file)
"Play some file using an asynchronous subprocess"
"Play some file in a child emacs process"
(if (fboundp 'play-sound-internal)
(start-process "tacc-play-sound"
tacc-buffer-name
nil
(car command-line-args)
"-Q"
"--batch"
"--eval" (format "(play-sound-file \"%s\")" file))
(warn "Emacs lacks builtin sound support")))
(defcustom tacc-play-sound-file #'tacc-play-sound-file-emacs
"Function used to play sounds. Set to nil to disable sound.
It's best to use something asynchronous (like spawning a child emacs process)"
"Asyncronous function to play sounds. Set to nil to disable sound"
:type '(choice (const nil)
function)
:group 'tacc-behavior)
@ -284,13 +280,17 @@ registered" sym-name)
;; (cond ((eq state 'break) (setq ticker (1+ ticker)))
;; ( 't ticker)))))
(defvar tacc-info `((history . ())
(cycle . 0)
(work-ts . nil)
(break-ts . nil)
(end-ts . nil)
(state . work)
(tag . ""))
(defun tacc-info-initial ()
"Returns the initial state of tacc-info"
`((history . ())
(cycle . 0)
(work-ts . nil)
(break-ts . nil)
(end-ts . nil)
(state . stop)
(tag . "")))
(defvar tacc-info (tacc-info-initial)
"State information related to the timer")
(defvar tacc-timer nil
@ -391,7 +391,7 @@ Note, if there is no tacc-buffer then you shouldn't be touching tacc-info"
(if work-ts
(push `((ts . ,work-ts)
(end . ,(if (cdr break-ts)
(cdr break-ts)
(time-seconds (cdr break-ts))
(cdr end-ts)))
(state . work)
(tag . ,tag))
@ -549,20 +549,20 @@ float"
(tacc-insert-between
.graph-start .graph-end
(let-alist tacc-info
(tacc-tag-render .tag)
(let* ((start-s (time-to-seconds start-ts))
(est-s (time-to-seconds est-ts))
(count-s (time-to-seconds countdown))
(now-s (time-to-seconds now))
(end-s (if (< est-s now-s) now-s est-s))
(work-s (time-to-seconds .work-ts))
(break-s (time-to-seconds .break-ts))
(total (- end-s work-s))
(work-prop (/ (- (if (numberp break-s) break-s now-s) work-s) total))
(break-prop (/ (if (numberp break-s) (- now-s break-s) 0) total))
(void-prop (- 1 (+ work-prop break-prop))))
(tacc-graph-bar-render width work-prop break-prop void-prop))))))
(concat (tacc-tag-render .tag)
(let* ((start-s (time-to-seconds start-ts))
(est-s (time-to-seconds est-ts))
(count-s (time-to-seconds countdown))
(now-s (time-to-seconds now))
(end-s (if (< est-s now-s) now-s est-s))
(work-s (time-to-seconds .work-ts))
(break-s (time-to-seconds .break-ts))
(total (- end-s work-s))
(work-prop (/ (- (if (numberp break-s) break-s now-s) work-s) total))
(break-prop (/ (if (numberp break-s) (- now-s break-s) 0) total))
(void-prop (- 1 (+ work-prop break-prop))))
(tacc-graph-bar-render width work-prop break-prop void-prop)))))))
(defun tacc-new-graph-bar-render ()
(tacc-render-with-buffer

Loading…
Cancel
Save