mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
Update template syntax, allow capture directly to nodes
This commit is contained in:
@ -54,12 +54,10 @@ during the Org-roam capture process.")
|
|||||||
"Keywords used in `org-roam-capture-templates' specific to Org-roam.")
|
"Keywords used in `org-roam-capture-templates' specific to Org-roam.")
|
||||||
|
|
||||||
(defcustom org-roam-capture-templates
|
(defcustom org-roam-capture-templates
|
||||||
(list (list :key "d"
|
'(("d" "default" plain "%?"
|
||||||
:desc "default"
|
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
|
||||||
:body "%?"
|
"#+title: ${title}\n")
|
||||||
:if-new '(file+head "%<%Y%m%d%H%M%S>-${slug}.org"
|
:unnarrowed t))
|
||||||
"#+title: ${title}\n")
|
|
||||||
:unnarrowed t))
|
|
||||||
"Capture templates for Org-roam.
|
"Capture templates for Org-roam.
|
||||||
|
|
||||||
TODO: Document this"
|
TODO: Document this"
|
||||||
@ -68,12 +66,10 @@ TODO: Document this"
|
|||||||
)
|
)
|
||||||
|
|
||||||
(defcustom org-roam-capture-ref-templates
|
(defcustom org-roam-capture-ref-templates
|
||||||
(list (list :key "r"
|
'(("r" "ref" plain "%?"
|
||||||
:desc "ref"
|
:if-new (file+head "${slug}.org"
|
||||||
:body "%?"
|
"#+title: ${title}")
|
||||||
:if-new '(file+head "${slug}.org"
|
:unnarrowed t))
|
||||||
"#+title: ${title}")
|
|
||||||
:unnarrowed t))
|
|
||||||
"The Org-roam templates used during a capture from the roam-ref protocol.
|
"The Org-roam templates used during a capture from the roam-ref protocol.
|
||||||
Details on how to specify for the template is given in `org-roam-capture-templates'."
|
Details on how to specify for the template is given in `org-roam-capture-templates'."
|
||||||
:group 'org-roam
|
:group 'org-roam
|
||||||
@ -140,42 +136,27 @@ This function is to be called in the Org-capture finalization process."
|
|||||||
(insert (org-link-make-string (concat "id:" id)
|
(insert (org-link-make-string (concat "id:" id)
|
||||||
(org-roam-capture--get :link-description)))))))
|
(org-roam-capture--get :link-description)))))))
|
||||||
|
|
||||||
(defun org-roam-capture--finalize-create-id ()
|
(defun org-roam-capture--add-ref ()
|
||||||
"Get ID for newly captured information."
|
|
||||||
(let ((buf (org-capture-get :buffer))
|
|
||||||
(pos (org-capture-get :exact-position)))
|
|
||||||
(with-current-buffer buf
|
|
||||||
(org-with-point-at pos
|
|
||||||
(org-id-get-create)))))
|
|
||||||
|
|
||||||
(defun org-roam-capture--add-ref (ref)
|
|
||||||
"Add REF to the newly captured item."
|
"Add REF to the newly captured item."
|
||||||
(let ((buf (org-capture-get :buffer))
|
(when-let ((ref (org-roam-capture--get :ref)))
|
||||||
(pos (org-capture-get :exact-position))
|
(let ((ref-lst (org-entry-get (point) "ROAM_REFS")))n
|
||||||
ref-lst)
|
(setq ref-lst (if ref-lst
|
||||||
(with-current-buffer buf
|
(cl-pushnew (split-string-and-unquote ref-lst) ref)
|
||||||
(org-with-point-at pos
|
(list ref)))
|
||||||
(setq ref-lst (org-entry-get (point) "ROAM_REFS"))
|
(org-set-property "ROAM_REFS" (combine-and-quote-strings ref-lst)))
|
||||||
(setq ref-lst (if ref-lst
|
(org-roam-capture--add-ref ref)))
|
||||||
(cl-pushnew (split-string-and-unquote ref-lst) ref)
|
|
||||||
(list ref)))
|
|
||||||
(org-set-property "ROAM_REFS" (combine-and-quote-strings ref-lst))))))
|
|
||||||
|
|
||||||
(defun org-roam-capture--finalize ()
|
(defun org-roam-capture--finalize ()
|
||||||
"Finalize the `org-roam-capture' process."
|
"Finalize the `org-roam-capture' process."
|
||||||
(let ((region (org-roam-capture--get :region))
|
(when-let ((region (org-roam-capture--get :region)))
|
||||||
id)
|
(org-roam-unshield-region (car region) (cdr region)))
|
||||||
(when region
|
(unless org-note-abort
|
||||||
(org-roam-unshield-region (car region) (cdr region)))
|
|
||||||
(unless org-note-abort
|
(when-let ((finalize (org-roam-capture--get :finalize)))
|
||||||
(setq id (org-roam-capture--finalize-create-id))
|
(funcall (intern (concat "org-roam-capture--finalize-"
|
||||||
(when-let ((ref (org-roam-capture--get :ref)))
|
(symbol-name (org-roam-capture--get :finalize))))
|
||||||
(org-roam-capture--add-ref ref))
|
:id (org-roam-capture--get :id))))
|
||||||
(when-let ((finalize (org-roam-capture--get :finalize)))
|
(remove-hook 'org-capture-after-finalize-hook #'org-roam-capture--finalize))
|
||||||
(funcall (intern (concat "org-roam-capture--finalize-"
|
|
||||||
(symbol-name (org-roam-capture--get :finalize))))
|
|
||||||
:id id)))
|
|
||||||
(remove-hook 'org-capture-after-finalize-hook #'org-roam-capture--finalize)))
|
|
||||||
|
|
||||||
(defun org-roam-capture--install-finalize ()
|
(defun org-roam-capture--install-finalize ()
|
||||||
"Install `org-roam-capture--finalize' if the capture is an Org-roam capture."
|
"Install `org-roam-capture--finalize' if the capture is an Org-roam capture."
|
||||||
@ -184,48 +165,53 @@ This function is to be called in the Org-capture finalization process."
|
|||||||
|
|
||||||
(add-hook 'org-capture-prepare-finalize-hook #'org-roam-capture--install-finalize)
|
(add-hook 'org-capture-prepare-finalize-hook #'org-roam-capture--install-finalize)
|
||||||
|
|
||||||
(defun org-roam-capture--fill-template (str)
|
(defun org-roam-capture--fill-template (str &optional org-capture-p)
|
||||||
"Expand the template STR, returning the string.
|
"Expand the template STR, returning the expanded template. It expands ${var} occurrences in STR.
|
||||||
This is an extension of org-capture's template expansion.
|
When ORG-CAPTURE-P, also run Org-capture's template expansion."
|
||||||
|
(funcall (if org-capture-p #'org-capture-fill-template #'identity)
|
||||||
First, it expands ${var} occurrences in STR, using the node in
|
(s-format str
|
||||||
`org-roam-capture--info'. Next, it expands the remaining template
|
(lambda (key)
|
||||||
string using `org-capture-fill-template'."
|
(let ((fn (intern (concat "org-roam-node-" key))))
|
||||||
(org-capture-fill-template
|
(if (fboundp fn)
|
||||||
(s-format str
|
(funcall fn org-roam-capture--node)
|
||||||
(lambda (key)
|
p(completing-read (format "%s: " key) nil)))))))
|
||||||
(let ((fn (intern (concat "org-roam-node-" key))))
|
|
||||||
(if (fboundp fn)
|
|
||||||
(funcall fn org-roam-capture--node)
|
|
||||||
(completing-read (format "%s: " key) nil)))))))
|
|
||||||
|
|
||||||
(defun org-roam-capture--goto-location ()
|
(defun org-roam-capture--goto-location ()
|
||||||
"Initialize the buffer, and goto the location of the new capture."
|
"Initialize the buffer, and goto the location of the new capture.
|
||||||
|
Return the ID of the location."
|
||||||
(pcase (or (org-roam-capture--get :if-new)
|
(pcase (or (org-roam-capture--get :if-new)
|
||||||
(user-error "Template needs to specify `:if-new'"))
|
(user-error "Template needs to specify `:if-new'"))
|
||||||
(`(file ,path)
|
(`(file ,path)
|
||||||
(setq path (expand-file-name
|
(setq path (expand-file-name
|
||||||
(s-trim (org-roam-capture--fill-template path))
|
(s-trim (org-roam-capture--fill-template path t))
|
||||||
org-roam-directory))
|
org-roam-directory))
|
||||||
(set-buffer (org-capture-target-buffer path))
|
(set-buffer (org-capture-target-buffer path))
|
||||||
(widen))
|
(widen)
|
||||||
|
(org-roam-capture--add-ref)
|
||||||
|
(org-id-get-create))
|
||||||
(`(file+olp ,path ,olp)
|
(`(file+olp ,path ,olp)
|
||||||
(setq path (expand-file-name
|
(setq path (expand-file-name
|
||||||
(s-trim (org-roam-capture--fill-template path))
|
(s-trim (org-roam-capture--fill-template path t))
|
||||||
org-roam-directory))
|
org-roam-directory))
|
||||||
(set-buffer (org-capture-target-buffer path))
|
(set-buffer (org-capture-target-buffer path))
|
||||||
(let ((m (org-roam-capture-find-or-create-olp olp)))
|
(let ((m (org-roam-capture-find-or-create-olp olp)))
|
||||||
(goto-char m))
|
(goto-char m))
|
||||||
(widen))
|
(widen)
|
||||||
|
(org-with-point-at 1
|
||||||
|
(org-roam-capture--add-ref)
|
||||||
|
(org-id-get-create)))
|
||||||
(`(file+head ,path ,head)
|
(`(file+head ,path ,head)
|
||||||
(setq path (expand-file-name
|
(setq path (expand-file-name
|
||||||
(s-trim (org-roam-capture--fill-template path))
|
(s-trim (org-roam-capture--fill-template path t))
|
||||||
org-roam-directory))
|
org-roam-directory))
|
||||||
(let ((exists-p (file-exists-p path)))
|
(let ((exists-p (file-exists-p path)))
|
||||||
(set-buffer (org-capture-target-buffer path))
|
(set-buffer (org-capture-target-buffer path))
|
||||||
(unless exists-p
|
(unless exists-p
|
||||||
(insert (org-roam-capture--fill-template head))))
|
(insert (org-roam-capture--fill-template head t))))
|
||||||
(widen))
|
(widen)
|
||||||
|
(org-with-point-at 1
|
||||||
|
(org-roam-capture--add-ref)
|
||||||
|
(org-id-get-create)))
|
||||||
;; TODO: support node
|
;; TODO: support node
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -292,55 +278,52 @@ you can catch it with `condition-case'."
|
|||||||
"Return exact point to file for org-capture-template.
|
"Return exact point to file for org-capture-template.
|
||||||
This function is used solely in Org-roam's capture templates: see
|
This function is used solely in Org-roam's capture templates: see
|
||||||
`org-roam-capture-templates'."
|
`org-roam-capture-templates'."
|
||||||
(cond ((plist-get org-roam-capture--info :ref)
|
(let ((id (cond ((plist-get org-roam-capture--info :ref)
|
||||||
(if-let ((file-pos (org-roam-capture--get-ref-path
|
(if-let ((file-pos (org-roam-capture--get-ref-path
|
||||||
(plist-get org-roam-capture--info :ref))))
|
(plist-get org-roam-capture--info :ref))))
|
||||||
(progn
|
(progn
|
||||||
(set-buffer (org-capture-target-buffer (car file-pos)))
|
(set-buffer (org-capture-target-buffer (car file-pos)))
|
||||||
(goto-char (cdr file-pos))
|
(goto-char (cdr file-pos))
|
||||||
(widen))
|
(widen))
|
||||||
(org-roam-capture--goto-location)))
|
(org-roam-capture--goto-location)))
|
||||||
((and (org-roam-node-file org-roam-capture--node)
|
((and (org-roam-node-file org-roam-capture--node)
|
||||||
(org-roam-node-point org-roam-capture--node))
|
(org-roam-node-point org-roam-capture--node))
|
||||||
(set-buffer (org-capture-target-buffer (org-roam-node-file org-roam-capture--node)))
|
(set-buffer (org-capture-target-buffer (org-roam-node-file org-roam-capture--node)))
|
||||||
(goto-char (org-roam-node-point org-roam-capture--node))
|
(goto-char (org-roam-node-point org-roam-capture--node))
|
||||||
(org-end-of-subtree))
|
(widen)
|
||||||
(t
|
(org-end-of-subtree t t)
|
||||||
(org-roam-capture--goto-location)))
|
(org-roam-node-id org-roam-capture--node))
|
||||||
(org-capture-put :template
|
(t
|
||||||
(org-roam-capture--fill-template (org-capture-get :template)))
|
(org-roam-capture--goto-location)))))
|
||||||
(org-roam-capture--put :finalize (or (org-capture-get :finalize)
|
(org-capture-put :template
|
||||||
(org-roam-capture--get :finalize))))
|
(org-roam-capture--fill-template (org-capture-get :template)))
|
||||||
|
(org-roam-capture--put :id id)
|
||||||
|
(org-roam-capture--put :finalize (or (org-capture-get :finalize)
|
||||||
|
(org-roam-capture--get :finalize)))))
|
||||||
|
|
||||||
(defun org-roam-capture--convert-template (template &optional props)
|
(defun org-roam-capture--convert-template (template &optional props)
|
||||||
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax.
|
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax.
|
||||||
PROPS is a plist containing additional Org-roam specific
|
PROPS is a plist containing additional Org-roam specific
|
||||||
properties to be added to the template."
|
properties to be added to the template."
|
||||||
(let* ((key (or (plist-get template :key)
|
(pcase template
|
||||||
(user-error "Template has no :key")))
|
(`(,key ,desc ,type ,body . ,rest)
|
||||||
(desc (or (plist-get template :desc)
|
(setq rest (append rest props))
|
||||||
(user-error "Template has no :desc")))
|
(let (org-roam-plist options)
|
||||||
(body (or (plist-get template :body)
|
(while rest
|
||||||
(user-error "Template has no :body")))
|
(let* ((key (pop rest))
|
||||||
(rest (org-plist-delete template :key))
|
(val (pop rest))
|
||||||
(rest (org-plist-delete rest :desc))
|
(custom (member key org-roam-capture--template-keywords)))
|
||||||
(rest (org-plist-delete rest :body))
|
(when (and custom
|
||||||
(rest (append rest props))
|
(not val))
|
||||||
org-roam-plist
|
(user-error "Invalid capture template format: %s\nkey %s cannot be nil" template key))
|
||||||
options)
|
(if custom
|
||||||
(while rest
|
(setq org-roam-plist (plist-put org-roam-plist key val))
|
||||||
(let* ((key (pop rest))
|
(setq options (plist-put options key val)))))
|
||||||
(val (pop rest))
|
(append `(,key ,desc ,type #'org-roam-capture--get-point ,body)
|
||||||
(custom (member key org-roam-capture--template-keywords)))
|
options
|
||||||
(when (and custom
|
(list :org-roam org-roam-plist))))
|
||||||
(not val))
|
(_
|
||||||
(user-error "Invalid capture template format: %s\nkey %s cannot be nil" template key))
|
(signal 'invalid-template template))))
|
||||||
(if custom
|
|
||||||
(setq org-roam-plist (plist-put org-roam-plist key val))
|
|
||||||
(setq options (plist-put options key val)))))
|
|
||||||
(append `(,key ,desc plain #'org-roam-capture--get-point ,body)
|
|
||||||
options
|
|
||||||
(list :org-roam org-roam-plist))))
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(cl-defun org-roam-capture- (&key goto keys node info props templates)
|
(cl-defun org-roam-capture- (&key goto keys node info props templates)
|
||||||
|
@ -61,11 +61,10 @@
|
|||||||
:type 'hook)
|
:type 'hook)
|
||||||
|
|
||||||
(defcustom org-roam-dailies-capture-templates
|
(defcustom org-roam-dailies-capture-templates
|
||||||
(list (list :key "d"
|
'(("d" "default" entry
|
||||||
:desc "default"
|
"* %?"
|
||||||
:body "* %?"
|
:if-new `(file+head ,(concat org-roam-dailies-directory "%<%Y-%m-%d>.org")
|
||||||
:if-new `(file+head ,(concat org-roam-dailies-directory "%<%Y-%m-%d>.org")
|
"#+title: %<%Y-%m-%d>\n")))
|
||||||
"#+title: %<%Y-%m-%d>\n")))
|
|
||||||
"Capture templates for daily-notes in Org-roam."
|
"Capture templates for daily-notes in Org-roam."
|
||||||
:group 'org-roam
|
:group 'org-roam
|
||||||
:type
|
:type
|
||||||
|
Reference in New Issue
Block a user