diff --git a/org-roam-capture.el b/org-roam-capture.el index 6167ed7..c58c49e 100644 --- a/org-roam-capture.el +++ b/org-roam-capture.el @@ -43,7 +43,7 @@ (defvar org-roam-title-to-slug-function) (defvar org-roam-capture--info nil - "An alist of additional information passed to the Org-roam template. + "A property-list of additional information passed to the Org-roam template. This variable is populated dynamically, and is only non-nil during the Org-roam capture process.") @@ -195,10 +195,12 @@ Next, it expands the remaining template string using (org-capture-fill-template (s-format str (lambda (key) - (or (s--aget org-roam-capture--info key) - (when-let ((val (completing-read (format "%s: " key) nil))) - (push (cons key val) org-roam-capture--info) - val)))))) + (let ((plist-key (intern (concat ":" key)))) + (or (plist-get org-roam-capture--info plist-key) + (when-let ((val (completing-read (format "%s: " key) nil))) + (setq org-roam-capture--info + (plist-put org-roam-capture--info plist-key val)) + val))))))) (defun org-roam-capture--save-file-maybe () "Save the file conditionally. @@ -308,18 +310,18 @@ you can catch it with `condition-case'." "Return exact point to file for org-capture-template. This function is used solely in Org-roam's capture templates: see `org-roam-capture-templates'." - (when-let ((time (cdr (assoc 'time org-roam-capture--info)))) + (when-let ((time (plist-get org-roam-capture--info :time))) (org-capture-put :default-time time)) (let ((file-path - (cond ((assoc 'file org-roam-capture--info) - (cdr (assoc 'file org-roam-capture--info))) - ((assoc 'ref org-roam-capture--info) - (let ((ref (cdr (assoc 'ref org-roam-capture--info)))) - (or (caar (org-roam-db-query [:select [file] - :from refs - :where (= ref $s1) - :limit 1] ref)) - (org-roam-capture--new-file)))) + (cond ((plist-get org-roam-capture--info :file) + (plist-get org-roam-capture--info :file)) + ((plist-get org-roam-capture--info :ref) + (or (caar (org-roam-db-query [:select [file] + :from refs + :where (= ref $s1) + :limit 1] + (plist-get org-roam-capture--info :ref))) + (org-roam-capture--new-file))) (t (org-roam-capture--new-file))))) (org-capture-put :template @@ -377,11 +379,14 @@ GOTO and KEYS correspond to `org-capture' arguments. INFO is an alist for filling up Org-roam's capture templates. PROPS is a plist containing additional Org-roam properties for each template. TEMPLATES is a list of org-roam templates." - (let ((org-capture-templates - (mapcar (lambda (t) - (org-roam-capture--convert-template t props)) - (or templates org-roam-capture-templates))) - (org-roam-capture--info info)) + (let* ((org-capture-templates + (mapcar (lambda (t) + (org-roam-capture--convert-template t props)) + (or templates org-roam-capture-templates))) + (info (plist-put info :slug + (funcall org-roam-title-to-slug-function + (plist-get info :title)))) + (org-roam-capture--info info)) (when (and (not keys) (= (length org-capture-templates) 1)) (setq keys (caar org-capture-templates))) @@ -396,10 +401,8 @@ Arguments GOTO and KEYS see `org-capture'." (let ((node (org-roam-node-read))) (org-roam-capture- :goto goto :keys keys - :info `((title . ,(org-roam-node-title node)) - (slug . ,(funcall org-roam-title-to-slug-function - (org-roam-node-title node))) - (file . ,(org-roam-node-file node))) + :info (list :title (org-roam-node-title node) + :file (org-roam-node-file node)) :props '(:immediate-finish nil)))) (provide 'org-roam-capture) diff --git a/org-roam-macs.el b/org-roam-macs.el index ffcd494..b677f91 100644 --- a/org-roam-macs.el +++ b/org-roam-macs.el @@ -30,6 +30,18 @@ ;; This library implements macros used throughout org-roam. ;; ;;; Code: +(defmacro org-roam-plist-map! (fn plist) + "Map FN over PLIST, modifying it in-place." + (declare (indent 1)) + (let ((plist-var (make-symbol "plist")) + (k (make-symbol "k")) + (v (make-symbol "v"))) + `(let ((,plist-var (copy-sequence ,plist))) + (while ,plist-var + (setq ,k (pop ,plist-var)) + (setq ,v (pop ,plist-var)) + (setq ,plist (plist-put ,plist ,k (funcall ,fn ,k ,v))))))) + (defmacro org-roam-with-file (file keep-buf-p &rest body) "Execute BODY within FILE. If FILE is nil, execute BODY in the current buffer. diff --git a/org-roam-protocol.el b/org-roam-protocol.el index 8c06eef..48957a9 100644 --- a/org-roam-protocol.el +++ b/org-roam-protocol.el @@ -37,6 +37,8 @@ ;;; Code: (require 'org-protocol) (require 'org-roam) +(eval-when-compile + (require 'org-roam-macs)) (require 'ol) ;; for org-link-decode (defcustom org-roam-protocol-store-links nil @@ -54,37 +56,31 @@ It opens or creates a note with the given ref. encodeURIComponent(location.href) + \\='&title=\\=' + \\ encodeURIComponent(document.title) + \\='&body=\\=' + \\ encodeURIComponent(window.getSelection())" - (when-let* ((alist (org-roam--plist-to-alist info)) - (decoded-alist (mapcar (lambda (k.v) - (let ((key (car k.v)) - (val (cdr k.v))) - (cons key (org-link-decode val)))) alist))) - (unless (assoc 'ref decoded-alist) - (error "No ref key provided")) - (when-let ((title (cdr (assoc 'title decoded-alist)))) - (push (cons 'slug (funcall org-roam-title-to-slug-function title)) decoded-alist)) - (let-alist decoded-alist - (let* ((ref (org-protocol-sanitize-uri .ref)) - (type (and (string-match org-link-plain-re ref) - (match-string 1 ref))) - (title (or .title "")) - (body (or .body "")) - (orglink - (org-link-make-string ref (or (org-string-nw-p title) ref))) - (org-capture-link-is-already-stored t)) - (when org-roam-protocol-store-links - (push (list ref title) org-stored-links)) - (org-link-store-props :type type - :link ref - :annotation orglink - :initial body) - (raise-frame) - (org-roam-capture- - :keys (cdr (assoc 'template decoded-alist)) - :info decoded-alist - :props (list :ref ref) - :templates org-roam-capture-ref-templates))) - nil)) + (unless (plist-get info :ref) + (user-error "No ref key provided")) + (org-roam-plist-map! (lambda (k v) + (when (equal k :ref) + (setq v (org-protocol-sanitize-uri v))) + (org-link-decode v)) info) + (when org-roam-protocol-store-links + (push (list (plist-get info :ref) + (plist-get info :title)) org-stored-links)) + (org-link-store-props :type (and (string-match org-link-plain-re + (plist-get info :ref)) + (match-string 1 (plist-get info :ref))) + :link (plist-get info :ref) + :annotation (org-link-make-string (plist-get info :ref) + (or (plist-get info :title) + (plist-get info :ref))) + :initial (or (plist-get info :body) + "")) + (raise-frame) + (org-roam-capture- + :keys (plist-get info :template) + :info info + :props `(:ref ,(plist-get info :ref)) + :templates org-roam-capture-ref-templates) + nil) (defun org-roam-protocol-open-file (info) "This handler simply opens the file with emacsclient. diff --git a/org-roam.el b/org-roam.el index b5c6c85..3c89437 100644 --- a/org-roam.el +++ b/org-roam.el @@ -688,9 +688,8 @@ If OTHER-WINDOW, visit the NODE in another window." (if (org-roam-node-file node) (org-roam-node-visit node other-window) (org-roam-capture- - :info `((title . ,(org-roam-node-title node)) - (slug . ,(funcall org-roam-title-to-slug-function (org-roam-node-title node)))) - :props (list :finalize 'find-file))))) + :info `(:title ,(org-roam-node-title node)) + :props '(:finalize find-file))))) (defun org-roam-node-insert (&optional filter-fn) "Find an Org-roam file, and insert a relative org link to it at point. @@ -721,8 +720,7 @@ which takes as its argument an alist of path-completions." (concat "id:" (org-roam-node-id node)) description))) (org-roam-capture- - :info `((title . ,(org-roam-node-title node)) - (slug . ,(funcall org-roam-title-to-slug-function (org-roam-node-title node)))) + :info `(:title ,(org-roam-node-title node)) :props (list :region (when (and beg end) (cons beg end)) :insert-at (point-marker)