aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron S. Hawley2013-01-08 14:13:31 -0500
committerStefan Monnier2013-01-08 14:13:31 -0500
commit3bace969f386056cedeaba7ac3661167d6d60190 (patch)
treed4dddc07a157d2f2be055c1d0a879d23d292de68
parent1c851e98b60d08404e5138b67ccf5b9d72fb4e47 (diff)
downloademacs-3bace969f386056cedeaba7ac3661167d6d60190.tar.gz
emacs-3bace969f386056cedeaba7ac3661167d6d60190.zip
* lisp/simple.el (primitive-undo): Move from undo.c.
* src/undo.c (Fprimitive_undo): Move to simple.el. (syms_of_undo): Remove declaration for Sprimitive_undo. * test/automated/undo-tests.el: New file.
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/simple.el135
-rw-r--r--src/ChangeLog5
-rw-r--r--src/undo.c212
-rw-r--r--test/ChangeLog4
-rw-r--r--test/automated/undo-tests.el231
6 files changed, 379 insertions, 212 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 18481cb5aa5..72390d1ff67 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
12013-01-08 Aaron S. Hawley <aaron.s.hawley@gmail.com>
2
3 * simple.el (primitive-undo): Move from undo.c.
4
12013-01-08 Stefan Monnier <monnier@iro.umontreal.ca> 52013-01-08 Stefan Monnier <monnier@iro.umontreal.ca>
2 6
3 * vc/pcvs.el (cvs-cleanup-collection): Extend meaning of `rm-handled'. 7 * vc/pcvs.el (cvs-cleanup-collection): Extend meaning of `rm-handled'.
diff --git a/lisp/simple.el b/lisp/simple.el
index 19140cba496..86c71cd2130 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1979,6 +1979,141 @@ then call `undo-more' one or more times to undo them."
1979 (if (null pending-undo-list) 1979 (if (null pending-undo-list)
1980 (setq pending-undo-list t)))) 1980 (setq pending-undo-list t))))
1981 1981
1982(defun primitive-undo (n list)
1983 "Undo N records from the front of the list LIST.
1984Return what remains of the list."
1985
1986 ;; This is a good feature, but would make undo-start
1987 ;; unable to do what is expected.
1988 ;;(when (null (car (list)))
1989 ;; ;; If the head of the list is a boundary, it is the boundary
1990 ;; ;; preceding this command. Get rid of it and don't count it.
1991 ;; (setq list (cdr list))))
1992
1993 (let ((arg n)
1994 ;; In a writable buffer, enable undoing read-only text that is
1995 ;; so because of text properties.
1996 (inhibit-read-only t)
1997 ;; Don't let `intangible' properties interfere with undo.
1998 (inhibit-point-motion-hooks t)
1999 ;; We use oldlist only to check for EQ. ++kfs
2000 (oldlist buffer-undo-list)
2001 (did-apply nil)
2002 (next nil))
2003 (while (> arg 0)
2004 (while (and (consp list)
2005 (progn
2006 (setq next (car list))
2007 (setq list (cdr list))
2008 ;; Exit inner loop at undo boundary.
2009 (not (null next))))
2010 ;; Handle an integer by setting point to that value.
2011 (cond
2012 ((integerp next) (goto-char next))
2013 ((consp next)
2014 (let ((car (car next))
2015 (cdr (cdr next)))
2016 (cond
2017 ;; Element (t . TIME) records previous modtime.
2018 ;; Preserve any flag of NONEXISTENT_MODTIME_NSECS or
2019 ;; UNKNOWN_MODTIME_NSECS.
2020 ((eq t car)
2021 ;; If this records an obsolete save
2022 ;; (not matching the actual disk file)
2023 ;; then don't mark unmodified.
2024 (when (or (equal cdr (visited-file-modtime))
2025 (and (consp cdr)
2026 (equal (list (car cdr) (cdr cdr))
2027 (visited-file-modtime))))
2028 (when (fboundp 'unlock-buffer)
2029 (unlock-buffer))
2030 (set-buffer-modified-p nil)))
2031 ;; Element (nil PROP VAL BEG . END) is property change.
2032 ((eq nil car)
2033 (let ((beg (nth 2 cdr))
2034 (end (nthcdr 3 cdr))
2035 (prop (car cdr))
2036 (val (cadr cdr)))
2037 (when (or (> (point-min) beg)
2038 (< (point-max) end))
2039 (error "Changes to be undone are outside visible portion of buffer"))
2040 (put-text-property beg end prop val)))
2041 ((and (integerp car) (integerp cdr))
2042 ;; Element (BEG . END) means range was inserted.
2043 (when (or (< car (point-min))
2044 (> cdr (point-max)))
2045 (error "Changes to be undone are outside visible portion of buffer"))
2046 ;; Set point first thing, so that undoing this undo
2047 ;; does not send point back to where it is now.
2048 (goto-char car)
2049 (delete-region car cdr))
2050 ((eq car 'apply)
2051 ;; Element (apply FUN . ARGS) means call FUN to undo.
2052 (let ((currbuff (current-buffer))
2053 (car (car cdr))
2054 (cdr (cdr cdr)))
2055 (if (integerp car)
2056 ;; Long format: (apply DELTA START END FUN . ARGS).
2057 (let* ((delta car)
2058 (start (car cdr))
2059 (end (cadr cdr))
2060 (start-mark (copy-marker start nil))
2061 (end-mark (copy-marker end t))
2062 (cdr (cddr cdr))
2063 (fun (car cdr))
2064 (args (cdr cdr)))
2065 (apply fun args) ;; Use `save-current-buffer'?
2066 ;; Check that the function did what the entry
2067 ;; said it would do.
2068 (unless (and (eq start
2069 (marker-position start-mark))
2070 (eq (+ delta end)
2071 (marker-position end-mark)))
2072 (error "Changes to be undone by function different than announced"))
2073 (set-marker start-mark nil)
2074 (set-marker end-mark nil))
2075 (apply car cdr))
2076 (unless (eq currbuff (current-buffer))
2077 (error "Undo function switched buffer"))
2078 (setq did-apply t)))
2079 ((and (stringp car) (integerp cdr))
2080 ;; Element (STRING . POS) means STRING was deleted.
2081 (let ((membuf car)
2082 (pos cdr))
2083 (when (or (< (abs pos) (point-min))
2084 (> (abs pos) (point-max)))
2085 (error "Changes to be undone are outside visible portion of buffer"))
2086 (if (< pos 0)
2087 (progn
2088 (goto-char (- pos))
2089 (insert membuf))
2090 (goto-char pos)
2091 ;; Now that we record marker adjustments
2092 ;; (caused by deletion) for undo,
2093 ;; we should always insert after markers,
2094 ;; so that undoing the marker adjustments
2095 ;; put the markers back in the right place.
2096 (insert membuf)
2097 (goto-char pos))))
2098 ((and (markerp car) (integerp cdr))
2099 ;; (MARKER . INTEGER) means a marker MARKER
2100 ;; was adjusted by INTEGER.
2101 (when (marker-buffer car)
2102 (set-marker car
2103 (- (marker-position car) cdr)
2104 (marker-buffer car))))
2105 (t (error "Unrecognized entry in undo list %S" next)))))
2106 (t (error "Unrecognized entry in undo list %S" next))))
2107 (setq arg (1- arg)))
2108 ;; Make sure an apply entry produces at least one undo entry,
2109 ;; so the test in `undo' for continuing an undo series
2110 ;; will work right.
2111 (if (and did-apply
2112 (eq oldlist buffer-undo-list))
2113 (setq buffer-undo-list
2114 (cons (list 'apply 'cdr nil) buffer-undo-list))))
2115 list)
2116
1982;; Deep copy of a list 2117;; Deep copy of a list
1983(defun undo-copy-list (list) 2118(defun undo-copy-list (list)
1984 "Make a copy of undo list LIST." 2119 "Make a copy of undo list LIST."
diff --git a/src/ChangeLog b/src/ChangeLog
index f5dacabd130..9ab201c8be4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
12013-01-08 Aaron S. Hawley <aaron.s.hawley@gmail.com>
2
3 * undo.c (Fprimitive_undo): Move to simple.el.
4 (syms_of_undo): Remove declarations for Sprimitive_undo.
5
12013-01-08 Stefan Monnier <monnier@iro.umontreal.ca> 62013-01-08 Stefan Monnier <monnier@iro.umontreal.ca>
2 7
3 * keyboard.c (echo_add_key): Rename from echo_add_char. 8 * keyboard.c (echo_add_key): Rename from echo_add_char.
diff --git a/src/undo.c b/src/undo.c
index 2626fd4ccfe..63edc8e9b8d 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -452,217 +452,6 @@ user_error (const char *msg)
452} 452}
453 453
454 454
455DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
456 doc: /* Undo N records from the front of the list LIST.
457Return what remains of the list. */)
458 (Lisp_Object n, Lisp_Object list)
459{
460 struct gcpro gcpro1, gcpro2;
461 Lisp_Object next;
462 ptrdiff_t count = SPECPDL_INDEX ();
463 register EMACS_INT arg;
464 Lisp_Object oldlist;
465 int did_apply = 0;
466
467#if 0 /* This is a good feature, but would make undo-start
468 unable to do what is expected. */
469 Lisp_Object tem;
470
471 /* If the head of the list is a boundary, it is the boundary
472 preceding this command. Get rid of it and don't count it. */
473 tem = Fcar (list);
474 if (NILP (tem))
475 list = Fcdr (list);
476#endif
477
478 CHECK_NUMBER (n);
479 arg = XINT (n);
480 next = Qnil;
481 GCPRO2 (next, list);
482 /* I don't think we need to gcpro oldlist, as we use it only
483 to check for EQ. ++kfs */
484
485 /* In a writable buffer, enable undoing read-only text that is so
486 because of text properties. */
487 if (NILP (BVAR (current_buffer, read_only)))
488 specbind (Qinhibit_read_only, Qt);
489
490 /* Don't let `intangible' properties interfere with undo. */
491 specbind (Qinhibit_point_motion_hooks, Qt);
492
493 oldlist = BVAR (current_buffer, undo_list);
494
495 while (arg > 0)
496 {
497 while (CONSP (list))
498 {
499 next = XCAR (list);
500 list = XCDR (list);
501 /* Exit inner loop at undo boundary. */
502 if (NILP (next))
503 break;
504 /* Handle an integer by setting point to that value. */
505 if (INTEGERP (next))
506 SET_PT (clip_to_bounds (BEGV, XINT (next), ZV));
507 else if (CONSP (next))
508 {
509 Lisp_Object car, cdr;
510
511 car = XCAR (next);
512 cdr = XCDR (next);
513 if (EQ (car, Qt))
514 {
515 /* Element (t . TIME) records previous modtime.
516 Preserve any flag of NONEXISTENT_MODTIME_NSECS or
517 UNKNOWN_MODTIME_NSECS. */
518 struct buffer *base_buffer = current_buffer;
519 EMACS_TIME mod_time;
520
521 if (CONSP (cdr)
522 && CONSP (XCDR (cdr))
523 && CONSP (XCDR (XCDR (cdr)))
524 && CONSP (XCDR (XCDR (XCDR (cdr))))
525 && INTEGERP (XCAR (XCDR (XCDR (XCDR (cdr)))))
526 && XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) < 0)
527 mod_time =
528 (make_emacs_time
529 (0, XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000));
530 else
531 mod_time = lisp_time_argument (cdr);
532
533 if (current_buffer->base_buffer)
534 base_buffer = current_buffer->base_buffer;
535
536 /* If this records an obsolete save
537 (not matching the actual disk file)
538 then don't mark unmodified. */
539 if (EMACS_TIME_NE (mod_time, base_buffer->modtime))
540 continue;
541#ifdef CLASH_DETECTION
542 Funlock_buffer ();
543#endif /* CLASH_DETECTION */
544 Fset_buffer_modified_p (Qnil);
545 }
546 else if (EQ (car, Qnil))
547 {
548 /* Element (nil PROP VAL BEG . END) is property change. */
549 Lisp_Object beg, end, prop, val;
550
551 prop = Fcar (cdr);
552 cdr = Fcdr (cdr);
553 val = Fcar (cdr);
554 cdr = Fcdr (cdr);
555 beg = Fcar (cdr);
556 end = Fcdr (cdr);
557
558 if (XINT (beg) < BEGV || XINT (end) > ZV)
559 user_error ("Changes to be undone are outside visible portion of buffer");
560 Fput_text_property (beg, end, prop, val, Qnil);
561 }
562 else if (INTEGERP (car) && INTEGERP (cdr))
563 {
564 /* Element (BEG . END) means range was inserted. */
565
566 if (XINT (car) < BEGV
567 || XINT (cdr) > ZV)
568 user_error ("Changes to be undone are outside visible portion of buffer");
569 /* Set point first thing, so that undoing this undo
570 does not send point back to where it is now. */
571 Fgoto_char (car);
572 Fdelete_region (car, cdr);
573 }
574 else if (EQ (car, Qapply))
575 {
576 /* Element (apply FUN . ARGS) means call FUN to undo. */
577 struct buffer *save_buffer = current_buffer;
578
579 car = Fcar (cdr);
580 cdr = Fcdr (cdr);
581 if (INTEGERP (car))
582 {
583 /* Long format: (apply DELTA START END FUN . ARGS). */
584 Lisp_Object delta = car;
585 Lisp_Object start = Fcar (cdr);
586 Lisp_Object end = Fcar (Fcdr (cdr));
587 Lisp_Object start_mark = Fcopy_marker (start, Qnil);
588 Lisp_Object end_mark = Fcopy_marker (end, Qt);
589
590 cdr = Fcdr (Fcdr (cdr));
591 apply1 (Fcar (cdr), Fcdr (cdr));
592
593 /* Check that the function did what the entry said it
594 would do. */
595 if (!EQ (start, Fmarker_position (start_mark))
596 || (XINT (delta) + XINT (end)
597 != marker_position (end_mark)))
598 error ("Changes to be undone by function different than announced");
599 Fset_marker (start_mark, Qnil, Qnil);
600 Fset_marker (end_mark, Qnil, Qnil);
601 }
602 else
603 apply1 (car, cdr);
604
605 if (save_buffer != current_buffer)
606 error ("Undo function switched buffer");
607 did_apply = 1;
608 }
609 else if (STRINGP (car) && INTEGERP (cdr))
610 {
611 /* Element (STRING . POS) means STRING was deleted. */
612 Lisp_Object membuf;
613 EMACS_INT pos = XINT (cdr);
614
615 membuf = car;
616 if (pos < 0)
617 {
618 if (-pos < BEGV || -pos > ZV)
619 user_error ("Changes to be undone are outside visible portion of buffer");
620 SET_PT (-pos);
621 Finsert (1, &membuf);
622 }
623 else
624 {
625 if (pos < BEGV || pos > ZV)
626 user_error ("Changes to be undone are outside visible portion of buffer");
627 SET_PT (pos);
628
629 /* Now that we record marker adjustments
630 (caused by deletion) for undo,
631 we should always insert after markers,
632 so that undoing the marker adjustments
633 put the markers back in the right place. */
634 Finsert (1, &membuf);
635 SET_PT (pos);
636 }
637 }
638 else if (MARKERP (car) && INTEGERP (cdr))
639 {
640 /* (MARKER . INTEGER) means a marker MARKER
641 was adjusted by INTEGER. */
642 if (XMARKER (car)->buffer)
643 Fset_marker (car,
644 make_number (marker_position (car) - XINT (cdr)),
645 Fmarker_buffer (car));
646 }
647 }
648 }
649 arg--;
650 }
651
652
653 /* Make sure an apply entry produces at least one undo entry,
654 so the test in `undo' for continuing an undo series
655 will work right. */
656 if (did_apply
657 && EQ (oldlist, BVAR (current_buffer, undo_list)))
658 bset_undo_list
659 (current_buffer,
660 Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list)));
661
662 UNGCPRO;
663 return unbind_to (count, list);
664}
665
666void 455void
667syms_of_undo (void) 456syms_of_undo (void)
668{ 457{
@@ -675,7 +464,6 @@ syms_of_undo (void)
675 last_undo_buffer = NULL; 464 last_undo_buffer = NULL;
676 last_boundary_buffer = NULL; 465 last_boundary_buffer = NULL;
677 466
678 defsubr (&Sprimitive_undo);
679 defsubr (&Sundo_boundary); 467 defsubr (&Sundo_boundary);
680 468
681 DEFVAR_INT ("undo-limit", undo_limit, 469 DEFVAR_INT ("undo-limit", undo_limit,
diff --git a/test/ChangeLog b/test/ChangeLog
index 43c783857f3..b7b628cce69 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,7 @@
12013-01-08 Aaron S. Hawley <aaron.s.hawley@gmail.com>
2
3 * automated/undo-tests.el: New file.
4
12012-12-27 Dmitry Gutov <dgutov@yandex.ru> 52012-12-27 Dmitry Gutov <dgutov@yandex.ru>
2 6
3 * automated/ruby-mode-tests.el 7 * automated/ruby-mode-tests.el
diff --git a/test/automated/undo-tests.el b/test/automated/undo-tests.el
new file mode 100644
index 00000000000..3e71d974e5b
--- /dev/null
+++ b/test/automated/undo-tests.el
@@ -0,0 +1,231 @@
1;;; undo-tests.el --- Tests of primitive-undo
2
3;; Copyright (C) 2012 Aaron S. Hawley
4
5;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
6
7;; This program is free software: you can redistribute it and/or
8;; modify it under the terms of the GNU General Public License as
9;; published by the Free Software Foundation, either version 3 of the
10;; License, or (at your option) any later version.
11;;
12;; This program is distributed in the hope that it will be useful, but
13;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;; General Public License for more details.
16;;
17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see `http://www.gnu.org/licenses/'.
19
20;;; Commentary:
21
22;; Profiling when the code was translate from C to Lisp on 2012-12-24.
23
24;;; C
25
26;; (elp-instrument-function 'primitive-undo)
27;; (load-file "undo-test.elc")
28;; (benchmark 100 '(let ((undo-test5-error nil)) (undo-test-all)))
29;; Elapsed time: 305.218000s (104.841000s in 14804 GCs)
30;; M-x elp-results
31;; Function Name Call Count Elapsed Time Average Time
32;; primitive-undo 2600 3.4889999999 0.0013419230
33
34;;; Lisp
35
36;; (load-file "primundo.elc")
37;; (elp-instrument-function 'primitive-undo)
38;; (benchmark 100 '(undo-test-all))
39;; Elapsed time: 295.974000s (104.582000s in 14704 GCs)
40;; M-x elp-results
41;; Function Name Call Count Elapsed Time Average Time
42;; primitive-undo 2700 3.6869999999 0.0013655555
43
44;;; Code:
45
46(require 'ert)
47
48(ert-deftest undo-test0 ()
49 "Test basics of \\[undo]."
50 (with-temp-buffer
51 (buffer-enable-undo)
52 (condition-case err
53 (undo)
54 (error
55 (unless (string= "No further undo information"
56 (cadr err))
57 (error err))))
58 (undo-boundary)
59 (insert "This")
60 (undo-boundary)
61 (erase-buffer)
62 (undo-boundary)
63 (insert "That")
64 (undo-boundary)
65 (forward-word -1)
66 (undo-boundary)
67 (insert "With ")
68 (undo-boundary)
69 (forward-word -1)
70 (undo-boundary)
71 (kill-word 1)
72 (undo-boundary)
73 (put-text-property (point-min) (point-max) 'face 'bold)
74 (undo-boundary)
75 (remove-text-properties (point-min) (point-max) '(face default))
76 (undo-boundary)
77 (set-buffer-multibyte (not enable-multibyte-characters))
78 (undo-boundary)
79 (undo)
80 (should
81 (equal (should-error (undo-more nil))
82 '(wrong-type-argument integerp nil)))
83 (undo-more 7)
84 (should (string-equal "" (buffer-string)))))
85
86(ert-deftest undo-test1 ()
87 "Test undo of \\[undo] command (redo)."
88 (with-temp-buffer
89 (buffer-enable-undo)
90 (undo-boundary)
91 (insert "This")
92 (undo-boundary)
93 (erase-buffer)
94 (undo-boundary)
95 (insert "That")
96 (undo-boundary)
97 (forward-word -1)
98 (undo-boundary)
99 (insert "With ")
100 (undo-boundary)
101 (forward-word -1)
102 (undo-boundary)
103 (kill-word 1)
104 (undo-boundary)
105 (facemenu-add-face 'bold (point-min) (point-max))
106 (undo-boundary)
107 (set-buffer-multibyte (not enable-multibyte-characters))
108 (undo-boundary)
109 (should
110 (string-equal (buffer-string)
111 (progn
112 (undo)
113 (undo-more 4)
114 (undo)
115 ;(undo-more -4)
116 (buffer-string))))))
117
118(ert-deftest undo-test2 ()
119 "Test basic redoing with \\[undo] command."
120 (with-temp-buffer
121 (buffer-enable-undo)
122 (undo-boundary)
123 (insert "One")
124 (undo-boundary)
125 (insert " Zero")
126 (undo-boundary)
127 (push-mark)
128 (delete-region (save-excursion
129 (forward-word -1)
130 (point)) (point))
131 (undo-boundary)
132 (beginning-of-line)
133 (insert "Zero")
134 (undo-boundary)
135 (undo)
136 (should
137 (string-equal (buffer-string)
138 (progn
139 (undo-more 2)
140 (undo)
141 (buffer-string))))))
142
143(ert-deftest undo-test3 ()
144 "Test modtime with \\[undo] command."
145 (let ((tmpfile (make-temp-file "undo-test3")))
146 (with-temp-file tmpfile
147 (let ((buffer-file-name tmpfile))
148 (buffer-enable-undo)
149 (set (make-local-variable 'make-backup-files) nil)
150 (undo-boundary)
151 (insert ?\s)
152 (undo-boundary)
153 (basic-save-buffer)
154 (insert ?\t)
155 (undo)
156 (should
157 (string-equal (buffer-string)
158 (progn
159 (undo)
160 (buffer-string)))))
161 (delete-file tmpfile))))
162
163(ert-deftest undo-test4 ()
164 "Test \\[undo] of \\[flush-lines]."
165 (with-temp-buffer
166 (buffer-enable-undo)
167 (dotimes (i 1048576)
168 (if (zerop (% i 2))
169 (insert "Evenses")
170 (insert "Oddses")))
171 (undo-boundary)
172 (should
173 ;; Avoid string-equal because ERT will save the `buffer-string'
174 ;; to the explanation. Using `not' will record nil or non-nil.
175 (not
176 (null
177 (string-equal (buffer-string)
178 (progn
179 (flush-lines "oddses" (point-min) (point-max))
180 (undo-boundary)
181 (undo)
182 (undo)
183 (buffer-string))))))))
184
185(ert-deftest undo-test5 ()
186 "Test basic redoing with \\[undo] command."
187 (with-temp-buffer
188 (buffer-enable-undo)
189 (undo-boundary)
190 (insert "AYE")
191 (undo-boundary)
192 (insert " BEE")
193 (undo-boundary)
194 (setq buffer-undo-list (cons '(0.0 bogus) buffer-undo-list))
195 (push-mark)
196 (delete-region (save-excursion
197 (forward-word -1)
198 (point)) (point))
199 (undo-boundary)
200 (beginning-of-line)
201 (insert "CEE")
202 (undo-boundary)
203 (undo)
204 (setq buffer-undo-list (cons "bogus" buffer-undo-list))
205 (should
206 (string-equal
207 (buffer-string)
208 (progn
209 (if (and (boundp 'undo-test5-error) (not undo-test5-error))
210 (progn
211 (should (null (undo-more 2)))
212 (should (undo)))
213 ;; Errors are generated by new Lisp version of
214 ;; `primitive-undo' not by built-in C version.
215 (should
216 (equal (should-error (undo-more 2))
217 '(error "Unrecognized entry in undo list (0.0 bogus)")))
218 (should
219 (equal (should-error (undo))
220 '(error "Unrecognized entry in undo list \"bogus\""))))
221 (buffer-string))))))
222
223(defun undo-test-all (&optional interactive)
224 "Run all tests for \\[undo]."
225 (interactive "p")
226 (if interactive
227 (ert-run-tests-interactively "^undo-")
228 (ert-run-tests-batch "^undo-")))
229
230(provide 'undo-tests)
231;;; undo-tests.el ends here