mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
(feat): rename file on title change (#1073)
Adds `org-roam-title-change-hook`. This now contains two functions: 1. `org-roam--update-links-on-title-change`: updates the link description of all files that link to the current file. 2. `org-roam--update-file-name-on-title-change`: updates the current buffer's filename to reflect the updated title.
This commit is contained in:
@ -9,7 +9,8 @@ In this release we support fuzzy links of the form `[[Title]]`, `[[*Headline]]`
|
||||
- [#910](https://github.com/org-roam/org-roam/pull/910) Deprecate `company-org-roam`, using `completion-at-point` instead. To use this with company, add the `company-capf` backend instead.
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
- [#1073](https://github.com/org-roam/org-roam/pull/1073) Rename file on title change, when `org-roam-rename-file-on-title-change` is non-nil.
|
||||
- [#1071](https://github.com/org-roam/org-roam/pull/1071) Update link descriptions on title changes, and clean-up rename file advice
|
||||
- [#1061](https://github.com/org-roam/org-roam/pull/1061) Speed up the extraction of file properties, headlines, and titles
|
||||
- [#1046](https://github.com/org-roam/org-roam/pull/1046) New user option to exclude files from Org-roam
|
||||
|
@ -461,22 +461,24 @@ connections, nil is returned."
|
||||
(org-roam-db--insert-headlines headlines))))
|
||||
|
||||
(defun org-roam-db--update-file (&optional file-path)
|
||||
"Update Org-roam cache for FILE-PATH."
|
||||
(when (org-roam--org-roam-file-p file-path)
|
||||
(let ((buf (or (and file-path
|
||||
(find-file-noselect file-path t))
|
||||
(current-buffer))))
|
||||
(with-current-buffer buf
|
||||
(org-with-wide-buffer
|
||||
(emacsql-with-transaction (org-roam-db)
|
||||
(org-roam-db--update-meta)
|
||||
(org-roam-db--update-tags)
|
||||
(org-roam-db--update-titles)
|
||||
(org-roam-db--update-refs)
|
||||
(when org-roam-enable-headline-linking
|
||||
(org-roam-db--update-headlines))
|
||||
(org-roam-db--update-links)))
|
||||
(org-roam-buffer--update-maybe :redisplay t)))))
|
||||
"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))))
|
||||
(cond ((not (file-exists-p file-path))
|
||||
(org-roam-db--clear-file file-path))
|
||||
((org-roam--org-roam-file-p file-path)
|
||||
(with-current-buffer (find-file-noselect file-path t)
|
||||
(org-with-wide-buffer
|
||||
(emacsql-with-transaction (org-roam-db)
|
||||
(org-roam-db--update-meta)
|
||||
(org-roam-db--update-tags)
|
||||
(org-roam-db--update-titles)
|
||||
(org-roam-db--update-refs)
|
||||
(when org-roam-enable-headline-linking
|
||||
(org-roam-db--update-headlines))
|
||||
(org-roam-db--update-links)))))))
|
||||
|
||||
(defun org-roam-db-build-cache (&optional force)
|
||||
"Build the cache for `org-roam-directory'.
|
||||
|
83
org-roam.el
83
org-roam.el
@ -1527,34 +1527,75 @@ replaced links are made relative to the current buffer."
|
||||
(replace-match (concat type ":" new-path)
|
||||
nil t nil 1))))))))
|
||||
|
||||
(defcustom org-roam-rename-file-on-title-change t
|
||||
"If non-nil, alter the filename on title change.
|
||||
The new title is converted into a slug using
|
||||
`org-roam-title-to-slug-function', and compared with the current
|
||||
filename."
|
||||
:group 'org-roam
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-roam-title-change-hook '(org-roam--update-file-name-on-title-change
|
||||
org-roam--update-links-on-title-change)
|
||||
"Hook run after detecting a title change.
|
||||
Each hook is passed two arguments: the old title, and new title
|
||||
respectively."
|
||||
:group 'org-roam
|
||||
:type 'hook)
|
||||
|
||||
(defvar-local org-roam-current-title nil
|
||||
"The current title of the Org-roam file.")
|
||||
|
||||
(defun org-roam--handle-title-change ()
|
||||
"Detect a title change, and run `org-roam-title-change-hook'."
|
||||
(let ((new-title (car (org-roam--extract-titles)))
|
||||
(old-title org-roam-current-title))
|
||||
(unless (string-equal old-title new-title)
|
||||
(run-hook-with-args 'org-roam-title-change-hook old-title new-title)
|
||||
(setq-local org-roam-current-title new-title))))
|
||||
|
||||
(defun org-roam--setup-title-auto-update ()
|
||||
"Setup automatic link description update on title change."
|
||||
(setq-local org-roam-current-title (car (org-roam--extract-titles)))
|
||||
(add-hook 'after-save-hook #'org-roam--update-links-on-title-change nil t))
|
||||
(add-hook 'after-save-hook #'org-roam--handle-title-change nil t))
|
||||
|
||||
(defun org-roam--update-links-on-title-change ()
|
||||
"Update the link description of other Org-roam files on title change.
|
||||
This function is to be called in `after-save-hook'. If the title
|
||||
of the Org-roam file has changed, it will iterate over all
|
||||
Org-roam files that link to the current file, and replace the
|
||||
link descriptions with the new title if applicable."
|
||||
(let ((new-title (car (org-roam--extract-titles)))
|
||||
(old-title org-roam-current-title))
|
||||
(unless (string-equal old-title new-title)
|
||||
(let* ((current-path (file-truename (buffer-file-name)))
|
||||
(files-affected (org-roam-db-query [:select :distinct [from]
|
||||
:from links
|
||||
:where (= to $s1)]
|
||||
current-path)))
|
||||
(dolist (file files-affected)
|
||||
(with-current-buffer (or (find-buffer-visiting (car file))
|
||||
(find-file-noselect (car file)))
|
||||
(org-roam--replace-link current-path current-path old-title new-title)
|
||||
(save-buffer)))))
|
||||
(setq-local org-roam-current-title new-title)))
|
||||
(defun org-roam--update-links-on-title-change (old-title new-title)
|
||||
"Update the link description of other Org-roam files.
|
||||
Iterate over all Org-roam files that have link description of
|
||||
OLD-TITLE, and replace the link descriptions with the NEW-TITLE
|
||||
if applicable.
|
||||
|
||||
To be added to `org-roam-title-change-hook'."
|
||||
(let* ((current-path (file-truename (buffer-file-name)))
|
||||
(files-affected (org-roam-db-query [:select :distinct [from]
|
||||
:from links
|
||||
:where (= to $s1)]
|
||||
current-path)))
|
||||
(dolist (file files-affected)
|
||||
(with-current-buffer (or (find-buffer-visiting (car file))
|
||||
(find-file-noselect (car file)))
|
||||
(org-roam--replace-link current-path current-path old-title new-title)
|
||||
(save-buffer)))))
|
||||
|
||||
(defun org-roam--update-file-name-on-title-change (old-title new-title)
|
||||
"Update the file name on title change.
|
||||
The slug is computed from OLD-TITLE using
|
||||
`org-roam-title-to-slug-function'. If the slug is part of the
|
||||
current filename, the new slug is computed with NEW-TITLE, and
|
||||
that portion of the filename is renamed.
|
||||
|
||||
To be added to `org-roam-title-change-hook'."
|
||||
(when org-roam-rename-file-on-title-change
|
||||
(let* ((old-slug (funcall org-roam-title-to-slug-function old-title))
|
||||
(file (buffer-file-name (buffer-base-buffer)))
|
||||
(file-name (file-name-nondirectory file)))
|
||||
(when (string-match-p old-slug file-name)
|
||||
(let* ((new-slug (funcall org-roam-title-to-slug-function new-title))
|
||||
(new-file-name (replace-regexp-in-string old-slug new-slug file-name)))
|
||||
(rename-file file-name new-file-name)
|
||||
(set-visited-file-name new-file-name t t)
|
||||
(add-to-list 'org-roam--file-update-queue new-file-name)
|
||||
(org-roam-message "File moved to %S" (abbreviate-file-name new-file-name)))))))
|
||||
|
||||
(defun org-roam--rename-file-advice (old-file new-file-or-dir &rest _args)
|
||||
"Rename backlinks of OLD-FILE to refer to NEW-FILE-OR-DIR.
|
||||
|
Reference in New Issue
Block a user