(feat): Allow one file to have multiple roam_key statements (#1215)

This commit is contained in:
Kisaragi Hiu
2020-11-07 16:33:31 +09:00
committed by GitHub
parent 440461a90b
commit c6797cbd75
8 changed files with 120 additions and 62 deletions

View File

@ -5,6 +5,7 @@
### Features ### Features
- [#1183](https://github.com/org-roam/org-roam/pull/1183) add interactive functions for managing aliases and tags in Org-roam file, namely `org-roam-alias-add`, `org-roam-alias-delete`, `org-roam-tag-add`, and `org-roam-tag-delete`. - [#1183](https://github.com/org-roam/org-roam/pull/1183) add interactive functions for managing aliases and tags in Org-roam file, namely `org-roam-alias-add`, `org-roam-alias-delete`, `org-roam-tag-add`, and `org-roam-tag-delete`.
- [#1215](https://github.com/org-roam/org-roam/pull/1215) Multiple `ROAM_KEY` keywords can now be specified in one file. This allows bibliographical entries to share the same note file.
- [#1238](https://github.com/org-roam/org-roam/pull/1238) add `org-roam-prefer-id-links` variable to select linking method - [#1238](https://github.com/org-roam/org-roam/pull/1238) add `org-roam-prefer-id-links` variable to select linking method
### Bugfixes ### Bugfixes

View File

@ -47,7 +47,7 @@
(defvar org-roam--org-link-bracket-typed-re) (defvar org-roam--org-link-bracket-typed-re)
(declare-function org-roam-db--ensure-built "org-roam-db") (declare-function org-roam-db--ensure-built "org-roam-db")
(declare-function org-roam--extract-ref "org-roam") (declare-function org-roam--extract-refs "org-roam")
(declare-function org-roam--extract-titles "org-roam") (declare-function org-roam--extract-titles "org-roam")
(declare-function org-roam--get-title-or-slug "org-roam") (declare-function org-roam--get-title-or-slug "org-roam")
(declare-function org-roam--get-backlinks "org-roam") (declare-function org-roam--get-backlinks "org-roam")
@ -149,10 +149,11 @@ ORIG-PATH is the path where the CONTENT originated."
(defun org-roam-buffer--insert-ref-links () (defun org-roam-buffer--insert-ref-links ()
"Insert ref backlinks for the current buffer." "Insert ref backlinks for the current buffer."
(when-let ((path (cdr (with-temp-buffer (when-let* ((refs (with-temp-buffer
(insert-buffer-substring org-roam-buffer--current) (insert-buffer-substring org-roam-buffer--current)
(org-roam--extract-ref))))) (org-roam--extract-refs)))
(if-let* ((key-backlinks (org-roam--get-backlinks path)) (paths (mapcar #'cdr refs)))
(if-let* ((key-backlinks (mapcan #'org-roam--get-backlinks paths))
(grouped-backlinks (--group-by (nth 0 it) key-backlinks))) (grouped-backlinks (--group-by (nth 0 it) key-backlinks)))
(progn (progn
(insert (let ((l (length key-backlinks))) (insert (let ((l (length key-backlinks)))

View File

@ -50,7 +50,7 @@
(declare-function org-roam--org-roam-file-p "org-roam") (declare-function org-roam--org-roam-file-p "org-roam")
(declare-function org-roam--extract-titles "org-roam") (declare-function org-roam--extract-titles "org-roam")
(declare-function org-roam--extract-ref "org-roam") (declare-function org-roam--extract-refs "org-roam")
(declare-function org-roam--extract-tags "org-roam") (declare-function org-roam--extract-tags "org-roam")
(declare-function org-roam--extract-ids "org-roam") (declare-function org-roam--extract-ids "org-roam")
(declare-function org-roam--extract-links "org-roam") (declare-function org-roam--extract-links "org-roam")
@ -274,15 +274,17 @@ Returns the number of rows inserted."
rows) rows)
(length rows))) (length rows)))
(defun org-roam-db--insert-ref (&optional update-p) (defun org-roam-db--insert-refs (&optional update-p)
"Update the ref of the current buffer into the cache. "Update the refs of the current buffer into the cache.
If UPDATE-P is non-nil, first remove the ref for the file in the database." If UPDATE-P is non-nil, first remove the ref for the file in the database."
(let ((file (or org-roam-file-name (buffer-file-name)))) (let ((file (or org-roam-file-name (buffer-file-name)))
(count 0))
(when update-p (when update-p
(org-roam-db-query [:delete :from refs (org-roam-db-query [:delete :from refs
:where (= file $s1)] :where (= file $s1)]
file)) file))
(if-let ((ref (org-roam--extract-ref))) (when-let ((refs (org-roam--extract-refs)))
(dolist (ref refs)
(let ((key (cdr ref)) (let ((key (cdr ref))
(type (car ref))) (type (car ref)))
(condition-case nil (condition-case nil
@ -290,7 +292,7 @@ If UPDATE-P is non-nil, first remove the ref for the file in the database."
(org-roam-db-query (org-roam-db-query
[:insert :into refs :values $v1] [:insert :into refs :values $v1]
(list (vector key file type))) (list (vector key file type)))
1) (cl-incf count))
(error (error
(lwarn '(org-roam) :error (lwarn '(org-roam) :error
(format "Duplicate ref %s in:\n\nA: %s\nB: %s\n\nskipping..." (format "Duplicate ref %s in:\n\nA: %s\nB: %s\n\nskipping..."
@ -299,9 +301,8 @@ If UPDATE-P is non-nil, first remove the ref for the file in the database."
(caar (org-roam-db-query (caar (org-roam-db-query
[:select file :from refs [:select file :from refs
:where (= ref $v1)] :where (= ref $v1)]
(vector key))))) (vector key))))))))))
0))) count))
0)))
(defun org-roam-db--insert-links (&optional update-p) (defun org-roam-db--insert-links (&optional update-p)
"Update the file links of the current buffer in the cache. "Update the file links of the current buffer in the cache.
@ -473,7 +474,7 @@ If the file exists, update the cache with information."
(org-roam-db--insert-meta 'update) (org-roam-db--insert-meta 'update)
(org-roam-db--insert-tags 'update) (org-roam-db--insert-tags 'update)
(org-roam-db--insert-titles 'update) (org-roam-db--insert-titles 'update)
(org-roam-db--insert-ref 'update) (org-roam-db--insert-refs 'update)
(when org-roam-enable-headline-linking (when org-roam-enable-headline-linking
(org-roam-db--insert-ids 'update)) (org-roam-db--insert-ids 'update))
(org-roam-db--insert-links 'update))))) (org-roam-db--insert-links 'update)))))
@ -538,7 +539,7 @@ If FORCE, force a rebuild of the cache from scratch."
(setq link-count (+ link-count (org-roam-db--insert-links))) (setq link-count (+ link-count (org-roam-db--insert-links)))
(setq tag-count (+ tag-count (org-roam-db--insert-tags))) (setq tag-count (+ tag-count (org-roam-db--insert-tags)))
(setq title-count (+ title-count (org-roam-db--insert-titles))) (setq title-count (+ title-count (org-roam-db--insert-titles)))
(setq ref-count (+ ref-count (org-roam-db--insert-ref)))) (setq ref-count (+ ref-count (org-roam-db--insert-refs))))
(file-error (file-error
(setq org-roam-files (remove file org-roam-files)) (setq org-roam-files (remove file org-roam-files))
(org-roam-db--clear-file file) (org-roam-db--clear-file file)

View File

@ -512,12 +512,13 @@ Use external shell commands if defined in `org-roam-list-files-commands'."
;;;; Org extraction functions ;;;; Org extraction functions
(defun org-roam--extract-global-props (props) (defun org-roam--extract-global-props (props)
"Extract PROPS from the current org buffer. "Extract PROPS from the current org buffer."
The search terminates when the first property is encountered." (let ((collected
;; Collect the raw props first
;; It'll be returned in the form of
;; (("PROP" "value" ...) ("PROP2" "value" ...))
(if (functionp 'org-collect-keywords) (if (functionp 'org-collect-keywords)
(->> (org-collect-keywords props) (org-collect-keywords props)
;; convert (("TITLE" "my title")) to (("TITLE" . "my title"))
(mapcar (pcase-lambda (`(,k ,v)) (cons k v))))
(let ((buf (org-element-parse-buffer)) (let ((buf (org-element-parse-buffer))
res) res)
(dolist (prop props) (dolist (prop props)
@ -525,9 +526,16 @@ The search terminates when the first property is encountered."
(lambda (kw) (lambda (kw)
(when (string-equal (org-element-property :key kw) prop) (when (string-equal (org-element-property :key kw) prop)
(org-element-property :value kw))) (org-element-property :value kw)))
:first-match t))) :first-match nil)))
(push (cons prop p) res))) (push (cons prop p) res)))
res))) res))))
;; convert (("TITLE" "a" "b") ("Another" "c"))
;; to (("TITLE" . "a") ("TITLE" . "b") ("Another" . "c"))
(let (ret)
(pcase-dolist (`(,key . ,values) collected)
(dolist (value values)
(push (cons key value) ret)))
ret)))
(defun org-roam--get-outline-path () (defun org-roam--get-outline-path ()
"Return the outline path to the current entry. "Return the outline path to the current entry.
@ -763,11 +771,16 @@ backlinks."
"website") "website")
(t type))) (t type)))
(defun org-roam--extract-ref () (defun org-roam--extract-refs ()
"Extract the ref from current buffer and return the type and the key of the ref." "Extract all refs (ROAM_KEY statements) from the current buffer.
Each ref is returned as a cons of its type and its key."
(let (refs)
(pcase-dolist
(`(,_ . ,roam-key)
(org-roam--extract-global-props '("ROAM_KEY")))
(let (type path) (let (type path)
(pcase (cdr (assoc "ROAM_KEY" (pcase roam-key
(org-roam--extract-global-props '("ROAM_KEY"))))
('nil nil) ('nil nil)
((pred string-empty-p) ((pred string-empty-p)
(user-error "Org property #+roam_key cannot be empty")) (user-error "Org property #+roam_key cannot be empty"))
@ -776,7 +789,12 @@ backlinks."
(setq type (org-roam--collate-types (match-string 1 ref)) (setq type (org-roam--collate-types (match-string 1 ref))
path (match-string 2 ref))))) path (match-string 2 ref)))))
(when (and type path) (when (and type path)
(cons type path)))) (push (cons type path) refs))))
refs))
(defun org-roam--extract-ref ()
"Extract the ref from current buffer and return the type and the key of the ref."
(car (org-roam--extract-refs)))
;;;; Title/Path/Slug conversion ;;;; Title/Path/Slug conversion
(defun org-roam--path-to-slug (path) (defun org-roam--path-to-slug (path)

View File

@ -0,0 +1 @@
#+roam_key: cite:mitsuha2007

View File

@ -0,0 +1,2 @@
#+roam_key: https://www.orgroam.com/
#+roam_key: cite:orgroam2020

View File

@ -45,7 +45,7 @@
(pcase (benchmark-run 1 (org-roam-db-build-cache t)) (pcase (benchmark-run 1 (org-roam-db-build-cache t))
(`(,time ,gcs ,time-in-gc) (`(,time ,gcs ,time-in-gc)
(message "Elapsed time: %fs (%fs in %d GCs)" time time-in-gc gcs) (message "Elapsed time: %fs (%fs in %d GCs)" time time-in-gc gcs)
(expect time :to-be-less-than 100)))) (expect time :to-be-less-than 110))))
(it "builds quickly without change" (it "builds quickly without change"
(pcase (benchmark-run 1 (org-roam-db-build-cache)) (pcase (benchmark-run 1 (org-roam-db-build-cache))
(`(,time ,gcs ,time-in-gc) (`(,time ,gcs ,time-in-gc)

View File

@ -71,6 +71,40 @@
(expect (org-roam--str-to-list "\"hello") (expect (org-roam--str-to-list "\"hello")
:to-throw))) :to-throw)))
(describe "Ref extraction"
(before-all
(test-org-roam--init))
(after-all
(test-org-roam--teardown))
(cl-flet
((test (fn file)
(let* ((fname (test-org-roam--abs-path file))
(buf (find-file-noselect fname)))
(with-current-buffer buf
;; Unlike tag extraction, it doesn't make sense to
;; pass a filename.
(funcall fn)))))
;; Enable "cite:" link parsing
(org-link-set-parameters "cite")
(it "extracts web keys"
(expect (test #'org-roam--extract-ref
"web_ref.org")
:to-equal
'("website" . "//google.com/")))
(it "extracts cite keys"
(expect (test #'org-roam--extract-ref
"cite_ref.org")
:to-equal
'("cite" . "mitsuha2007")))
(it "extracts all keys"
(expect (test #'org-roam--extract-refs
"multiple-refs.org")
:to-have-same-items-as
'(("cite" . "orgroam2020")
("website" . "//www.orgroam.com/"))))))
(describe "Title extraction" (describe "Title extraction"
:var (org-roam-title-sources) :var (org-roam-title-sources)
(before-all (before-all