从某处抄来的, 因为我用 Zettelsktan 笔记方法, 我会经常修改知识卡片的编号, 有了这个命令, 绑定到某键位上, 很方便.
(defun my-rename-roam-file-by-title (&optional path)
"Rename file in current buffer, based on its Org
,#+title property.
Can also take a file PATH instead of current buffer."
(interactive)
(unless path
(setq path (buffer-file-name)))
(unless (equal "org" (file-name-extension path))
(user-error "File doesn't end in .org: %s" path))
(let* ((visiting (find-buffer-visiting path))
(on-window (and visiting (get-buffer-window visiting)))
(slug
(with-current-buffer (or visiting (find-file-noselect path))
(goto-char (point-min))
(let ((node (org-roam-node-at-point t)))
(unless (org-roam-node-title node)
(user-error "Node not yet known to org-roam DB"))
(org-roam-node-slug node))))
(new-path (expand-file-name (concat slug ".org")
(file-name-directory path))))
(if (equal path new-path)
(message "Filename already correct: %s" path)
(if (and visiting (buffer-modified-p visiting))
(message "Unsaved file, letting it be: %s" path)
(unless (file-writable-p path)
(error "No permissions to rename file: %s" path))
(unless (file-writable-p new-path)
(error "No permissions to write a new file at: %s" new-path))
;; Kill buffer before renaming, to be safe
(when visiting
(kill-buffer visiting))
(rename-file path new-path)
(prog1 (message "File %s renamed to %s"
(file-name-nondirectory path)
(file-name-nondirectory new-path))
;; Visit the file again if you had it open
(when visiting
(let ((buf (find-file-noselect new-path)))
(when on-window
(set-window-buffer on-window buf)))))))))