]> code.delx.au - gnu-emacs/blobdiff - lisp/desktop.el
Merge branch 'emacs-25-merge'
[gnu-emacs] / lisp / desktop.el
index c2724904b5837d21fcb73825968cace787ff7132..5a709b9d5b6952744e428527aa5d2f78ca0ea4dd 100644 (file)
 ;;    (add-to-list 'desktop-minor-mode-handlers
 ;;                 '(bar-mode . bar-desktop-restore))
 
-;; in the module itself, and make sure that the mode function is
-;; autoloaded.  See the docstrings of `desktop-buffer-mode-handlers' and
+;; in the module itself.  The mode function must either be autoloaded,
+;; or of the form "foobar-mode" and defined in library "foobar", so that
+;; desktop can guess how to load its definition.
+;; See the docstrings of `desktop-buffer-mode-handlers' and
 ;; `desktop-minor-mode-handlers' for more info.
 
 ;; Minor modes.
@@ -163,8 +165,8 @@ one session to another.  In particular, Emacs will save the desktop when
 it exits (this may prompt you; see the option `desktop-save').  The next
 time Emacs starts, if this mode is active it will restore the desktop.
 
-To manually save the desktop at any time, use the command `M-x desktop-save'.
-To load it, use `M-x desktop-read'.
+To manually save the desktop at any time, use the command `\\[desktop-save]'.
+To load it, use `\\[desktop-read]'.
 
 Once a desktop file exists, Emacs will auto-save it according to the
 option `desktop-auto-save-timeout'.
@@ -517,10 +519,12 @@ code like
 
    (defun foo-restore-desktop-buffer
    ...
-   (add-to-list 'desktop-buffer-mode-handlers
-                '(foo-mode . foo-restore-desktop-buffer))
+   (add-to-list \\='desktop-buffer-mode-handlers
+                \\='(foo-mode . foo-restore-desktop-buffer))
 
-Furthermore the major mode function must be autoloaded.")
+The major mode function must either be autoloaded, or of the form
+\"foobar-mode\" and defined in library \"foobar\", so that desktop
+can guess how to load the mode's definition.")
 
 ;;;###autoload
 (put 'desktop-buffer-mode-handlers 'risky-local-variable t)
@@ -582,10 +586,12 @@ code like
 
    (defun foo-desktop-restore
    ...
-   (add-to-list 'desktop-minor-mode-handlers
-                '(foo-mode . foo-desktop-restore))
+   (add-to-list \\='desktop-minor-mode-handlers
+                \\='(foo-mode . foo-desktop-restore))
 
-Furthermore the minor mode function must be autoloaded.
+The minor mode function must either be autoloaded, or of the form
+\"foobar-mode\" and defined in library \"foobar\", so that desktop
+can guess how to load the mode's definition.
 
 See also `desktop-minor-mode-table'.")
 
@@ -756,6 +762,24 @@ is nil, ask the user where to save the desktop."
 
 ;; ----------------------------------------------------------------------------
 (defun desktop-buffer-info (buffer)
+  "Return information describing BUFFER.
+This function is not pure, as BUFFER is made current with
+`set-buffer'.
+
+Returns a list of all the necessary information to recreate the
+buffer, which is (in order):
+
+    `uniquify-buffer-base-name';
+    `buffer-file-name';
+    `buffer-name';
+    `major-mode';
+    list of minor-modes,;
+    `point';
+    `mark';
+    `buffer-read-only';
+    auxiliary information given by `desktop-save-buffer';
+    local variables;
+    auxiliary information given by `desktop-var-serdes-funs'."
   (set-buffer buffer)
   (list
    ;; base name of the buffer; replaces the buffer name if managed by uniquify
@@ -766,16 +790,13 @@ is nil, ask the user where to save the desktop."
    major-mode
    ;; minor modes
    (let (ret)
-     (mapc
-      #'(lambda (minor-mode)
-         (and (boundp minor-mode)
-              (symbol-value minor-mode)
-              (let* ((special (assq minor-mode desktop-minor-mode-table))
-                     (value (cond (special (cadr special))
-                                  ((functionp minor-mode) minor-mode))))
-                (when value (add-to-list 'ret value)))))
-      (mapcar #'car minor-mode-alist))
-     ret)
+     (dolist (minor-mode (mapcar #'car minor-mode-alist) ret)
+       (and (boundp minor-mode)
+            (symbol-value minor-mode)
+            (let* ((special (assq minor-mode desktop-minor-mode-table))
+                   (value (cond (special (cadr special))
+                                ((functionp minor-mode) minor-mode))))
+              (when value (cl-pushnew value ret))))))
    ;; point and mark, and read-only status
    (point)
    (list (mark t) mark-active)
@@ -1136,7 +1157,8 @@ It returns t if a desktop file was loaded, nil otherwise."
              (desktop-buffer-fail-count 0)
              (owner (desktop-owner))
              ;; Avoid desktop saving during evaluation of desktop buffer.
-             (desktop-save nil))
+             (desktop-save nil)
+             (desktop-autosave-was-enabled))
          (if (and owner
                   (memq desktop-load-locked-desktop '(nil ask))
                   (or (null desktop-load-locked-desktop)
@@ -1152,6 +1174,8 @@ Using it may cause conflicts.  Use it anyway? " owner)))))
            ;; Temporarily disable the autosave that will leave it
            ;; disabled when loading the desktop fails with errors,
            ;; thus not overwriting the desktop with broken contents.
+           (setq desktop-autosave-was-enabled
+                 (memq 'desktop-auto-save-set-timer window-configuration-change-hook))
            (desktop-auto-save-disable)
            ;; Evaluate desktop buffer and remember when it was modified.
            (load (desktop-full-file-name) t t t)
@@ -1205,7 +1229,7 @@ Using it may cause conflicts.  Use it anyway? " owner)))))
                                  (set-window-prev-buffers window nil)
                                  (set-window-next-buffers window nil))))
            (setq desktop-saved-frameset nil)
-           (desktop-auto-save-enable)
+           (if desktop-autosave-was-enabled (desktop-auto-save-enable))
            t))
       ;; No desktop file found.
       (let ((default-directory desktop-dirname))
@@ -1334,9 +1358,18 @@ after that many seconds of idle time."
       nil)))
 
 (defun desktop-load-file (function)
-  "Load the file where auto loaded FUNCTION is defined."
-  (when (fboundp function)
-    (autoload-do-load (symbol-function function) function)))
+  "Load the file where auto loaded FUNCTION is defined.
+If FUNCTION is not currently defined, guess the library that defines it
+and try to load that."
+  (if (fboundp function)
+      (autoload-do-load (symbol-function function) function)
+    ;; Guess that foobar-mode is defined in foobar.
+    ;; TODO rather than guessing or requiring an autoload, the desktop
+    ;; file should record the name of the library.
+    (let ((name (symbol-name function)))
+      (if (string-match "\\`\\(.*\\)-mode\\'" name)
+          (with-demoted-errors "Require error in desktop-load-file: %S"
+              (require (intern (match-string 1 name)) nil t))))))
 
 ;; ----------------------------------------------------------------------------
 ;; Create a buffer, load its file, set its mode, ...;
@@ -1450,7 +1483,7 @@ after that many seconds of idle time."
            (dolist (record compacted-vars)
              (let*
                  ((var (car record))
-                  (deser-fun (cl-caddr (assq var desktop-var-serdes-funs))))
+                  (deser-fun (nth 2 (assq var desktop-var-serdes-funs))))
                (if deser-fun (set var (funcall deser-fun (cadr record))))))))
        result))))
 
@@ -1554,13 +1587,6 @@ If there are no buffers left to create, kill the timer."
         (desktop-read)
         (setq inhibit-startup-screen t)))))
 
-;; So we can restore vc-dir buffers.
-(autoload 'vc-dir-mode "vc-dir" nil t)
-
 (provide 'desktop)
 
 ;;; desktop.el ends here
-
-;; Local Variables:
-;; coding: utf-8
-;; End: