Earlier in v1 when titles were basically notes, vs title with ID is a note, one could rename the title and the filename used to change. After v2 implementation when I change title I see the filename is still the same.
Can someone suggest on how to achieve this?
Thanks!
2 Likes
I am also asking about this and like to know if anyone has achieved this.
arozbiz
September 8, 2021, 3:34pm
3
I wrote this function to update backlinks and file names on a node-name change. It’s messy and I haven’t tested it much, but maybe it’s a start:
(defun azr/org-roam-modify-title ()
"Modify title of org-roam current node and update all backlinks in roam database."
(interactive)
(unless (org-roam-buffer-p) (error "Not in an org-roam buffer."))
(save-some-buffers t)
(let* ((old-title (org-roam-get-keyword "title"))
(ID (org-entry-get (point) "ID"))
(new-title (read-string "Enter new title: " old-title)))
(org-roam-set-keyword "title" new-title)
(save-buffer)
(let* ((new-slug (org-roam-node-slug (org-roam-node-at-point)))
(new-file-name (replace-regexp-in-string "-.*\\.org" (format "-%s.org" new-slug) (buffer-file-name)))
(new-buffer-name (file-name-nondirectory new-file-name)))
(rename-buffer new-buffer-name)
(rename-file (buffer-file-name) new-file-name 1)
(set-visited-file-name new-file-name)) ; I don't know why this last command is necessary. Getting it from here: https://stackoverflow.com/a/384346/2422698
(save-buffer)
;; Rename backlinks in the rest of the Org-roam database.
(let* ((search (format "[[id:%s][%s]]" ID old-title))
(replace (format "[[id:%s][%s]]" ID new-title))
(rg-command (format "rg -t org -lF %s ~/Org/roam/" search))
(file-list (split-string (shell-command-to-string rg-command))))
(dolist (file file-list)
(let ((file-open (get-file-buffer file)))
(find-file file)
(beginning-of-buffer)
(while (search-forward search nil t)
(replace-match replace))
(save-buffer)
(unless file-open
(kill-buffer)))))))
1 Like
Thanks @arozbiz .
I just have a test and it works!
BTW, I adjust the rg-command a little bit, to make ‘org-roam-directory’ not hardcoded.
From:
(rg-command (format “rg -t org -lF %s ~/Org/roam/” search)
To:
(rg-command (format (concat "rg -t org -lF %s " org-roam-directory) search)
Thank you!
Awesome guys! thanks a lot
My solution to this is
(add-hook! 'after-save-hook
(defun org-rename-to-new-title ()
(when-let*
((old-file (buffer-file-name))
(is-roam-file (org-roam-file-p old-file))
(file-node (save-excursion
(goto-char 1)
(org-roam-node-at-point)))
(slug (org-roam-node-slug file-node))
(new-file (expand-file-name (concat slug ".org")))
(different-name? (not (string-equal old-file new-file))))
(rename-buffer new-file)
(rename-file old-file new-file)
(set-visited-file-name new-file)
(set-buffer-modified-p nil))))
(note using Doom’s add-hook!
rather than the standard add-hook
which is slightly different)
This renames the file, but does not rename link references (I don’t like doing this)
@arozbiz , the set-visited-file-name
assigns the buffer to the new file so that writing the buffer will write to the correct new file.
This work great for me. one little thing: from a UX perspective, I found it confusing that after renaming #+title
and hitting C-x C-s
the minibuffer prints a message saying that the buffer has been saved to /path/to/org-roam/old-title.org (even though it actually saves it to /path/to/org-roam/new-title.org as one would expect):
Saving file /path/to/org-roam/old-title.org...
Wrote /path/to/org-roam/old-title.org
I replaced the last line of code with the following two lines, which seems to fix the issue
(set-buffer-modified-p t)
(save-buffer))))
After hitting C-x C-s
the minibuffer now prints
Saving file /path/to/org-roam/old-title.org...
Wrote /path/to/org-roam/old-title.org
Saving file /path/to/org-roam/new-title.org...
Wrote /path/to/org-roam/new-title.org
Disclaimer: I am new to elisp, so please correct me if I got anything wrong. Or if there is a better way to improve this.
quolpr
October 8, 2022, 7:54pm
8
I made a version that will keep date prefix of the file:
(add-hook! 'after-save-hook
(defun org-rename-to-new-title ()
(when-let*
((old-file (buffer-file-name))
(is-roam-file (org-roam-file-p old-file))
(file-node (save-excursion
(goto-char 1)
(org-roam-node-at-point)))
(file-name (file-name-base (org-roam-node-file file-node)))
(file-time (or (and (string-match "\\`\\([0-9]\\{14\\}\\)-" file-name)
(concat (match-string 1 file-name) "-"))
""))
(slug (org-roam-node-slug file-node))
(new-file (expand-file-name (concat file-time slug ".org")))
(different-name? (not (string-equal old-file new-file))))
(rename-buffer new-file)
(rename-file old-file new-file)
(set-visited-file-name new-file)
(set-buffer-modified-p nil))))
@quolpr thanks for sharing. BTW:
quolpr:
"\\
\([0-9]\{14\}\)-"`
Would the regexp “^\\([0-9]\\{14\\}\\)-
” be a better one?