dotfiles/emacs-lisp/org_agenda.org
main dc4f6833d5
Emacs stuff
Signed-off-by: main <magic_rb@redalder.org>
2022-03-12 23:06:42 +01:00

4.8 KiB

Org Agenda

Put state changes into the LOGBOOK section and not into a random spot.

  (setq org-log-into-drawer t)

Set priority levels to A, B, and C.

  (setq org-highest-priority ?A)
  (setq org-default-priority ?B)
  (setq org-lowest-priority ?C)

Dynamic Org Agenda using Org Roam DB

This whole system depends on Vulpea

  (with-eval-after-load "vulpea"

First we have to exclude the agenda tag from inheritance.

  (add-to-list 'org-tags-exclude-from-inheritance "project")

Then we need a function to check whether a buffer contains any todo entry.

  (defun vulpea-project-p ()
    "Return non-nil if current buffer has any todo entry.

  TODO entries marked as done are ignored, meaning the this
  function returns nil if current buffer contains only completed
  tasks."
    (when (eq major-mode 'org-mode)
      (org-element-map
          (org-element-parse-buffer 'headline)
          'headline
        (lambda (h)
          (eq (org-element-property :todo-type h)
              'todo))
        nil 'first-match)))

Then we need a function which will check whether the current buffer contains any TODOs and if so, then add a roam tag to that file, so that we can easily get a list of all files with TODOs.

    (add-hook 'find-file-hook #'vulpea-project-update-tag)
    (add-hook 'before-save-hook #'vulpea-project-update-tag)

    (defun vulpea-project-update-tag ()
      "Update PROJECT tag in the current buffer."
      (when (and (not (active-minibuffer-window))
                 (vulpea-buffer-p))
        (message "2")
        (save-excursion
          (goto-char (point-min))
          (let* ((tags (vulpea-buffer-tags-get))
                 (original-tags tags))
            (if (vulpea-project-p)
                (setq tags (cons "project" tags))
              (setq tags (remove "project" tags)))

            ;; cleanup duplicates
            (setq tags (seq-uniq tags))

            ;; update tags if changed
            (when (or (seq-difference tags original-tags)
                      (seq-difference original-tags tags))
              (apply #'vulpea-buffer-tags-set tags))))))

    (defun vulpea-buffer-p ()
      "Return non-nil if the currently visited buffer is a note."
      (and buffer-file-name
           (or (string-prefix-p
                (expand-file-name (file-name-as-directory org-roam-directory))
                (file-name-directory buffer-file-name))
               (string-prefix-p
                (expand-file-name (file-name-as-directory "~/dotfiles/emacs-lisp"))
                (file-name-directory buffer-file-name)))))

Now for the second last function, we need to actually return the list of files containing the project tag, to be consumed by org-agenda.

  (defun vulpea-project-files ()
    "Return a list of note files containing 'project' tag." ;
    (seq-uniq
     (seq-map
      #'car
      (org-roam-db-query
       [:select [nodes:file]
        :from tags
        :left-join nodes
        :on (= tags:node-id nodes:id)
        :where (like tag (quote "%\"project\"%"))]))))

Finally we can update the list of project files before every org-agenda invocation.

  (defun vulpea-agenda-files-update (&rest _)
    "Update the value of `org-agenda-files'."
    (setq org-agenda-files (vulpea-project-files)))
  
  (advice-add 'org-agenda :before #'vulpea-agenda-files-update)

Migration

To migrate existing org-roam files to this new system, run this elisp code.

  (dolist (file (org-roam-list-files))
    (message "processing %s" file)
    (with-current-buffer (or (find-buffer-visiting file)
                             (find-file-noselect file))
      (vulpea-project-update-tag)
      (save-buffer)))

Custom Tags

Define a number of custom tags to ease organisation.

  (setq org-agenda-custom-commands
        '(("h" "Agenda and Home-related tasks"
           ((agenda "")
            (tags-todo "home")
            (tags "garden")))
          ("o" "Agenda and Office-related tasks"
           ((agenda "")
            (tags-todo "work")
            (tags "office")))
          ("i" "Agenda and School-related tasks"
           ((agenda "")
            (tags-todo "school")
            (tags "school")))))