Home GitHub Patreon
Discussions RSS Twitter

Restrict agenda to multiple subtrees

The function org-agenda-set-restriction-lock is very useful for speeding up agenda when working on a specific project (implemented as a file or an Orgmode subtree). Personally, I use two agenda views, one "quick" with 5 simple sections and one "full" with 10 rather complicated sections.

The quick one lists all the actionable tasks, all the stuck tasks or notes that need to be processed and refiled. The full one lists all the tasks from the project, including hierarchical project dependencies, tasks on hold, bugs, waiting tasks and so on. The full view takes a lot more processing power and is not useful maybe 80% of the time when I simply want to find work to do next.

For the times when I want to get a complete overview over a project and do some light management or planning, I use the full agenda view.

One thing that kept bothering me was that the only option was to restrict to a file or a subtree, but nothing in between1, such as a region spanning multiple subtrees. Since I'm not a huge fan of nesting headers just for the sake of nesting (flatter structures and graphs are much nicer for organization).

Luckily, the function org-agenda-set-restriction-lock is fairly hackable. It uses overlays and markers for managing the restriction, so all we need to do is grab the current active region's bounds and set the org variables appropriately.

(defun my-org-agenda-set-restriction-lock (orig-fun &optional type)
  (if (not (use-region-p))
      ;; unless a region is active, use the original function for
      ;; cancel/file/subtree
      (funcall orig-fun type)
    ;; here we do approximately the same as subtree except find the
    ;; beginning of subtree at region's beginning and end of subtree
    ;; at region's end (could span multiple subtrees)
    (setq org-agenda-restrict (current-buffer))
    ;; use 'my-region to avoid potential future conflict
    (setq org-agenda-overriding-restriction 'my-region)
    (put 'org-agenda-files 'org-restrict
         (list (buffer-file-name (buffer-base-buffer))))
    (let ((beg (region-beginning))
          (end (region-end)))
      (save-excursion
        (goto-char beg)
        (org-back-to-heading t)
        (setq beg (point)))
      (save-excursion
        (goto-char end)
        (org-end-of-subtree t t)
        (setq end (point)))
      (move-overlay org-agenda-restriction-lock-overlay
                    beg
                    (if org-agenda-restriction-lock-highlight-subtree
                        end
                      (point-at-eol)))
      (move-marker org-agenda-restrict-begin beg)
      (move-marker org-agenda-restrict-end end))
    (message "Locking agenda restriction to region")
    (org-agenda-maybe-redo)))

(advice-add 'org-agenda-set-restriction-lock :around #'my-org-agenda-set-restriction-lock)

Footnotes:

1

While it is possible to restrict to a region from the org-agenda speed dial, I find it quite impractical and prefer to do the restrictions from the project's buffer


Published at: 2021-05-29 15:09 Last updated at: 2023-02-08 16:00
Found a typo? Edit on GitHub!