Building an Org-mode Workflow: Scheduling and Deadlines

by Jeff Bradberry

As I mentioned at the end of part 2, I want to schedule things I need to do on the calendar. So, this week I explored the deadlines and scheduling features.

Usage

There are two types of these timestamps that you can give to your agenda items — schedules and deadlines. Schedules are for events that happen at a particular time, or for when you want to set aside time to work on something particular. Deadlines are exactly what they sound like — a date and/or time something is due by. Both of these seem to behave nearly identically, and you can apply either type or both at the same time to an item.

In order to apply one of these timestamps to an item, use C-c C-s for a schedule, or C-c C-d for a deadline. This will open up a little calendar frame, and will request input in the mini-buffer.

Org-mode schedule input calendar frame and mini-buffer

This prompt is fairly intelligent about what date and time specifications it will take.

When complete, the result will show up as an all-caps keyword immediately under the headline. It must be the next line, with no other lines between it and the task it applies to.

* TODO Thing
  SCHEDULED: <2022-06-21 Tue>

* TODO Thing with a deadline
  DEADLINE: <2022-11-09 Wed>

* TODO Thing with both
  SCHEDULED: <2022-06-21 Tue> DEADLINE: <2022-11-09 Wed>

Once we start having tasks marked with timestamps, we can start using the weekly agenda view (C-c a a). This takes you into a view of the current week, and from there you can navigate to the previous or following weeks by pressing b or f. Each day of the week is shown, and scheduled items are shown under the day they are scheduled for. Deadlines on the other hand get a warning about how soon they are due, in addition to the actual date they fall under.

Week-agenda (W25):
Monday     20 June 2022 W25
  home:       In  10 d.:  TODO Replace water filter
  home:       In  11 d.:  TODO Pay bills
Tuesday    21 June 2022
  home:       14:00-15:00 Scheduled:  TODO foo bar baz
Wednesday  22 June 2022
Thursday   23 June 2022
Friday     24 June 2022
Saturday   25 June 2022
Sunday     26 June 2022

Another thing I was interested in was to have recurring tasks. This can be done by adding a 'cookie' to the end of your timestamp. The prompt doesn't seem to allow for including it in your original specification of the timestamp, but it is easy enough to manually edit it in afterwards.

The most basic of these repeater cookies uses a single + with an amount of time, e.g. +1m. This repeater will advance by exactly the specified time no matter the circumstances, past due or not.

before:

* TODO foo
  DEADLINE: <2022-07-01 Fri +1m>

* TODO bar
  DEADLINE: <2022-06-01 Fri +1m>

* TODO baz
  DEADLINE: <2022-05-01 Fri +1m>

after:

* TODO foo
  DEADLINE: <2022-08-01 Mon +1m>
  :PROPERTIES:
  :LAST_REPEAT: [2022-06-20 Mon 12:37]
  :END:
  - State "DONE"       from "TODO"       [2022-06-20 Mon 12:37]

* TODO bar
  DEADLINE: <2022-07-01 Fri +1m>
  :PROPERTIES:...
  - State "DONE"       from "TODO"       [2022-06-20 Mon 12:37]

* TODO baz
  DEADLINE: <2022-06-01 Wed +1m>
  :PROPERTIES:...
  - State "DONE"       from "TODO"       [2022-06-20 Mon 12:37]

Notice that overdue item baz is still overdue after marking it as complete. Under most circumstances I would think this isn't what you would want, so I'm not sure when I will actually use this version instead of the ones I'm about to talk about.

Each time you mark a recurring task as done it gets an entry under :PROPERTIES: and a timestamped note. This could potentially get bulky, but we'll deal with that presently. For the remaining examples I will show them with the properties and notes trimmed off to save space.

The next repeater cookie type uses a ++ in front of the time spec, e.g. ++2w. This will potentially cause the recurrence to advance multiple times until the result is in the future. This is so that if you complete something overdue enough that its next iteration would also be overdue, it will just skip ahead.

before:

* TODO foo
  DEADLINE: <2022-07-01 Fri ++1m>

* TODO bar
  DEADLINE: <2022-06-01 Fri ++1m>

* TODO baz
  DEADLINE: <2022-05-01 Fri ++1m>

after:

* TODO foo
  DEADLINE: <2022-08-01 Mon ++1m>

* TODO bar
  DEADLINE: <2022-07-01 Fri ++1m>

* TODO baz
  DEADLINE: <2022-07-01 Fri ++1m>

Seriously overdue item baz is now brought fully up to date, without needing to deal explicitly with the June 1st iteration. However, it still conforms to the day of month or weekday or whatever specification you originally gave the task.

Finally, there is the .+ repeater. This is for tasks where there isn't some hard external constraint on when each deadline is, and you want the result to be based on when you did the last iteration. I'm only going to give two examples here because the results will be the same regardless.

before:

* TODO foo
  DEADLINE: <2022-07-01 Fri .+1m>

* TODO bar
  DEADLINE: <2022-06-01 Fri .+1m>

after:

* TODO foo
  DEADLINE: <2022-07-20 Wed .+1m>

* TODO bar
  DEADLINE: <2022-07-20 Wed .+1m>

This is great for chores where there is some leeway on when they get done, e.g. replacing the A/C air filter.

I tend to like having a record of things, so I have enabled some settings that Org-mode provides to make sure changes to schedules or deadlines get a timestamped entry showing when the change happened: org-log-redeadline for changes to deadlines, and org-log-reschedule for changes to schedules. These seem like they would only rarely need to be examined, though, so I additionally enabled a setting (org-log-into-drawer) that causes these logs to be stashed into a drawer, named LOGBOOK by default.

This is my first use of Org-mode drawers, and I suspect that I'm going to want to use them more later on.

In addition to scheduling changes, this setting will also cause TODO state changes to be logged, but only if that state change would result in a note. See the entry in Settings for details.

I should note, however, that these settings will only cause an entry to be logged if you use the command or key binding to issue a new schedule or deadline, not if you edit the timestamp as text.

Before I wrap up, I have a couple of new usage patterns this week that do not fit the theme of schedules and deadlines:

I have discovered a more streamlined way of accessing my org files: C-' will cycle to the next org file, even if it isn't actually an open buffer. I'm finding this considerably handier than using C-x C-f or C-x b to pick out the file that I want next.

Also, I have discovered that it is possible to open an agenda view based on a search for an arbitrary string: C-c a s. This does supposedly also include regex searches, though I haven't tried that part out yet. Mostly I've been using this to quickly find tasks by ticket number. I can quickly get to the task at hand by pressing SPC (space) with my cursor on the item in the agenda view list to cause the upper panel to move to it, then q to quit out of the agenda view.

Settings

  • org-log-into-drawer: Folds all logged timestamp items into a drawer, by default LOGBOOK. In addition to rescheduling or changing deadlines, this will also include changes to the TODO state if
  • org-log-redeadline: Adds a timestamp to the log for this item when you change an existing deadline.
  • org-log-reschedule: Adds a timestamp to the log for this item when you change an existing schedule.

After these changes, my org-mode section in .emacs looks like this:

(global-set-key (kbd "C-c l") #'org-store-link)
(global-set-key (kbd "C-c a") #'org-agenda)
(global-set-key (kbd "C-c c") #'org-capture)

(setq org-agenda-files   (list "~/org/")
      org-refile-targets '((org-agenda-files :maxlevel . 5))
      org-refile-use-outline-path 'file
      org-log-into-drawer t
      org-log-done 'time
      org-log-redeadline 'time
      org-log-reschedule 'time
)

Note that I've moved org-log-done down to group it with these new settings, since its purpose is similar.

Key Bindings Learned

  • C-c C-s: Set a scheduled time for an entry.
  • C-c C-d: Set a deadline for an entry.
  • C-c a a: Show the agenda view for the current week.
    • f, b: Change the display to the next / previous week.
  • C-c a s: Put together an agenda view using a search.
  • Within agenda views
    • SPC: Immediately takes you to the item your cursor is on, without changing focus away from the agenda view panel.
    • q: Quit out of agenda views. Not really new, but wanted to reiterate it since this is a new agenda view.
  • C-': Cycle through your agenda files.
  • TAB: Can also be used to toggle the visibility of a drawer such as :LOGBOOK:. However, for drawers you have to place your cursor directly on the drawer when you press TAB.

Not exactly new to me, but the process of learning Org-mode these past few weeks has caused me to use them considerably more:

  • C-h v: Look up an Emacs variable in the manual.
  • C-h k: Look up an Emacs key binding in the manual.
  • C-h f: Look up an Emacs function in the manual.

And a not particularly related one that I needed this week:

  • C-x 8: Prefix for composing an accented character, e.g. C-x 8 ' e resulting in a 'é' character. You can see a list of these with C-x 8 C-h.

Next Steps

After three weeks of using Org-mode, it's becoming less clear what the next obvious need is that can easily be addressed. What I'm using now definitely feels like the low-hanging fruit. Having said that, though, there are a few things I could explore:

I have been writing quite large and complex notes in some of my subtrees for tasks at work. This is getting a bit bulky, and it might be worthwhile to explore whether stashing them in drawers is a good solution.

As our new release cycle starts up at work, I am going to start running into the need to break down tasks into a bunch of sub-tasks and check them off as well. This would likely be quite a short blog post, though.

Another possibility would be to double-down on logging things. There are a number of Org-mode features around doing timestamped notes that might be useful for me.