Function: set-visited-file-name

set-visited-file-name is an interactive and byte-compiled function defined in files.el.gz.

Signature

(set-visited-file-name FILENAME &optional NO-QUERY ALONG-WITH-FILE)

Documentation

Change name of file visited in current buffer to FILENAME.

This also renames the buffer to correspond to the new file. The next time the buffer is saved it will go in the newly specified file. FILENAME nil or an empty string means mark buffer as not visiting any file. Remember to delete the initial contents of the minibuffer if you wish to pass an empty string as the argument.

The optional second argument NO-QUERY, if non-nil, inhibits asking for confirmation in the case where another buffer is already visiting FILENAME.

The optional third argument ALONG-WITH-FILE, if non-nil, means that the old visited file has been renamed to the new name FILENAME.

View in manual

Probably introduced at or before Emacs version 18.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun set-visited-file-name (filename &optional no-query along-with-file)
  "Change name of file visited in current buffer to FILENAME.
This also renames the buffer to correspond to the new file.
The next time the buffer is saved it will go in the newly specified file.
FILENAME nil or an empty string means mark buffer as not visiting any file.
Remember to delete the initial contents of the minibuffer
if you wish to pass an empty string as the argument.

The optional second argument NO-QUERY, if non-nil, inhibits asking for
confirmation in the case where another buffer is already visiting FILENAME.

The optional third argument ALONG-WITH-FILE, if non-nil, means that
the old visited file has been renamed to the new name FILENAME."
  (interactive "FSet visited file name: ")
  (if (buffer-base-buffer)
      (error "An indirect buffer cannot visit a file"))
  (let (truename old-try-locals)
    (if filename
	(setq filename
	      (if (string-equal filename "")
		  nil
		(expand-file-name filename))))
    (if filename
	(progn
	  (setq truename (file-truename filename))
	  (if find-file-visit-truename
	      (setq filename truename))))
    (if filename
	(let ((new-name (file-name-nondirectory filename)))
	  (if (string= new-name "")
	      (error "Empty file name"))))
    (let ((buffer (and filename (find-buffer-visiting filename))))
      (and buffer (not (eq buffer (current-buffer)))
	   (not no-query)
	   (not (y-or-n-p (format "A buffer is visiting %s; proceed? "
				  filename)))
	   (user-error "Aborted")))
    (or (equal filename buffer-file-name)
	(progn
	  (and filename (lock-buffer filename))
	  (unlock-buffer)))
    (setq old-try-locals (not (inhibit-local-variables-p))
	  buffer-file-name filename)
    (if filename			; make buffer name reflect filename.
	(let ((new-name (file-name-nondirectory buffer-file-name)))
	  (setq default-directory (file-name-directory buffer-file-name))
	  ;; If new-name == old-name, renaming would add a spurious <2>
	  ;; and it's considered as a feature in rename-buffer.
	  (or (string= new-name (buffer-name))
	      (rename-buffer new-name t))))
    (setq buffer-backed-up nil)
    (or along-with-file
	(clear-visited-file-modtime))
    ;; Abbreviate the file names of the buffer.
    (if truename
	(progn
	  (setq buffer-file-truename (abbreviate-file-name truename))
	  (if find-file-visit-truename
	      (setq buffer-file-name truename))))
    (setq buffer-file-number
	  (if filename
	      (file-attribute-file-identifier (file-attributes buffer-file-name))
	    nil))
    ;; write-file-functions is normally used for things like ftp-find-file
    ;; that visit things that are not local files as if they were files.
    ;; Changing to visit an ordinary local file instead should flush the hook.
    (kill-local-variable 'write-file-functions)
    (kill-local-variable 'local-write-file-hooks)
    (kill-local-variable 'revert-buffer-function)
    (kill-local-variable 'backup-inhibited)
    ;; If buffer was read-only because of version control,
    ;; that reason is gone now, so make it writable.
    (if vc-mode
	(setq buffer-read-only nil))
    (kill-local-variable 'vc-mode)
    ;; Turn off backup files for certain file names.
    ;; Since this is a permanent local, the major mode won't eliminate it.
    (and buffer-file-name
	 backup-enable-predicate
	 (not (funcall backup-enable-predicate buffer-file-name))
         (setq-local backup-inhibited t))
    (let ((oauto buffer-auto-save-file-name))
      (cond ((null filename)
	     (setq buffer-auto-save-file-name nil))
	    ((not buffer-auto-save-file-name)
	     ;; If auto-save was not already on, turn it on if appropriate.
	     (and buffer-file-name auto-save-default (auto-save-mode t)))
	    (t
	     ;; If auto save is on, start using a new name. We
	     ;; deliberately don't rename or delete the old auto save
	     ;; for the old visited file name.  This is because
	     ;; perhaps the user wants to save the new state and then
	     ;; compare with the previous state from the auto save
	     ;; file.
	     (setq buffer-auto-save-file-name (make-auto-save-file-name))))
      ;; Rename the old auto save file if any.
      (and oauto buffer-auto-save-file-name
	   (file-exists-p oauto)
	   (rename-file oauto buffer-auto-save-file-name t)))
    (and buffer-file-name
	 (not along-with-file)
	 (set-buffer-modified-p t))
    ;; Update the major mode, if the file name determines it.
    (condition-case nil
	;; Don't change the mode if it is special.
	(or (not change-major-mode-with-file-name)
	    (get major-mode 'mode-class)
	    ;; Don't change the mode if the local variable list specifies it.
	    ;; The file name can influence whether the local variables apply.
	    (and old-try-locals
		 ;; h-l-v also checks it, but might as well be explicit.
		 (not (inhibit-local-variables-p))
		 (hack-local-variables t))
	    ;; TODO consider making normal-mode handle this case.
	    (let ((old major-mode))
	      (set-auto-mode t)
	      (or (eq old major-mode)
		  (hack-local-variables))))
      (error nil))
    (run-hooks 'after-set-visited-file-name-hook)))