diff --git a/org-roam.el b/org-roam.el index 422ad08..7131c89 100644 --- a/org-roam.el +++ b/org-roam.el @@ -598,34 +598,64 @@ See `org-roam--get-ref-path-completions' for details." :type 'boolean :group 'org-roam) -(defun org-roam--get-ref-path-completions (&optional interactive) +(defun org-roam--get-ref-path-completions (&optional interactive filter) "Return a list of cons pairs for refs to absolute path of Org-roam files. -When INTERACTIVE `org-roam-include-type-in-ref-path-completions' -are non-nil, format the car of the completion-candidates as -'type:ref'." +When `org-roam-include-type-in-ref-path-completions' and +INTERACTIVE are non-nil, format the car of the +completion-candidates as 'type:ref'. +FILTER can either be a string or a function: +- If it is a string, it should be the type of refs to include as +candidates (e.g. \"cite\" ,\"website\" ,etc.) +- If it is a function, it should be the name of a function that +takes three arguments: the type, the ref, and the file of the +current candidate. It should return t if that candidate is to be +included as a candidate." (let ((rows (org-roam-db-query [:select [type ref file] :from refs])) (include-type (and interactive - org-roam-include-type-in-ref-path-completions))) - (mapcar (lambda (row) - (cl-destructuring-bind (type ref file) row - (cons (if include-type - (format "%s:%s" type ref) - ref) - file))) - rows))) + org-roam-include-type-in-ref-path-completions)) + candidates) + (dolist (row rows (nreverse candidates)) + (cl-destructuring-bind (type ref file) row + (when (pcase filter + ('nil t) + ((pred stringp) (string= type filter)) + ((pred functionp) (funcall filter type ref file)) + (wrong-type (signal 'wrong-type-argument + `((stringp functionp) + ,wrong-type)))) + (let ((candidate (cons (if include-type + (format "%s:%s" type ref) + ref) + file))) + (push candidate candidates))))))) -(defun org-roam-find-ref (arg &optional info) +(defun org-roam--find-ref (ref) + "Find and open and Org-roam file from REF if it exists. +REF should be the value of '#+ROAM_KEY:' without any +type-information (e.g. 'cite:'). +Return nil if the file does not exist." + (when-let* ((completions (org-roam--get-ref-path-completions)) + (file (cdr (assoc ref completions)))) + (find-file file))) + +(defun org-roam-find-ref (arg &optional filter) "Find and open an Org-roam file from a ref. -INFO is an alist containing additional information. ARG is used to forward interactive calls to -`org-roam--get-ref-path-completions'" +`org-roam--get-ref-path-completions' +FILTER can either be a string or a function: +- If it is a string, it should be the type of refs to include as +candidates (e.g. \"cite\" ,\"website\" ,etc.) +- If it is a function, it should be the name of a function that +takes three arguments: the type, the ref, and the file of the +current candidate. It should return t if that candidate is to be +included as a candidate." (interactive "p") - (let* ((completions (org-roam--get-ref-path-completions arg)) - (ref (or (cdr (assoc 'ref info)) - (org-roam-completion--completing-read "Ref: " - completions - :require-match t)))) - (find-file (cdr (assoc ref completions))))) + (let* ((completions (org-roam--get-ref-path-completions arg filter)) + (ref (org-roam-completion--completing-read "Ref: " + completions + :require-match t)) + (file (cdr (assoc ref completions)))) + (find-file file))) (defun org-roam--get-roam-buffers () "Return a list of buffers that are Org-roam files."