Function: basic-save-buffer
basic-save-buffer is an interactive and byte-compiled function defined
in files.el.gz.
Signature
(basic-save-buffer &optional CALLED-INTERACTIVELY)
Documentation
Save the current buffer in its visited file, if it has been modified.
The hooks write-contents-functions, local-write-file-hooks
and write-file-functions get a chance to do the job of saving;
if they do not, then the buffer is saved in the visited file in
the usual way.
Before and after saving the buffer, this function runs
before-save-hook and after-save-hook, respectively.
Probably introduced at or before Emacs version 19.11.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun basic-save-buffer (&optional called-interactively)
"Save the current buffer in its visited file, if it has been modified.
The hooks `write-contents-functions', `local-write-file-hooks'
and `write-file-functions' get a chance to do the job of saving;
if they do not, then the buffer is saved in the visited file in
the usual way.
Before and after saving the buffer, this function runs
`before-save-hook' and `after-save-hook', respectively."
(interactive '(called-interactively))
(save-current-buffer
;; In an indirect buffer, save its base buffer instead.
(if (buffer-base-buffer)
(set-buffer (buffer-base-buffer)))
(if (or (buffer-modified-p)
;; Handle the case when no modification has been made but
;; the file disappeared since visited.
(and buffer-file-name
(not (file-exists-p buffer-file-name))))
(let ((recent-save (recent-auto-save-p))
setmodes)
(or (null buffer-file-name)
(verify-visited-file-modtime (current-buffer))
(not (file-exists-p buffer-file-name))
(yes-or-no-p
(format
"%s has changed since visited or saved. Save anyway? "
(file-name-nondirectory buffer-file-name)))
(user-error "Save not confirmed"))
(save-restriction
(widen)
(save-excursion
(and (> (point-max) (point-min))
(not find-file-literally)
(null buffer-read-only)
(/= (char-after (1- (point-max))) ?\n)
(not (and (eq selective-display t)
(= (char-after (1- (point-max))) ?\r)))
(or (eq require-final-newline t)
(eq require-final-newline 'visit-save)
(and require-final-newline
(y-or-n-p
(format "Buffer %s does not end in newline. Add one? "
(buffer-name)))))
(save-excursion
(goto-char (point-max))
(insert ?\n))))
;; Don't let errors prevent saving the buffer.
(with-demoted-errors "Before-save hook error: %S"
(run-hooks 'before-save-hook))
;; Give `write-contents-functions' a chance to
;; short-circuit the whole process.
(unless (run-hook-with-args-until-success 'write-contents-functions)
;; If buffer has no file name, ask user for one.
(or buffer-file-name
(let ((filename
(expand-file-name
(read-file-name "File to save in: "
nil (expand-file-name (buffer-name))))))
(if (file-exists-p filename)
(if (file-directory-p filename)
;; Signal an error if the user specified the name of an
;; existing directory.
(error "%s is a directory" filename)
(unless (y-or-n-p (format-message
"File `%s' exists; overwrite? "
filename))
(error "Canceled"))))
(set-visited-file-name filename)))
;; Support VC version backups.
(vc-before-save)
(or (run-hook-with-args-until-success 'local-write-file-hooks)
(run-hook-with-args-until-success 'write-file-functions)
;; If a hook returned t, file is already "written".
;; Otherwise, write it the usual way now.
(let ((file (buffer-file-name))
(dir (file-name-directory
(expand-file-name buffer-file-name))))
;; Some systems have directories (like /content on
;; Android) in which files can exist without a
;; corresponding parent directory.
(unless (or (file-exists-p file)
(file-exists-p dir))
(if (y-or-n-p
(format-message
"Directory `%s' does not exist; create? " dir))
(make-directory dir t)
(error "Canceled")))
(setq setmodes (basic-save-buffer-1)))))
;; Now we have saved the current buffer. Let's make sure
;; that buffer-file-coding-system is fixed to what
;; actually used for saving by binding it locally.
(when buffer-file-name
(if save-buffer-coding-system
(setq save-buffer-coding-system last-coding-system-used)
(setq buffer-file-coding-system last-coding-system-used))
(setq buffer-file-number
(file-attribute-file-identifier
(file-attributes buffer-file-name)))
(if setmodes
(condition-case ()
(progn
(unless
(with-demoted-errors "Error setting file modes: %S"
(set-file-modes buffer-file-name (car setmodes)))
(set-file-extended-attributes buffer-file-name
(nth 1 setmodes))))
(error nil)))
;; Support VC `implicit' locking.
(vc-after-save))
;; If the auto-save file was recent before this command,
;; delete it now.
(delete-auto-save-file-if-necessary recent-save))
(run-hooks 'after-save-hook))
(or noninteractive
(not called-interactively)
(files--message "(No changes need to be saved)")))))