mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
(feature): allow multiple org-roam directories (#178)
Each org-roam-directory gets its own cache. One can override the `org-roam-directory` variable locally via dir-locals: ((org-mode . ((eval . (setq-local org-roam-directory (expand-file-name "./"))))))
This commit is contained in:
@ -160,6 +160,7 @@ ITEM is of the form: (:from from-path :to to-path :properties (:content preview-
|
||||
(puthash file title file-titles)))
|
||||
org-roam-files))
|
||||
(list
|
||||
:directory dir
|
||||
:forward forward-links
|
||||
:backward backward-links
|
||||
:titles file-titles)))
|
||||
|
251
org-roam.el
251
org-roam.el
@ -42,6 +42,7 @@
|
||||
(require 's)
|
||||
(require 'f)
|
||||
(require 'org-roam-utils)
|
||||
(require 'eieio)
|
||||
|
||||
;;; Customizations
|
||||
(defgroup org-roam nil
|
||||
@ -159,29 +160,77 @@ If called interactively, then PARENTS is non-nil."
|
||||
(make-directory paren-dir parents)))
|
||||
(write-region "" nil filename nil 0)))
|
||||
|
||||
;;; Classes
|
||||
|
||||
(defclass org-roam-cache ()
|
||||
((initialized :initarg :initialized
|
||||
:documentation "Is cache valid?")
|
||||
(forward-links :initarg :forward-links
|
||||
:documentation "Cache containing forward links.")
|
||||
(backward-links :initarg :backward-links
|
||||
:documentation "Cache containing backward links.")
|
||||
(titles :initarg :titles
|
||||
:documentation "Cache containing titles for org-roam files."))
|
||||
"All cache for an org-roam directory.")
|
||||
|
||||
;;; Dynamic variables
|
||||
(defvar org-roam-cache-initialized nil
|
||||
"Boolean value indicating whether the cache is initialized.")
|
||||
|
||||
(defvar org-roam-forward-links-cache (make-hash-table :test #'equal)
|
||||
"Cache containing forward links.")
|
||||
|
||||
(defvar org-roam-backward-links-cache (make-hash-table :test #'equal)
|
||||
"Cache containing backward-links.")
|
||||
|
||||
(defvar org-roam-titles-cache (make-hash-table :test #'equal)
|
||||
"Cache containing titles for org-roam files.")
|
||||
|
||||
(defvar org-roam--current-buffer nil
|
||||
"Currently displayed file in `org-roam' buffer.")
|
||||
|
||||
(defvar org-roam-last-window nil
|
||||
"Last window `org-roam' was called from.")
|
||||
|
||||
(defvar org-roam--cache nil
|
||||
"The list of cache separated by directory.")
|
||||
|
||||
;;; Utilities
|
||||
(defun org-roam-directory-normalized ()
|
||||
"Get the org-roam-directory normalized so that it can be used
|
||||
as a unique key."
|
||||
(directory-file-name (file-truename org-roam-directory)))
|
||||
|
||||
(defmacro org-roam--get-local (name)
|
||||
"Get a variable that is local to the current org-roam-directory."
|
||||
`(alist-get (org-roam-directory-normalized) ,name nil nil #'equal))
|
||||
|
||||
(defmacro org-roam--set-local (name value)
|
||||
"Set a variable that is local to the current org-roam-directory."
|
||||
`(setf (alist-get (org-roam-directory-normalized) ,name nil nil #'equal)
|
||||
,value))
|
||||
|
||||
(defun org-roam--get-directory-cache ()
|
||||
"Get the cache object for the current org-roam-directory."
|
||||
(let* ((cache (org-roam--get-local org-roam--cache)))
|
||||
(if cache
|
||||
cache
|
||||
(let ((new-cache (org-roam--default-cache)))
|
||||
(org-roam--set-local org-roam--cache new-cache)
|
||||
new-cache))))
|
||||
|
||||
(defun org-roam--set-directory-cache (data)
|
||||
"Set the cache object for the current org-roam-directory."
|
||||
(setf (alist-get (org-roam-directory-normalized)
|
||||
org-roam--cache nil nil #'equal) data))
|
||||
|
||||
(defun org-roam--cache-initialized-p ()
|
||||
"Is cache valid?"
|
||||
(oref (org-roam--get-directory-cache) initialized))
|
||||
|
||||
(defun org-roam--forward-links-cache ()
|
||||
"Cache containing forward links."
|
||||
(oref (org-roam--get-directory-cache) forward-links))
|
||||
|
||||
(defun org-roam--backward-links-cache ()
|
||||
"Cache containing backward links."
|
||||
(oref (org-roam--get-directory-cache) backward-links))
|
||||
|
||||
(defun org-roam--titles-cache ()
|
||||
"Cache containing titles for org-roam files."
|
||||
(oref (org-roam--get-directory-cache) titles))
|
||||
|
||||
(defun org-roam--ensure-cache-built ()
|
||||
"Ensures that org-roam cache is built."
|
||||
(unless org-roam-cache-initialized
|
||||
(unless (org-roam--cache-initialized-p)
|
||||
(org-roam--build-cache-async)
|
||||
(user-error "Your Org-Roam cache isn't built yet! Please wait")))
|
||||
|
||||
@ -196,9 +245,9 @@ If called interactively, then PARENTS is non-nil."
|
||||
|
||||
(defun org-roam--get-title-from-cache (file)
|
||||
"Return title of `FILE' from the cache."
|
||||
(or (gethash file org-roam-titles-cache)
|
||||
(or (gethash file (org-roam--titles-cache))
|
||||
(progn
|
||||
(unless org-roam-cache-initialized
|
||||
(unless (org-roam--cache-initialized-p)
|
||||
(user-error "The Org-Roam caches aren't built! Please run org-roam--build-cache-async"))
|
||||
nil)))
|
||||
|
||||
@ -366,37 +415,44 @@ If PREFIX, downcase the title before insertion."
|
||||
build has completed.")
|
||||
|
||||
;;; Building the org-roam cache
|
||||
(defun org-roam--build-cache-async ()
|
||||
(defun org-roam--build-cache-async (&optional on-success)
|
||||
"Builds the caches asychronously."
|
||||
(interactive)
|
||||
(unless (and (processp org-roam--ongoing-async-build)
|
||||
(not (async-ready org-roam--ongoing-async-build)))
|
||||
(setq org-roam--ongoing-async-build
|
||||
(async-start
|
||||
`(lambda ()
|
||||
(setq load-path ',load-path)
|
||||
(package-initialize)
|
||||
(require 'org-roam-utils)
|
||||
,(async-inject-variables "org-roam-directory")
|
||||
(cons org-roam-directory (org-roam--build-cache org-roam-directory)))
|
||||
(lambda (pair)
|
||||
(let ((directory (car pair))
|
||||
(cache (cdr pair)))
|
||||
(setq org-roam-directory directory ;; ensure dir matches cache
|
||||
org-roam-forward-links-cache (plist-get cache :forward)
|
||||
org-roam-backward-links-cache (plist-get cache :backward)
|
||||
org-roam-titles-cache (plist-get cache :titles)
|
||||
org-roam-cache-initialized t)
|
||||
(unless org-roam-mute-cache-build
|
||||
(message "Org-roam cache built!"))))))))
|
||||
(let ((existing (org-roam--get-local org-roam--ongoing-async-build)))
|
||||
(unless (and (processp existing)
|
||||
(not (async-ready existing)))
|
||||
(org-roam--set-local
|
||||
org-roam--ongoing-async-build
|
||||
(async-start
|
||||
`(lambda ()
|
||||
(setq load-path ',load-path)
|
||||
(package-initialize)
|
||||
(require 'org-roam-utils)
|
||||
,(async-inject-variables "org-roam-directory")
|
||||
(org-roam--build-cache org-roam-directory))
|
||||
(lambda (cache)
|
||||
(let ((org-roam-directory (plist-get cache :directory)))
|
||||
(org-roam--set-directory-cache
|
||||
(org-roam-cache :initialized t
|
||||
:forward-links (plist-get cache :forward)
|
||||
:backward-links (plist-get cache :backward)
|
||||
:titles (plist-get cache :titles)))
|
||||
(unless org-roam-mute-cache-build
|
||||
(message "Org-roam cache built!"))
|
||||
(when on-success
|
||||
(funcall on-success)))))))))
|
||||
|
||||
(defun org-roam--clear-cache ()
|
||||
"Clears all entries in the caches."
|
||||
(interactive)
|
||||
(setq org-roam-cache-initialized nil)
|
||||
(setq org-roam-forward-links-cache (make-hash-table :test #'equal))
|
||||
(setq org-roam-backward-links-cache (make-hash-table :test #'equal))
|
||||
(setq org-roam-titles-cache (make-hash-table :test #'equal)))
|
||||
(org-roam--set-directory-cache (org-roam--default-cache)))
|
||||
|
||||
(defun org-roam--default-cache ()
|
||||
"A default, uninitialized cache object."
|
||||
(org-roam-cache :initialized nil
|
||||
:forward-links (make-hash-table :test #'equal)
|
||||
:backward-links (make-hash-table :test #'equal)
|
||||
:titles (make-hash-table :test #'equal)))
|
||||
|
||||
(defun org-roam--clear-file-from-cache (&optional filepath)
|
||||
"Remove any related links to the file.
|
||||
@ -406,23 +462,23 @@ This is equivalent to removing the node from the graph."
|
||||
(buffer-file-name (current-buffer))))
|
||||
(file (file-truename path)))
|
||||
;; Step 1: Remove all existing links for file
|
||||
(when-let ((forward-links (gethash file org-roam-forward-links-cache)))
|
||||
(when-let ((forward-links (gethash file (org-roam--forward-links-cache))))
|
||||
;; Delete backlinks to file
|
||||
(dolist (link forward-links)
|
||||
(when-let ((backward-links (gethash link org-roam-backward-links-cache)))
|
||||
(when-let ((backward-links (gethash link (org-roam--backward-links-cache))))
|
||||
(remhash file backward-links)
|
||||
(puthash link backward-links org-roam-backward-links-cache)))
|
||||
(puthash link backward-links (org-roam--backward-links-cache))))
|
||||
;; Clean out forward links
|
||||
(remhash file org-roam-forward-links-cache))
|
||||
(remhash file (org-roam--forward-links-cache)))
|
||||
;; Step 2: Remove from the title cache
|
||||
(remhash file org-roam-titles-cache)))
|
||||
(remhash file (org-roam--titles-cache))))
|
||||
|
||||
(defun org-roam--update-cache-title ()
|
||||
"Insert the title of the current buffer into the cache."
|
||||
(when-let ((title (org-roam--extract-title)))
|
||||
(puthash (file-truename (buffer-file-name (current-buffer)))
|
||||
title
|
||||
org-roam-titles-cache)))
|
||||
(org-roam--titles-cache))))
|
||||
|
||||
(defun org-roam--update-cache ()
|
||||
"Update org-roam caches for the current buffer file."
|
||||
@ -435,8 +491,8 @@ This is equivalent to removing the node from the graph."
|
||||
(dolist (item items)
|
||||
(org-roam--insert-item
|
||||
item
|
||||
:forward org-roam-forward-links-cache
|
||||
:backward org-roam-backward-links-cache)))
|
||||
:forward (org-roam--forward-links-cache)
|
||||
:backward (org-roam--backward-links-cache))))
|
||||
;; Rerender buffer
|
||||
(org-roam--maybe-update-buffer :redisplay t)))
|
||||
|
||||
@ -497,42 +553,46 @@ Bindings:
|
||||
|
||||
(defun org-roam-update (file-path)
|
||||
"Show the backlinks for given org file for file at `FILE-PATH'."
|
||||
(org-roam--ensure-cache-built)
|
||||
(let ((buffer-title (org-roam--get-title-or-slug file-path)))
|
||||
(with-current-buffer org-roam-buffer
|
||||
;; Locally overwrite the file opening function to re-use the
|
||||
;; last window org-roam was called from
|
||||
(setq-local
|
||||
org-link-frame-setup
|
||||
(cons '(file . org-roam--find-file) org-link-frame-setup))
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(when (not (eq major-mode 'org-roam-backlinks-mode))
|
||||
(org-roam-backlinks-mode))
|
||||
(make-local-variable 'org-return-follows-link)
|
||||
(setq org-return-follows-link t)
|
||||
(insert
|
||||
(propertize buffer-title 'font-lock-face 'org-document-title))
|
||||
(if-let ((backlinks (gethash file-path org-roam-backward-links-cache)))
|
||||
(progn
|
||||
(insert (format "\n\n* %d Backlinks\n"
|
||||
(hash-table-count backlinks)))
|
||||
(maphash (lambda (file-from contents)
|
||||
(insert (format "** [[file:%s][%s]]\n"
|
||||
file-from
|
||||
(org-roam--get-title-or-slug file-from)))
|
||||
(dolist (properties contents)
|
||||
(let ((content (propertize
|
||||
(s-trim (s-replace "\n" " "
|
||||
(plist-get properties :content)))
|
||||
'font-lock-face 'org-block
|
||||
'help-echo "mouse-1: visit backlinked note"
|
||||
'file-from file-from
|
||||
'file-from-point (plist-get properties :point))))
|
||||
(insert (format "%s \n\n" content)))))
|
||||
backlinks))
|
||||
(insert "\n\n* No backlinks!")))
|
||||
(read-only-mode 1))))
|
||||
(let* ((source-org-roam-directory org-roam-directory))
|
||||
(org-roam--ensure-cache-built)
|
||||
(let ((buffer-title (org-roam--get-title-or-slug file-path)))
|
||||
(with-current-buffer org-roam-buffer
|
||||
;; When dir-locals.el is used to override org-roam-directory,
|
||||
;; org-roam-buffer may have a different local org-roam-directory.
|
||||
(let ((org-roam-directory source-org-roam-directory))
|
||||
;; Locally overwrite the file opening function to re-use the
|
||||
;; last window org-roam was called from
|
||||
(setq-local
|
||||
org-link-frame-setup
|
||||
(cons '(file . org-roam--find-file) org-link-frame-setup))
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(when (not (eq major-mode 'org-roam-backlinks-mode))
|
||||
(org-roam-backlinks-mode))
|
||||
(make-local-variable 'org-return-follows-link)
|
||||
(setq org-return-follows-link t)
|
||||
(insert
|
||||
(propertize buffer-title 'font-lock-face 'org-document-title))
|
||||
(if-let ((backlinks (gethash file-path (org-roam--backward-links-cache))))
|
||||
(progn
|
||||
(insert (format "\n\n* %d Backlinks\n"
|
||||
(hash-table-count backlinks)))
|
||||
(maphash (lambda (file-from contents)
|
||||
(insert (format "** [[file:%s][%s]]\n"
|
||||
file-from
|
||||
(org-roam--get-title-or-slug file-from)))
|
||||
(dolist (properties contents)
|
||||
(let ((content (propertize
|
||||
(s-trim (s-replace "\n" " "
|
||||
(plist-get properties :content)))
|
||||
'font-lock-face 'org-block
|
||||
'help-echo "mouse-1: visit backlinked note"
|
||||
'file-from file-from
|
||||
'file-from-point (plist-get properties :point))))
|
||||
(insert (format "%s \n\n" content)))))
|
||||
backlinks))
|
||||
(insert "\n\n* No backlinks!")))
|
||||
(read-only-mode 1))))))
|
||||
|
||||
;;; Building the Graphviz graph
|
||||
(defun org-roam-build-graph ()
|
||||
@ -557,7 +617,7 @@ Bindings:
|
||||
(insert (format " \"%s\" -> \"%s\";\n"
|
||||
(org-roam--get-title-or-slug from-link)
|
||||
(org-roam--get-title-or-slug to-link)))))
|
||||
org-roam-forward-links-cache)
|
||||
(org-roam--forward-links-cache))
|
||||
(insert "}")
|
||||
(buffer-string)))
|
||||
|
||||
@ -588,6 +648,7 @@ This needs to be quick/infrequent, because this is run at
|
||||
(when (and (or redisplay
|
||||
(not (eq org-roam--current-buffer buffer)))
|
||||
(eq 'visible (org-roam--current-visibility))
|
||||
(org-roam--cache-initialized-p)
|
||||
(buffer-local-value 'buffer-file-truename buffer))
|
||||
(setq org-roam--current-buffer buffer)
|
||||
(org-roam-update (expand-file-name
|
||||
@ -609,9 +670,21 @@ Applies `org-roam-link-face' if PATH correponds to a Roam file."
|
||||
(defun org-roam--find-file-hook-function ()
|
||||
"Called by `find-file-hook' when `org-roam-mode' is on."
|
||||
(when (org-roam--org-roam-file-p)
|
||||
(org-link-set-parameters "file" :face 'org-roam--roam-link-face)
|
||||
(setq org-roam-last-window (get-buffer-window))
|
||||
(add-hook 'post-command-hook #'org-roam--maybe-update-buffer nil t)
|
||||
(add-hook 'after-save-hook #'org-roam--update-cache nil t)))
|
||||
(add-hook 'after-save-hook #'org-roam--update-cache nil t)
|
||||
(if (org-roam--cache-initialized-p)
|
||||
(org-roam--setup-found-file)
|
||||
(org-roam--build-cache-async
|
||||
(let ((buf (buffer-name)))
|
||||
#'(lambda ()
|
||||
(with-current-buffer buf
|
||||
(org-roam--setup-found-file))))))))
|
||||
|
||||
(defun org-roam--setup-found-file ()
|
||||
"Setup a buffer recognized via the \"find-file-hook\"."
|
||||
(org-link-set-parameters "file" :face 'org-roam--roam-link-face)
|
||||
(org-roam--maybe-update-buffer :redisplay nil))
|
||||
|
||||
(defvar org-roam-mode-map
|
||||
(make-sparse-keymap)
|
||||
@ -629,7 +702,7 @@ Applies `org-roam-link-face' if PATH correponds to a Roam file."
|
||||
(org-roam--ensure-cache-built)
|
||||
(org-roam--clear-file-from-cache file)
|
||||
|
||||
(let* ((files (gethash file org-roam-backward-links-cache nil))
|
||||
(let* ((files (gethash file (org-roam--backward-links-cache) nil))
|
||||
(path (file-truename file))
|
||||
(new-path (file-truename new-file))
|
||||
(slug (org-roam--get-title-or-slug file))
|
||||
@ -678,7 +751,7 @@ If ARG is `toggle', toggle `org-roam-mode'. Otherwise, behave as if called inter
|
||||
:global t
|
||||
(cond
|
||||
(org-roam-mode
|
||||
(unless org-roam-cache-initialized
|
||||
(unless (org-roam--cache-initialized-p)
|
||||
(org-roam--build-cache-async))
|
||||
(add-hook 'find-file-hook #'org-roam--find-file-hook-function)
|
||||
(advice-add 'rename-file :after #'org-roam--rename-file-advice)
|
||||
|
7
tests/roam-files-multi/mf1.org
Normal file
7
tests/roam-files-multi/mf1.org
Normal file
@ -0,0 +1,7 @@
|
||||
#+TITLE: Multi-File 1
|
||||
|
||||
link to [[file:nested/mf1.org][Nested Multi-File 1]]
|
||||
link to [[file:mf2.org][Multi-File 2]]
|
||||
|
||||
Arbitrary [[https://google.com][HTML]] link
|
||||
Arbitrary text
|
3
tests/roam-files-multi/mf2.org
Normal file
3
tests/roam-files-multi/mf2.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+TITLE: Multi-File 2
|
||||
|
||||
This file has no links.
|
5
tests/roam-files-multi/mf3.org
Normal file
5
tests/roam-files-multi/mf3.org
Normal file
@ -0,0 +1,5 @@
|
||||
#+TITLE: Multi-File 3
|
||||
|
||||
This file has a link to an file with no title.
|
||||
|
||||
[[file:multi-no-title.org][multi-no-title]]
|
1
tests/roam-files-multi/multi-no-title.org
Normal file
1
tests/roam-files-multi/multi-no-title.org
Normal file
@ -0,0 +1 @@
|
||||
no title in this file :O
|
4
tests/roam-files-multi/nested/mf1.org
Normal file
4
tests/roam-files-multi/nested/mf1.org
Normal file
@ -0,0 +1,4 @@
|
||||
#+TITLE: Nested Multi-File 1
|
||||
|
||||
Link to [[file:mf2.org][Nested Multi-File 2]]
|
||||
Link to [[file:../mf1.org][Mulit-File 1]]
|
3
tests/roam-files-multi/nested/mf2.org
Normal file
3
tests/roam-files-multi/nested/mf2.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+TITLE: Nested Multi-File 2
|
||||
|
||||
Link to [[file:mf1.org][Nested Multi-File 1]]
|
@ -42,6 +42,9 @@
|
||||
(defvar org-roam--tests-directory (file-truename (concat default-directory "tests/roam-files"))
|
||||
"Directory containing org-roam test org files.")
|
||||
|
||||
(defvar org-roam--tests-multi (file-truename (concat default-directory "tests/roam-files-multi"))
|
||||
"Directory containing org-roam test org files.")
|
||||
|
||||
(defun org-roam--test-init ()
|
||||
(let ((original-dir org-roam--tests-directory)
|
||||
(new-dir (expand-file-name (make-temp-name "org-roam") temporary-file-directory)))
|
||||
@ -50,37 +53,52 @@
|
||||
(setq org-roam-mute-cache-build t))
|
||||
(org-roam-mode +1))
|
||||
|
||||
(defun org-roam--test-multi-init ()
|
||||
(let ((original-dir-1 org-roam--tests-directory)
|
||||
(original-dir-2 org-roam--tests-multi)
|
||||
(new-dir-1 (expand-file-name (make-temp-name "org-roam") temporary-file-directory))
|
||||
(new-dir-2 (expand-file-name (make-temp-name "org-roam") temporary-file-directory)))
|
||||
(copy-directory original-dir-1 new-dir-1)
|
||||
(copy-directory original-dir-2 new-dir-2)
|
||||
(setq org-roam-directory new-dir-1)
|
||||
(setq org-roam-directory2 new-dir-2)
|
||||
(setq org-roam-mute-cache-build t))
|
||||
(org-roam-mode +1))
|
||||
|
||||
(defun org-roam--test-build-cache ()
|
||||
"Builds the caches synchronously."
|
||||
(let ((cache (org-roam--build-cache org-roam-directory)))
|
||||
(setq org-roam-forward-links-cache (plist-get cache :forward))
|
||||
(setq org-roam-backward-links-cache (plist-get cache :backward))
|
||||
(setq org-roam-titles-cache (plist-get cache :titles))
|
||||
(setq org-roam-cache-initialized t)))
|
||||
(org-roam--set-directory-cache
|
||||
(org-roam-cache :initialized t
|
||||
:forward-links (plist-get cache :forward)
|
||||
:backward-links (plist-get cache :backward)
|
||||
:titles (plist-get cache :titles)))))
|
||||
|
||||
;;; Tests
|
||||
(describe "org-roam--build-cache-async"
|
||||
(it "initializes correctly"
|
||||
(org-roam--test-init)
|
||||
(expect org-roam-cache-initialized :to-be nil)
|
||||
(expect (hash-table-count org-roam-forward-links-cache) :to-be 0)
|
||||
(expect (hash-table-count org-roam-backward-links-cache) :to-be 0)
|
||||
(expect (hash-table-count org-roam-titles-cache) :to-be 0)
|
||||
(expect (org-roam--cache-initialized-p) :to-be nil)
|
||||
(expect (hash-table-count (org-roam--forward-links-cache)) :to-be 0)
|
||||
(expect (hash-table-count (org-roam--backward-links-cache)) :to-be 0)
|
||||
(expect (hash-table-count (org-roam--titles-cache)) :to-be 0)
|
||||
|
||||
(org-roam--build-cache-async)
|
||||
(sleep-for 3) ;; Because it's async
|
||||
|
||||
;; Caches should be populated
|
||||
(expect org-roam-cache-initialized :to-be t)
|
||||
(expect (hash-table-count org-roam-forward-links-cache) :to-be 4)
|
||||
(expect (hash-table-count org-roam-backward-links-cache) :to-be 5)
|
||||
(expect (hash-table-count org-roam-titles-cache) :to-be 5)
|
||||
(expect (org-roam--cache-initialized-p) :to-be t)
|
||||
(expect (hash-table-count (org-roam--forward-links-cache)) :to-be 4)
|
||||
(expect (hash-table-count (org-roam--backward-links-cache)) :to-be 5)
|
||||
(expect (hash-table-count (org-roam--titles-cache)) :to-be 5)
|
||||
|
||||
;; Forward cache
|
||||
(let ((f1 (gethash (abs-path "f1.org") org-roam-forward-links-cache))
|
||||
(f2 (gethash (abs-path "f2.org") org-roam-forward-links-cache))
|
||||
(nested-f1 (gethash (abs-path "nested/f1.org") org-roam-forward-links-cache))
|
||||
(nested-f2 (gethash (abs-path "nested/f2.org") org-roam-forward-links-cache))
|
||||
(let ((f1 (gethash (abs-path "f1.org") (org-roam--forward-links-cache)))
|
||||
(f2 (gethash (abs-path "f2.org") (org-roam--forward-links-cache)))
|
||||
(nested-f1 (gethash (abs-path "nested/f1.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(nested-f2 (gethash (abs-path "nested/f2.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")
|
||||
(abs-path "f2.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
@ -93,10 +111,14 @@
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Backward cache
|
||||
(let ((f1 (hash-table-keys (gethash (abs-path "f1.org") org-roam-backward-links-cache)))
|
||||
(f2 (hash-table-keys (gethash (abs-path "f2.org") org-roam-backward-links-cache)))
|
||||
(nested-f1 (hash-table-keys(gethash (abs-path "nested/f1.org") org-roam-backward-links-cache)))
|
||||
(nested-f2 (hash-table-keys (gethash (abs-path "nested/f2.org") org-roam-backward-links-cache)))
|
||||
(let ((f1 (hash-table-keys (gethash (abs-path "f1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(f2 (hash-table-keys (gethash (abs-path "f2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-f1 (hash-table-keys(gethash (abs-path "nested/f1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-f2 (hash-table-keys (gethash (abs-path "nested/f2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")))
|
||||
(expected-f2 (list (abs-path "f1.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
@ -108,11 +130,153 @@
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Titles Cache
|
||||
(expect (gethash (abs-path "f1.org") org-roam-titles-cache) :to-equal "File 1")
|
||||
(expect (gethash (abs-path "f2.org") org-roam-titles-cache) :to-equal "File 2")
|
||||
(expect (gethash (abs-path "nested/f1.org") org-roam-titles-cache) :to-equal "Nested File 1")
|
||||
(expect (gethash (abs-path "nested/f2.org") org-roam-titles-cache) :to-equal "Nested File 2")
|
||||
(expect (gethash (abs-path "no-title.org") org-roam-titles-cache) :to-be nil)))
|
||||
(expect (gethash (abs-path "f1.org") (org-roam--titles-cache)) :to-equal "File 1")
|
||||
(expect (gethash (abs-path "f2.org") (org-roam--titles-cache)) :to-equal "File 2")
|
||||
(expect (gethash (abs-path "nested/f1.org") (org-roam--titles-cache)) :to-equal "Nested File 1")
|
||||
(expect (gethash (abs-path "nested/f2.org") (org-roam--titles-cache)) :to-equal "Nested File 2")
|
||||
(expect (gethash (abs-path "no-title.org") (org-roam--titles-cache)) :to-be nil)))
|
||||
|
||||
(describe "org-roam--build-cache-async-multi"
|
||||
(it "initializes correctly"
|
||||
(org-roam--clear-cache)
|
||||
(org-roam--test-multi-init)
|
||||
(expect (org-roam--cache-initialized-p) :to-be nil)
|
||||
(expect (hash-table-count (org-roam--forward-links-cache)) :to-be 0)
|
||||
(expect (hash-table-count (org-roam--backward-links-cache)) :to-be 0)
|
||||
(expect (hash-table-count (org-roam--titles-cache)) :to-be 0)
|
||||
|
||||
(org-roam--build-cache-async)
|
||||
(sleep-for 3) ;; Because it's async
|
||||
|
||||
;; Caches should be populated
|
||||
(expect (org-roam--cache-initialized-p) :to-be t)
|
||||
(expect (hash-table-count (org-roam--forward-links-cache)) :to-be 4)
|
||||
(expect (hash-table-count (org-roam--backward-links-cache)) :to-be 5)
|
||||
(expect (hash-table-count (org-roam--titles-cache)) :to-be 5)
|
||||
|
||||
;; Forward cache
|
||||
(let ((f1 (gethash (abs-path "f1.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(f2 (gethash (abs-path "f2.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(nested-f1 (gethash (abs-path "nested/f1.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(nested-f2 (gethash (abs-path "nested/f2.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")
|
||||
(abs-path "f2.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
(abs-path "f1.org")))
|
||||
(expected-nested-f2 (list (abs-path "nested/f1.org"))))
|
||||
|
||||
(expect f1 :to-have-same-items-as expected-f1)
|
||||
(expect f2 :to-be nil)
|
||||
(expect nested-f1 :to-have-same-items-as expected-nested-f1)
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Backward cache
|
||||
(let ((f1 (hash-table-keys (gethash (abs-path "f1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(f2 (hash-table-keys (gethash (abs-path "f2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-f1 (hash-table-keys
|
||||
(gethash (abs-path "nested/f1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-f2 (hash-table-keys
|
||||
(gethash (abs-path "nested/f2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")))
|
||||
(expected-f2 (list (abs-path "f1.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
(abs-path "f1.org")))
|
||||
(expected-nested-f2 (list (abs-path "nested/f1.org"))))
|
||||
(expect f1 :to-have-same-items-as expected-f1)
|
||||
(expect f2 :to-have-same-items-as expected-f2)
|
||||
(expect nested-f1 :to-have-same-items-as expected-nested-f1)
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Titles Cache
|
||||
(expect (gethash (abs-path "f1.org")
|
||||
(org-roam--titles-cache)) :to-equal "File 1")
|
||||
(expect (gethash (abs-path "f2.org")
|
||||
(org-roam--titles-cache)) :to-equal "File 2")
|
||||
(expect (gethash (abs-path "nested/f1.org")
|
||||
(org-roam--titles-cache)) :to-equal "Nested File 1")
|
||||
(expect (gethash (abs-path "nested/f2.org")
|
||||
(org-roam--titles-cache)) :to-equal "Nested File 2")
|
||||
(expect (gethash (abs-path "no-title.org")
|
||||
(org-roam--titles-cache)) :to-be nil)
|
||||
|
||||
;; Multi
|
||||
(let ((org-roam-directory org-roam-directory2))
|
||||
(org-roam--build-cache-async)
|
||||
(sleep-for 3) ;; Because it's async
|
||||
|
||||
;; Caches should be populated
|
||||
(expect (org-roam--cache-initialized-p) :to-be t)
|
||||
(expect (hash-table-count (org-roam--forward-links-cache)) :to-be 4)
|
||||
(expect (hash-table-count (org-roam--backward-links-cache)) :to-be 5)
|
||||
(expect (hash-table-count (org-roam--titles-cache)) :to-be 5)
|
||||
|
||||
;; Forward cache
|
||||
(let ((mf1 (gethash (abs-path "mf1.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(mf2 (gethash (abs-path "mf2.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(nested-mf1 (gethash (abs-path "nested/mf1.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(nested-mf2 (gethash (abs-path "nested/mf2.org")
|
||||
(org-roam--forward-links-cache)))
|
||||
(expected-mf1 (list (abs-path "nested/mf1.org")
|
||||
(abs-path "mf2.org")))
|
||||
(expected-nested-mf1 (list (abs-path "nested/mf2.org")
|
||||
(abs-path "mf1.org")))
|
||||
(expected-nested-mf2 (list (abs-path "nested/mf1.org"))))
|
||||
|
||||
(expect mf1 :to-have-same-items-as expected-mf1)
|
||||
(expect mf2 :to-be nil)
|
||||
(expect nested-mf1 :to-have-same-items-as expected-nested-mf1)
|
||||
(expect nested-mf2 :to-have-same-items-as expected-nested-mf2))
|
||||
|
||||
;; Backward cache
|
||||
(let ((mf1 (hash-table-keys
|
||||
(gethash (abs-path "mf1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(mf2 (hash-table-keys
|
||||
(gethash (abs-path "mf2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-mf1 (hash-table-keys
|
||||
(gethash (abs-path "nested/mf1.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(nested-mf2 (hash-table-keys
|
||||
(gethash (abs-path "nested/mf2.org")
|
||||
(org-roam--backward-links-cache))))
|
||||
(expected-mf1 (list (abs-path "nested/mf1.org")))
|
||||
(expected-mf2 (list (abs-path "mf1.org")))
|
||||
(expected-nested-mf1 (list (abs-path "nested/mf2.org")
|
||||
(abs-path "mf1.org")))
|
||||
(expected-nested-mf2 (list (abs-path "nested/mf1.org"))))
|
||||
(expect mf1 :to-have-same-items-as expected-mf1)
|
||||
(expect mf2 :to-have-same-items-as expected-mf2)
|
||||
(expect nested-mf1 :to-have-same-items-as expected-nested-mf1)
|
||||
(expect nested-mf2 :to-have-same-items-as expected-nested-mf2))
|
||||
|
||||
;; Titles Cache
|
||||
(expect (gethash (abs-path "mf1.org")
|
||||
(org-roam--titles-cache))
|
||||
:to-equal "Multi-File 1")
|
||||
(expect (gethash (abs-path "mf2.org")
|
||||
(org-roam--titles-cache))
|
||||
:to-equal "Multi-File 2")
|
||||
(expect (gethash (abs-path "nested/mf1.org")
|
||||
(org-roam--titles-cache))
|
||||
:to-equal "Nested Multi-File 1")
|
||||
(expect (gethash (abs-path "nested/mf2.org")
|
||||
(org-roam--titles-cache))
|
||||
:to-equal "Nested Multi-File 2")
|
||||
(expect (gethash (abs-path "no-title.org")
|
||||
(org-roam--titles-cache))
|
||||
:to-be nil))))
|
||||
|
||||
(describe "org-roam-insert"
|
||||
(before-each
|
||||
@ -162,16 +326,16 @@
|
||||
(rename-file (abs-path "f1.org")
|
||||
(abs-path "new_f1.org"))
|
||||
;; Cache should be cleared of old file
|
||||
(expect (gethash (abs-path "f1.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(expect (gethash (abs-path "f1.org") (org-roam--forward-links-cache)) :to-be nil)
|
||||
(expect (->> (org-roam--backward-links-cache)
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(hash-table-keys)
|
||||
(member (abs-path "f1.org"))) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(expect (->> (org-roam--forward-links-cache)
|
||||
(gethash (abs-path "new_f1.org"))) :not :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(expect (->> (org-roam--forward-links-cache)
|
||||
(gethash (abs-path "new_f1.org"))
|
||||
(member (abs-path "nested/f1.org"))) :not :to-be nil)
|
||||
;; Links are updated
|
||||
@ -184,8 +348,8 @@
|
||||
(rename-file (abs-path "f1.org")
|
||||
(abs-path "f1 with spaces.org"))
|
||||
;; Cache should be cleared of old file
|
||||
(expect (gethash (abs-path "f1.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(expect (gethash (abs-path "f1.org") (org-roam--forward-links-cache)) :to-be nil)
|
||||
(expect (->> (org-roam--backward-links-cache)
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(hash-table-keys)
|
||||
(member (abs-path "f1.org"))) :to-be nil)
|
||||
@ -198,14 +362,15 @@
|
||||
(rename-file (abs-path "no-title.org")
|
||||
(abs-path "meaningful-title.org"))
|
||||
;; File has no forward links
|
||||
(expect (gethash (abs-path "no-title.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (gethash (abs-path "meaningful-title.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (gethash (abs-path "no-title.org") (org-roam--forward-links-cache)) :to-be nil)
|
||||
(expect (gethash (abs-path "meaningful-title.org")
|
||||
(org-roam--forward-links-cache)) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(expect (->> (org-roam--forward-links-cache)
|
||||
(gethash (abs-path "f3.org"))
|
||||
(member (abs-path "no-title.org"))) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(expect (->> (org-roam--forward-links-cache)
|
||||
(gethash (abs-path "f3.org"))
|
||||
(member (abs-path "meaningful-title.org"))) :not :to-be nil)
|
||||
|
||||
@ -221,11 +386,11 @@
|
||||
(org-roam--test-build-cache))
|
||||
(it "delete f1"
|
||||
(delete-file (abs-path "f1.org"))
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(expect (->> (org-roam--forward-links-cache)
|
||||
(gethash (abs-path "f1.org"))) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(expect (->> (org-roam--backward-links-cache)
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(gethash (abs-path "f1.org"))) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(expect (->> (org-roam--backward-links-cache)
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(gethash (abs-path "nested/f2.org"))) :not :to-be nil)))
|
||||
|
Reference in New Issue
Block a user