From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Markus Triska <triska@metalevel.at>
Cc: Phillip Lord <phillip.lord@russet.org.uk>, 23906@debbugs.gnu.org
Subject: bug#23906: 25.0.95; Undo boundary after process output is not consistent
Date: Mon, 18 Jul 2016 00:18:36 -0400 [thread overview]
Message-ID: <jwv60s34m4x.fsf-monnier+emacsbugs@gnu.org> (raw)
In-Reply-To: <87shvccl2h.fsf@metalevel.at> (Markus Triska's message of "Thu, 14 Jul 2016 17:10:14 +0200")
> Please let us use this opportunity to fix the more general case
> too. Stefan agreed that the following primitives would work:
> -) undo-begin-transaction
> Starts a new transaction.
> -) undo-end-transaction
> Ends the most recently started undo transaction.
> The effects of all commands between would be undone as a single unit.
How 'bout the patch below (see the viper part to get an idea about how
to use it in ediprolog)?
Stefan
diff --git a/lisp/simple.el b/lisp/simple.el
index f114235..e54d4f2 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3054,6 +3054,41 @@ undo-auto--undoable-change
(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
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 3d9d1cc..3ce1b4d 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -1709,40 +1709,20 @@ viper-undo-more
;; 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.
-(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)))))))
+(viper-deflocalvar viper--undo-change-group-handle nil)
+(put 'viper--undo-change-group-handle 'permanent-local t)
+(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 ()
- (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
diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el
index 086daf2..838d846 100644
--- a/lisp/emulation/viper-init.el
+++ b/lisp/emulation/viper-init.el
@@ -369,15 +369,6 @@ viper-set-input-method
;; 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
next prev parent reply other threads:[~2016-07-18 4:18 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-06 17:56 bug#23906: 25.0.95; Undo boundary after process output is not consistent Markus Triska
2016-07-06 18:38 ` Eli Zaretskii
2016-07-11 11:45 ` Phillip Lord
2016-07-11 13:54 ` Markus Triska
2016-07-12 16:29 ` Phillip Lord
2016-07-12 17:03 ` Stefan Monnier
2016-07-12 18:56 ` Markus Triska
2016-07-12 20:22 ` Stefan Monnier
2016-07-12 21:02 ` Markus Triska
2016-07-12 21:20 ` Stefan Monnier
2016-07-12 22:35 ` Markus Triska
2016-07-12 22:51 ` Stefan Monnier
2016-07-12 22:45 ` Markus Triska
2016-07-13 22:12 ` Phillip Lord
2016-07-14 8:34 ` Markus Triska
2016-07-14 13:33 ` Phillip Lord
2016-07-14 15:10 ` Markus Triska
2016-07-14 20:25 ` Phillip Lord
2016-07-14 22:12 ` Stefan Monnier
2016-07-18 4:18 ` Stefan Monnier [this message]
2016-07-18 19:03 ` Markus Triska
2016-07-19 0:41 ` Stefan Monnier
2016-07-19 1:05 ` Stefan Monnier
2016-07-24 15:45 ` Phillip Lord
2016-07-24 21:36 ` Stefan Monnier
2020-09-04 13:55 ` Lars Ingebrigtsen
2016-07-13 8:09 ` Phillip Lord
2016-07-13 14:29 ` Markus Triska
2016-07-13 22:23 ` Phillip Lord
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=jwv60s34m4x.fsf-monnier+emacsbugs@gnu.org \
--to=monnier@iro.umontreal.ca \
--cc=23906@debbugs.gnu.org \
--cc=phillip.lord@russet.org.uk \
--cc=triska@metalevel.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.