From ac93e56b698c82d9fcfbf39394740ec1f8d411c5 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 24 Jul 2013 00:56:12 -0400 Subject: [PATCH] * lisp/files.el (revert-buffer-function): Use a non-nil default. (revert-buffer-preserve-modes): Declare var to provide access to the `preserve-modes' argument. (revert-buffer): Let-bind it. (revert-buffer--default): New function, extracted from revert-buffer. --- lisp/ChangeLog | 8 ++ lisp/files.el | 224 +++++++++++++++++++++++++------------------------ 2 files changed, 124 insertions(+), 108 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4c115d8435a..24fbe1acb2c 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,11 @@ +2013-07-24 Stefan Monnier + + * files.el (revert-buffer-function): Use a non-nil default. + (revert-buffer-preserve-modes): Declare var to + provide access to the `preserve-modes' argument. + (revert-buffer): Let-bind it. + (revert-buffer--default): New function, extracted from revert-buffer. + 2013-07-24 Stefan Monnier * lpr.el: Signal print errors more prominently. diff --git a/lisp/files.el b/lisp/files.el index ff4ccec2279..10d66e0b2e0 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5246,10 +5246,12 @@ comparison." (put 'revert-buffer-function 'permanent-local t) -(defvar revert-buffer-function nil +(defvar revert-buffer-function #'revert-buffer--default "Function to use to revert this buffer, or nil to do the default. The function receives two arguments IGNORE-AUTO and NOCONFIRM, -which are the arguments that `revert-buffer' received.") +which are the arguments that `revert-buffer' received. +It also has access to the `preserve-modes' argument of `revert-buffer' +via the `revert-buffer-preserve-modes' dynamic variable.") (put 'revert-buffer-insert-file-contents-function 'permanent-local t) (defvar revert-buffer-insert-file-contents-function nil @@ -5296,6 +5298,11 @@ This is true even if a `revert-buffer-function' is being used.") (defvar revert-buffer-internal-hook) +;; `revert-buffer-function' was defined long ago to be a function of only +;; 2 arguments, so we have to use a dynbind variable to pass the +;; `preserve-modes' argument of `revert-buffer'. +(defvar revert-buffer-preserve-modes) + (defun revert-buffer (&optional ignore-auto noconfirm preserve-modes) "Replace current buffer text with the text of the visited file on disk. This undoes all changes since the file was visited or saved. @@ -5337,112 +5344,113 @@ non-nil, it is called instead of rereading visited file contents." ;; reversal of the argument sense. So I'm just changing the user ;; interface, but leaving the programmatic interface the same. (interactive (list (not current-prefix-arg))) - (if revert-buffer-function - (let ((revert-buffer-in-progress-p t)) - (funcall revert-buffer-function ignore-auto noconfirm)) - (with-current-buffer (or (buffer-base-buffer (current-buffer)) - (current-buffer)) - (let* ((revert-buffer-in-progress-p t) - (auto-save-p (and (not ignore-auto) - (recent-auto-save-p) - buffer-auto-save-file-name - (file-readable-p buffer-auto-save-file-name) - (y-or-n-p - "Buffer has been auto-saved recently. Revert from auto-save file? "))) - (file-name (if auto-save-p - buffer-auto-save-file-name - buffer-file-name))) - (cond ((null file-name) - (error "Buffer does not seem to be associated with any file")) - ((or noconfirm - (and (not (buffer-modified-p)) - (catch 'found - (dolist (regexp revert-without-query) - (when (string-match regexp file-name) - (throw 'found t))))) - (yes-or-no-p (format "Revert buffer from file %s? " - file-name))) - (run-hooks 'before-revert-hook) - ;; If file was backed up but has changed since, - ;; we should make another backup. - (and (not auto-save-p) - (not (verify-visited-file-modtime (current-buffer))) - (setq buffer-backed-up nil)) - ;; Effectively copy the after-revert-hook status, - ;; since after-find-file will clobber it. - (let ((global-hook (default-value 'after-revert-hook)) - (local-hook (when (local-variable-p 'after-revert-hook) - after-revert-hook)) - (inhibit-read-only t)) - (cond - (revert-buffer-insert-file-contents-function - (unless (eq buffer-undo-list t) - ;; Get rid of all undo records for this buffer. - (setq buffer-undo-list nil)) - ;; Don't make undo records for the reversion. - (let ((buffer-undo-list t)) - (funcall revert-buffer-insert-file-contents-function - file-name auto-save-p))) - ((not (file-exists-p file-name)) - (error (if buffer-file-number - "File %s no longer exists!" - "Cannot revert nonexistent file %s") - file-name)) - ((not (file-readable-p file-name)) - (error (if buffer-file-number - "File %s no longer readable!" - "Cannot revert unreadable file %s") - file-name)) - (t - ;; Bind buffer-file-name to nil - ;; so that we don't try to lock the file. - (let ((buffer-file-name nil)) - (or auto-save-p - (unlock-buffer))) - (widen) - (let ((coding-system-for-read - ;; Auto-saved file should be read by Emacs's - ;; internal coding. - (if auto-save-p 'auto-save-coding - (or coding-system-for-read - (and - buffer-file-coding-system-explicit - (car buffer-file-coding-system-explicit)))))) - (if (and (not enable-multibyte-characters) - coding-system-for-read - (not (memq (coding-system-base - coding-system-for-read) - '(no-conversion raw-text)))) - ;; As a coding system suitable for multibyte - ;; buffer is specified, make the current - ;; buffer multibyte. - (set-buffer-multibyte t)) - - ;; This force after-insert-file-set-coding - ;; (called from insert-file-contents) to set - ;; buffer-file-coding-system to a proper value. - (kill-local-variable 'buffer-file-coding-system) - - ;; Note that this preserves point in an intelligent way. - (if preserve-modes - (let ((buffer-file-format buffer-file-format)) - (insert-file-contents file-name (not auto-save-p) - nil nil t)) - (insert-file-contents file-name (not auto-save-p) - nil nil t))))) - ;; Recompute the truename in case changes in symlinks - ;; have changed the truename. - (setq buffer-file-truename - (abbreviate-file-name (file-truename buffer-file-name))) - (after-find-file nil nil t nil preserve-modes) - ;; Run after-revert-hook as it was before we reverted. - (setq-default revert-buffer-internal-hook global-hook) - (if local-hook - (set (make-local-variable 'revert-buffer-internal-hook) - local-hook) - (kill-local-variable 'revert-buffer-internal-hook)) - (run-hooks 'revert-buffer-internal-hook)) - t)))))) + (let ((revert-buffer-in-progress-p t) + (revert-buffer-preserve-modes preserve-modes)) + (funcall (or revert-buffer-function #'revert-buffer--default) + ignore-auto noconfirm))) +(defun revert-buffer--default (ignore-auto noconfirm) + (with-current-buffer (or (buffer-base-buffer (current-buffer)) + (current-buffer)) + (let* ((auto-save-p (and (not ignore-auto) + (recent-auto-save-p) + buffer-auto-save-file-name + (file-readable-p buffer-auto-save-file-name) + (y-or-n-p + "Buffer has been auto-saved recently. Revert from auto-save file? "))) + (file-name (if auto-save-p + buffer-auto-save-file-name + buffer-file-name))) + (cond ((null file-name) + (error "Buffer does not seem to be associated with any file")) + ((or noconfirm + (and (not (buffer-modified-p)) + (catch 'found + (dolist (regexp revert-without-query) + (when (string-match regexp file-name) + (throw 'found t))))) + (yes-or-no-p (format "Revert buffer from file %s? " + file-name))) + (run-hooks 'before-revert-hook) + ;; If file was backed up but has changed since, + ;; we should make another backup. + (and (not auto-save-p) + (not (verify-visited-file-modtime (current-buffer))) + (setq buffer-backed-up nil)) + ;; Effectively copy the after-revert-hook status, + ;; since after-find-file will clobber it. + (let ((global-hook (default-value 'after-revert-hook)) + (local-hook (when (local-variable-p 'after-revert-hook) + after-revert-hook)) + (inhibit-read-only t)) + (cond + (revert-buffer-insert-file-contents-function + (unless (eq buffer-undo-list t) + ;; Get rid of all undo records for this buffer. + (setq buffer-undo-list nil)) + ;; Don't make undo records for the reversion. + (let ((buffer-undo-list t)) + (funcall revert-buffer-insert-file-contents-function + file-name auto-save-p))) + ((not (file-exists-p file-name)) + (error (if buffer-file-number + "File %s no longer exists!" + "Cannot revert nonexistent file %s") + file-name)) + ((not (file-readable-p file-name)) + (error (if buffer-file-number + "File %s no longer readable!" + "Cannot revert unreadable file %s") + file-name)) + (t + ;; Bind buffer-file-name to nil + ;; so that we don't try to lock the file. + (let ((buffer-file-name nil)) + (or auto-save-p + (unlock-buffer))) + (widen) + (let ((coding-system-for-read + ;; Auto-saved file should be read by Emacs's + ;; internal coding. + (if auto-save-p 'auto-save-coding + (or coding-system-for-read + (and + buffer-file-coding-system-explicit + (car buffer-file-coding-system-explicit)))))) + (if (and (not enable-multibyte-characters) + coding-system-for-read + (not (memq (coding-system-base + coding-system-for-read) + '(no-conversion raw-text)))) + ;; As a coding system suitable for multibyte + ;; buffer is specified, make the current + ;; buffer multibyte. + (set-buffer-multibyte t)) + + ;; This force after-insert-file-set-coding + ;; (called from insert-file-contents) to set + ;; buffer-file-coding-system to a proper value. + (kill-local-variable 'buffer-file-coding-system) + + ;; Note that this preserves point in an intelligent way. + (if revert-buffer-preserve-modes + (let ((buffer-file-format buffer-file-format)) + (insert-file-contents file-name (not auto-save-p) + nil nil t)) + (insert-file-contents file-name (not auto-save-p) + nil nil t))))) + ;; Recompute the truename in case changes in symlinks + ;; have changed the truename. + (setq buffer-file-truename + (abbreviate-file-name (file-truename buffer-file-name))) + (after-find-file nil nil t nil revert-buffer-preserve-modes) + ;; Run after-revert-hook as it was before we reverted. + (setq-default revert-buffer-internal-hook global-hook) + (if local-hook + (set (make-local-variable 'revert-buffer-internal-hook) + local-hook) + (kill-local-variable 'revert-buffer-internal-hook)) + (run-hooks 'revert-buffer-internal-hook)) + t))))) (defun recover-this-file () "Recover the visited file--get contents from its last auto-save file." -- 2.39.2