dotfiles/emacs-lisp/org_agenda.org
Magic_RB bbaae4362b
Move Org Mode configuration from base.org into Org Roam files
Signed-off-by: Magic_RB <magic_rb@redalder.org>
2021-10-17 20:01:45 +02:00

151 lines
4.5 KiB
Org Mode

:PROPERTIES:
:ID: 22d678ce-7a3a-486c-abfb-f6cebdd77f90
:END:
#+title: Org Agenda
#+filetags: :project:emacs-load:
Put state changes into the ~LOGBOOK~ section and not into a random spot.
#+BEGIN_SRC emacs-lisp
(setq org-log-into-drawer t)
#+END_SRC
Set priority levels to A, B, and C.
#+BEGIN_SRC emacs-lisp :resutls none
(setq org-highest-priority ?A)
(setq org-default-priority ?B)
(setq org-lowest-priority ?C)
#+END_SRC
* Dynamic Org Agenda using Org Roam DB
#+BEGIN_NOTE
This whole system depends on [[id:a56794cf-b8f9-4537-a390-bd7ee6bb35ae][Vulpea]]
#+END_NOTE
#+BEGIN_SRC emacs-lisp :results none
(with-eval-after-load "vulpea"
#+END_SRC
First we have to exclude the =agenda= tag from inheritance.
#+BEGIN_SRC emacs-lisp :results none
(add-to-list 'org-tags-exclude-from-inheritance "project")
#+END_SRC
Then we need a function to check whether a buffer contains any todo entry.
#+BEGIN_SRC emacs-lisp :results none
(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))
#+END_SRC
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.
#+BEGIN_SRC emacs-lisp :results none
(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))
(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
(string-prefix-p
(expand-file-name (file-name-as-directory org-roam-directory))
(file-name-directory buffer-file-name))))
#+END_SRC
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.
#+BEGIN_SRC emacs-lisp :results none
(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\"%"))]))))
#+END_SRC
Finally we can update the list of project files before every =org-agenda= invocation.
#+BEGIN_SRC emacs-lisp :results none
(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)
#+END_SRC
** Migration
To migrate existing org-roam files to this new system, run this elisp code.
#+BEGIN_SRC emacs-lisp :results none :tangle no
(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)))
#+END_SRC
#+BEGIN_SRC emacs-lisp :results none :exports none
)
#+END_SRC
* Custom Tags
Define a number of custom tags to ease organisation.
#+BEGIN_SRC emacs-lisp :results none
(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")))))
#+END_SRC
** TODO Come up with more templates