pomm.el

pomm.el

Implementation of Pomodoro and Third Time techniques for Emacs.

Features:

  • Managing the timer with the excellent transient.el.
  • Persistent state between Emacs sessions. The timer state isn’t reset if you close Emacs. If necessary, the state file can be synchronized between machines.
  • History. History of the timer can be stored 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.

Installation

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 pomm-third-time))

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.

Usage

Pomodoro

Run M-x pomm to open the transient buffer.

The listed commands are 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 continued with “s” / M-x pomm-start or stopped completely 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.

Third Time

Run M-x pomm-third-time to open the transient buffer for the Third Time technique.

Essentially, the technique is designed around the formula:

Time of break = 1/3 x Time of work.

I.e., you work as long as you want or need, and then take a break with the maximum duration of 1/3 of the time worked. If you take a shorter break, the remaining break time is saved and added to the next break within the same session. Here is a more detailed explanation.

The Third Time timer can have 2 states:

  • Stopped. Can be started with “s” or M-x pomm-third-time-start.
  • Running. Can be stopped with “S” or M-x pomm-third-time-stop. This resets the accumulated break time.

Use “b” or M-x pomm-third-time-switch to switch the current period type (work or break). If the break time runs out, the timer automatically switches to work.

Customization

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 and M-x customize-group pomm-third-time for more information.

Alerts

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)

Sounds

By default, sounds are disabled. Set pomm-audio-enabled to t to toggle them. Set pomm-audio-tick-enabled to t if you want the ticking sound.

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.

Modeline

If you want the timer to display in the modeline, activate the pomm-mode-line-mode minor mode.

Polybar module

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

State file location

To implement persistence between Emacs sessions, the package stores its state in the following files:

  • pomm-state-file-location, .emacs.d/pomm by default
  • pomm-third-time-state-file-location, /.emacs.d/pomm-third-time by default

Set these paths however like.

History

If you set the pomm-csv-history-file (and/or pomm-third-time-csv-history-file) variable, the package will log its history in CSV format. Just keep in mind that the parent directory has to exist.

The file for the Pomodoro technique has the following columns:

  • timestamp
  • status (stopped, paused or running, according to the usage section)
  • kind (work, short-break, long-break or nil)
  • iteration
  • context

The one for the Third Time technique has an extra column called break-time-remaining.

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.

Usage with org-clock

The package can be used with org-clock in the following way. Set up these two hooks:

(add-hook 'pomm-on-status-changed-hook #'pomm--sync-org-clock)
(add-hook 'pomm-third-time-on-status-changed-hook
	  #'pomm-third-time--sync-org-clock

Then, start the timer (either pomm or pomm-third-time) and org-clock-in, in whichever order. The package will call org-clock-out when a break starts and org-clock-in-last when it ends.

Setting pomm-org-clock-in-immediately to nil “defers” calling org-clock-in-last until after any command from the user (via post-command-hook). I’ve added this because I occasionally return to my PC a few minutes after the break ends, so I don’t want these minutes to show up in org-clock.

Also see this comment (#13) for an alternative approach.

Alternatives

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 + sounds
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 of 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 to Emacs interactive commands

Also take a look at org-pomodoro-third-time, which adapts org-pomodoro for the Third Time technique.

P.S.

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.