emacs-pretest-bug
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Undo discard prompt (was: [T. V. Raman] read-only modes should be us


From: Luc Teirlinck
Subject: Re: Undo discard prompt (was: [T. V. Raman] read-only modes should be using buffer-disable-undo?)
Date: Mon, 24 Jan 2005 17:29:25 -0600 (CST)

Richard Stallman wrote:

   there was indeed a bug where Emacs generated lots of undo info during
   a single command and crashed, and the only fix I could see was to
   discard the undo info.  So I don't think turning off the question is a
   good default.

If you mean just silently allowing the undo info to pile up and
running the small but real (because actually occurring) risk of a
crash, that would indeed not be a good default.

   However, we could probably substantially increase the size threshold.
   If we multiply it by 10, it might still be good enough to prevent a
   problem, but it might rarely be encountered when there is no problem.

In some of the cases we looked at, the undo info went to infinity over
time.  (Which of course was a bug, but there is no way to be sure
there are no similar bugs left, nor is there any way to prevent people
from making similar bugs in the future.)

What about the following patches to simple.el and undo.c which keep
the current behavior as default, but provide two alternatives through
a customizable option: discard the undo info and print a warning
message in the echo area and discard completely silently?  It is
obvious that many people dislike the current behavior, hence I believe
that we need at the very least to make it customizable.

I personally believe that discarding with warning would be a better
default, but the patches below keep the current default.  I can
install if desired.

Somebody who would want to experiment with the patches below could for
instance enable the following two timers:

(setq timer1
      (run-at-time 5 5
                   (lambda ()
                     (with-current-buffer (get-buffer-create "sillybuf")
                       (insert-file-contents "~/.emacs")))))

(setq timer2
      (run-at-time 2  2
                   (lambda ()
                     (with-current-buffer (get-buffer-create "sillybuf")
                       (erase-buffer))))) 

Of course, you might want to replace ".emacs" in the above with some
other, appropriately sized file.


===File ~/simple.el-diff====================================
*** simple.el   23 Jan 2005 09:35:35 -0600      1.686
--- simple.el   24 Jan 2005 16:50:25 -0600      
***************
*** 1524,1550 ****
  (defvar undo-extra-outer-limit nil
    "If non-nil, an extra level of size that's ok in an undo item.
  We don't ask the user about truncating the undo list until the
! current item gets bigger than this amount.")
  (make-variable-buffer-local 'undo-extra-outer-limit)
  
  ;; When the first undo batch in an undo list is longer than undo-outer-limit,
  ;; this function gets called to ask the user what to do.
  ;; Garbage collection is inhibited around the call,
  ;; so it had better not do a lot of consing.
  (setq undo-outer-limit-function 'undo-outer-limit-truncate)
  (defun undo-outer-limit-truncate (size)
!   (when (or (null undo-extra-outer-limit)
            (> size undo-extra-outer-limit))
      ;; Don't ask the question again unless it gets even bigger.
      ;; This applies, in particular, if the user quits from the question.
      ;; Such a quit quits out of GC, but something else will call GC
      ;; again momentarily.  It will call this function again,
      ;; but we don't want to ask the question again.
!     (setq undo-extra-outer-limit (+ size 50000))
!     (if (let (use-dialog-box)
!         (yes-or-no-p (format "Buffer %s undo info is %d bytes long; discard 
it? "
!                              (buffer-name) size)))
!       (progn (setq buffer-undo-list nil)
               (setq undo-extra-outer-limit nil)
               t)
        nil)))
--- 1524,1571 ----
  (defvar undo-extra-outer-limit nil
    "If non-nil, an extra level of size that's ok in an undo item.
  We don't ask the user about truncating the undo list until the
! current item gets bigger than this amount.
! This variable has no effect if `undo-discard-silently' is t.")
  (make-variable-buffer-local 'undo-extra-outer-limit)
  
+ (defcustom undo-discard-silently nil
+   "If non-nil Emacs discards oversized undo info without asking.
+ If nil, Emacs asks before discarding the undo info for the most recent
+ command if the size exceeds `undo-outer-limit'.
+ If the value is the symbol `warn', Emacs prints a warning message.
+ Any other non-nil value means to discard silently.
+ Note that if you set this non-nil, you may, on rare occasions,
+ not be able to undo the last command."
+   :type '(choice (const :tag "Ask" nil)
+                (const :tag "Warn" warn)
+                (other :tag "Discard silently" t))
+   :group 'undo
+   :version "21.4")
+ 
  ;; When the first undo batch in an undo list is longer than undo-outer-limit,
  ;; this function gets called to ask the user what to do.
  ;; Garbage collection is inhibited around the call,
  ;; so it had better not do a lot of consing.
  (setq undo-outer-limit-function 'undo-outer-limit-truncate)
  (defun undo-outer-limit-truncate (size)
!   (when (or undo-discard-silently
!           (null undo-extra-outer-limit)
            (> size undo-extra-outer-limit))
      ;; Don't ask the question again unless it gets even bigger.
      ;; This applies, in particular, if the user quits from the question.
      ;; Such a quit quits out of GC, but something else will call GC
      ;; again momentarily.  It will call this function again,
      ;; but we don't want to ask the question again.
!     (unless undo-discard-silently (setq undo-extra-outer-limit (+ size 
50000)))
!     (if (or undo-discard-silently
!           (let (use-dialog-box)
!             (yes-or-no-p
!              (format "Buffer %s undo info is %d bytes long; discard it? "
!                      (buffer-name) size))))
!       (progn (when (eq undo-discard-silently 'warn)
!                (message
!                 "Undo entry exceeded `undo-outer-limit' and was discarded"))
!              (setq buffer-undo-list nil)
               (setq undo-extra-outer-limit nil)
               t)
        nil)))
============================================================

===File ~/undo.c-diff=======================================
*** undo.c      22 Dec 2004 18:50:07 -0600      1.63
--- undo.c      24 Jan 2005 14:16:53 -0600      
***************
*** 628,634 ****
              doc: /* Outer limit on size of undo information for one command.
  At garbage collection time, if the current command has produced
  more than this much undo information, it asks you whether to delete
! the information.  This is a last-ditch limit to prevent memory overflow.
  
  The size is counted as the number of bytes occupied,
  which includes both saved text and other data.
--- 628,635 ----
              doc: /* Outer limit on size of undo information for one command.
  At garbage collection time, if the current command has produced
  more than this much undo information, it asks you whether to delete
! the information.  If `undo-discard-silently' is non-nil, it deletes the info
! without querying.  This is a last-ditch limit to prevent memory overflow.
  
  The size is counted as the number of bytes occupied,
  which includes both saved text and other data.
============================================================




reply via email to

[Prev in Thread] Current Thread [Next in Thread]