Wai Hon's Blog

Distinguish Repeated Tasks in Org Agenda

2025-01-03 #emacs #org-mode

Problem: Repeated or Not?

In the Org agenda view, repeated and non-repeated tasks look identical. This similarity makes me hesitant to mark a task as DONE; if a task that should be recurring is missing its repeater (e.g., ++1w), it will disappear permanently from the agenda instead of being rescheduled.

It would be helpful if repeated tasks were visually distinct in the Org agenda, for example, by displaying the repeater interval (++1w) as part of the entry.

Solution: Setting the Prefix Format

org-agenda-repeat-prefix-compare.png

Thanks to a tip from yantar92 (the current Org maintainer), I was able to add the repeater to the Org agenda using org-agenda-prefix-format. The process involves three steps:

  • Shorten the scheduled leaders to make space for the repeater.
  • Add a function to retrieve the formatted repeater.
  • Include the new function in org-agenda-prefix-format.

This requires only a few lines of Elisp:

;; Shorten leaders to reserve space for the repeater.
(setq org-agenda-scheduled-leaders '("Sched." "S.%2dx"))
(setq org-agenda-deadline-leaders '("Deadl." "In%2dd" "D.%2dx"))

(defun my/org-agenda-repeater ()
  "Return the repeater string for the current agenda entry."
  (if (org-before-first-heading-p)
      "-------"  ; Align with the time grid
    (format "%5s: " (or (org-get-repeat) ""))))

;; Add `my/org-agenda-repeater' to the agenda prefix format.
(setcdr (assoc 'agenda org-agenda-prefix-format)
        " %i %-12:c%?-12t%s%(my/org-agenda-repeater)")

Alternatives

Using the Agenda Finalize Hook (Hacky)

Before learning about yantar92's tip, I used a hackier solution (gist):

  • Fetch the repeater using text properties associated with the agenda entry.
  • Use org-agenda-finalize-hook, which runs after the agenda view is built but before it is displayed, to insert the repeater string.

Using Column View (Cluttered)

Prior to that, I tried another solution using column view (M-x org-agenda-columns). This method involves setting the :COLUMNS: property to display the SCHEDULED date as a separate column.

org-agenda-columns-with-scheduled.png
(setq org-columns-default-format-for-agenda
      "%TODO %PRIORITY(Pri) %60ITEM(Task) %SCHEDULED")

While this approach works and is built-in, the resulting display is verbose and difficult to parse visually. This led me to seek a better solution with custom Elisp.