Some days might be busy, but at the end of the day you can't even remember if you got anything done. If you keep your Org mode files in a git repository, there's a way to get continuous feedback on whether or not you're getting stuff done.

Let's create a productivity-of-the-day function returning the total number of TODO statements that have either been added or removed from all agenda files. This is a pretty good proxy for productivity - or at least to see that there's a bit of progress throughout the day.

The code does the following:

  1. For any org-agenda-file, go to its base directory.
  2. Count the added or removed TODO statements for today using good old command-line tooling like:

    git log --since=yesterday -p ~/Dropbox/org/things.org \
     | grep TODO \
     | grep -E "^\+|^\-" \
     | wc -l
    
  3. For all org-agenda-files, aggregate this number and print the result.

Here's the code:

(defun count-lines-with-expression (s exp)
  "Count the number of lines in the string S that contain the regular expression EXP."
  (let ((count 0))
    (mapc (lambda (line)
	    (when (string-match-p exp line)
	      (setq count (+ 1 count))))
	  (split-string s "\n"))
    count))

(defun productivity-of-the-day ()
  (seq-reduce
   (lambda (acc it)
     (let* ((folder (file-name-directory it))
	    (file (file-name-nondirectory it))
	    (base-cmd (concat "cd "
			      folder
			      "; git log --since=midnight -p "
			      file
			      "| grep TODO"))
	    (changed (shell-command-to-string base-cmd))
	    (added (count-lines-with-expression changed "^\\+"))
	    (removed (count-lines-with-expression changed "^\\-")))
       (cons (+ (car acc) added)
	     (- (cdr acc) removed))))
   org-agenda-files
   '(0 . 0)))

You can then show this number in a convenient place - for example, in the Emacs modeline. Personally, I show it in the status bar (polybar) of my window manager (i3). Here's what it looks like:

This is done by calling emacsclient in a custom module:

[module/productivity]
type = custom/script
exec = echo 💪 `emacsclient -a "" --eval "(productivity-of-the-day)"`

If you're new to calling Emacs functions from the command-line or other scripts, we've got you covered. Here's a blog post outlining this in detail.

Happy hacking!

P.S.: Don't conflate quantity with quality.


If you liked this post, please consider supporting our Free and Open Source software work – you can sponsor us on Github and Patreon or star our FLOSS repositories.