Update template syntax, allow capture directly to nodes

This commit is contained in:
Jethro Kuan
2021-04-13 19:28:47 +08:00
parent c9636d6551
commit e612b3f068
2 changed files with 97 additions and 115 deletions

View File

@ -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)

View File

@ -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