diff options
| author | Phillip Lord | 2015-08-06 21:33:58 +0100 |
|---|---|---|
| committer | Phillip Lord | 2015-11-12 21:06:05 +0000 |
| commit | 44dfa86b7d382b84564d68472da1448d08f48129 (patch) | |
| tree | 778e2228ec90a4401b2be6cd7b258ee44a212b26 /lisp | |
| parent | 0aec2aaccd8b745fa7214f3edd453c04a04bfba4 (diff) | |
| download | emacs-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.el | 137 |
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 | |||
| 2765 | If `explicit', the last boundary was caused by an explicit call to | ||
| 2766 | `undo-boundary', that is one not called by the code in this | ||
| 2767 | section. | ||
| 2768 | |||
| 2769 | If it is equal to `timer', then the last boundary was inserted | ||
| 2770 | by `undo-auto--boundary-timer'. | ||
| 2771 | |||
| 2772 | If it is equal to `command', then the last boundary was inserted | ||
| 2773 | automatically after a command, that is by the code defined in | ||
| 2774 | this section. | ||
| 2775 | |||
| 2776 | If it is equal to a list, then the last boundary was inserted by | ||
| 2777 | an amalgamating command. The car of the list is the number of | ||
| 2778 | times an amalgamating command has been called, and the cdr are the | ||
| 2779 | buffers 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 | |||
| 2784 | If 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. | ||
| 2788 | This variable is set to nil by `undo-auto--boundaries' and is set | ||
| 2789 | by `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. | ||
| 2797 | Amalgamating commands are, by default, either | ||
| 2798 | `self-insert-command' and `delete-char', but can be any command | ||
| 2799 | that 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. | ||
| 2804 | REASON 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. | ||
| 2820 | REASON 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 | |||
| 2842 | This list is maintained by `undo-auto--undoable-change' and | ||
| 2843 | `undo-auto--boundaries' and can be affected by changes to their | ||
| 2844 | default values. | ||
| 2845 | |||
| 2846 | See 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. | ||
| 2858 | This function can be called after an amalgamating command. It | ||
| 2859 | removes the previous `undo-boundary' if a series of such calls | ||
| 2860 | have been made. By default `self-insert-command' and | ||
| 2861 | `delete-char' are the only amalgamating commands, although this | ||
| 2862 | function could be called by any command wishing to have this | ||
| 2863 | behaviour." | ||
| 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. |
| 2759 | Normally, Emacs discards the undo info for the current command if | 2896 | Normally, Emacs discards the undo info for the current command if |