aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorPhillip Lord2015-08-06 21:33:58 +0100
committerPhillip Lord2015-11-12 21:06:05 +0000
commit44dfa86b7d382b84564d68472da1448d08f48129 (patch)
tree778e2228ec90a4401b2be6cd7b258ee44a212b26 /lisp
parent0aec2aaccd8b745fa7214f3edd453c04a04bfba4 (diff)
downloademacs-44dfa86b7d382b84564d68472da1448d08f48129.tar.gz
emacs-44dfa86b7d382b84564d68472da1448d08f48129.zip
The heuristic that Emacs uses to add an `undo-boundary' has been
reworked, as it interacts poorly with functions on `post-command-hook' or `after-change-functions'. * lisp/simple.el: New section added. * src/cmds.c (remove_excessive_undo_boundaries): Now in lisp. (self_insert_command): Calls simple.el to amalgamate. (delete_char): Calls simple.el to amalgamate. * src/keyboard.c (last_undo_boundary): Removed. * src/undo.c (run_undoable_change): New function.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/simple.el137
1 files changed, 137 insertions, 0 deletions
diff --git a/lisp/simple.el b/lisp/simple.el
index 00c25db07d7..821c7665c6c 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2754,6 +2754,143 @@ with < or <= based on USE-<."
2754 '(0 . 0))) 2754 '(0 . 0)))
2755 '(0 . 0))) 2755 '(0 . 0)))
2756 2756
2757;;; Default undo-boundary addition
2758;;
2759;; This section adds a new undo-boundary at either after a command is
2760;; called or in some cases on a timer called after a change is made in
2761;; any buffer.
2762(defvar-local undo-auto--last-boundary-cause nil
2763 "Describe the cause of the last undo-boundary.
2764
2765If `explicit', the last boundary was caused by an explicit call to
2766`undo-boundary', that is one not called by the code in this
2767section.
2768
2769If it is equal to `timer', then the last boundary was inserted
2770by `undo-auto--boundary-timer'.
2771
2772If it is equal to `command', then the last boundary was inserted
2773automatically after a command, that is by the code defined in
2774this section.
2775
2776If it is equal to a list, then the last boundary was inserted by
2777an amalgamating command. The car of the list is the number of
2778times an amalgamating command has been called, and the cdr are the
2779buffers that were changed during the last command.")
2780
2781(defvar undo-auto--current-boundary-timer nil
2782 "Current timer which will run `undo-auto--boundary-timer' or nil.
2783
2784If set to non-nil, this will effectively disable the timer.")
2785
2786(defvar undo-auto--this-command-amalgamating nil
2787 "Non-nil if `this-command' should be amalgamated.
2788This variable is set to nil by `undo-auto--boundaries' and is set
2789by `undo-auto--amalgamate'." )
2790
2791(defun undo-auto--needs-boundary-p ()
2792 "Return non-nil if `buffer-undo-list' needs a boundary at the start."
2793 (car-safe buffer-undo-list))
2794
2795(defun undo-auto--last-boundary-amalgamating-number ()
2796 "Return the number of amalgamating last commands or nil.
2797Amalgamating commands are, by default, either
2798`self-insert-command' and `delete-char', but can be any command
2799that calls `undo-auto--amalgamate'."
2800 (car-safe undo-auto--last-boundary-cause))
2801
2802(defun undo-auto--ensure-boundary (cause)
2803 "Add an `undo-boundary' to the current buffer if needed.
2804REASON describes the reason that the boundary is being added; see
2805`undo-auto--last-boundary' for more information."
2806 (when (and
2807 (undo-auto--needs-boundary-p))
2808 (let ((last-amalgamating
2809 (undo-auto--last-boundary-amalgamating-number)))
2810 (undo-boundary)
2811 (setq undo-auto--last-boundary-cause
2812 (if (eq 'amalgamate cause)
2813 (cons
2814 (if last-amalgamating (1+ last-amalgamating) 0)
2815 undo-auto--undoably-changed-buffers)
2816 cause)))))
2817
2818(defun undo-auto--boundaries (cause)
2819 "Check recently changed buffers and add a boundary if necessary.
2820REASON describes the reason that the boundary is being added; see
2821`undo-last-boundary' for more information."
2822 (dolist (b undo-auto--undoably-changed-buffers)
2823 (when (buffer-live-p b)
2824 (with-current-buffer b
2825 (undo-auto--ensure-boundary cause))))
2826 (setq undo-auto--undoably-changed-buffers nil))
2827
2828(defun undo-auto--boundary-timer ()
2829 "Timer which will run `undo--auto-boundary-timer'."
2830 (setq undo-auto--current-boundary-timer nil)
2831 (undo-auto--boundaries 'timer))
2832
2833(defun undo-auto--boundary-ensure-timer ()
2834 "Ensure that the `undo-auto-boundary-timer' is set."
2835 (unless undo-auto--current-boundary-timer
2836 (setq undo-auto--current-boundary-timer
2837 (run-at-time 10 nil #'undo-auto--boundary-timer))))
2838
2839(defvar undo-auto--undoably-changed-buffers nil
2840 "List of buffers that have changed recently.
2841
2842This list is maintained by `undo-auto--undoable-change' and
2843`undo-auto--boundaries' and can be affected by changes to their
2844default values.
2845
2846See also `undo-auto--buffer-undoably-changed'.")
2847
2848(defun undo-auto--add-boundary ()
2849 "Add an `undo-boundary' in appropriate buffers."
2850 (undo-auto--boundaries
2851 (if undo-auto--this-command-amalgamating
2852 'amalgamate
2853 'command))
2854 (setq undo-auto--this-command-amalgamating nil))
2855
2856(defun undo-auto--amalgamate ()
2857 "Amalgamate undo if necessary.
2858This function can be called after an amalgamating command. It
2859removes the previous `undo-boundary' if a series of such calls
2860have been made. By default `self-insert-command' and
2861`delete-char' are the only amalgamating commands, although this
2862function could be called by any command wishing to have this
2863behaviour."
2864 (let ((last-amalgamating-count
2865 (undo-auto--last-boundary-amalgamating-number)))
2866 (setq undo-auto--this-command-amalgamating t)
2867 (when
2868 last-amalgamating-count
2869 (if
2870 (and
2871 (< last-amalgamating-count 20)
2872 (eq this-command last-command))
2873 ;; Amalgamate all buffers that have changed.
2874 (dolist (b (cdr undo-auto--last-boundary-cause))
2875 (when (buffer-live-p b)
2876 (with-current-buffer
2877 b
2878 (when
2879 ;; The head of `buffer-undo-list' is nil.
2880 ;; `car-safe' doesn't work because
2881 ;; `buffer-undo-list' need not be a list!
2882 (and (listp buffer-undo-list)
2883 (not (car buffer-undo-list)))
2884 (setq buffer-undo-list
2885 (cdr buffer-undo-list))))))
2886 (setq undo-auto--last-boundary-cause 0)))))
2887
2888(defun undo-auto--undoable-change ()
2889 "Called after every undoable buffer change."
2890 (add-to-list 'undo-auto--undoably-changed-buffers (current-buffer))
2891 (undo-auto--boundary-ensure-timer))
2892;; End auto-boundary section
2893
2757(defcustom undo-ask-before-discard nil 2894(defcustom undo-ask-before-discard nil
2758 "If non-nil ask about discarding undo info for the current command. 2895 "If non-nil ask about discarding undo info for the current command.
2759Normally, Emacs discards the undo info for the current command if 2896Normally, Emacs discards the undo info for the current command if