* 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.
This commit is contained in:
parent
73f0715df5
commit
99fe98d37a
4 changed files with 49 additions and 40 deletions
3
etc/NEWS
3
etc/NEWS
|
@ -458,6 +458,9 @@ function 'check-declare-errmsg' has been removed.
|
|||
|
||||
* 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
|
||||
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'.
|
||||
|
|
|
@ -1709,40 +1709,20 @@ invokes the command before that, etc."
|
|||
;; 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,
|
||||
;; they are undone all at once.
|
||||
(viper-deflocalvar viper--undo-change-group-handle nil)
|
||||
(put 'viper--undo-change-group-handle 'permanent-local t)
|
||||
|
||||
(defun viper-adjust-undo ()
|
||||
(if viper-undo-needs-adjustment
|
||||
(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)))))))
|
||||
|
||||
(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 ()
|
||||
(if (listp buffer-undo-list)
|
||||
(if (not viper-undo-needs-adjustment)
|
||||
(let ((inhibit-quit t))
|
||||
(setq buffer-undo-list
|
||||
(cons viper-buffer-undo-list-mark buffer-undo-list))
|
||||
(setq viper-undo-needs-adjustment t)))))
|
||||
(and (listp buffer-undo-list)
|
||||
(not viper--undo-change-group-handle)
|
||||
(setq viper--undo-change-group-handle
|
||||
(prepare-change-group))))
|
||||
|
||||
|
||||
;;; Viper's destructive Command ring utilities
|
||||
|
|
|
@ -369,15 +369,6 @@ Use `\\[viper-set-expert-level]' to change this.")
|
|||
|
||||
;; 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
|
||||
"Non-nil means not to move point while undoing commands.
|
||||
This style is different from Emacs and Vi. Try it to see if
|
||||
|
|
|
@ -2958,6 +2958,41 @@ behavior."
|
|||
(undo-auto--boundary-ensure-timer))
|
||||
;; 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
|
||||
"If non-nil ask about discarding undo info for the current command.
|
||||
Normally, Emacs discards the undo info for the current command if
|
||||
|
|
Loading…
Add table
Reference in a new issue