From 11d239d66105cdd7ff221507e05c433eb73f32dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ktu=C4=9F=20Karaka=C5=9Fl=C4=B1?= <20567087+goktug97@users.noreply.github.com> Date: Mon, 4 May 2020 15:44:15 +0300 Subject: [PATCH] (feat): fix citation links not showing up in graph (#547) This change adds a `type` column to the refs column, and strips the prefix before storing the key in the `refs` table. --- CHANGELOG.md | 3 ++ org-roam-buffer.el | 12 +++--- org-roam-compat.el | 2 + org-roam-db.el | 36 +++++++++-------- org-roam-graph.el | 3 +- org-roam.el | 88 ++++++++++++++++++++++++++++++++++-------- tests/test-org-roam.el | 4 +- 7 files changed, 105 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99fefb5..e0f9573 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,15 @@ ### Breaking Changes * [#523](https://github.com/jethrokuan/org-roam/pull/523) remove `org-roam-completion-fuzzy-match` in favor of using completion mechanism's configuration options directly +* [#547](https://github.com/jethrokuan/org-roam/pull/547) Deprecate `org-roam-db--maybe-update`, in favour of `org-roam-db--update-maybe`. +* [#547](https://github.com/jethrokuan/org-roam/pull/547) Added `type` column to the `refs` table. ### Bugfixes * [#509](https://github.com/jethrokuan/org-roam/pull/509) fix backup files being tracked in database * [#509](https://github.com/jethrokuan/org-roam/pull/509) fix external org files being tracked in database * [#537](https://github.com/jethrokuan/org-roam/pull/537) quote graphviz node and edge configuration options to allow multi-word configurations * [#545](https://github.com/jethrokuan/org-roam/pull/545) fix `org-roam--extract-links` to ensure that multiple citations (`cite:key1,key2`) are split correctly +* [#547](https://github.com/jethrokuan/org-roam/pull/547) Fix unlinked citations. ### Features * [#538](https://github.com/jethrokuan/org-roam/pull/538) Optionally use text in first headline as title diff --git a/org-roam-buffer.el b/org-roam-buffer.el index 4ddd1c0..a1e5199 100644 --- a/org-roam-buffer.el +++ b/org-roam-buffer.el @@ -114,14 +114,11 @@ When non-nil, the window will not be closed when deleting other windows." (defun org-roam-buffer--insert-citelinks () "Insert citation backlinks for the current buffer." - (if-let* ((roam-key (with-temp-buffer - (insert-buffer-substring org-roam-buffer--current) - (org-roam--extract-ref))) + (if-let* ((ref (with-temp-buffer + (insert-buffer-substring org-roam-buffer--current) + (org-roam--extract-ref))) (org-ref-p (require 'org-ref nil t)) ; Ensure that org-ref is present - (cite-prefixes (-map (lambda (type) - (concat type ":")) org-ref-cite-types)) - (key-backlinks (org-roam--get-backlinks - (s-chop-prefixes cite-prefixes roam-key))) + (key-backlinks (org-roam--get-backlinks (cdr ref))) (grouped-backlinks (--group-by (nth 0 it) key-backlinks))) (progn (insert (let ((l (length key-backlinks))) @@ -196,6 +193,7 @@ When non-nil, the window will not be closed when deleting other windows." (run-hooks 'org-roam-buffer-prepare-hook) (read-only-mode 1))))) + (cl-defun org-roam-buffer--update-maybe (&key redisplay) "Reconstructs `org-roam-buffer'. This needs to be quick or infrequent, because this is run at diff --git a/org-roam-compat.el b/org-roam-compat.el index abc6834..7d5f39b 100644 --- a/org-roam-compat.el +++ b/org-roam-compat.el @@ -77,6 +77,8 @@ "org-roam 1.1.0") (define-obsolete-function-alias 'org-roam--capture 'org-roam-capture--capture "org-roam 1.1.0") +(define-obsolete-function-alias 'org-roam-db--maybe-update 'org-roam-db--update-maybe + "org-roam 1.1.0") ;;;; Variables (define-obsolete-variable-alias 'org-roam-graphviz-extra-options diff --git a/org-roam-db.el b/org-roam-db.el index 679fbd7..60bbc62 100644 --- a/org-roam-db.el +++ b/org-roam-db.el @@ -56,7 +56,7 @@ when used with multiple Org-roam instances." :type 'string :group 'org-roam) -(defconst org-roam-db--version 2) +(defconst org-roam-db--version 3) (defconst org-roam-db--sqlite-available-p (with-demoted-errors "Org-roam initialization: %S" (emacsql-sqlite-ensure-binary) @@ -94,7 +94,7 @@ Performs a database upgrade when required." (when init-db (org-roam-db--init conn)) (let* ((version (caar (emacsql conn "PRAGMA user_version"))) - (version (org-roam-db--maybe-update conn version))) + (version (org-roam-db--update-maybe conn version))) (cond ((> version org-roam-db--version) (emacsql-close conn) @@ -134,7 +134,8 @@ SQL can be either the emacsql vector representation, or a string." (refs [(ref :unique :not-null) - (file :not-null)]))) + (file :not-null) + (type :not-null)]))) (defun org-roam-db--init (db) "Initialize database DB with the correct schema and user version." @@ -143,16 +144,16 @@ SQL can be either the emacsql vector representation, or a string." (emacsql db [:create-table $i1 $S2] table schema)) (emacsql db (format "PRAGMA user_version = %s" org-roam-db--version)))) -(defun org-roam-db--maybe-update (db version) +(defun org-roam-db--update-maybe (db version) "Upgrades the database schema for DB, if VERSION is old." (emacsql-with-transaction db 'ignore - (when (= version 1) - (progn - (warn "No good way to perform a DB upgrade, rebuilding from scratch...") - (delete-file (org-roam-db--get)) - (org-roam-db-build-cache))) - version)) + (if (< version org-roam-db--version) + (progn + (message (format "Upgrading the Org-roam database from version %d to version %d" + version org-roam-db--version)) + (org-roam-db-build-cache t)))) + version) (defun org-roam-db--close (&optional db) "Closes the database connection for database DB. @@ -228,10 +229,11 @@ This is equivalent to removing the node from the graph." (defun org-roam-db--insert-ref (file ref) "Insert REF for FILE into the Org-roam cache." - (org-roam-db-query - [:insert :into refs - :values $v1] - (list (vector ref file)))) + (let ((key (cdr ref)) + (type (car ref))) + (org-roam-db-query + [:insert :into refs :values $v1] + (list (vector key file type))))) ;;;;; Fetching (defun org-roam-db--get-current-files () @@ -368,8 +370,10 @@ If FORCE, force a rebuild of the cache from scratch." (setq all-links (append links all-links))) (let ((titles (org-roam--extract-and-format-titles file))) (setq all-titles (cons (vector file titles) all-titles))) - (when-let ((ref (org-roam--extract-ref))) - (setq all-refs (cons (vector ref file) all-refs)))) + (when-let* ((ref (org-roam--extract-ref)) + (type (car ref)) + (key (cdr ref))) + (setq all-refs (cons (vector key file type) all-refs)))) (remhash file current-files)))) (dolist (file (hash-table-keys current-files)) ;; These files are no longer around, remove from cache... diff --git a/org-roam-graph.el b/org-roam-graph.el index aa859ff..867fe8d 100644 --- a/org-roam-graph.el +++ b/org-roam-graph.el @@ -173,7 +173,8 @@ into a digraph." `[:with selected :as [:select [file] :from ,node-query] :select :distinct [file from] :from links :inner :join refs :on (and (= links:to refs:ref) - (= links:type "cite")) + (= links:type "cite") + (= refs:type "cite")) :where (and (in file selected) (in from selected))]) (edges (org-roam-db-query edges-query)) (edges-cites (org-roam-db-query edges-cites-query))) diff --git a/org-roam.el b/org-roam.el index fb61e49..ae5b417 100644 --- a/org-roam.el +++ b/org-roam.el @@ -375,9 +375,44 @@ current buffer is used." (org-roam--format-title title file-path)) (org-roam--extract-titles))) +(defun org-roam--ref-type-p (type) + "Return t if the ref from current buffer is TYPE." + (let ((current (car (org-roam--extract-ref)))) + (eq current type))) + (defun org-roam--extract-ref () - "Extract the ref from current buffer." - (cdr (assoc "ROAM_KEY" (org-roam--extract-global-props '("ROAM_KEY"))))) + "Extract the ref from current buffer and return the type and the key of the ref." + (if-let ((ref (cdr (assoc "ROAM_KEY" (org-roam--extract-global-props '("ROAM_KEY")))))) + (let* ((type (org-roam--ref-type ref)) + (key (cond ((string= "cite" type) + (s-chop-prefix (org-roam--cite-prefix ref) ref)) + (t ref)))) + (cons type key)) + nil)) + +(defun org-roam--ref-type (ref) + "Determine the type of the REF from the prefix." + (let* ((cite-prefix (org-roam--cite-prefix ref)) + (is-website (seq-some + (lambda (prefix) (s-prefix? prefix ref)) + '("http" "https"))) + (type (cond (cite-prefix "cite") + (is-website "website") + (t "roam")))) + type)) + +(defun org-roam--cite-prefix (ref) + "Return the citation prefix of REF, or nil otherwise. +The prefixes are defined in `org-ref-cite-types`. +Examples: + (org-roam--cite-prefix \"cite:foo\") -> \"cite:\" + (org-roam--cite-prefix \"https://google.com\") -> nil" + (when (require 'org-ref nil t) + (seq-find + (lambda (prefix) (s-prefix? prefix ref)) + (-map (lambda (type) (concat type ":")) + org-ref-cite-types)))) + ;;;; Title/Path/Slug conversion (defun org-roam--path-to-slug (path) "Return a slug from PATH." @@ -555,18 +590,37 @@ command will offer you to create one." (when (y-or-n-p "Index file does not exist. Would you like to create it? ") (org-roam-find-file "Index"))))) -(defun org-roam--get-ref-path-completions () - "Return a list of cons pairs for refs to absolute path of Org-roam files." - (let ((rows (org-roam-db-query [:select [ref file] :from refs]))) - (mapcar (lambda (row) - (cons (car row) - (cadr row))) rows))) +;;;; org-roam-find-ref +(defcustom org-roam-include-type-in-ref-path-completions nil + "When t, include the type in ref-path completions. +Note that this only affects interactive calls. +See `org-roam--get-ref-path-completions' for details." + :type 'boolean + :group 'org-roam) -(defun org-roam-find-ref (&optional info) +(defun org-roam--get-ref-path-completions (&optional interactive) + "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'." + (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))) + +(defun org-roam-find-ref (arg &optional info) "Find and open an Org-roam file from a ref. -INFO is an alist containing additional information." - (interactive) - (let* ((completions (org-roam--get-ref-path-completions)) +INFO is an alist containing additional information. +ARG is used to forward interactive calls to +`org-roam--get-ref-path-completions'" + (interactive "p") + (let* ((completions (org-roam--get-ref-path-completions arg)) (ref (or (cdr (assoc 'ref info)) (org-roam-completion--completing-read "Ref: " completions @@ -658,7 +712,7 @@ file." (define-key map [mouse-1] 'org-open-at-point) (define-key map (kbd "RET") 'org-open-at-point) map) - "Keymap for `org-roam-backlinks-mode'.") + "Keymap for symbol `org-roam-backlinks-mode'.") (define-minor-mode org-roam-backlinks-mode "Minor mode for the `org-roam-buffer'. @@ -731,7 +785,7 @@ for Org-ref cite links." ;;; The global minor org-roam-mode (defvar org-roam-mode-map (make-sparse-keymap) - "Keymap for mode `org-roam-mode'.") + "Keymap for mode symbol `org-roam-mode'.") ;;;###autoload (define-minor-mode org-roam-mode @@ -755,11 +809,11 @@ Otherwise, behave as if called interactively." :global t (cond (org-roam-mode - (org-roam-db-build-cache) (add-hook 'find-file-hook #'org-roam--find-file-hook-function) (add-hook 'kill-emacs-hook #'org-roam-db--close-all) (advice-add 'rename-file :after #'org-roam--rename-file-advice) - (advice-add 'delete-file :before #'org-roam--delete-file-advice)) + (advice-add 'delete-file :before #'org-roam--delete-file-advice) + (org-roam-db-build-cache)) (t (remove-hook 'find-file-hook #'org-roam--find-file-hook-function) (remove-hook 'kill-emacs-hook #'org-roam-db--close-all) @@ -774,7 +828,7 @@ Otherwise, behave as if called interactively." (remove-hook 'after-save-hook #'org-roam-db--update-file t)))))) (defun org-roam--find-file-hook-function () - "Called by `find-file-hook' when mode `org-roam-mode' is on." + "Called by `find-file-hook' when mode symbol `org-roam-mode' is on." (when (org-roam--org-roam-file-p) (setq org-roam-last-window (get-buffer-window)) (add-hook 'post-command-hook #'org-roam-buffer--update-maybe nil t) diff --git a/tests/test-org-roam.el b/tests/test-org-roam.el index 38bca9e..1168c89 100644 --- a/tests/test-org-roam.el +++ b/tests/test-org-roam.el @@ -107,7 +107,7 @@ (expect (org-roam-db-query [:select * :from refs]) :to-have-same-items-as - (list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org")))) + (list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org") "website"))) ;; Expect rebuilds to be really quick (nothing changed) (expect (org-roam-db-build-cache) @@ -299,7 +299,7 @@ (it "delete web_ref" (expect (org-roam-db-query [:select * :from refs]) :to-have-same-items-as - (list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org")))) + (list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org") "website"))) (delete-file (org-roam-test-abs-path "web_ref.org")) (expect (org-roam-db-query [:select * :from refs]) :to-have-same-items-as