redoakprof · 2022-08-11 23:03
Hi - how can you search for tagless headings (headings without any tags added) in org files? All the search options/functions I can find allow filtering or selection by specific tags, but I can't find a :no-tag or similar to use as argument
(my org roam daily workflow involves tagging headlines by topic, sometimes i miss the tag on capturing the note, so want to go back and file all notes (headings within files) that don't have tags)
thank you!
dm_g · 2022-08-12 04:40
if you can write some emacs-lisp you can write two queries using org-ql:
\- one for all headings
\- one for headings without tags
and compute the difference.
organic-bookworm · 2022-08-12 15:52
Define a filter function
(defun my/org-roam-node-filter-no-tags (node)
(null (org-roam-node-tags node)))
Define a custom command to find existing nodes without capturing
(defun my/org-roam-node-find-no-tags ()
(interactive)
(org-roam-node-visit
(org-roam-node-read nil #'my/org-roam-node-filter-no-tags nil t)))
Or wrap `org-roam-node-find` command to also allow capturing new nodes
(defun my/org-roam-node-find-no-tags ()
(interactive)
(org-roam-node-find nil nil #'my/org-roam-node-filter-no-tags))
redoakprof · 2022-08-12 16:58
>(defun my/org-roam-node-filter-no-tags (node)
(null (org-roam-node-tags node)))
>
>Define a custom command to find existing nodes without capturing
>
>(defun my/org-roam-node-find-no-tags ()
(interactive)
(org-roam-node-visit
(org-roam-node-read nil #'my/org-roam-node-filter-no-tags nil t)))
>
>Or wrap org-roam-node-find command to also allow capturing new nodes
>
>(defun my/org-roam-node-find-no-tags ()
(interactive)
(org-roam-node-find nil nil #'my/org-roam-node-filter-no-tags))
thank you! appreciate it - though I think this is picking up the nodes and not the individual headlines within each node - i manage org roam dailies with a node ID for each day, but then have multiple headlines under each node. those headlines are tagged with the topics (or are left tagless - and it's those I'm trying to find)
and it would be ok to have results buffer listing the files in which there are tagless headings
organic-bookworm · 2022-08-12 19:33
> multiple headlines under each node.
Oh, I see.
I would probably use `org-ql` here.
Use an `org-agenda`-like UI
(defun my/org-roam-dailies-find-no-tags ()
(interactive)
(org-ql-search #'org-roam-dailies--list-files
'(not (or (property "ID") (property "TAGS")))))
Use a `completing-read` UI
(defun my/org-roam-dailies-find-no-tags ()
(interactive)
(org-ql-find (org-roam-dailies--list-files)
:query-prefix "!property:ID !property:TAGS"))
redoakprof · 2022-08-13 11:15
>(defun my/org-roam-dailies-find-no-tags ()
Alright! Thank you very much. Got this working. Revised to the below, found that needed to exclude the parent folder name from the list of files and `directory-files-no-dot-files-regexp` made it work. Below is final code:
(defun ql-org-roam-dailies-find-no-tags ()
(interactive)
(org-ql-search (directory-files "~/OrgFiles/OrgRoam/daily" nil directory-files-no-dot-files-regexp)
'(not (or (property "ID") (property "TAGS")))))
Generates a list of the headings in files that have no explicit tags. Headlines with inherited tags but no explicit tags are still listed, but that's no problem as I need to clean up those errant `FILETAGS` entries anyway.
Only thing I've found: I have my entire Org file structure in a git repo and projectile picks it up as a project. The function above *only* works properly if I have an actual file in the `.../daily` folder open. Not a problem for me to do that, but not sure why it's required.
Now playing with :super-groups to get more helpful results formatting.
organic-bookworm · 2022-08-13 11:48
>The function above only works properly if I have an actual file in the `.../daily` folder open.
You use file names relative to "~/OrgFiles/OrgRoam/daily".
Try `(directory-files "~/OrgFiles/OrgRoam/daily" t directory-files-no-dot-files-regexp)`.
redoakprof · 2022-08-13 13:45
>Try
>
>(directory-files "\~/OrgFiles/OrgRoam/daily" t directory-files-no-dot-files-regexp)
>
>.
Bingo. That fixed it.
Got another function working to filter by user input tag as well:
(defun my-read-tag-with-completion ()
(interactive)
(completing-read "Enter a tag: " (org-get-buffer-tags)))
(defun ql-org-roam-dailies-find-by-user-tag ()
(interactive)
(set 'user-tag (my-read-tag-with-completion))
(org-ql-search (directory-files "~/OrgFiles/OrgRoam/daily" t directory-files-no-dot-files-regexp)
'(tags user-tag)
:super-groups '((:auto-category t))))
Thanks for all the help! This has been on my to-do list for months, and now means I can clean up all the prior files.
EDIT: actually, the above function works only first time around, there's some issue with persistence in the results buffer even if killed after first execution. Solve another time.