Filter org-roam-node-{find, insert} using tags and folders

I wanted to filter out daily nodes and refs nodes so I wrote the following in my configuration. Hope it will help someone else out there.

(Btw I use Doom.)

(cl-defun my/org-roam-node--filter-by-tags (node &optional included-tags excluded-tags)
  "Filter org-roam-node by tags."
  (let* ((tags (org-roam-node-tags node))
         (file-path (org-roam-node-file node))
         (rel-file-path (f-relative file-path org-roam-directory))
         (parent-directories (butlast (f-split rel-file-path)))
         (tags (cl-union tags parent-directories)))
    (if (or
         ;; (and included-tags (cl-notevery (lambda (x) (cl-member x tags :test #'string=)) included-tags))
         (and included-tags (not (cl-intersection included-tags tags :test #'string=)))
         (and excluded-tags (cl-intersection excluded-tags tags :test #'string=))
         ) nil t)))

(cl-defun my/org-roam-node-find (included-tags excluded-tags)
  "Modded org-roam-node-find which filters nodes using tags."
  (interactive)
  (org-roam-node-find nil nil
                      (lambda (node) (my/org-roam-node--filter-by-tags node included-tags excluded-tags))))

(cl-defun my/org-roam-node-insert (included-tags excluded-tags)
  "Modded org-roam-node-insert which filters nodes using tags."
  (interactive)
  (org-roam-node-insert
   (lambda (node) (my/org-roam-node--filter-by-tags node included-tags excluded-tags))))

(map!
 :leader
 (:prefix ("r" . "org-roam")
  "f" #'(lambda () (interactive) (my/org-roam-node-find nil '("daily" "captures")))
  "i" #'(lambda () (interactive) (my/org-roam-node-insert nil '("daily" "captures")))
  "F" #'(lambda () (interactive) (my/org-roam-node-find '("daily" "captures") nil))
  "I" #'(lambda () (interactive) (my/org-roam-node-insert '("daily" "captures") nil)))
2 Likes

You can customize the node inclusion/exclusion by implementing the function org-node-node-inclusion-function, as explained in the What to cache section in the org-roam manual. So there is no need to override the functions.

But your code snippet inspired me to achieve the same, because I liked the directory-based tagging in org-roam v1. In my example, I would like to exclude all nodes in the daily directory:

  (setq my/org-roam-excluded-dirs '("daily"))
  
  (setq org-roam-db-node-include-function (lambda ()
                                            (let* ((file-path (buffer-file-name (buffer-base-buffer)))
                                                   (rel-file-path (f-relative file-path org-roam-directory))
                                                   (parent-directories (butlast (f-split rel-file-path))))
                                              (if (cl-intersection my/org-roam-excluded-dirs parent-directories :test #'string=) nil t))))

(thanks to Jethro for the nudge in the right direction)

2 Likes

Thanks for the information about org-node-node-inclusion-function!
However, I think our cases are slightly different. I wanted to filter out certain tags on demand while still keeping them in database so that I would still be able to access them whenever I need to. (eg. “nsfw” tag)

I’d love to your Aur3l14no’s function, too, but I use vanilla emacs. I don’t have enough lisp knowledge to rewrite it, buy I’m sure it’s not hard. Any1 out there?

I can’t test this but by a quick glance it appears that you don’t need doom for the functions. Make sure you have the f package. The map! is doom specific but you can use the built-in define-key for the keybindings.