org.nvim

Weekly review (GTD)

Stability: experimental (org-extensions-stability)

review walks you through a GTD weekly review, one step at a time, in a floating window:

require("org").setup({ extensions = { review = {} } })

:Org review (action review, global key <prefix>W) starts the review, or resumes the one you left. The header shows the progress (a dot per step) and the step's title; the footer lists the keys. The default steps:

  inbox     Empty the inbox: the top-level entries of inbox (default
            default_notes_file), to refile, schedule, give a TODO state,
            delete or skip one by one
  stuck     Stuck projects, as the agenda finds them
            (agenda.stuck_projects, org-agenda)
  waiting   Entries in a waiting_keywords state (WAITING)
  overdue   Open entries scheduled or due before today, oldest first
  upcoming  Scheduled, due and dated entries of the next upcoming_days
            (14) days, repeaters included, in date order
  someday   Entries tagged or in a state of someday (:someday:,
            :maybe:, SOMEDAY, MAYBE)
  clock     The time clocked in the last clock_days (7) days, and the
            clock_top (10) entries it went to
  reflect   Questions (questions) answered in a note buffer

:Org review <step> jumps to a step by name or number (<Tab> completes the names), and :Org review restart drops an unfinished review and starts over.

Keys in the review window

  n  ]]        next step                      -> review_next
  p  [[        previous step                  -> review_prev
  <CR>         go to the entry (the review is paused), or answer the
               question under the cursor
  r            refile the entry (org-refile)
  s  S         schedule it / set a deadline (the date prompt)
  t            set its TODO state from a list
  d            delete it (asks first, confirm_delete)
  x            skip it: it is marked and the cursor moves on
  i            answer the question under the cursor
  R            refresh (collect the step's entries again)
  F            finish                         -> review_finish
  <Esc>  q     pause                          -> review_quit
Change them with keys (a key, a list, or false for none).

The entries are read from the agenda files, and every change is saved to its file right away. An entry is found again by a mark in its buffer, its ID, its line or, failing those, as the only entry with its title, level and outline path: when two entries could be meant, nothing is done and R lists them again. The entries of a builtin step are collected again only when an agenda file changed (or R). The progress (the step, the answers, what was skipped and the counts) is kept in state_file, so closing the window, going to an entry with <CR> or quitting Neovim pauses the review and :Org review picks it up again.

Finishing

F writes a review entry into a date tree of log_file (default "review.org" in org_directory; a week tree, log_tree_type): the time, what was done with the inbox, how many entries each step listed, the time clocked, and each answer under its question as a subheading. The text is indented for the entry's level when adapt_indentation is on, and an answer line starting with * gets a leading space so it can't become a headline. A new log file starts with its date tree, without the empty first line an Emacs date tree leaves. With capture_template set to a template key, the review is captured with that template instead, the summary being its initial text (%i), so it can be edited before it is stored. The saved progress is then forgotten.

Custom steps

steps lists the steps in order. An entry is a builtin name, a builtin with overrides ({ "waiting", title = "Blocked" }), a function returning the items of a new step, or a table:

steps = {
  "inbox",
  {
    name = "reading",
    title = "Reading list",
    description = "Anything worth reading next week?",
    items = function(ctx)
      local ql = require("org.extensions.ql")
      return ql.select(ctx.files, '(tags "read")', {
        action = function(hl)
          return { hl = hl, path = hl.file.filename, lnum = hl.line }
        end,
      })
    end,
    keys = { a = function(item, session) end },
  },
  "reflect",
}

items(ctx) returns { hl, path, lnum, info? } entries (info is shown after the title) or { text = "..." } lines; lines(ctx) adds text above them; keys are mapped while the step is shown. ctx has opts, today, now, files (the agenda files) and state.

Options

  steps             the steps (see above)
  inbox             inbox file(s) (nil: default_notes_file)
  waiting_keywords  { "WAITING" }
  someday           { tags = { "someday", "maybe" },
                      keywords = { "SOMEDAY", "MAYBE" } }
  upcoming_days     days of the "upcoming" step (14)
  clock_days        days summed by the "clock" step (7)
  clock_top         entries listed by the "clock" step (10)
  questions         the questions of the "reflect" step
  log_file          the review log (nil: "review.org" in org_directory)
  log_tree_type     "day", "week" (default) or "month"
  log_heading       heading of the logged review ("Weekly review")
  capture_template  finish with this capture template (nil)
  open_log          show the new log entry after finishing (true)
  confirm_delete    ask before deleting an entry (true)
  state_file        the saved progress
                      (stdpath("data")/org/review.json)
  width height    size of the window (96 x 30, clamped to the screen)
  border            its border ("rounded")
  keys              keys in the window (see above)