dotfiles/emacs-lisp/org_agenda.org
Magic_RB ebbc878087
Update emacs packages and fix some Org Agenda issues
Signed-off-by: Magic_RB <magic_rb@redalder.org>
2021-11-21 16:19:06 +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."
    (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."
      (message "%s" (vulpea-buffer-p))
      (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")))))