| 1 | ;;; -*- Package: Hemlock; Log: hemlock.log -*-
|
|---|
| 2 | ;;;
|
|---|
| 3 | ;;; **********************************************************************
|
|---|
| 4 | ;;; This code was written as part of the CMU Common Lisp project at
|
|---|
| 5 | ;;; Carnegie Mellon University, and has been placed in the public domain.
|
|---|
| 6 | ;;;
|
|---|
| 7 | #+CMU (ext:file-comment
|
|---|
| 8 | "$Header$")
|
|---|
| 9 | ;;;
|
|---|
| 10 | ;;; **********************************************************************
|
|---|
| 11 | ;;;
|
|---|
| 12 | ;;; Auto-Save Mode
|
|---|
| 13 | ;;; Written by Christopher Hoover
|
|---|
| 14 | ;;;
|
|---|
| 15 |
|
|---|
| 16 | (in-package :hemlock)
|
|---|
| 17 |
|
|---|
| 18 | |
|---|
| 19 |
|
|---|
| 20 | ;;;; Per Buffer State Information
|
|---|
| 21 |
|
|---|
| 22 | ;;;
|
|---|
| 23 | ;;; The auto-save-state structure is used to store the state information for
|
|---|
| 24 | ;;; a particular buffer in "Save" mode, namely the buffer-signature at the last
|
|---|
| 25 | ;;; key stroke, the buffer-signature at the time of the last checkpoint, a count
|
|---|
| 26 | ;;; of the number of destructive keystrokes which have occured since the time of
|
|---|
| 27 | ;;; the last checkpoint, and the pathname used to write the last checkpoint. It
|
|---|
| 28 | ;;; is generally kept in a buffer-local hvar called "Auto Save State".
|
|---|
| 29 | ;;;
|
|---|
| 30 | (defstruct (auto-save-state
|
|---|
| 31 | (:conc-name save-state-)
|
|---|
| 32 | (:print-function print-auto-save-state))
|
|---|
| 33 | "Per buffer state for auto-save"
|
|---|
| 34 | (buffer nil) ; buffer this state is for; for printing
|
|---|
| 35 | (key-signature 0 :type fixnum) ; buffer-signature at last keystroke
|
|---|
| 36 | (last-ckp-signature 0 :type fixnum) ; buffer-signature at last checkpoint
|
|---|
| 37 | (key-count 0 :type fixnum) ; # destructive keystrokes since ckp
|
|---|
| 38 | (pathname nil)) ; pathname used to write last ckp file
|
|---|
| 39 |
|
|---|
| 40 | (defun print-auto-save-state (auto-save-state stream depth)
|
|---|
| 41 | (declare (ignore depth))
|
|---|
| 42 | (format stream "#<Auto Save Buffer State for buffer ~A>"
|
|---|
| 43 | (buffer-name (save-state-buffer auto-save-state))))
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 | ;;; GET-AUTO-SAVE-STATE tries to get the auto-save-state for the buffer. If
|
|---|
| 47 | ;;; the buffer is not in "Save" mode then this function returns NIL.
|
|---|
| 48 | ;;;
|
|---|
| 49 | (defun get-auto-save-state (buffer)
|
|---|
| 50 | (if (hemlock-bound-p 'auto-save-state :buffer buffer)
|
|---|
| 51 | (variable-value 'auto-save-state :buffer buffer)))
|
|---|
| 52 |
|
|---|
| 53 | ;;; RESET-AUTO-SAVE-STATE resets the auto-save-state of the buffer making it
|
|---|
| 54 | ;;; look as if the buffer was just checkpointed. This is in fact how
|
|---|
| 55 | ;;; checkpoint-buffer updates the state. If the buffer is not in "Save" mode
|
|---|
| 56 | ;;; this function punts the attempt and does nothing.
|
|---|
| 57 | ;;;
|
|---|
| 58 | (defun reset-auto-save-state (buffer)
|
|---|
| 59 | (let ((state (get-auto-save-state buffer)))
|
|---|
| 60 | (when state
|
|---|
| 61 | (let ((signature (buffer-signature buffer)))
|
|---|
| 62 | (setf (save-state-key-signature state)
|
|---|
| 63 | signature)
|
|---|
| 64 | (setf (save-state-last-ckp-signature state)
|
|---|
| 65 | signature)
|
|---|
| 66 | (setf (save-state-key-count state)
|
|---|
| 67 | 0)))))
|
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 | |
|---|
| 71 |
|
|---|
| 72 | ;;;; Checkpoint Pathname Interface/Internal Routines
|
|---|
| 73 |
|
|---|
| 74 | ;;; GET-CHECKPOINT-PATHNAME -- Interface
|
|---|
| 75 | ;;;
|
|---|
| 76 | ;;; Returns the pathname of the checkpoint file for the specified
|
|---|
| 77 | ;;; buffer; Returns NIL if no checkpoints have been written thus
|
|---|
| 78 | ;;; far or if the buffer isn't in "Save" mode.
|
|---|
| 79 | ;;;
|
|---|
| 80 | (defun get-checkpoint-pathname (buffer)
|
|---|
| 81 | "Returns the pathname of the checkpoint file for the specified buffer.
|
|---|
| 82 | If no checkpoints have been written thus far, or if the buffer is not in
|
|---|
| 83 | \"Save\" mode, return nil."
|
|---|
| 84 | (let ((state (get-auto-save-state buffer)))
|
|---|
| 85 | (if state
|
|---|
| 86 | (save-state-pathname state))))
|
|---|
| 87 |
|
|---|
| 88 | ;;; MAKE-UNIQUE-SAVE-PATHNAME is used as the default value for "Auto Save
|
|---|
| 89 | ;;; Pathname Hook" and is mentioned in the User's manual, so it gets a doc
|
|---|
| 90 | ;;; doc string.
|
|---|
| 91 | ;;;
|
|---|
| 92 | (defun make-unique-save-pathname (buffer)
|
|---|
| 93 | "Returns a pathname for a non-existing file in DEFAULT-DIRECTORY. Uses
|
|---|
| 94 | GENSYM to for a file name: save-GENSYM.CKP."
|
|---|
| 95 | (declare (ignore buffer))
|
|---|
| 96 | (let ((def-dir (hemlock-ext:default-directory)))
|
|---|
| 97 | (loop
|
|---|
| 98 | (let* ((sym (gensym))
|
|---|
| 99 | (f (merge-pathnames (format nil "save-~A.CKP" sym) def-dir)))
|
|---|
| 100 | (unless (probe-file f)
|
|---|
| 101 | (return f))))))
|
|---|
| 102 |
|
|---|
| 103 | (defhvar "Auto Save Pathname Hook"
|
|---|
| 104 | "This hook is called by Auto Save to get a checkpoint pathname when there
|
|---|
| 105 | is no pathname associated with a buffer. If this value is NIL, then
|
|---|
| 106 | \"Save\" mode is turned off in the buffer. Otherwise, the function
|
|---|
| 107 | will be called. It should take a buffer as its argument and return either
|
|---|
| 108 | NIL or a pathname. If NIL is returned, then \"Save\" mode is turned off
|
|---|
| 109 | in the buffer; else the pathname returned is used as the checkpoint
|
|---|
| 110 | pathname for the buffer."
|
|---|
| 111 | :value #'make-unique-save-pathname)
|
|---|
| 112 |
|
|---|
| 113 |
|
|---|
| 114 | ;;; MAKE-BUFFER-CKP-PATHNAME attempts to form a pathname by using the buffer's
|
|---|
| 115 | ;;; associated pathname (from buffer-pathname). If there isn't a pathname
|
|---|
| 116 | ;;; associated with the buffer, the function returns nil. Otherwise, it uses
|
|---|
| 117 | ;;; the "Auto Save Filename Pattern" and FORMAT to make the checkpoint
|
|---|
| 118 | ;;; pathname.
|
|---|
| 119 | ;;;
|
|---|
| 120 | (defun make-buffer-ckp-pathname (buffer)
|
|---|
| 121 | (let ((buffer-pn (buffer-pathname buffer)))
|
|---|
| 122 | (if buffer-pn
|
|---|
| 123 | (pathname (format nil
|
|---|
| 124 | (value auto-save-filename-pattern)
|
|---|
| 125 | (directory-namestring buffer-pn)
|
|---|
| 126 | (file-namestring buffer-pn))))))
|
|---|
| 127 |
|
|---|
| 128 |
|
|---|
| 129 | |
|---|
| 130 |
|
|---|
| 131 | ;;;; Buffer-level Checkpoint Routines
|
|---|
| 132 |
|
|---|
| 133 | ;;;
|
|---|
| 134 | ;;; write-checkpoint-file -- Internal
|
|---|
| 135 | ;;;
|
|---|
| 136 | ;;; Does the low-level write of the checkpoint. Returns T if it succeeds
|
|---|
| 137 | ;;; and NIL if it fails. Echoes winnage or lossage to the luser.
|
|---|
| 138 | ;;;
|
|---|
| 139 | (defun write-checkpoint-file (pathname buffer)
|
|---|
| 140 | (let ((ns (namestring pathname)))
|
|---|
| 141 | (cond ((hemlock-ext:file-writable pathname)
|
|---|
| 142 | (message "Saving ~A" ns)
|
|---|
| 143 | (handler-case (progn
|
|---|
| 144 | (write-file (buffer-region buffer) pathname
|
|---|
| 145 | :keep-backup nil
|
|---|
| 146 | :access #o600) ;read/write by owner.
|
|---|
| 147 | t)
|
|---|
| 148 | (error (condition)
|
|---|
| 149 | (loud-message "Auto Save failure: ~A" condition)
|
|---|
| 150 | nil)))
|
|---|
| 151 | (t
|
|---|
| 152 | (message "Can't write ~A" ns)
|
|---|
| 153 | nil))))
|
|---|
| 154 |
|
|---|
| 155 |
|
|---|
| 156 | ;;;
|
|---|
| 157 | ;;; To save, or not to save... and to save as what?
|
|---|
| 158 | ;;;
|
|---|
| 159 | ;;; First, make-buffer-ckp-pathname is called. It will return either NIL or
|
|---|
| 160 | ;;; a pathname formed by using buffer-pathname in conjunction with the hvar
|
|---|
| 161 | ;;; "Auto Save Filename Pattern". If there isn't an associated pathname or
|
|---|
| 162 | ;;; make-buffer-ckp-pathname returns NIL, then we use the pathname we used
|
|---|
| 163 | ;;; the last time we checkpointed the buffer. If we've never checkpointed
|
|---|
| 164 | ;;; the buffer, then we check "Auto Save Pathname Hook". If it is NIL then
|
|---|
| 165 | ;;; we turn Save mode off for the buffer, else we funcall the function on
|
|---|
| 166 | ;;; the hook with the buffer as an argument. The function on the hook should
|
|---|
| 167 | ;;; return either NIL or a pathname. If it returns NIL, we toggle Save mode
|
|---|
| 168 | ;;; off for the buffer; otherwise, we use the pathname it returned.
|
|---|
| 169 | ;;;
|
|---|
| 170 |
|
|---|
| 171 | ;;;
|
|---|
| 172 | ;;; checkpoint-buffer -- Internal
|
|---|
| 173 | ;;;
|
|---|
| 174 | ;;; This functions takes a buffer as its argument and attempts to write a
|
|---|
| 175 | ;;; checkpoint for that buffer. See the notes at the beginning of this page
|
|---|
| 176 | ;;; for how it determines what pathname to use as the checkpoint pathname.
|
|---|
| 177 | ;;; Note that a checkpoint is not necessarily written -- instead "Save"
|
|---|
| 178 | ;;; mode may be turned off for the buffer.
|
|---|
| 179 | ;;;
|
|---|
| 180 | (defun checkpoint-buffer (buffer)
|
|---|
| 181 | (let* ((state (get-auto-save-state buffer))
|
|---|
| 182 | (buffer-ckp-pn (make-buffer-ckp-pathname buffer))
|
|---|
| 183 | (last-pathname (save-state-pathname state)))
|
|---|
| 184 | (cond (buffer-ckp-pn
|
|---|
| 185 | (when (write-checkpoint-file buffer-ckp-pn buffer)
|
|---|
| 186 | (reset-auto-save-state buffer)
|
|---|
| 187 | (setf (save-state-pathname state) buffer-ckp-pn)
|
|---|
| 188 | (when (and last-pathname
|
|---|
| 189 | (not (equal last-pathname buffer-ckp-pn))
|
|---|
| 190 | (probe-file last-pathname))
|
|---|
| 191 | (delete-file last-pathname))))
|
|---|
| 192 | (last-pathname
|
|---|
| 193 | (when (write-checkpoint-file last-pathname buffer)
|
|---|
| 194 | (reset-auto-save-state buffer)))
|
|---|
| 195 | (t
|
|---|
| 196 | (let* ((save-pn-hook (value auto-save-pathname-hook))
|
|---|
| 197 | (new-pn (if save-pn-hook
|
|---|
| 198 | (funcall save-pn-hook buffer))))
|
|---|
| 199 | (cond ((or (not new-pn)
|
|---|
| 200 | (zerop (length
|
|---|
| 201 | (the simple-string (namestring new-pn)))))
|
|---|
| 202 | (setf (buffer-minor-mode buffer "Save") nil))
|
|---|
| 203 | (t
|
|---|
| 204 | (when (write-checkpoint-file new-pn buffer)
|
|---|
| 205 | (reset-auto-save-state buffer)
|
|---|
| 206 | (setf (save-state-pathname state) new-pn)))))))))
|
|---|
| 207 |
|
|---|
| 208 | ;;;
|
|---|
| 209 | ;;; checkpoint-all-buffers -- Internal
|
|---|
| 210 | ;;;
|
|---|
| 211 | ;;; This function looks through the buffer list and checkpoints
|
|---|
| 212 | ;;; each buffer that is in "Save" mode that has been modified since
|
|---|
| 213 | ;;; its last checkpoint.
|
|---|
| 214 | ;;;
|
|---|
| 215 | (defun checkpoint-all-buffers (elapsed-time)
|
|---|
| 216 | (declare (ignore elapsed-time))
|
|---|
| 217 | (dolist (buffer *buffer-list*)
|
|---|
| 218 | (let ((state (get-auto-save-state buffer)))
|
|---|
| 219 | (when (and state
|
|---|
| 220 | (buffer-modified buffer)
|
|---|
| 221 | (not (eql
|
|---|
| 222 | (save-state-last-ckp-signature state)
|
|---|
| 223 | (buffer-signature buffer))))
|
|---|
| 224 | (checkpoint-buffer buffer)))))
|
|---|
| 225 |
|
|---|
| 226 | |
|---|
| 227 |
|
|---|
| 228 | ;;;; Random Hooks: cleanup, buffer-modified, change-save-freq.
|
|---|
| 229 |
|
|---|
| 230 | ;;;
|
|---|
| 231 | ;;; cleanup-checkpoint -- Internal
|
|---|
| 232 | ;;;
|
|---|
| 233 | ;;; Cleans up checkpoint file for a given buffer if Auto Save Cleanup
|
|---|
| 234 | ;;; Checkpoints is non-NIL. This is called via "Write File Hook"
|
|---|
| 235 | ;;;
|
|---|
| 236 | (defun cleanup-checkpoint (buffer)
|
|---|
| 237 | (let ((ckp-pathname (get-checkpoint-pathname buffer)))
|
|---|
| 238 | (when (and (value auto-save-cleanup-checkpoints)
|
|---|
| 239 | ckp-pathname
|
|---|
| 240 | (probe-file ckp-pathname))
|
|---|
| 241 | (delete-file ckp-pathname))))
|
|---|
| 242 |
|
|---|
| 243 | (add-hook write-file-hook 'cleanup-checkpoint)
|
|---|
| 244 |
|
|---|
| 245 | ;;;
|
|---|
| 246 | ;;; notice-buffer-modified -- Internal
|
|---|
| 247 | ;;;
|
|---|
| 248 | ;;; This function is called on "Buffer Modified Hook" to reset
|
|---|
| 249 | ;;; the Auto Save state. It makes the buffer look like it has just
|
|---|
| 250 | ;;; been checkpointed.
|
|---|
| 251 | ;;;
|
|---|
| 252 | (defun notice-buffer-modified (buffer flag)
|
|---|
| 253 | ;; we care only when the flag has gone to false
|
|---|
| 254 | (when (not flag)
|
|---|
| 255 | (reset-auto-save-state buffer)))
|
|---|
| 256 |
|
|---|
| 257 | (add-hook buffer-modified-hook 'notice-buffer-modified)
|
|---|
| 258 |
|
|---|
| 259 | ;;;
|
|---|
| 260 | ;;; change-save-frequency -- Internal
|
|---|
| 261 | ;;;
|
|---|
| 262 | ;;; This keeps us scheduled at the proper interval. It is stuck on
|
|---|
| 263 | ;;; the hook list for the hvar "Auto Save Checkpoint Frequency" and
|
|---|
| 264 | ;;; is therefore called whenever this value is set.
|
|---|
| 265 | ;;;
|
|---|
| 266 | (defun change-save-frequency (name kind where new-value)
|
|---|
| 267 | (declare (ignore name kind where))
|
|---|
| 268 | (setq new-value (truncate new-value))
|
|---|
| 269 | (remove-scheduled-event 'checkpoint-all-buffers)
|
|---|
| 270 | (when (and new-value
|
|---|
| 271 | (plusp new-value))
|
|---|
| 272 | (schedule-event new-value 'checkpoint-all-buffers t)))
|
|---|
| 273 |
|
|---|
| 274 |
|
|---|
| 275 | ;;; "Save" mode is in "Default Modes", so turn it off in these modes.
|
|---|
| 276 | ;;;
|
|---|
| 277 |
|
|---|
| 278 | (defun interactive-modes (buffer on)
|
|---|
| 279 | (when on (setf (buffer-minor-mode buffer "Save") nil)))
|
|---|
| 280 |
|
|---|
| 281 | #+GBNIL (add-hook typescript-mode-hook 'interactive-modes)
|
|---|
| 282 | #+GBNIL (add-hook eval-mode-hook 'interactive-modes)
|
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 | |
|---|
| 286 |
|
|---|
| 287 | ;;;; Key Count Routine for Input Hook
|
|---|
| 288 |
|
|---|
| 289 | ;;;
|
|---|
| 290 | ;;; auto-save-count-keys -- Internal
|
|---|
| 291 | ;;;
|
|---|
| 292 | ;;; This function sits on the Input Hook to eat cycles. If the current
|
|---|
| 293 | ;;; buffer is not in Save mode or if the current buffer is the echo area
|
|---|
| 294 | ;;; buffer, it does nothing. Otherwise, we check to see if we have exceeded
|
|---|
| 295 | ;;; the key count threshold (and write a checkpoint if we have) and we
|
|---|
| 296 | ;;; increment the key count for the buffer.
|
|---|
| 297 | ;;;
|
|---|
| 298 | (defun auto-save-count-keys ()
|
|---|
| 299 | #.*fast*
|
|---|
| 300 | (let ((buffer (current-buffer)))
|
|---|
| 301 | (unless (eq buffer *echo-area-buffer*)
|
|---|
| 302 | (let ((state (value auto-save-state))
|
|---|
| 303 | (threshold (value auto-save-key-count-threshold)))
|
|---|
| 304 | (when (and state threshold)
|
|---|
| 305 | (let ((signature (buffer-signature buffer)))
|
|---|
| 306 | (declare (fixnum signature))
|
|---|
| 307 | (when (not (eql signature
|
|---|
| 308 | (save-state-key-signature state)))
|
|---|
| 309 | ;; see if we exceeded threshold last time...
|
|---|
| 310 | (when (>= (save-state-key-count state)
|
|---|
| 311 | (the fixnum threshold))
|
|---|
| 312 | (checkpoint-buffer buffer))
|
|---|
| 313 | ;; update state
|
|---|
| 314 | (setf (save-state-key-signature state) signature)
|
|---|
| 315 | (incf (save-state-key-count state)))))))))
|
|---|
| 316 |
|
|---|
| 317 | (add-hook input-hook 'auto-save-count-keys)
|
|---|
| 318 |
|
|---|
| 319 | |
|---|
| 320 |
|
|---|
| 321 | ;;;; Save Mode Hemlock Variables
|
|---|
| 322 |
|
|---|
| 323 | ;;;
|
|---|
| 324 | ;;; Hemlock variables/parameters for Auto-Save Mode
|
|---|
| 325 | ;;;
|
|---|
| 326 |
|
|---|
| 327 | (defhvar "Auto Save Filename Pattern"
|
|---|
| 328 | "This control-string is used with format to make the filename of the
|
|---|
| 329 | checkpoint file. Format is called with two arguments, the first
|
|---|
| 330 | being the directory namestring and the second being the file
|
|---|
| 331 | namestring of the default buffer pathname."
|
|---|
| 332 | :value "~A~A.CKP")
|
|---|
| 333 |
|
|---|
| 334 | (defhvar "Auto Save Key Count Threshold"
|
|---|
| 335 | "This value is the number of destructive/modifying keystrokes that will
|
|---|
| 336 | automatically trigger an checkpoint. This value may be NIL to turn this
|
|---|
| 337 | feature off."
|
|---|
| 338 | :value 256)
|
|---|
| 339 |
|
|---|
| 340 | (defhvar "Auto Save Cleanup Checkpoints"
|
|---|
| 341 | "This variable controls whether or not \"Save\" mode will delete the
|
|---|
| 342 | checkpoint file for a buffer after it is saved. If this value is
|
|---|
| 343 | non-NIL then cleanup will occur."
|
|---|
| 344 | :value t)
|
|---|
| 345 |
|
|---|
| 346 | (defhvar "Auto Save Checkpoint Frequency"
|
|---|
| 347 | "All modified buffers (in \"Save\" mode) will be checkpointed after this
|
|---|
| 348 | amount of time (in seconds). This value may be NIL (or non-positive)
|
|---|
| 349 | to turn this feature off."
|
|---|
| 350 | :value (* 2 60)
|
|---|
| 351 | :hooks '(change-save-frequency))
|
|---|
| 352 |
|
|---|
| 353 | (defhvar "Auto Save State"
|
|---|
| 354 | "Shadow magic. This variable is seen when in buffers that are not
|
|---|
| 355 | in \"Save\" mode. Do not change this value or you will lose."
|
|---|
| 356 | :value nil)
|
|---|
| 357 |
|
|---|
| 358 | |
|---|
| 359 |
|
|---|
| 360 | ;;;; "Save" mode
|
|---|
| 361 |
|
|---|
| 362 | (defcommand "Auto Save Mode" (p)
|
|---|
| 363 | "If the argument is zero or negative, turn \"Save\" mode off. If it
|
|---|
| 364 | is positive turn \"Save\" mode on. If there is no argument, toggle
|
|---|
| 365 | \"Save\" mode in the current buffer. When in \"Save\" mode, files
|
|---|
| 366 | are automatically checkpointed every \"Auto Save Checkpoint Frequency\"
|
|---|
| 367 | seconds or every \"Auto Save Key Count Threshold\" destructive
|
|---|
| 368 | keystrokes. If there is a pathname associated with the buffer, the
|
|---|
| 369 | filename used for the checkpoint file is controlled by the hvar \"Auto
|
|---|
| 370 | Save Filename Pattern\". Otherwise, the hook \"Auto Save Pathname Hook\"
|
|---|
| 371 | is used to generate a checkpoint pathname. If the buffer's pathname
|
|---|
| 372 | changes between checkpoints, the checkpoint file will be written under
|
|---|
| 373 | the new name and the old checkpoint file will be deleted if it exists.
|
|---|
| 374 | When a buffer is written out, the checkpoint will be deleted if the
|
|---|
| 375 | hvar \"Auto Save Cleanup Checkpoints\" is non-NIL."
|
|---|
| 376 | "Turn on, turn off, or toggle \"Save\" mode in the current buffer."
|
|---|
| 377 | (setf (buffer-minor-mode (current-buffer) "Save")
|
|---|
| 378 | (if p
|
|---|
| 379 | (plusp p)
|
|---|
| 380 | (not (buffer-minor-mode (current-buffer) "Save")))))
|
|---|
| 381 |
|
|---|
| 382 | (defun setup-auto-save-mode (buffer)
|
|---|
| 383 | (let* ((signature (buffer-signature buffer))
|
|---|
| 384 | (state (make-auto-save-state
|
|---|
| 385 | :buffer buffer
|
|---|
| 386 | :key-signature (the fixnum signature)
|
|---|
| 387 | :last-ckp-signature (the fixnum signature))))
|
|---|
| 388 | ;; shadow the global value with a variable which will
|
|---|
| 389 | ;; contain our per buffer state information
|
|---|
| 390 | (defhvar "Auto Save State"
|
|---|
| 391 | "This is the \"Save\" mode state information for this buffer."
|
|---|
| 392 | :buffer buffer
|
|---|
| 393 | :value state)))
|
|---|
| 394 |
|
|---|
| 395 | (defun cleanup-auto-save-mode (buffer)
|
|---|
| 396 | (delete-variable 'auto-save-state
|
|---|
| 397 | :buffer buffer))
|
|---|
| 398 |
|
|---|
| 399 | (defmode "Save"
|
|---|
| 400 | :setup-function 'setup-auto-save-mode
|
|---|
| 401 | :cleanup-function 'cleanup-auto-save-mode)
|
|---|