diff options
| author | Aaron S. Hawley | 2013-01-08 14:13:31 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2013-01-08 14:13:31 -0500 |
| commit | 3bace969f386056cedeaba7ac3661167d6d60190 (patch) | |
| tree | d4dddc07a157d2f2be055c1d0a879d23d292de68 /lisp | |
| parent | 1c851e98b60d08404e5138b67ccf5b9d72fb4e47 (diff) | |
| download | emacs-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.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 4 | ||||
| -rw-r--r-- | lisp/simple.el | 135 |
2 files changed, 139 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 18481cb5aa5..72390d1ff67 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | 2013-01-08 Aaron S. Hawley <aaron.s.hawley@gmail.com> | ||
| 2 | |||
| 3 | * simple.el (primitive-undo): Move from undo.c. | ||
| 4 | |||
| 1 | 2013-01-08 Stefan Monnier <monnier@iro.umontreal.ca> | 5 | 2013-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. | ||
| 1984 | Return 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." |