From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.bugs Subject: bug#23906: 25.0.95; Undo boundary after process output is not consistent Date: Mon, 18 Jul 2016 00:18:36 -0400 Message-ID: References: <83r3b6lih2.fsf@gnu.org> <87h9bw5rfd.fsf@russet.org.uk> <87eg70i8k5.fsf@metalevel.at> <87d1mikef5.fsf@russet.org.uk> <874m7usn1m.fsf@metalevel.at> <8760sao9im.fsf@metalevel.at> <87mvllyypo.fsf@russet.org.uk> <87zipkzkge.fsf@metalevel.at> <87shvcfiox.fsf@russet.org.uk> <87shvccl2h.fsf@metalevel.at> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1468815449 22734 80.91.229.3 (18 Jul 2016 04:17:29 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 18 Jul 2016 04:17:29 +0000 (UTC) Cc: Phillip Lord , 23906@debbugs.gnu.org To: Markus Triska Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Jul 18 06:17:18 2016 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bOzzZ-0007wc-GM for geb-bug-gnu-emacs@m.gmane.org; Mon, 18 Jul 2016 06:17:17 +0200 Original-Received: from localhost ([::1]:44174 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bOzzV-0000qP-1X for geb-bug-gnu-emacs@m.gmane.org; Mon, 18 Jul 2016 00:17:13 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:45304) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bOzzO-0000q8-IA for bug-gnu-emacs@gnu.org; Mon, 18 Jul 2016 00:17:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bOzzK-0001o3-26 for bug-gnu-emacs@gnu.org; Mon, 18 Jul 2016 00:17:05 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:42656) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bOzzJ-0001nx-Vb for bug-gnu-emacs@gnu.org; Mon, 18 Jul 2016 00:17:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1bOzzJ-0008Mx-OJ for bug-gnu-emacs@gnu.org; Mon, 18 Jul 2016 00:17:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 18 Jul 2016 04:17:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 23906 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 23906-submit@debbugs.gnu.org id=B23906.146881539332131 (code B ref 23906); Mon, 18 Jul 2016 04:17:01 +0000 Original-Received: (at 23906) by debbugs.gnu.org; 18 Jul 2016 04:16:33 +0000 Original-Received: from localhost ([127.0.0.1]:54993 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bOzyr-0008MB-DP for submit@debbugs.gnu.org; Mon, 18 Jul 2016 00:16:33 -0400 Original-Received: from ironport2-out.teksavvy.com ([206.248.154.181]:14442) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bOzyo-0008Lx-Vi for 23906@debbugs.gnu.org; Mon, 18 Jul 2016 00:16:32 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0BCFgA731xV/3mcpUVcgxCEAoVVwD6CTQQCAoE8PRABAQEBAQEBgQpBBYNdAQEDAVYjBQsLNBIUGA0kiDcIzyMBAQEBAQEEAQEBAR6LOoUFB4QtBZ8Xg2uQPYFFI4Fmgi4igTQkgSABAQE X-IPAS-Result: A0BCFgA731xV/3mcpUVcgxCEAoVVwD6CTQQCAoE8PRABAQEBAQEBgQpBBYNdAQEDAVYjBQsLNBIUGA0kiDcIzyMBAQEBAQEEAQEBAR6LOoUFB4QtBZ8Xg2uQPYFFI4Fmgi4igTQkgSABAQE X-IronPort-AV: E=Sophos;i="5.13,465,1427774400"; d="scan'208";a="248312453" Original-Received: from 69-165-156-121.dsl.teksavvy.com (HELO ceviche.home) ([69.165.156.121]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 18 Jul 2016 00:16:23 -0400 Original-Received: by ceviche.home (Postfix, from userid 20848) id EB9E5661DE; Mon, 18 Jul 2016 00:18:36 -0400 (EDT) In-Reply-To: <87shvccl2h.fsf@metalevel.at> (Markus Triska's message of "Thu, 14 Jul 2016 17:10:14 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:121207 Archived-At: > 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