(provide 'cce/dynamic-fast-agenda)Archive of this blog post about keeping the size of the org-agenda-files list as light as it can be
In my experience once I reached 1200 note files org-agenda constantly took more than 50 seconds to build rendering this tool completely useless. But then I realised that only 3% of those files actually contain any TODO entries so there is no need to traverse whole org-roam-directory!
This is a clever use of the org-roam APIs and database to automatically populate the Org-mode Agendas file list and has some really neat ideas which I'll integrate in to the CCE I think.
Without migrating out of Projects I have src_elisp{(length org-agenda-files)} {{{results(22)}}} files which are Project and Agendize tagged.
I use this to keep track of todo items in my org day-journal to split out work that needs to be done in my Agendas and not to lose track of long-term or low priority projects
It works by having a save-hook that adds or removes a Project filetag if there are any TODO items on the page and then there is a hook in the org-agenda functionality to use the org-roam database
org-element search and update
I might turn this off.
There is some really sharp code in here to use the Org Element API to search for TODO headlines and add a Project tag to the ROAM_TAGS org-roam metadata keyword:
(defun +org-notes-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."
(seq-find
(lambda (type)
(eq type 'todo))
(org-element-map
(org-element-parse-buffer 'headline)
'headline
(lambda (h)
(org-element-property :todo-type h)))))
(add-hook 'before-save-hook #'+org-notes-project-update-tag)
(defun +org-notes-project-update-tag ()
"Update PROJECT tag in the current buffer."
(when (eq major-mode 'org-mode)
(save-excursion
(goto-char (point-min))
(when (and (not (active-minibuffer-window))
(+org-notes-buffer-p))
(if (+org-notes-project-p)
(org-roam-tag-add '("Project"))
(org-roam-tag-remove '("Project")))))))
(defun +org-notes-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))))DONE Evaluate turning this off.
Note taken on \\ i think this works pretty well now that i have it working...
State "DONE" from "NEXT" I'm not sure I want this on by default but it seems nice and great to have documented lying around.
org-agenda-list updating
a query against the org-roam tags table is unfortunately un-normalized. I want to add Agendize roam tag to it as well and since it's non-normal and I think unsorted in the DB i need to be careful about it. Finally remove files tagged Icebox. it basically works though:
(defun cce/org-roam-tags-for-file (file)
(org-roam-db-query [:select [tag] :from tags
:inner :join nodes :on (= node-id id)
:where (= file $s1)]
file))
(defun cce/org-roam-files-for-tag (tag)
(org-roam-db-query [:select [file] :from tags
:inner :join nodes :on (= node-id id)
:where (= tag $s1)]
tag))
(defun cce/org-roam-files-with-tags (&optional tags exclusion)
"Return a list of note files containing Project tag."
(let ((tags (or tags '("Project" "Agendize")))
(exclusion (or exclusion '("Icebox")))
(filter-fn (lambda (file)
(not (-intersection
(apply #'append (cce/org-roam-tags-for-file file))
exclusion)))))
(thread-last tags
(mapcar #'cce/org-roam-files-for-tag)
(apply #'append)
(seq-filter filter-fn))))and an advice function to update the DB before showing the agenda:
(defun cce/agenda-files-update (&rest _)
"Update the value of `org-agenda-files'."
(setq org-agenda-files (cce/org-roam-files-with-tags)))
(advice-add 'org-agenda :before #'cce/agenda-files-update)Tasks
DONE extend this to include Journal tasks!
State "DONE" from "NEXT"
Note taken on \\ those should have a ROAM_TAG anyways.......