Nodeを挿入時に自動でTAGを追加する Emacs OrgMode OrgRoam
Org-roamでNodeをInsertした時にタグを引き継げないかと思って、 探していたら関連記事を見つけたので、参考にして実装してみた。
この記事では org-roam-node-insert にadviceしているが、現在この関数はRoamNodeを返さないようだ。
つまりそのままコピペするだけで動作しない。残念。
https://d12frosted.io/posts/2020-07-07-task-management-with-roam-vol4.html(defun org-roam-node-insert-wrapper (fn) "Insert a link to the note using FN. If inserted node has PEOPLE tag on it, tag the current outline accordingly." (interactive) (when-let* ((node (funcall fn)) ; ← この箇所でNodeを取得できない ...
post-node-insert-hook を利用する
org-roam-post-node-insert-hook という、今回の用途にぴったりのHookを見つけたのでこれを使うことにする。
おそらく引用記事の執筆時点では実装されていなかったのだろう。
記事では people タグがついている場合のみタグをInsertするようにしているが、
私はそれに関わらずタグを付与したい場合もあるので、別途 NODE_INSERT_WITH_TAGS というプロパティを用意して判定することにした。
ちなみに新しいプロパティをつける場合 ROAM_* prefixをつけるとroam-dbに保存されないので、それ以外のPrefixを使うこと。プチハマりした。
(defun my/org-roam-node-add-auto-tag (id _description)
"Insert node with tags. Node found with iD."
(interactive)
(when-let*
((node (org-roam-node-from-id id))
(tags (org-roam-node-tags node))
(prop (org-roam-node-properties node))
(inherit (assoc "NODE_INSERT_WITH_TAGS" prop)))
(save-excursion
(ignore-errors
(org-back-to-heading)
(org-set-tags
(seq-uniq
(append
tags
(org-get-tags nil t))))))))
(add-hook
'org-roam-post-node-insert-hook
#'my/org-roam-node-add-auto-tag)
;; (org-roam-node-insert)
同じようにCategoryを継承するためのHookも作った。冗長だが、まあ動くのでよし。
(defun my/org-roam-node-add-auto-category (id _description)
"Insert node with category as prop. Node found with iD."
(interactive)
(when-let*
((node (org-roam-node-from-id id))
(prop (org-roam-node-properties node))
(inherit (assoc "NODE_INSERT_WITH_CATEGORY" prop))
(category (cdr (assoc "CATEGORY" prop))))
(save-excursion
(ignore-errors
(org-back-to-heading)
(org-set-property "CATEGORY" category)))))
(add-hook
'org-roam-post-node-insert-hook
#'my/org-roam-node-add-auto-category)
;; (org-roam-node-insert)
completion-at-point に対応する
Nodeの挿入は completion-at-point による補完を使うこともできるが、先の方法では対応できない。
completion-at-point による挿入直後は roam:[Description] 形式でIDの解決を行うが、この時点ではまだ対応するNodeへのリンクにはなっていない。
これは before-save-hook で解決されるので、この変数を見れば org-roam-link-replace-all という関数が設定されていることがわかった。
さらに内部で各リンクごとに org-roam-link-replace-at-point が呼ばれているので、この関数に対して advice すればよさそうだ。
(defun my/org-roam-link-repalce-auto-tags-to-heading (old-func &rest args)
(apply old-func args)
(let* ((link (org-element-context))
(id (org-element-property :path link)))
(my/org-roam-node-add-auto-tag id nil)))
(advice-add
#'org-roam-link-replace-at-point
:around
#'my/org-roam-link-repalce-auto-tags-to-heading)