(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.
This commit is contained in:
parent
31b4c84809
commit
e5780ae17e
1 changed files with 91 additions and 149 deletions
240
lisp/desktop.el
240
lisp/desktop.el
|
@ -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 @@ The variables are saved only when they really are local."
|
|||
(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 @@ Possible values are:
|
|||
: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-file-version
|
||||
desktop-buffer-file-name
|
||||
desktop-buffer-name
|
||||
desktop-buffer-misc
|
||||
|
||||
Furthermore, they may use the following variables:
|
||||
|
||||
desktop-file-version
|
||||
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 @@ See also `desktop-base-file-name'."
|
|||
(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 @@ It returns t if a desktop file was loaded, nil otherwise."
|
|||
"~"))))
|
||||
(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 @@ It returns t if a desktop file was loaded, nil otherwise."
|
|||
(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 @@ directory DIRNAME."
|
|||
(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 @@ directory DIRNAME."
|
|||
(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 @@ directory DIRNAME."
|
|||
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 @@ directory DIRNAME."
|
|||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue