有没有办法在Emacs中重命名打开的文件?在我看的时候?类似于另存为,但原始文件应该删除。


当前回答

这是另一个版本,它非常健壮,并且支持VC:

(defun rename-file-and-buffer ()
  "Rename the current buffer and file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (message "Buffer is not visiting a file!")
      (let ((new-name (read-file-name "New name: " filename)))
        (cond
         ((vc-backend filename) (vc-rename-file filename new-name))
         (t
          (rename-file filename new-name t)
          (set-visited-file-name new-name t t)))))))

你可以在这里阅读更多信息。

其他回答

我最喜欢的是来自Magnars (emacs岩石屏幕录制的名声)。

与其他选项不同的是,您不必从头输入名称—您可以获得要修改的当前名称。

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " (file-name-directory filename) basename nil basename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

感谢James Yang的正确版本。

基于magnars版本,我修改如下,修复了INIT文件名部分:

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " (file-name-directory filename) basename nil basename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

这是另一个版本,它非常健壮,并且支持VC:

(defun rename-file-and-buffer ()
  "Rename the current buffer and file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (message "Buffer is not visiting a file!")
      (let ((new-name (read-file-name "New name: " filename)))
        (cond
         ((vc-backend filename) (vc-rename-file filename new-name))
         (t
          (rename-file filename new-name t)
          (set-visited-file-name new-name t t)))))))

你可以在这里阅读更多信息。

我没有发现任何建议的解决方案足以满足我的需求(缓冲区选择,覆盖确认,快速响应,实际工作等),以下是我正在使用的:

(defun rename-buffer-and-file (buffer newname)
  (interactive "bRename buffer and its visiting file: \nFNew name: ")
  (let ((oldname (buffer-file-name)))
    (if (not oldname)
        (message "Buffer '%s' is not visiting a file" buffer)
      (if (file-exists-p newname)
          (if (file-directory-p newname)
              ;; Signal an error if the user specified the name of an
              ;; existing directory.
              (error "%s is a directory" newname)
            (unless (y-or-n-p (format-message
                               "File `%s' exists; overwrite? "
                               newname))
              (error "Canceled"))))
      ;; Rename buffer and its visiting file
      (set-visited-file-name newname)
      ;; Delete old file
      (delete-file oldname)
      (save-buffer))))

绑定到C-x - C-r以便于

(global-set-key (kbd "C-x C-r") 'rename-buffer-and-file)

优秀的crux包具有crux-rename-file-and-buffer(以及许多其他有用的函数)。