diff --git a/README.md b/README.md index 238f7fb..4adaedd 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Here's a sample configuration with `use-package`: ;; Dailies ("C-c n j" . org-roam-dailies-capture-today)) :config - (org-roam-setup) + (org-roam-db-autosync-mode) ;; If using org-roam-protocol (require 'org-roam-protocol)) ``` diff --git a/doc/org-roam.org b/doc/org-roam.org index 6e7cae5..b6a9b9a 100644 --- a/doc/org-roam.org +++ b/doc/org-roam.org @@ -308,7 +308,7 @@ is to use [[https://www.msys2.org/][MSYS2]] as at the time of this writing: Note that you do not need to manually set the PATH for MSYS2; the installer automatically takes care of it for you. -4. Open Emacs and call ~M-x org-roam-setup~ +4. Open Emacs and call ~M-x org-roam-db-autosync-mode~ This will automatically start compiling ~emacsql-sqlite~; you should see a message in minibuffer. It may take a while until compilation completes. Once @@ -376,12 +376,12 @@ The ~file-truename~ function is only necessary when you use symbolic links inside ~org-roam-directory~: Org-roam does not resolve symbolic links. Next, we setup Org-roam to run functions on file changes to maintain cache -consistency. This is achieved by running ~M-x org-roam-setup~. To ensure that -Org-roam is available on startup, place this in your Emacs configuration: +consistency. This is achieved by running ~M-x org-roam-db-autosync-mode~. To +ensure that Org-roam is available on startup, place this in your Emacs +configuration: #+begin_src emacs-lisp - (require 'org-roam) - (org-roam-setup) +(org-roam-db-autosync-mode) #+end_src To build the cache manually, run ~M-x org-roam-db-sync~. Cache builds may diff --git a/doc/org-roam.texi b/doc/org-roam.texi index 4a2cd5f..943c1a9 100644 --- a/doc/org-roam.texi +++ b/doc/org-roam.texi @@ -550,7 +550,7 @@ installer automatically takes care of it for you. @itemize @item -Open Emacs and call @code{M-x org-roam-setup} +Open Emacs and call @code{M-x org-roam-db-autosync-mode} This will automatically start compiling @code{emacsql-sqlite}; you should see a @end itemize @@ -637,12 +637,12 @@ The @code{file-truename} function is only necessary when you use symbolic links inside @code{org-roam-directory}: Org-roam does not resolve symbolic links. Next, we setup Org-roam to run functions on file changes to maintain cache -consistency. This is achieved by running @code{M-x org-roam-setup}. To ensure that -Org-roam is available on startup, place this in your Emacs configuration: +consistency. This is achieved by running @code{M-x org-roam-db-autosync-mode~}. +To ensure that Org-roam is available on startup, place this in your Emacs +configuration: @lisp -(require 'org-roam) -(org-roam-setup) +(org-roam-db-autosync-mode) @end lisp To build the cache manually, run @code{M-x org-roam-db-sync}. Cache builds may diff --git a/org-roam-compat.el b/org-roam-compat.el index bda8032..edff0de 100644 --- a/org-roam-compat.el +++ b/org-roam-compat.el @@ -96,6 +96,13 @@ recursion." (nconc result (nreverse files)))) ;;; Obsolete aliases (remove after next major release) +(define-obsolete-function-alias + 'org-roam-setup + 'org-roam-db-autosync-enable "org-roam 2.0") +(define-obsolete-function-alias + 'org-roam-teardown + 'org-roam-db-autosync-disable "org-roam 2.0") + (define-obsolete-variable-alias 'org-roam-current-node 'org-roam-buffer-current-node "org-roam 2.0") diff --git a/org-roam-db.el b/org-roam-db.el index ffdbad1..f48fe12 100644 --- a/org-roam-db.el +++ b/org-roam-db.el @@ -469,7 +469,32 @@ If UPDATE-P is non-nil, first remove the file in the database." (org-with-wide-buffer (secure-hash 'sha1 (current-buffer))))) -;;;; Interactives +;;;; Synchronization +(defun org-roam-db-update-file (&optional file-path) + "Update Org-roam cache for FILE-PATH. +If the file does not exist anymore, remove it from the cache. +If the file exists, update the cache with information." + (setq file-path (or file-path (buffer-file-name (buffer-base-buffer)))) + (let ((content-hash (org-roam-db--file-hash file-path)) + (db-hash (caar (org-roam-db-query [:select hash :from files + :where (= file $s1)] file-path)))) + (unless (string= content-hash db-hash) + (org-roam-with-file file-path nil + (save-excursion + (org-set-regexps-and-options 'tags-only) + (org-roam-db-clear-file) + (org-roam-db-insert-file) + (org-roam-db-insert-file-node) + (setq org-outline-path-cache nil) + (org-roam-db-map-nodes + (list #'org-roam-db-insert-node-data + #'org-roam-db-insert-aliases + #'org-roam-db-insert-tags + #'org-roam-db-insert-refs)) + (setq org-outline-path-cache nil) + (org-roam-db-map-links + (list #'org-roam-db-insert-link))))))) + ;;;###autoload (defun org-roam-db-sync (&optional force) "Synchronize the cache state with the current Org files on-disk. @@ -503,42 +528,90 @@ If FORCE, force a rebuild of the cache from scratch." (dolist (file modified-files) (org-roam-db-update-file file)))))) -(defun org-roam-db-update-file (&optional file-path) - "Update Org-roam cache for FILE-PATH. -If the file does not exist anymore, remove it from the cache. -If the file exists, update the cache with information." - (setq file-path (or file-path (buffer-file-name (buffer-base-buffer)))) - (let ((content-hash (org-roam-db--file-hash file-path)) - (db-hash (caar (org-roam-db-query [:select hash :from files - :where (= file $s1)] file-path)))) - (unless (string= content-hash db-hash) - (org-roam-with-file file-path nil - (save-excursion - (org-set-regexps-and-options 'tags-only) - (org-roam-db-clear-file) - (org-roam-db-insert-file) - (org-roam-db-insert-file-node) - (setq org-outline-path-cache nil) - (org-roam-db-map-nodes - (list #'org-roam-db-insert-node-data - #'org-roam-db-insert-aliases - #'org-roam-db-insert-tags - #'org-roam-db-insert-refs)) - (setq org-outline-path-cache nil) - (org-roam-db-map-links - (list #'org-roam-db-insert-link))))))) +;;;###autoload +(define-minor-mode org-roam-db-autosync-mode + "Global minor mode to keep your Org-roam session automatically synchronized. +Through the session this will continue to setup your +buffers (that are Org-roam file visiting), keep track of the +related changes, maintain cache consistency and incrementally +update the currently active database. -;;;; Hook Setups -(add-hook 'org-roam-find-file-hook #'org-roam-db--setup-update-on-save-h) -(defun org-roam-db--setup-update-on-save-h () +If you need to manually trigger resync of the currently active +database, see `org-roam-db-sync' command." + :group 'org-roam + :global t + :init-value nil + (let ((enabled org-roam-db-autosync-mode)) + (cond + (enabled + (add-hook 'find-file-hook #'org-roam-db-autosync--setup-file-h) + (add-hook 'kill-emacs-hook #'org-roam-db--close-all) + (advice-add #'rename-file :after #'org-roam-db-autosync--rename-file-a) + (advice-add #'delete-file :before #'org-roam-db-autosync--delete-file-a) + (org-roam-db-sync)) + (t + (remove-hook 'find-file-hook #'org-roam-db-autosync--setup-file-h) + (remove-hook 'kill-emacs-hook #'org-roam-db--close-all) + (advice-remove #'rename-file #'org-roam-db-autosync--rename-file-a) + (advice-remove #'delete-file #'org-roam-db-autosync--delete-file-a) + (org-roam-db--close-all) + ;; Disable local hooks for all org-roam buffers + (dolist (buf (org-roam-buffer-list)) + (with-current-buffer buf + (remove-hook 'after-save-hook #'org-roam-db-autosync--try-update-on-save-h t))))))) + +;;;###autoload +(defun org-roam-db-autosync-enable () + "Activate `org-roam-db-autosync-mode'." + (org-roam-db-autosync-mode +1)) + +(defun org-roam-db-autosync-disable () + "Deactivate `org-roam-db-autosync-mode'." + (org-roam-db-autosync-mode -1)) + +(defun org-roam-db-autosync-toggle () + "Toggle `org-roam-db-autosync-mode' enabled/disabled." + (org-roam-db-autosync-mode 'toggle)) + +(defun org-roam-db-autosync--delete-file-a (file &optional _trash) + "Maintain cache consistency when file deletes. +FILE is removed from the database." + (when (and (not (auto-save-file-name-p file)) + (not (backup-file-name-p file)) + (org-roam-file-p file)) + (org-roam-db-clear-file (expand-file-name file)))) + +(defun org-roam-db-autosync--rename-file-a (old-file new-file-or-dir &rest _args) + "Maintain cache consistency of file rename. +OLD-FILE is cleared from the database, and NEW-FILE-OR-DIR is added." + (let ((new-file (if (directory-name-p new-file-or-dir) + (expand-file-name (file-name-nondirectory old-file) new-file-or-dir) + new-file-or-dir))) + (setq new-file (expand-file-name new-file)) + (setq old-file (expand-file-name old-file)) + (when (and (not (auto-save-file-name-p old-file)) + (not (auto-save-file-name-p new-file)) + (not (backup-file-name-p old-file)) + (not (backup-file-name-p new-file)) + (org-roam-file-p old-file)) + (org-roam-db-clear-file old-file)) + (when (org-roam-file-p new-file) + (org-roam-db-update-file new-file)))) + +(defun org-roam-db-autosync--setup-file-h () + "Setup the current buffer if it visits an Org-roam file." + (when (org-roam-file-p) (run-hooks 'org-roam-find-file-hook))) + +(add-hook 'org-roam-find-file-hook #'org-roam-db-autosync--setup-update-on-save-h) +(defun org-roam-db-autosync--setup-update-on-save-h () "Setup the current buffer to update the DB after saving the current file." - (add-hook 'after-save-hook #'org-roam-db--try-update-on-save-h nil t)) + (add-hook 'after-save-hook #'org-roam-db-autosync--try-update-on-save-h nil t)) -(defun org-roam-db--try-update-on-save-h () +(defun org-roam-db-autosync--try-update-on-save-h () "If appropriate, update the database for the current file after saving buffer." (when org-roam-db-update-on-save (org-roam-db-update-file))) -;; Diagnostic Interactives +;;; Diagnostics (defun org-roam-db-diagnose-node () "Print information about node at point." (interactive) diff --git a/org-roam.el b/org-roam.el index dc393a2..0d16746 100644 --- a/org-roam.el +++ b/org-roam.el @@ -49,10 +49,10 @@ ;; ;; ----------------------------------------------------------------------------- ;; -;; In order for the package to correctly work it's mandatory to add somewhere to -;; your configuration the next form: +;; In order for the package to correctly work through your interactive session +;; it's mandatory to add somewhere to your configuration the next form: ;; -;; (org-roam-setup) +;; (org-roam-db-autosync-mode) ;; ;; The form can be called both, before or after loading the package, which is up ;; to your preferences. If you call this before the package is loaded, then it @@ -178,66 +178,7 @@ method symbol as a cons cell. For example: '(find (rg . \"/path/to/rg\"))." (const :tag "rg" rg) (const :tag "elisp" nil))) -;;; Session watcher -;;;###autoload -(defun org-roam-setup () - "Setup Org-roam and initialize its database. -This will install the needed hooks and advices to keep everything -in sync with the connected databases." - (interactive) - (add-hook 'find-file-hook #'org-roam--file-setup-h) - (add-hook 'kill-emacs-hook #'org-roam-db--close-all) - (advice-add 'rename-file :after #'org-roam--rename-file-a) - (advice-add 'delete-file :before #'org-roam--delete-file-a) - (org-roam-db-sync)) - -(defun org-roam-teardown () - "Teardown Org-roam to completely disable it. -This will remove all the hooks and advices installed by -`org-roam-setup' and close all the database connections made by -Org-roam." - (interactive) - (remove-hook 'find-file-hook #'org-roam--file-setup-h) - (remove-hook 'kill-emacs-hook #'org-roam-db--close-all) - (advice-remove 'rename-file #'org-roam--rename-file-a) - (advice-remove 'delete-file #'org-roam--delete-file-a) - (org-roam-db--close-all) - ;; Disable local hooks for all org-roam buffers - (dolist (buf (org-roam-buffer-list)) - (with-current-buffer buf - (remove-hook 'after-save-hook #'org-roam-db--try-update-on-save-h t)))) - -(defun org-roam--file-setup-h () - "Setup an Org-roam file." - (when (org-roam-file-p) - (run-hooks 'org-roam-find-file-hook))) - -(defun org-roam--delete-file-a (file &optional _trash) - "Maintain cache consistency when file deletes. -FILE is removed from the database." - (when (and (not (auto-save-file-name-p file)) - (not (backup-file-name-p file)) - (org-roam-file-p file)) - (org-roam-db-clear-file (expand-file-name file)))) - -(defun org-roam--rename-file-a (old-file new-file-or-dir &rest _args) - "Maintain cache consistency of file rename. -OLD-FILE is cleared from the database, and NEW-FILE-OR-DIR is added." - (let ((new-file (if (directory-name-p new-file-or-dir) - (expand-file-name (file-name-nondirectory old-file) new-file-or-dir) - new-file-or-dir))) - (setq new-file (expand-file-name new-file)) - (setq old-file (expand-file-name old-file)) - (when (and (not (auto-save-file-name-p old-file)) - (not (auto-save-file-name-p new-file)) - (not (backup-file-name-p old-file)) - (not (backup-file-name-p new-file)) - (org-roam-file-p old-file)) - (org-roam-db-clear-file old-file)) - (when (org-roam-file-p new-file) - (org-roam-db-update-file new-file)))) - -;;;; Library +;;; Library (defun org-roam-file-p (&optional file) "Return t if FILE is an Org-roam file, nil otherwise. If FILE is not specified, use the current buffer's file-path. diff --git a/tests/test-org-roam.el b/tests/test-org-roam.el index c292fba..4921807 100644 --- a/tests/test-org-roam.el +++ b/tests/test-org-roam.el @@ -54,7 +54,7 @@ (org-roam-db-sync)) (after-all - (org-roam-teardown) + (org-roam-db--close) (delete-file org-roam-db-location)) (it "has the correct number of files"