Yet another implementation of a pomodoro timer for Emacs.
This particular package features:
- Managing the timer with the excellent transient.el.
- Persistent state between Emacs sessions. The timer state isn’t reset if you close Emacs. Also, the state file can be synchronized between machines.
- History. I’ve implemented an option to store the timer history in a CSV file. Eventually, I want to join this with other activity data to see if the state of the timer changes how I use the computer.
None of the available alternatives were doing quite what I wanted, and the idea of the timer is quite simple, so I figured I’d implement one myself.
The package is available on MELPA. Install it however you usually install Emacs packages, e.g.
M-x package-install pomm
My preferred way is use-package
with straight.el
:
(use-package pomm
:straight t
:commands (pomm))
If you want sounds before the MELPA recipe got updated to include resources, use:
(use-package pomm
:straight (:host github :repo "SqrtMinusOne/pomm.el" :files (:defaults "resources"))
:commands (pomm))
Or you can clone the repository, add the package to the load-path
and load it with require
:
(require 'pomm)
The package requires Emacs 27.1 because the time API of the previous versions is kinda crazy and 27.1 has time-convert
.
Run M-x pomm
to open the transient buffer.
The listed commands are rather self-descriptive and match the Pomodoro ideology.
The timer can have 3 states:
- Stopped. Can be started with “s” or
M-x pomm-start
. A new iteration of the timer will be started. - Paused. Can be continuted with “s” /
M-x pomm-start
or stopped competely with “S” /M-x pomm-stop
. - Running. Can be paused with “p” /
M-x pomm-pause
or stopped with “S” /M-x pomm-stop
.
The state of the timer can be reset with “R” or M-x pomm-reset
.
“u” updates the transient buffer. The update is manual because I didn’t figure out how to automate this, and I think this is not really necessary.
With “r” or M-x pomm-set-context
you can set the current “context”, that is some description of the task you are currently working on. This description will show up in history and in the csv file. Also, M-x pomm-start-with-context
will prompt for the context and then start the timer.
Some settings are available in the transient buffer, but you can customize the relevant variables to make them permanent. Check M-x customize-group
pomm
for more information.
The package sends alerts via alert.el
. The default style of alert is a plain message
, but if you want an actual notification, set alert-default-style
accordingly:
(setq alert-default-style 'libnotify)
By default sounds are disabled. Set pomm-audio-enabled
to t
to toggle them.
This functionality needs pomm-audio-player-executable
to be set so that the program could be invoked like: <executable> /path/to/sound.wav
.
The package ships with some built-it sounds, which you can replace by customizing the pomm-audio-files
variable.
If you want the timer to display in the modeline, activate the pomm-mode-line-mode
minor mode.
If you want to display the Pomodoro status in something like polybar, you can add the following lines to your config:
(add-hook 'pomm-on-tick-hook 'pomm-update-mode-line-string)
(add-hook 'pomm-on-status-changed-hook 'pomm-update-mode-line-string)
Create a script like this:
if ps -e | grep emacs >> /dev/null; then
emacsclient --eval "(if (boundp 'pomm-current-mode-line-string) pomm-current-mode-line-string \"\") " | xargs echo -e
fi
And add a polybar module definition to your polybar config:
[module/pomm]
type = custom/script
exec = /home/pavel/bin/polybar/pomm.sh
interval = 1
The package stores the current state to a file by the path pomm-state-file-location
, which is emacs.d/pomm
by default. Set it to wherever you like.
If you set the pomm-csv-history-file
variable, the package will write CSV with the usage history there. Just keep in mind that the parent directory has to exist.
The file has the following columns:
timestamp
status
(stopped
,paused
orrunning
, according to the usage section)kind
(work
,short-break
,long-break
ornil
)iteration
context
A new entry is written after a particular state of the timer comes into being.
To customize timestamp, set the pomm-csv-history-file-timestamp-format
variable. For example, for traditional YYYY-MM-DD HH:mm:ss
:
(setq pomm-csv-history-file-timestamp-format "%F %T")
The format is the same as in format-time-string
.
There is a number of packages with a similar purpose, here is a rough comparison of features:
Package | 3rd party integrations | Control method (1) | Persistent history | Persistent state | Notifications |
---|---|---|---|---|---|
pomm.el | - | transient.el | CSV | + | alert.el |
org-pomodoro | Org Mode! | via Org commands | via Org mode | - | alert.el + sounds |
pomidor | - | self-cooked interactive buffer | custom delimited format? | +, but saving on-demand | alert.el + sounds |
pomodoro.el | - | - | - | - | notifications.el + sounds |
tomatinho | - | self-cooked interactive buffer | - | - | message + sounds |
redtick | - | mode-line icon | + | - | sounds |
gtk-pomodoro-indicator | GTK panel | CLI | - | -, but the program is independent from Emacs | GTK notifications |
Be sure to check those out if this one doesn’t quite fit your workflow!
(1) Means of timer control with exception of Emacs interactive commands
The package name is not an abbreviation. I just hope it doesn’t mean something horrible in some language I don’t know.
The sounds are made by Mike Koening under CC BY 3.0.