(C4-213F): Use `<-original-ideograph*sources' instead of char-ref in
[chise/xemacs-chise.git-] / lisp / auto-save.el
1 ;;; auto-save.el -- Safer autosaving for EFS and tmp.
2
3 ;; Copyright (C) 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1992 by Sebastian Kremer <sk@thp.uni-koeln.de>
5 ;; Copyright (C) 2001 Ben Wing.
6
7 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
8 ;; Maintainer: XEmacs Development Team
9 ;; Keywords: extensions, dumped
10 ;; Version: 1.26
11
12 ;; XEmacs is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 1, or (at your option)
15 ;; any later version.
16
17 ;; XEmacs is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 ;; General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING.  If not, write to the Free
24 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 ;; 02111-1307, USA.
26
27 ;;; Synched up with: Not in FSF
28
29 ;;; Commentary:
30
31 ;; This file is dumped with XEmacs.
32
33 ;; Combines autosaving for efs (to a local or remote directory)
34 ;; with the ability to do autosaves to a fixed directory on a local
35 ;; disk, in case NFS is slow.  The auto-save file used for
36 ;;     /usr/foo/bar/baz.txt
37 ;; will be
38 ;;     AUTOSAVE/#=2Fusr=2Ffoo=2Fbar=2Fbaz.txt#"
39 ;; assuming AUTOSAVE is the non-nil value of the variable
40 ;; `auto-save-directory'.
41
42 ;; Autosaves even if the current directory is not writable.
43
44 ;; Can limit autosave names to 14 characters using a hash function,
45 ;; see `auto-save-hash-p'.
46
47 ;; See `auto-save-directory' and `make-auto-save-file-name' and
48 ;; references therein for complete documentation.
49
50 ;; `M-x recover-all-files' will effectively do recover-file on all
51 ;; files whose autosave file is newer (one of the benefits of having
52 ;; all autosave files in the same place).
53
54 ;; This file is dumped with XEmacs.
55
56 ;; If you want to autosave in the fixed directory /tmp/USER-autosave/
57 ;; (setq auto-save-directory
58 ;;       (concat "/tmp/" (user-login-name) "-autosave/"))
59
60 ;; If you don't want to save in /tmp (e.g., because it is swap
61 ;; mounted) but rather in ~/.autosave/
62 ;;   (setq auto-save-directory (expand-file-name "~/.autosave/"))
63
64 ;; If you want to save each file in its own directory (the default)
65 ;;   (setq auto-save-directory nil)
66 ;; You still can take advantage of autosaving efs remote files
67 ;; in a fixed local directory, `auto-save-directory-fallback' will
68 ;; be used.
69
70 ;; If you want to use 14 character hashed autosave filenames
71 ;;   (setq auto-save-hash-p t)
72
73 ;; Finally, put this line after the others in your ~/.emacs:
74 ;;   (require 'auto-save)
75
76
77 ;;; Acknowledgement:
78
79 ;; This code is loosely derived from autosave-in-tmp.el by Jamie
80 ;; Zawinski <jwz@jwz.org> (the version I had was last modified 22
81 ;; dec 90 jwz) and code submitted to ange-ftp-lovers on Sun, 5 Apr
82 ;; 92 23:20:47 EDT by drw@BOURBAKI.MIT.EDU (Dale R. Worley).
83 ;; auto-save.el tries to cover the functionality of those two
84 ;; packages.
85
86 ;; Valuable comments and help from Dale Worley, Andy Norman, Jamie
87 ;; Zawinski and Sandy Rutherford are gratefully acknowledged.
88
89 (defconst auto-save-version "1.26"
90   "Version number of auto-save.")
91
92 (provide 'auto-save)
93
94 \f
95 ;;; Customization:
96
97 (defgroup auto-save nil
98   "Autosaving with support for efs and /tmp."
99   :group 'data)
100
101 (put 'auto-save-interval 'custom-type 'integer)
102 (put 'auto-save-interval 'factory-value '(300))
103 (custom-add-to-group 'auto-save 'auto-save-interval 'custom-variable)
104
105 (defcustom auto-save-directory nil
106
107   ;; Don't make this user-variable-p, it should be set in .emacs and
108   ;; left at that.  In particular, it should remain constant across
109   ;; several Emacs session to make recover-all-files work.
110
111   ;; However, it's OK for it to be customizable, as most of the
112   ;; customizable variables are set at the time `.emacs' is read.
113   ;; -hniksic
114
115   "If non-nil, fixed directory for autosaving: all autosave files go
116 there.  If this directory does not yet exist at load time, it is
117 created and its mode is set to 0700 so that nobody else can read your
118 autosave files.
119
120 If nil, each autosave files goes into the same directory as its
121 corresponding visited file.
122
123 A non-nil `auto-save-directory' could be on a local disk such as in
124 /tmp, then auto-saves will always be fast, even if NFS or the
125 automounter is slow.  In the usual case of /tmp being locally mounted,
126 note that if you run emacs on two different machines, they will not
127 see each other's auto-save files.
128
129 The value \(expand-file-name \"~/.autosave/\"\) might be better if /tmp
130 is mounted from swap (possible in SunOS, type `df /tmp' to find out)
131 and thus vanishes after a reboot, or if your system is particularly
132 thorough when cleaning up /tmp, clearing even non-empty subdirectories.
133
134 It should never be an efs remote filename because that would
135 defeat `efs-auto-save-remotely'.
136
137 Unless you set `auto-save-hash-p', you shouldn't set this to a
138 directory in a filesystem that does not support long filenames, since
139 a file named
140
141     /home/sk/lib/emacs/lisp/auto-save.el
142
143 will have a longish filename like
144
145     AUTO-SAVE-DIRECTORY/#=2Fhome=2Fsk=2Flib=2Femacs=2Flisp=2Fauto-save.el#
146
147 as auto save file.
148
149 See also variables `auto-save-directory-fallback',
150 `efs-auto-save' and `efs-auto-save-remotely'."
151   :type '(choice (const :tag "Same as file" nil)
152                  directory)
153   :group 'auto-save)
154
155
156 (defcustom auto-save-hash-p nil
157   "If non-nil, hashed autosave names of length 14 are used.
158 This is to avoid autosave filenames longer than 14 characters.
159 The directory used is `auto-save-hash-directory' regardless of
160 `auto-save-directory'.
161 Hashing defeats `recover-all-files', you have to recover files
162 individually by doing `recover-file'."
163   :type 'boolean
164   :group 'auto-save)
165
166 ;;; This defvar is in efs.el now, but doesn't hurt to give it here as
167 ;;; well so that loading first auto-save.el does not abort.
168
169 ;; #### Now that `auto-save' is dumped, this is looks obnoxious.
170 (or (boundp 'efs-auto-save) (defvar efs-auto-save 0))
171 (or (boundp 'efs-auto-save-remotely) (defvar efs-auto-save-remotely nil))
172
173 (defcustom auto-save-offer-delete nil
174   "*If non-nil, `recover-all-files' offers to delete autosave files
175 that are out of date or were dismissed for recovering.
176 Special value 'always deletes those files silently."
177   :type '(choice (const :tag "on" t)
178                  (const :tag "off" nil)
179                  (const :tag "Delete silently" always))
180   :group 'auto-save)
181
182 ;;;; end of customization
183
184 \f
185 ;;; Preparations to be done at load time
186
187 ;; Do not call expand-file-name! This is evaluated at dump time now!
188 (defvar auto-save-directory-fallback "~/.autosave/"
189   ;; not user-variable-p, see above
190   "Directory used for local autosaving of remote files if
191 both `auto-save-directory' and `efs-auto-save-remotely' are nil.
192 Also used if a working directory to be used for autosaving is not writable.
193 This *must* always be the name of directory that exists or can be
194 created by you, never nil.")
195
196 (defvar auto-save-hash-directory
197   (expand-file-name "hash/" (or auto-save-directory
198                                 auto-save-directory-fallback))
199   "If non-nil, directory used for hashed autosave filenames.")
200
201 (defun auto-save-checked-directory (dir)
202   "Make sure the directory DIR exists and return it expanded if non-nil."
203     (when dir
204       (setq dir (expand-file-name dir))
205       ;; Make sure directory exists
206       (unless (file-directory-p dir)
207         ;; Else we create and chmod 0700 the directory
208         (setq dir (directory-file-name dir)) ; some systems need this
209         (make-directory dir)
210         (set-file-modes dir #o700))
211       dir))
212
213 ;; This make no sense at dump time
214 ;; (mapc #'auto-save-check-directory
215 ;     '(auto-save-directory auto-save-directory-fallback))
216
217 ;(and auto-save-hash-p
218 ;     (auto-save-check-directory 'auto-save-hash-directory))
219
220 \f
221 ;;; Computing an autosave name for a file and vice versa
222
223 (defun make-auto-save-file-name (&optional file-name)
224   "Return file name to use for auto-saves of current buffer.
225 Does not consider `auto-save-visited-file-name'; that is checked
226 before calling this function.
227
228 Offers to autosave all files in the same `auto-save-directory'.  All
229 autosave files can then be recovered at once with function
230 `recover-all-files'.
231
232 Takes care to make autosave files for files accessed through efs
233 be local files if variable `efs-auto-save-remotely' is nil.
234
235 Takes care of slashes in buffer names to prevent autosave errors.
236
237 Takes care that autosave files for buffers not visiting any file (such
238 as `*mail*') from two simultaneous Emacses don't collide by prepending
239 the Emacs pid.
240
241 Uses 14 character autosave names if `auto-save-hash-p' is true.
242
243 Autosaves even if the current directory is not writable, using
244 directory `auto-save-directory-fallback'.
245
246 You can redefine this for customization (he he :-).
247 See also function `auto-save-file-name-p'."
248
249   ;; We have to be very careful about not signalling an error in this
250   ;; function since files.el does not provide for this (e.g. find-file
251   ;; would fail for each new file).
252
253   (setq file-name (or file-name
254                       buffer-file-truename
255                       (and buffer-file-name
256                            (expand-file-name buffer-file-name))))
257   (condition-case error-data
258       (let (
259             ;; So autosavename looks like #%...#, roughly as with the
260             ;; old make-auto-save-file-name function.  The
261             ;; make-temp-name inserts the pid of this Emacs: this
262             ;; avoids autosaving from two Emacses into the same file.
263             ;; It cannot be recovered automatically then because in
264             ;; the next Emacs session (the one after the crash) the
265             ;; pid will be different, but file-less buffers like
266             ;; *mail* must be recovered manually anyway.
267
268             ;; jwz: putting the emacs PID in the auto-save file name is bad
269             ;; news, because that defeats auto-save-recovery of *mail*
270             ;; buffers -- the (sensible) code in sendmail.el calls
271             ;; (make-auto-save-file-name) to determine whether there is
272             ;; unsent, auto-saved mail to recover. If that mail came from a
273             ;; previous emacs process (far and away the most likely case)
274             ;; then this can never succeed as the pid differs.
275             ;;(name-prefix (if file-name nil (make-temp-name "#%")))
276             (name-prefix (if file-name nil "#%"))
277
278             (save-name (or file-name
279                            ;; Prevent autosave errors.  Buffername
280                            ;; (to become non-dir part of filename) will
281                            ;; be escaped twice.  Don't care.
282                            (auto-save-escape-name (buffer-name))))
283             (remote-p (and (stringp file-name)
284                            (fboundp 'efs-ftp-path)
285                            (efs-ftp-path file-name))))
286         ;; Return the appropriate auto save file name:
287         (expand-file-name;; a buffername needs this, a filename not
288          (cond (remote-p
289                 (if efs-auto-save-remotely
290                     (auto-save-name-in-same-directory save-name)
291                   ;; We have to use the `fixed-directory' now since the
292                   ;; `same-directory' would be remote.
293                   ;; It will use the fallback if needed.
294                   (auto-save-name-in-fixed-directory save-name)))
295                ;; Else it is a local file (or a buffer without a file,
296                ;; hence the name-prefix).
297                ((or auto-save-directory auto-save-hash-p)
298                 ;; Hashed files always go into the special hash dir,
299                 ;; never in the same directory, to make recognizing
300                 ;; reliable.
301                 (auto-save-name-in-fixed-directory save-name name-prefix))
302                (t
303                 (auto-save-name-in-same-directory save-name name-prefix)))))
304
305     ;; If any error occurs in the above code, return what the old
306     ;; version of this function would have done.  It is not ok to
307     ;; return nil, e.g., when after-find-file tests
308     ;; file-newer-than-file-p, nil would bomb.
309
310     (error (warn "Error caught in `make-auto-save-file-name':\n%s"
311                  (error-message-string error-data))
312            (let ((fname
313                   (if file-name
314                       (concat (file-name-directory file-name)
315                               "#"
316                               (file-name-nondirectory file-name)
317                               "#")
318                     (expand-file-name
319                      (concat "#%" (auto-save-escape-name (buffer-name))
320                              "#")))))
321              (if (or (file-writable-p fname)
322                      (file-exists-p fname))
323                  fname
324                (expand-file-name (concat "~/"
325                                          (file-name-nondirectory fname))))))))
326
327 (defun auto-save-file-name-p (filename)
328   "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
329 FILENAME should lack slashes.
330 You can redefine this for customization."
331   (string-match "\\`#.*#\\'" filename))
332
333 (defun auto-save-original-name (savename)
334   "Reverse of `make-auto-save-file-name'.
335 Returns nil if SAVENAME was not associated with a file (e.g., it came
336 from an autosaved `*mail*' buffer) or does not appear to be an
337 autosave file at all.
338 Hashed files are not understood, see `auto-save-hash-p'."
339   (let ((basename (file-name-nondirectory savename))
340         (savedir (file-name-directory savename)))
341     (cond ((or (not (auto-save-file-name-p basename))
342                (string-match "^#%" basename))
343            nil)
344           ;; now we know it looks like #...# thus substring is safe to use
345           ((or (equal savedir
346                       (and auto-save-directory
347                            (expand-file-name auto-save-directory)))
348                                         ; 2nd arg may be nil
349                (equal savedir
350                       (expand-file-name auto-save-directory-fallback)))
351            ;; it is of the `-fixed-directory' type
352            (auto-save-unescape-name (substring basename 1 -1)))
353           (t
354            ;; else it is of `-same-directory' type
355            (concat savedir (substring basename 1 -1))))))
356
357 (defun auto-save-name-in-fixed-directory (filename &optional prefix)
358   ;; Escape and enclose the whole FILENAME in `#' to make an auto
359   ;; save file in the auto-save-directory, or if that is nil, in
360   ;; auto-save-directory-fallback (which must be the name of an
361   ;; existing directory).  If the results would be too long for 14
362   ;; character filenames, and `auto-save-hash-p' is set, hash FILENAME
363   ;; into a shorter name.
364   ;; Optional PREFIX is string to use instead of "#" to prefix name.
365   (let ((base-name (concat (or prefix "#")
366                            (auto-save-escape-name filename)
367                            "#")))
368     (if (and auto-save-hash-p
369              auto-save-hash-directory
370              (> (length base-name) 14))
371         (expand-file-name (auto-save-cyclic-hash-14 filename)
372                           (auto-save-checked-directory auto-save-hash-directory))
373       (expand-file-name base-name
374                         (auto-save-checked-directory
375                            (or auto-save-directory
376                                auto-save-directory-fallback))))))
377
378 (defun auto-save-name-in-same-directory (filename &optional prefix)
379   ;; Enclose the non-directory part of FILENAME in `#' to make an auto
380   ;; save file in the same directory as FILENAME.  But if this
381   ;; directory is not writable, use auto-save-directory-fallback.
382   ;; FILENAME is assumed to be in non-directory form (no trailing slash).
383   ;; It may be a name without a directory part (presumably it really
384   ;; comes from a buffer name then), the fallback is used then.
385   ;; Optional PREFIX is string to use instead of "#" to prefix name.
386   (let ((directory (file-name-directory filename)))
387     (or (null directory)
388         (file-writable-p directory)
389         (setq directory (auto-save-checked-directory
390                          auto-save-directory-fallback)))
391     (concat directory                   ; (concat nil) is ""
392             (or prefix "#")
393             (file-name-nondirectory filename)
394             "#")))
395
396 (defconst auto-save-reserved-chars
397   '(
398     ?\0 ?\1 ?\2 ?\3 ?\4 ?\5 ?\6 ?\7 ?\10 ?\11 ?\12 ?\13 ?\14 ?\15 ?\16
399     ?\17 ?\20 ?\21 ?\22 ?\23 ?\24 ?\25 ?\26 ?\27 ?\30 ?\31 ?\32 ?\33
400     ?\34 ?\35 ?\36 ?\37 ?\40 ?? ?* ?: ?< ?> ?| ?/ ?\\ ?& ?^ ?% ?= ?\")
401   "List of characters disallowed (or potentially disallowed) in filenames.
402 Includes everything that can get us into trouble under MS Windows or Unix.")
403
404 ;; This code based on code in Bill Perry's url.el.
405     
406 (defun auto-save-escape-name (str)
407   "Escape any evil nasty characters in a potential filename.
408 Uses quoted-printable-style escaping -- e.g. the dreaded =3D.
409 Does not use URL escaping (with %) because filenames beginning with #% are
410 a special signal for non-file buffers."
411   (mapconcat
412    (function
413     (lambda (char)
414       (if (memq char auto-save-reserved-chars)
415           (if (< char 16)
416               (upcase (format "=0%x" char))
417             (upcase (format "=%x" char)))
418         (char-to-string char))))
419    str ""))
420
421 (defun auto-save-unhex (x)
422   (if (> x ?9)
423       (if (>= x ?a)
424           (+ 10 (- x ?a))
425         (+ 10 (- x ?A)))
426     (- x ?0)))
427
428 (defun auto-save-unescape-name (str)
429   "Undo any escaping of evil nasty characters in a file name.
430 See `auto-save-escape-name'."
431   (setq str (or str ""))
432   (let ((tmp "")
433         (case-fold-search t))
434     (while (string-match "=[0-9a-f][0-9a-f]" str)
435       (let* ((start (match-beginning 0))
436              (ch1 (auto-save-unhex (elt str (+ start 1))))
437              (code (+ (* 16 ch1)
438                       (auto-save-unhex (elt str (+ start 2))))))
439         (setq tmp (concat tmp (substring str 0 start)
440                           (char-to-string code))
441               str (substring str (match-end 0)))))
442     (setq tmp (concat tmp str))
443     tmp))
444
445 ;; The old versions are below.
446
447 ;(defun auto-save-escape-name (s)
448 ;  ;;  "Quote any slashes in string S by replacing them with the two
449 ;  ;;characters `\\!'.
450 ;  ;;Also, replace any backslash by double backslash, to make it one-to-one."
451 ;  (let ((limit 0))
452 ;    (while (string-match "[/\\]" s limit)
453 ;      (setq s (concat (substring s 0 (match-beginning 0))
454 ;                     (if (string= (substring s
455 ;                                             (match-beginning 0)
456 ;                                             (match-end 0))
457 ;                                  "/")
458 ;                         "\\!"
459 ;                       "\\\\")
460 ;                     (substring s (match-end 0))))
461 ;      (setq limit (1+ (match-end 0)))))
462 ;  s)
463
464 ;(defun auto-save-unescape-name (s)
465 ;  ;;"Reverse of `auto-save-escape-name'."
466 ;  (let (pos)
467 ;    (while (setq pos (string-match "\\\\[\\!]" s pos))
468 ;      (setq s (concat (substring s 0 pos)
469 ;                     (if (eq ?! (aref s (1+ pos))) "/" "\\")
470 ;                     (substring s (+ pos 2)))
471 ;           pos (1+ pos))))
472 ;  s)
473
474 \f
475 ;;; Hashing for autosave names
476
477 ;;; Hashing function contributed by Andy Norman <ange@hplb.hpl.hp.com>
478 ;;; based upon C code from pot@fly.cnuce.cnr.IT (Francesco Potorti`).
479
480 (defun auto-save-cyclic-hash-14 (s)
481   ;;   "Hash string S into a string of length 14.
482   ;; A 7-bytes cyclic code for burst correction is calculated on a
483   ;; byte-by-byte basis. The polynomial used is D^7 + D^6 + D^3 +1.
484   ;; The resulting string consists of hexadecimal digits [0-9a-f].
485   ;; In particular, it contains no slash, so it can be used as autosave name."
486   (let ((crc (make-vector 7 ?\0)))
487     (mapc
488      (lambda (new)
489        (setq new (+ new (aref crc 6)))
490        (aset crc 6 (+ (aref crc 5) new))
491        (aset crc 5 (aref crc 4))
492        (aset crc 4 (aref crc 3))
493        (aset crc 3 (+ (aref crc 2) new))
494        (aset crc 2 (aref crc 1))
495        (aset crc 1 (aref crc 0))
496        (aset crc 0 new))
497      s)
498     (format "%02x%02x%02x%02x%02x%02x%02x"
499             (logand 255 (aref crc 0))
500             (logand 255 (aref crc 1))
501             (logand 255 (aref crc 2))
502             (logand 255 (aref crc 3))
503             (logand 255 (aref crc 4))
504             (logand 255 (aref crc 5))
505             (logand 255 (aref crc 6)))))
506
507 ;; #### It is unclear to me how the following function is useful.  It
508 ;; should be used in `auto-save-name-in-same-directory', if anywhere.
509 ;; -hniksic
510
511 ;; This leaves two characters that could be used to wrap it in `#' or
512 ;; make two filenames from it: one for autosaving, and another for a
513 ;; file containing the name of the autosaved file, to make hashing
514 ;; reversible.
515 ;(defun auto-save-cyclic-hash-12 (s)
516 ;  "Outputs the 12-characters ascii hex representation of a 6-bytes
517 ;cyclic code for burst correction calculated on STRING on a
518 ;byte-by-byte basis. The used polynomial is D^6 + D^5 + D^4 + D^3 +1."
519 ;  (let ((crc (make-string 6 0)))
520 ;    (mapc
521 ;     (lambda (new)
522 ;       (setq new (+ new (aref crc 5)))
523 ;       (aset crc 5 (+ (aref crc 4) new))
524 ;       (aset crc 4 (+ (aref crc 3) new))
525 ;       (aset crc 3 (+ (aref crc 2) new))
526 ;       (aset crc 2 (aref crc 1))
527 ;       (aset crc 1 (aref crc 0))
528 ;       (aset crc 0 new))
529 ;     s)
530 ;    (format "%02x%02x%02x%02x%02x%02x"
531 ;            (aref crc 0)
532 ;            (aref crc 1)
533 ;            (aref crc 2)
534 ;            (aref crc 3)
535 ;            (aref crc 4)
536 ;            (aref crc 5))))
537
538 \f
539
540 ;;; Recovering files
541
542 (defun recover-all-files (&optional silent)
543   "Do recover-file for all autosave files which are current.
544 Only works if you have a non-nil `auto-save-directory'.
545
546 Optional prefix argument SILENT means to be silent about non-current
547 autosave files.  This is useful if invoked automatically at Emacs
548 startup.
549
550 If `auto-save-offer-delete' is t, this function will offer to delete
551 old or rejected autosave files.
552
553 Hashed files (see `auto-save-hash-p') are not understood, use
554 `recover-file' to recover them individually."
555   (interactive "P")
556   (let ((savefiles (directory-files auto-save-directory
557                                     t "\\`#" nil t))
558         afile                           ; the auto save file
559         file                            ; its original file
560         (total 0)                       ; # of files offered to recover
561         (count 0))                      ; # of files actually recovered
562     (or (equal (expand-file-name auto-save-directory)
563                (expand-file-name auto-save-directory-fallback))
564         (setq savefiles
565               (nconc savefiles
566                      (directory-files auto-save-directory-fallback
567                                       t "\\`#" nil t))))
568     (while savefiles
569       (setq afile (car savefiles)
570             file (auto-save-original-name afile)
571             savefiles (cdr savefiles))
572       (cond ((and file (not (file-newer-than-file-p afile file)))
573              (warn "Autosave file \"%s\" is not current." afile))
574             (t
575              (incf total)
576              (with-output-to-temp-buffer "*Directory*"
577                (buffer-disable-undo standard-output)
578                (save-excursion
579                  (set-buffer "*Directory*")
580                  (setq default-directory (file-name-directory afile))
581                  (insert-directory afile "-l")
582                  (when file
583                    (setq default-directory (file-name-directory file))
584                    (insert-directory file "-l"))))
585              (if (yes-or-no-p (format "Recover %s from auto save file? "
586                                       (or file "non-file buffer")))
587                  (let* ((obuf (current-buffer)))
588                    (set-buffer (if file
589                                    (find-file-noselect file t)
590                                  (generate-new-buffer "*recovered*")))
591                    (setq buffer-read-only nil)
592                    (erase-buffer)
593                    (insert-file-contents afile nil)
594                    (ignore-errors
595                      (after-find-file nil))
596                    (setq buffer-auto-save-file-name nil)
597                    (incf count)
598                    (message "\
599 Auto-save off in buffer \"%s\" till you do M-x auto-save-mode."
600                             (buffer-name))
601                    (set-buffer obuf)
602                    (sit-for 1))
603                ;; If not used for recovering, offer to delete
604                ;; autosave file
605                (and auto-save-offer-delete
606                     (or (eq 'always auto-save-offer-delete)
607                         (yes-or-no-p
608                          (format "Delete autosave file for `%s'? " file)))
609                     (delete-file afile))))))
610     (if (zerop total)
611         (or silent (message "Nothing to recover."))
612       (message "%d/%d file%s recovered." count total (if (= count 1) "" "s"))))
613   (and (get-buffer "*Directory*")
614        (kill-buffer "*Directory*")))
615
616 ;;; auto-save.el ends here