Commit 99fe98d3 authored by Stefan Monnier's avatar Stefan Monnier
Browse files

* lisp/simple.el (undo-amalgamate-change-group): New function

* lisp/emulation/viper-cmd.el (viper-adjust-undo): Use it.
(viper-set-complex-command-for-undo): Save current state with
prepare-change-group.
* lisp/emulation/viper-init.el (viper-undo-needs-adjustment)
(viper-buffer-undo-list-mark): Remove.
parent 73f0715d
...@@ -458,6 +458,9 @@ function 'check-declare-errmsg' has been removed. ...@@ -458,6 +458,9 @@ function 'check-declare-errmsg' has been removed.
* Lisp Changes in Emacs 25.2 * Lisp Changes in Emacs 25.2
** New function undo-amalgamate-change-group to get rid of undo-boundaries
between two states.
** New var `definition-prefixes' is a hashtable mapping prefixes to the ** New var `definition-prefixes' is a hashtable mapping prefixes to the
files where corresponding definitions can be found. This can be used files where corresponding definitions can be found. This can be used
to fetch definitions that are not yet loaded, for example for `C-h f'. to fetch definitions that are not yet loaded, for example for `C-h f'.
......
...@@ -1709,40 +1709,20 @@ invokes the command before that, etc." ...@@ -1709,40 +1709,20 @@ invokes the command before that, etc."
;; The following two functions are used to set up undo properly. ;; The following two functions are used to set up undo properly.
;; In VI, unlike Emacs, if you open a line, say, and add a bunch of lines, ;; In VI, unlike Emacs, if you open a line, say, and add a bunch of lines,
;; they are undone all at once. ;; they are undone all at once.
(defun viper-adjust-undo () (viper-deflocalvar viper--undo-change-group-handle nil)
(if viper-undo-needs-adjustment (put 'viper--undo-change-group-handle 'permanent-local t)
(let ((inhibit-quit t)
tmp tmp2)
(setq viper-undo-needs-adjustment nil)
(when (listp buffer-undo-list)
(let ((had-boundary (null (car buffer-undo-list))))
(if (setq tmp (memq viper-buffer-undo-list-mark buffer-undo-list))
(progn
(setq tmp2 (cdr tmp)) ; the part after mark
;; cut tail from buffer-undo-list temporarily by direct
;; manipulation with pointers in buffer-undo-list
(setcdr tmp nil)
(setq buffer-undo-list (delq nil buffer-undo-list))
(setq buffer-undo-list
(delq viper-buffer-undo-list-mark buffer-undo-list))
;; restore tail of buffer-undo-list
(setq buffer-undo-list (nconc buffer-undo-list tmp2)))
(setq buffer-undo-list (delq nil buffer-undo-list)))
;; The top-level loop only adds boundaries if there has been
;; modifications in the buffer, so make sure we don't accidentally
;; drop the "final" boundary (bug#22295).
(if had-boundary (undo-boundary)))))))
(defun viper-adjust-undo ()
(when viper--undo-change-group-handle
(undo-amalgamate-change-group
(prog1 viper--undo-change-group-handle
(setq viper--undo-change-group-handle nil)))))
(defun viper-set-complex-command-for-undo () (defun viper-set-complex-command-for-undo ()
(if (listp buffer-undo-list) (and (listp buffer-undo-list)
(if (not viper-undo-needs-adjustment) (not viper--undo-change-group-handle)
(let ((inhibit-quit t)) (setq viper--undo-change-group-handle
(setq buffer-undo-list (prepare-change-group))))
(cons viper-buffer-undo-list-mark buffer-undo-list))
(setq viper-undo-needs-adjustment t)))))
;;; Viper's destructive Command ring utilities ;;; Viper's destructive Command ring utilities
......
...@@ -369,15 +369,6 @@ Use `\\[viper-set-expert-level]' to change this.") ...@@ -369,15 +369,6 @@ Use `\\[viper-set-expert-level]' to change this.")
;; VI-style Undo ;; VI-style Undo
;; Used to 'undo' complex commands, such as replace and insert commands.
(viper-deflocalvar viper-undo-needs-adjustment nil)
(put 'viper-undo-needs-adjustment 'permanent-local t)
;; A mark that Viper puts on buffer-undo-list. Marks the beginning of a
;; complex command that must be undone atomically. If inserted, it is
;; erased by viper-change-state-to-vi and viper-repeat.
(defconst viper-buffer-undo-list-mark 'viper)
(defcustom viper-keep-point-on-undo nil (defcustom viper-keep-point-on-undo nil
"Non-nil means not to move point while undoing commands. "Non-nil means not to move point while undoing commands.
This style is different from Emacs and Vi. Try it to see if This style is different from Emacs and Vi. Try it to see if
......
...@@ -2958,6 +2958,41 @@ behavior." ...@@ -2958,6 +2958,41 @@ behavior."
(undo-auto--boundary-ensure-timer)) (undo-auto--boundary-ensure-timer))
;; End auto-boundary section ;; End auto-boundary section
(defun undo-amalgamate-change-group (handle)
"Amalgamate changes in change-group since HANDLE.
Remove all undo boundaries between the state of HANDLE and now.
HANDLE is as returned by `prepare-change-group'."
(dolist (elt handle)
(with-current-buffer (car elt)
(setq elt (cdr elt))
(when (consp buffer-undo-list)
(let ((old-car (car-safe elt))
(old-cdr (cdr-safe elt)))
(unwind-protect
(progn
;; Temporarily truncate the undo log at ELT.
(when (consp elt)
(setcar elt t) (setcdr elt nil))
(when
(or (null elt) ;The undo-log was empty.
;; `elt' is still in the log: normal case.
(eq elt (last buffer-undo-list))
;; `elt' is not in the log any more, but that's because
;; the log is "all new", so we should remove all
;; boundaries from it.
(not (eq (last buffer-undo-list) (last old-cdr))))
(cl-callf (lambda (x) (delq nil x))
(if (car buffer-undo-list)
buffer-undo-list
;; Preserve the undo-boundaries at either ends of the
;; change-groups.
(cdr buffer-undo-list)))))
;; Reset the modified cons cell ELT to its original content.
(when (consp elt)
(setcar elt old-car)
(setcdr elt old-cdr))))))))
(defcustom undo-ask-before-discard nil (defcustom undo-ask-before-discard nil
"If non-nil ask about discarding undo info for the current command. "If non-nil ask about discarding undo info for the current command.
Normally, Emacs discards the undo info for the current command if Normally, Emacs discards the undo info for the current command if
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment