Merge branch 'org-manual' into dev

This commit is contained in:
contrapunctus 2021-05-31 01:26:25 +05:30
commit bdae4e0245
4 changed files with 328 additions and 218 deletions

215
README.md
View File

@ -1,215 +0,0 @@
[![MELPA](https://melpa.org/packages/chronometrist-badge.svg)](https://melpa.org/#/chronometrist)
# chronometrist
A time tracker in Emacs with a nice interface
Largely modelled after the Android application, [A Time Tracker](https://github.com/netmackan/ATimeTracker)
* Benefits
1. Extremely simple and efficient to use
2. Displays useful information about your time usage
3. Support for both mouse and keyboard
4. Human errors in tracking are easily fixed by editing a plain text file
5. Hooks to let you perform arbitrary actions when starting/stopping tasks
* Limitations
1. No support (yet) for adding a task without clocking into it.
2. No support for concurrent tasks.
**IMPORTANT: with version v0.3, chronometrist no longer uses timeclock as a dependency and will use its own s-expression-based backend. A command to migrate the timeclock-file, `chronometrist-migrate-timelog-file->sexp-file`, is provided.**
## Comparisons
### timeclock.el
Compared to timeclock.el, Chronometrist
* stores data in an s-expression format rather than a line-based one
* supports attaching tags and arbitrary key-values to time intervals
* has commands to shows useful summaries
* has more hooks (see [Hooks](#Hooks))
### Org time tracking
Chronometrist and Org time tracking seem to be equivalent in terms of capabilities, approaching the same ends through different means.
* Chronometrist doesn't have a mode line indicator at the moment. (planned)
* Chronometrist doesn't have Org's sophisticated querying facilities. (an SQLite backend is planned)
* Org does so many things that keybindings seem to necessarily get longer. Chronometrist has far fewer commands than Org, so most of the keybindings are single keys, without modifiers.
* Chronometrist's UI makes keybindings discoverable - they are displayed in the buffers themselves.
* Chronometrist's UI is cleaner, since the storage is separate from the display. It doesn't show tasks as trees like Org, but it uses tags and key-values to achieve that. Additionally, navigating a flat list takes fewer user operations than navigating a tree.
* Chronometrist data is just s-expressions (plists), and may be easier to parse than a complex text format with numerous use-cases.
## Installation
### from MELPA
1. Set up MELPA - https://melpa.org/#/getting-started
(Chronometrist uses semantic versioning and only releases are pushed to the master branch, so using MELPA Stable is recommended and has no effect on frequency of updates.)
2. `M-x package-install RET chronometrist RET`
### from Git
You can get `chronometrist` from https://github.com/contrapunctus-1/chronometrist
`chronometrist` requires
* Emacs v25 or higher
* [dash.el](https://github.com/magnars/dash.el)
* [ts.el](https://github.com/alphapapa/ts.el)
The optional extension `chronometrist-key-values` requires `choice.el`, apart from `chronometrist` itself.
Add the "elisp/" subdirectory to your load-path, and `(require 'chronometrist)`.
## Usage
In the buffers created by the following three commands, you can press `l` (`chronometrist-open-log`) to view/edit your `chronometrist-file`, which by default is `~/.emacs.d/chronometrist.sexp`.
All of these commands will kill their buffer when run again with the buffer visible, so the keys you bind them to behave as a toggle.
### chronometrist
Run `M-x chronometrist` to see your projects, the time you spent on them today, which one is active, and the total time clocked today.
Hit `RET` (`chronometrist-toggle-task`) on a project to start tracking time for it. If it's already clocked in, it will be clocked out. This command runs some [hooks](#Hooks), which are useful for a wide range of functionality (see [Adding more information](#adding-more-information-experimental) below). In some cases, you may want to skip running the hooks - use `M-RET` (`chronometrist-toggle-task-no-hooks`) to do that.
You can also hit `<numeric prefix> RET` anywhere in the buffer to toggle the corresponding project, e.g. `C-1 RET` will toggle the project with index 1.
Press `r` to see a weekly report (see `chronometrist-report`)
`chronometrist` keeps itself updated via an idle timer - no need to frequently press `g` to update.
### chronometrist-report
Run `M-x chronometrist-report` (or `chronometrist` with a prefix argument of 1, or press `r` in the `chronometrist` buffer) to see a weekly report.
Press `b` to look at past weeks, and `f` for future weeks.
`chronometrist-report` keeps itself updated via an idle timer - no pressing `g` to update.
### chronometrist-statistics
Run `M-x chronometrist-statistics` (or `chronometrist` with a prefix argument of 2) to view statistics.
Press `b` to look at past time ranges, and `f` for future ones.
### Attaching tags and key values
Part of the reason Chronometrist stores time intervals as property lists is to allow you to add tags and arbitrary key-values to them.
#### Tags
To be prompted for tags, add `chronometrist-tags-add` to any hook except `chronometrist-before-in-functions`, based on your preference (see [Hooks](#Hooks)). The prompt suggests past combinations you used for the current task, which you can browse with `M-p`/`M-n`. You can leave it blank by pressing `RET`, or skip the prompt just this once by pressing `M-RET` (`chronometrist-toggle-task-no-hooks`).
#### Key-value pairs
Similarly, to be prompted for key-values, add `chronometrist-kv-add` to any hook except `chronometrist-before-in-functions`. To exit the prompt, press the key it indicates for quitting - you can then edit the resulting key-values by hand if required. Press `C-c C-c` to accept the key-values, or `C-c C-k` to cancel.
### Prompt when exiting Emacs
If you wish to be prompted when you exit Emacs while tracking time, you can use this -
`(add-hook 'kill-emacs-query-functions 'chronometrist-query-stop)`
### Time goals/targets
If you wish you could define time goals for some tasks, and have Chronometrist notify you when you're approaching the goal, completing it, or exceeding it, check out the extension [chronometrist-goal.el](https://github.com/contrapunctus-1/chronometrist-goal/).
## Customization
See the Customize groups `chronometrist` and `chronometrist-report` for variables intended to be user-customizable.
### Hooks
Chronometrist currently has the following hooks -
1. `chronometrist-mode-hook`
2. `chronometrist-before-in-functions`
3. `chronometrist-after-in-functions`
4. `chronometrist-before-out-functions`
5. `chronometrist-after-out-functions`
6. `chronometrist-list-format-transformers`
7. `chronometrist-entry-transformers`
8. `chronometrist-file-change-hook`
The hooks whose names end with `-functions` are abnormal hooks - each function must accept exactly one argument, which is the name of the project which is being started or stopped, as a string.
`chronometrist-before-out-functions` is different from the other three, in that it runs until failure - the task will be clocked out only if all functions in this hook return `t`.
### Opening certain files when you start a task
An idea from the author's own init -
```elisp
(defun my-start-project (project)
(pcase project
("Guitar"
(find-file-other-window "~/repertoire.org"))
;; ...
))
(add-hook 'chronometrist-before-in-functions 'my-start-project)
```
### Reminding you to commit your changes
Another one, prompting the user if they have uncommitted changes in a git repository (assuming they use [Magit](https://magit.vc/)) -
```elisp
(autoload 'magit-anything-modified-p "magit")
(defun my-commit-prompt ()
"Prompt user if `default-directory' is a dirty Git repository.
Return t if the user answers yes, if the repository is clean, or
if there is no Git repository.
Return nil (and run `magit-status') if the user answers no."
(cond ((not (magit-anything-modified-p)) t)
((yes-or-no-p
(format "You have uncommitted changes in %S. Really clock out? "
default-directory)) t)
(t (magit-status) nil)))
(add-hook 'chronometrist-before-out-functions 'my-commit-prompt)
```
### Displaying the current time interval in the activity indicator
```elisp
(defun my-activity-indicator ()
(thread-last (plist-put (chronometrist-last)
:stop (chronometrist-format-time-iso8601))
list
chronometrist-events-to-durations
(-reduce #'+)
truncate
chronometrist-format-time))
(setq chronometrist-activity-indicator #'my-activity-indicator)
```
## Roadmap/Ideas
* Show details for time spent on a project when clicking on a non-zero "time spent" field (in both Chronometrist and Chronometrist-Report buffers).
### chronometrist
1. Use `make-thread` in v26 or the emacs-async library for `chronometrist-entries`/`chronometrist-report-entries`
2. Some way to update buffers every second without making Emacs unusable. (impossible?)
3. "Day summary" - for users who use the "reason" feature to note the specifics of their actual work. Combine the reasons together to create a descriptive overview of the work done in the day.
### chronometrist-statistics
1. Show range counter and max ranges; don't scroll past first/last time ranges
2. activity-specific - average time spent in $TIMEPERIOD, average days worked on in $TIMEPERIOD, current/longest/last streak, % of $TIMEPERIOD, % of active (tracked) time in $TIMEPERIOD, ...
3. general - most productive $TIMEPERIOD, GitHub-style work heatmap calendar, ...
4. press 1 for weekly stats, 2 for monthly, 3 for yearly
### Miscellaneous
1. README - add images
2. [-] Create test timelog file and UI behaviour tests
3. Use for `chronometrist-report-weekday-number-alist` whatever variables like `initial-frame-alist` use to get that fancy Custom UI for alists.
4. Multi-timelog-file support?
5. [inflatable raptor](https://github.com/MichaelMure/git-bug/#planned-features)
## Contributions and contact
Feedback and MRs are very welcome. 🙂
* [TODO.org](TODO.org) has a long list of tasks
* [doc/manual.org](doc/manual.org) contains an overview of the codebase, explains various mechanisms and decisions, and has a reference of definitions.
If you have tried using Chronometrist, I'd love to hear your experiences! Get in touch with the author and other Emacs users in the Emacs channel on the Jabber network - [xmpp:emacs@salas.suchat.org?join](https://conversations.im/j/emacs@salas.suchat.org) ([web chat](https://inverse.chat/#converse/room?jid=emacs@salas.suchat.org))
(For help in getting started with Jabber, [click here](https://xmpp.org/getting-started/))
## License
I dream of a world where all software is liberated - transparent, trustable, and accessible for anyone to use or improve. But I don't want to make demands or threats (e.g. via legal conditions) to get there.
I'd rather make a request - please do everything you can to help that dream come true. Please Unlicense as much software as you can.
Chronometrist is released under your choice of [Unlicense](https://unlicense.org/) or the [WTFPL](http://www.wtfpl.net/).
(See files [UNLICENSE](UNLICENSE) and [WTFPL](WTFPL)).
## Thanks
wasamasa, bpalmer, aidalgol, pjb and the rest of #emacs for their tireless help and support
jwiegley for timeclock.el, which we used as a backend in earlier versions
blandest for helping me with the name
fiete and wu-lee for testing and bug reports

1
README.org Symbolic link
View File

@ -0,0 +1 @@
manual.org

View File

@ -235,7 +235,9 @@ Some options and ideas -
* It might be easier to just have a 'remove last interval' (the operation I use undo for most often), so we don't reimplement an undo for SQLite.
3. [X] Enhanced tag/key-value prompt - before asking for tags/key-values, if the last occurence of task had tags/key-values, ask if they should be reused. y - yes, n - no (continue to usual prompts).
* [X] Show what those tags/key-values are, so the user knows what will be added.
4. [X] "Explain" command - show intervals for task today
4. [X] =chronometrist-details=
* "Explain" command - show intervals for task today
* "Day summary" - for users who use the "reason" feature to note the specifics of their actual work. Combine the reasons together to create a descriptive overview of the work done in the day.
5. [ ] Switch #4 between intervals and tag-combination breakdown
6. [ ] Magit/other VCS integration
* [ ] Add support for using key-values to point to a commit (commit hash + repo path?)
@ -255,11 +257,12 @@ Some options and ideas -
16. [ ] Ask existing users if they'd like to have a prop line added to =chronometrist-file=
* check if =chronometrist-sexp-mode= is active in the buffer
* offer to never ask again
16. Show details for time spent on a project when clicking on a non-zero "time spent" field (in both Chronometrist and Chronometrist-Report buffers).
** chronometrist-report [0%]
1. [ ] Show week counter and max weeks; don't scroll past first/last weeks
2. [ ] Highlight column of current day
3. [ ] Command to narrow report to specific project(s)
3. [ ] narrow to specific project(s)
4. [ ] Jump to beginning/end of data (keys B/F)
5. [ ] "Explain" command - show tag-combination-based breakdown
@ -384,10 +387,15 @@ Some options and ideas -
4. [ ] Tag-sensitive key suggestions, tag-sensitive value suggestions...?
* Might complicate things quite a bit.
* Lack of task-sensitive value suggestions (#3) is an inconsistency, because tags and keys are already task-sensitive. From that perspective, tag-sensitive key and value suggestions are a whole new can of worms.
6. Change precision of timestamps from seconds to minutes. (like Org)
5. Change precision of timestamps from seconds to minutes. (like Org)
6. Use =make-thread= in v26 or the emacs-async library for =chronometrist-entries=/=chronometrist-report-entries=
7. Some way to update buffers every second without making Emacs unusable. (impossible?)
** chronometrist-report [0%]
1. [ ] Add support for other locale weeks/weekday names
2. narrow to specific task - average time spent in $TIMEPERIOD, average days worked on in $TIMEPERIOD, current/longest/last streak, % of $TIMEPERIOD, % of active (tracked) time in $TIMEPERIOD, ...
3. general - most productive $TIMEPERIOD, GitHub-style work heatmap calendar, ...
4. press 1 for weekly stats, 2 for monthly, 3 for yearly
** chronometrist-goals [0%]
1. [ ] Colorize times in Chronometrist buffer

316
manual.org Normal file
View File

@ -0,0 +1,316 @@
#+TITLE: Chronometrist
#+SUBTITLE: An extensible time tracker for Emacs
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css" />
[[https://melpa.org/#/chronometrist][file:https://melpa.org/packages/chronometrist-badge.svg]]
* chronometrist
:PROPERTIES:
:CUSTOM_ID: chronometrist
:END:
A time tracker in Emacs with a nice interface
Largely modelled after the Android application, [[https://github.com/netmackan/ATimeTracker][A Time Tracker]]
** Benefits
1. Extremely simple and efficient to use
2. Displays useful information about your time usage
3. Support for both mouse and keyboard
4. Human errors in tracking are easily fixed by editing a plain text file
5. Hooks to let you perform arbitrary actions when starting/stopping tasks
** Limitations
1. No support (yet) for adding a task without clocking into it.
2. No support for concurrent tasks.
** Comparisons
:PROPERTIES:
:CUSTOM_ID: comparisons
:END:
*** timeclock.el
:PROPERTIES:
:CUSTOM_ID: timeclock.el
:END:
Compared to timeclock.el, Chronometrist
+ stores data in an s-expression format rather than a line-based one
+ supports attaching tags and arbitrary key-values to time intervals
+ has commands to shows useful summaries
+ has more hooks
*** Org time tracking
:PROPERTIES:
:CUSTOM_ID: org-time-tracking
:END:
Chronometrist and Org time tracking seem to be equivalent in terms of capabilities, approaching the same ends through different means.
+ Chronometrist doesn't have a mode line indicator at the moment. (planned)
+ Chronometrist doesn't have Org's sophisticated querying facilities. (an SQLite backend is planned)
+ Org does so many things that keybindings seem to necessarily get longer. Chronometrist has far fewer commands than Org, so most of the keybindings are single keys, without modifiers.
+ Chronometrist's UI makes keybindings discoverable - they are displayed in the buffers themselves.
+ Chronometrist's UI is cleaner, since the storage is separate from the display. It doesn't show tasks as trees like Org, but it uses tags and key-values to achieve that. Additionally, navigating a flat list takes fewer user operations than navigating a tree.
+ Chronometrist data is just s-expressions (plists), and may be easier to parse than a complex text format with numerous use-cases.
** Installation
:PROPERTIES:
:CUSTOM_ID: installation
:END:
*** from MELPA
:PROPERTIES:
:CUSTOM_ID: from-melpa
:END:
1. Set up MELPA - https://melpa.org/#/getting-started
(Chronometrist uses semantic versioning and only releases are pushed to the master branch, so using MELPA Stable is recommended and has no effect on frequency of updates.)
2. =M-x package-install RET chronometrist RET=
*** from Git
:PROPERTIES:
:CUSTOM_ID: from-git
:END:
You can get =chronometrist= from https://tildegit.org/contrapunctus/chronometrist
=chronometrist= requires
+ Emacs v25 or higher
+ [[https://github.com/magnars/dash.el][dash.el]]
+ [[https://github.com/alphapapa/ts.el][ts.el]]
The optional extension =chronometrist-key-values= requires =choice.el=, apart from =chronometrist= itself.
Add the "elisp/" subdirectory to your load-path, and =(require 'chronometrist)=.
** Usage
:PROPERTIES:
:CUSTOM_ID: usage
:END:
*** chronometrist
:PROPERTIES:
:CUSTOM_ID: chronometrist-1
:END:
Run =M-x chronometrist= to see your projects, the time you spent on them today, which one is active, and the total time clocked today.
Click or hit =RET= (=chronometrist-toggle-task=) on a project to start tracking time for it. If it's already clocked in, it will be clocked out.
You can also hit =<numeric prefix> RET= anywhere in the buffer to toggle the corresponding project, e.g. =C-1 RET= will toggle the project with index 1.
Press =r= to see a weekly report (see =chronometrist-report=)
*** chronometrist-report
:PROPERTIES:
:CUSTOM_ID: chronometrist-report
:END:
Run =M-x chronometrist-report= (or =chronometrist= with a prefix argument of 1, or press =r= in the =chronometrist= buffer) to see a weekly report.
Press =b= to look at past weeks, and =f= for future weeks.
*** chronometrist-statistics
:PROPERTIES:
:CUSTOM_ID: chronometrist-statistics
:END:
Run =M-x chronometrist-statistics= (or =chronometrist= with a prefix argument of 2) to view statistics.
Press =b= to look at past time ranges, and =f= for future ones.
*** chronometrist-details
*** common commands
In the buffers created by the previous three commands, you can press =l= (=chronometrist-open-log=) to view/edit your =chronometrist-file=, which by default is =~/.emacs.d/chronometrist.sexp=.
All of these commands will kill their buffer when run again with the buffer visible, so the keys you bind them to behave as a toggle.
All buffers keep themselves updated via an idle timer - no need to frequently press =g= to update.
*** Prompt when exiting Emacs
:PROPERTIES:
:CUSTOM_ID: prompt-when-exiting-emacs
:END:
If you wish to be prompted when you exit Emacs while tracking time, you can use this -
=(add-hook 'kill-emacs-query-functions 'chronometrist-query-stop)=
*** Time goals/targets
:PROPERTIES:
:CUSTOM_ID: time-goalstargets
:END:
If you wish you could define time goals for some tasks, and have Chronometrist notify you when you're approaching the goal, completing it, or exceeding it, check out the extension [[https://github.com/contrapunctus-1/chronometrist-goal/][chronometrist-goal.el]].
** How-to
:PROPERTIES:
:CUSTOM_ID: customization
:END:
See the Customize groups =chronometrist= and =chronometrist-report= for variables intended to be user-customizable.
*** How to attach tags to time intervals
:PROPERTIES:
:CUSTOM_ID: how-to-tags
:END:
1. Add =chronometrist-tags-add= to one or more of these hooks [fn:1] -
#+BEGIN_SRC emacs-lisp
(add-to-list 'chronometrist-after-in-functions 'chronometrist-tags-add)
(add-to-list 'chronometrist-before-out-functions 'chronometrist-tags-add)
(add-to-list 'chronometrist-after-out-functions 'chronometrist-tags-add)
#+END_SRC
2. clock in/clock out to trigger the hook.
The prompt suggests past combinations you used for the current task, which you can browse with =M-p=/=M-n=. You can leave it blank by pressing =RET=.
[fn:1] but not =chronometrist-before-in-functions=
*** How to attach key-values to time intervals
:PROPERTIES:
:CUSTOM_ID: how-to-key-value-pairs
:END:
1. Add =chronometrist-kv-add= to one or more of these hooks [fn:2] -
#+BEGIN_SRC emacs-lisp
(add-to-list 'chronometrist-after-in-functions 'chronometrist-kv-add)
(add-to-list 'chronometrist-before-out-functions 'chronometrist-kv-add)
(add-to-list 'chronometrist-after-out-functions 'chronometrist-kv-add)
#+END_SRC
To exit the prompt, press the key it indicates for quitting - you can then edit the resulting key-values by hand if required. Press =C-c C-c= to accept the key-values, or =C-c C-k= to cancel.
[fn:2] but not =chronometrist-before-in-functions=
*** How to skip running hooks/attaching tags and key values
Use =M-RET= (=chronometrist-toggle-task-no-hooks=) to clock in/out.
*** How to open certain files when you start a task
:PROPERTIES:
:CUSTOM_ID: open-certain-files-when-you-start-a-task
:END:
An idea from the author's own init -
#+BEGIN_SRC emacs-lisp
(defun my-start-project (project)
(pcase project
("Guitar"
(find-file-other-window "~/repertoire.org"))
;; ...
))
(add-hook 'chronometrist-before-in-functions 'my-start-project)
#+END_SRC
*** How to warn yourself about uncommitted changes
:PROPERTIES:
:CUSTOM_ID: uncommitted-changes
:END:
Another one, prompting the user if they have uncommitted changes in a git repository (assuming they use [[https://magit.vc/][Magit]]) -
#+BEGIN_SRC emacs-lisp
(autoload 'magit-anything-modified-p "magit")
(defun my-commit-prompt ()
"Prompt user if `default-directory' is a dirty Git repository.
Return t if the user answers yes, if the repository is clean, or
if there is no Git repository.
Return nil (and run `magit-status') if the user answers no."
(cond ((not (magit-anything-modified-p)) t)
((yes-or-no-p
(format "You have uncommitted changes in %S. Really clock out? "
default-directory)) t)
(t (magit-status) nil)))
(add-hook 'chronometrist-before-out-functions 'my-commit-prompt)
#+END_SRC
*** How to display the current time interval in the activity indicator
:PROPERTIES:
:CUSTOM_ID: current-time-interval-in-activity-indicator
:END:
#+BEGIN_SRC emacs-lisp
(defun my-activity-indicator ()
(thread-last (plist-put (chronometrist-last)
:stop (chronometrist-format-time-iso8601))
list
chronometrist-events-to-durations
(-reduce #'+)
truncate
chronometrist-format-time))
(setq chronometrist-activity-indicator #'my-activity-indicator)
#+END_SRC
** User's reference
All variables intended for user customization are listed here. They serve as the public API for this project for the purpose of semantic versioning. Any changes to these which require a user to modify their configuration are considered breaking changes.
1. =chronometrist-file=
2. =chronometrist-buffer-name=
3. =chronometrist-report-buffer-name=
4. =chronometrist-details-buffer-name=
5. =chronometrist-sexp-pretty-print-function=
6. =chronometrist-hide-cursor=
7. =chronometrist-update-interval=
8. =chronometrist-activity-indicator=
Buffer schemas
1. =chronometrist-schema=
2. =chronometrist-details-schema=
Hooks
1. =chronometrist-mode-hook=
2. =chronometrist-schema-transformers=
3. =chronometrist-row-transformers=
4. =chronometrist-before-in-functions=
5. =chronometrist-after-in-functions=
6. =chronometrist-before-out-functions=
7. =chronometrist-after-out-functions=
8. =chronometrist-file-change-hook=
9. =chronometrist-timer-hook=
** Contributions and contact
:PROPERTIES:
:CUSTOM_ID: contributions-and-contact
:END:
Feedback and MRs are very welcome. 🙂
+ [[file:TODO.org]] has a long list of tasks
+ [[file:doc/manual.org]] contains an overview of the codebase, explains various mechanisms and decisions, and has a reference of definitions.
If you have tried using Chronometrist, I'd love to hear your experiences! Get in touch with the author and other Emacs users in the Emacs channel on the Jabber network - [[https://conversations.im/j/emacs@salas.suchat.org][xmpp:emacs@salas.suchat.org?join]] ([[https://inverse.chat/#converse/room?jid=emacs@salas.suchat.org][web chat]])
(For help in getting started with Jabber, [[https://xmpp.org/getting-started/][click here]])
** License
:PROPERTIES:
:CUSTOM_ID: license
:END:
I dream of a world where all software is liberated - transparent, trustable, and accessible for anyone to use or improve. But I don't want to make demands or threats (e.g. via legal conditions) to get there.
I'd rather make a request - please do everything you can to help that dream come true. Please Unlicense as much software as you can.
Chronometrist is released under your choice of [[https://unlicense.org/][Unlicense]] or the [[http://www.wtfpl.net/][WTFPL]].
(See files [[file:UNLICENSE]] and [[file:WTFPL]]).
** Thanks
:PROPERTIES:
:CUSTOM_ID: thanks
:END:
wasamasa, bpalmer, aidalgol, pjb and the rest of #emacs for their tireless help and support
jwiegley for timeclock.el, which we used as a backend in earlier versions
blandest for helping me with the name
fiete and wu-lee for testing and bug reports