# HG changeset patch # User Lars Hansen # Date 1082580815 0 # Node ID fa9573e2db2a4e11672e2db0fe798e953c26791e # Parent 053797c3d44741b9a472b2973076124ff130768b (desktop-buffer-mode-handlers): New variabel. Alist of major mode specific functions to restore a desktop buffer. (desktop-buffer-handlers): Make variabel obsolete. (desktop-create-buffer): Use desktop-buffer-mode-handlers. Catch errors signaled in handlers. Update buffer count. Evaluate desktop-buffer-point. (desktop-buffer-dired): Rename to dired-restore-desktop-buffer and move to dired.el. (desktop-buffer-info): Rename to Info-restore-desktop-buffer and move to info.el. (desktop-buffer-rmail): Rename to rmail-restore-desktop-buffer and move to mail/rmail.el. (desktop-buffer-mh): Rename to mh-restore-desktop-buffer and move to mh-e/mh-e.el. (desktop-buffer-file): Rename to desktop-restore-file-buffer. An fail, print message (to message buffer) even if desktop-missing-file-warning is nil. (desktop-buffer-misc-data-function): New buffer local variable. Function returning major mode specific data. (desktop-buffer-misc-functions): Make variable obsolete. (desktop-save): Use desktop-buffer-misc-data-function. (desktop-buffer-dired-misc-data): Rename to dired-desktop-buffer-misc-data and move to dired.el. (desktop-buffer-info-misc-data): Rename to Info-desktop-buffer-misc-data and move to info.el. (desktop-read): Add message about number of buffers restored/failed. diff -r 053797c3d447 -r fa9573e2db2a lisp/desktop.el --- a/lisp/desktop.el Wed Apr 21 20:52:18 2004 +0000 +++ b/lisp/desktop.el Wed Apr 21 20:53:35 2004 +0000 @@ -83,12 +83,6 @@ ;;; Code: -;; Make the compilation more silent -(eval-when-compile - ;; We use functions from these modules - ;; We can't (require 'mh-e) since that wants to load something. - (mapcar 'require '(info dired reporter))) - (defvar desktop-file-version "206" "Version number of desktop file format. Written into the desktop file and used at desktop read to provide @@ -253,8 +247,9 @@ (defcustom desktop-buffer-modes-to-save '(Info-mode rmail-mode) "If a buffer is of one of these major modes, save the buffer state. -It is up to the functions in `desktop-buffer-handlers' to decide -whether the buffer should be recreated or not, and how." +This applies to buffers not visiting a file and not beeing a dired buffer. +Modes specified here must have a handler in `desktop-buffer-mode-handlers' +to be restored." :type '(repeat symbol) :group 'desktop) @@ -272,53 +267,59 @@ :type '(choice (const absolute) (const tilde) (const local)) :group 'desktop) -(defcustom desktop-buffer-misc-functions - '(desktop-buffer-info-misc-data - desktop-buffer-dired-misc-data) - "*Functions used to determine auxiliary information for a buffer. -These functions are called by `desktop-save' in order, with no -arguments. If a function returns non-nil, its value is saved along -with the state of the buffer for which it was called; no further -functions will be called. +;;;###autoload +(defvar desktop-buffer-misc-data-function nil + "Function returning major mode specific data for desktop file. +This variable becomes buffer local when set. +The function specified is called by `desktop-save', with argument +DESKTOP-DIRNAME. If it returns non-nil, its value is saved along +with the state of the buffer for which it was called. When file names are returned, they should be formatted using the call -\"(desktop-file-name FILE-NAME dirname)\". +\"(desktop-file-name FILE-NAME DESKTOP-DIRNAME)\". -Later, when `desktop-read' restores buffers, each of the functions in -`desktop-buffer-handlers' will have access to a buffer local variable, -named `desktop-buffer-misc', whose value is what the function in -`desktop-buffer-misc-functions' returned." - :type '(repeat function) - :group 'desktop) +Later, when `desktop-read' calls a function in `desktop-buffer-mode-handlers' +to restore the buffer, the auxiliary information is passed as argument.") +(make-variable-buffer-local 'desktop-buffer-misc-data-function) +(make-obsolete-variable 'desktop-buffer-misc-functions + 'desktop-buffer-misc-data-function) -(defcustom desktop-buffer-handlers - '(desktop-buffer-dired - desktop-buffer-rmail - desktop-buffer-mh - desktop-buffer-info - desktop-buffer-file) - "*Functions called by `desktop-read' in order to create a buffer. -The functions are called without explicit parameters but can use the -following variables: +(defcustom desktop-buffer-mode-handlers '( + (dired-mode . dired-restore-desktop-buffer) + (rmail-mode . rmail-restore-desktop-buffer) + (mh-folder-mode . mh-restore-desktop-buffer) + (Info-mode . Info-restore-desktop-buffer)) + "Alist of major mode specific functions to restore a desktop buffer. +Functions are called by `desktop-read'. List elements must have the form +\(MAJOR-MODE . FUNCTION). + +Buffers with a major mode not specified here, are restored by the default +handler `desktop-restore-file-buffer'. + +Handlers are called with parameters + + desktop-buffer-file-name + desktop-buffer-name + desktop-buffer-misc + +Furthermore, they may use the following variables: desktop-file-version - desktop-buffer-file-name - desktop-buffer-name desktop-buffer-major-mode desktop-buffer-minor-modes desktop-buffer-point desktop-buffer-mark desktop-buffer-read-only - desktop-buffer-misc desktop-buffer-locals -If one function returns non-nil, no further functions are called. -If the function returns a buffer, then the saved mode settings +If a handler returns a buffer, then the saved mode settings and variable values for that buffer are copied into it." - :type '(repeat function) + :type 'alist :group 'desktop) -(put 'desktop-buffer-handlers 'risky-local-variable t) +(put 'desktop-buffer-mode-handlers 'risky-local-variable t) +(make-obsolete-variable 'desktop-buffer-handlers + 'desktop-buffer-mode-handlers) (defcustom desktop-minor-mode-table '((auto-fill-function auto-fill-mode) @@ -608,7 +609,9 @@ (point) (list (mark t) mark-active) buffer-read-only - (run-hook-with-args-until-success 'desktop-buffer-misc-functions) + ;; Auxiliary information + (when desktop-buffer-misc-data-function + (funcall desktop-buffer-misc-data-function dirname)) (let ((locals desktop-locals-to-save) (loclist (buffer-local-variables)) (ll)) @@ -703,7 +706,9 @@ "~")))) (if (file-exists-p (expand-file-name desktop-base-file-name desktop-dirname)) ;; Desktop file found, process it. - (let ((desktop-first-buffer nil)) + (let ((desktop-first-buffer nil) + (desktop-buffer-ok-count 0) + (desktop-buffer-fail-count 0)) ;; Evaluate desktop buffer. (load (expand-file-name desktop-base-file-name desktop-dirname) t t t) ;; `desktop-create-buffer' puts buffers at end of the buffer list. @@ -715,7 +720,12 @@ (run-hooks 'desktop-delay-hook) (setq desktop-delay-hook nil) (run-hooks 'desktop-after-read-hook) - (message "Desktop loaded.") + (message "Desktop: %d buffer%s restored%s." + desktop-buffer-ok-count + (if (= 1 desktop-buffer-ok-count) "" "s") + (if (< 0 desktop-buffer-fail-count) + (format ", %d failed to restore" desktop-buffer-fail-count) + "")) t) ;; No desktop file found. (desktop-clear) @@ -772,106 +782,21 @@ (desktop-read desktop-dirname)) ;; ---------------------------------------------------------------------------- -;; Note: the following functions use the dynamic variable binding in Lisp. -;; - -(eval-when-compile ; Just to silence the byte compiler - (defvar desktop-file-version) - (defvar desktop-buffer-file-name) - (defvar desktop-buffer-name) - (defvar desktop-buffer-major-mode) - (defvar desktop-buffer-minor-modes) - (defvar desktop-buffer-point) - (defvar desktop-buffer-mark) - (defvar desktop-buffer-read-only) - (defvar desktop-buffer-misc) - (defvar desktop-buffer-locals) -) - -(defun desktop-buffer-info-misc-data () - (if (eq major-mode 'Info-mode) - (list Info-current-file - Info-current-node))) - -;; ---------------------------------------------------------------------------- -(defun desktop-buffer-dired-misc-data () - (when (eq major-mode 'dired-mode) - (eval-when-compile (defvar dirname)) - (cons - ;; Value of `dired-directory'. - (if (consp dired-directory) - ;; Directory name followed by list of files. - (cons (desktop-file-name (car dired-directory) dirname) (cdr dired-directory)) - ;; Directory name, optionally with with shell wildcard. - (desktop-file-name dired-directory dirname)) - ;; Subdirectories in `dired-subdir-alist'. - (cdr - (nreverse - (mapcar - (function (lambda (f) (desktop-file-name (car f) dirname))) - dired-subdir-alist)))))) - -;; ---------------------------------------------------------------------------- -(defun desktop-buffer-info () "Load an info file." - (if (eq 'Info-mode desktop-buffer-major-mode) - (progn - (let ((first (nth 0 desktop-buffer-misc)) - (second (nth 1 desktop-buffer-misc))) - (when (and first second) - (require 'info) - (with-no-warnings - (Info-find-node first second)) - (current-buffer)))))) - -;; ---------------------------------------------------------------------------- -(eval-when-compile (defvar rmail-buffer)) ; Just to silence the byte compiler. -(defun desktop-buffer-rmail () "Load an RMAIL file." - (if (eq 'rmail-mode desktop-buffer-major-mode) - (condition-case error - (progn (rmail-input desktop-buffer-file-name) - (if (eq major-mode 'rmail-mode) - (current-buffer) - rmail-buffer)) - (file-locked - (kill-buffer (current-buffer)) - 'ignored)))) - -;; ---------------------------------------------------------------------------- -(defun desktop-buffer-mh () "Load a folder in the mh system." - (if (eq 'mh-folder-mode desktop-buffer-major-mode) - (with-no-warnings - (mh-find-path) - (mh-visit-folder desktop-buffer-name) - (current-buffer)))) - -;; ---------------------------------------------------------------------------- -(defun desktop-buffer-dired () "Load a directory using dired." - (if (eq 'dired-mode desktop-buffer-major-mode) - ;; First element of `desktop-buffer-misc' is the value of `dired-directory'. - ;; This value is a directory name, optionally with with shell wildcard or - ;; a directory name followed by list of files. - (let* ((dired-dir (car desktop-buffer-misc)) - (dir (if (consp dired-dir) (car dired-dir) dired-dir))) - (if (file-directory-p (file-name-directory dir)) - (progn - (dired dired-dir) - ;; The following elements of `desktop-buffer-misc' are the keys - ;; from `dired-subdir-alist'. - (mapcar 'dired-maybe-insert-subdir (cdr desktop-buffer-misc)) - (current-buffer)) - (message "Directory %s no longer exists." dir) - (sit-for 1) - 'ignored)))) - -;; ---------------------------------------------------------------------------- -(defun desktop-buffer-file () - "Load a file." +(defun desktop-restore-file-buffer (desktop-buffer-file-name + desktop-buffer-name + desktop-buffer-misc) + "Restore a file buffer." + (eval-when-compile ; Just to silence the byte compiler + (defvar desktop-buffer-major-mode) + (defvar desktop-buffer-locals)) (if desktop-buffer-file-name (if (or (file-exists-p desktop-buffer-file-name) - (and desktop-missing-file-warning - (y-or-n-p (format - "File \"%s\" no longer exists. Re-create? " - desktop-buffer-file-name)))) + (let ((msg (format "Desktop: File \"%s\" no longer exists." + desktop-buffer-file-name))) + (if desktop-missing-file-warning + (y-or-n-p (concat msg " Re-create? ")) + (message msg) + nil))) (let* ((auto-insert nil) ; Disable auto insertion (coding-system-for-read (or coding-system-for-read @@ -885,7 +810,7 @@ (functionp desktop-buffer-major-mode) (funcall desktop-buffer-major-mode)) buf) - 'ignored))) + nil))) ;; ---------------------------------------------------------------------------- ;; Create a buffer, load its file, set is mode, ...; called from Desktop file @@ -907,20 +832,32 @@ desktop-buffer-misc &optional desktop-buffer-locals) + ;; Just to silence the byte compiler. Bound locally in `desktop-read'. + (eval-when-compile + (defvar desktop-buffer-ok-count) + (defvar desktop-buffer-fail-count)) ;; To make desktop files with relative file names possible, we cannot ;; allow `default-directory' to change. Therefore we save current buffer. (save-current-buffer (let ( (buffer-list (buffer-list)) - (hlist desktop-buffer-handlers) - (result) - (handler) + (result + (condition-case err + (funcall (or (cdr (assq desktop-buffer-major-mode desktop-buffer-mode-handlers)) + 'desktop-restore-file-buffer) + desktop-buffer-file-name + desktop-buffer-name + desktop-buffer-misc) + (error + (message "Desktop: Can't load buffer %s: %s" + desktop-buffer-name (error-message-string err)) + (when desktop-missing-file-warning (sit-for 1)) + nil))) ) - ;; Call desktop-buffer-handlers to create buffer. - (while (and (not result) hlist) - (setq handler (car hlist)) - (setq result (funcall handler)) - (setq hlist (cdr hlist))) + (if (bufferp result) + (setq desktop-buffer-ok-count (1+ desktop-buffer-ok-count)) + (setq desktop-buffer-fail-count (1+ desktop-buffer-fail-count)) + (setq result nil)) (unless (bufferp result) (setq result nil)) ;; Restore buffer list order with new buffer at end. Don't change ;; the order for old desktop files (old desktop module behaviour). @@ -947,7 +884,12 @@ desktop-buffer-minor-modes))) ;; Even though point and mark are non-nil when written by `desktop-save' ;; they may be modified by handlers wanting to set point or mark themselves. - (when desktop-buffer-point (goto-char desktop-buffer-point)) + (when desktop-buffer-point + (goto-char + (condition-case err + ;; Evaluate point. Thus point can be something like '(search-forward ... + (eval desktop-buffer-point) + (error (message "%s" (error-message-string err)) 1)))) (when desktop-buffer-mark (if (consp desktop-buffer-mark) (progn