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)