Subject: bug#16411: undo-only bugs

From: Stefan Monnier <[email-masked]>
Date: Fri, 10 Jan 2014 18:54:57 -0500

> I think the solution entails moving this sort of thing into a loop in
> undo-more:

>   (when (and (consp equiv) undo-no-redo)
>     ;; The equiv entry might point to another redo record if we have done
>     ;; undo-redo-undo-redo-... so skip to the very last equiv.
>     (while (let ((next (gethash equiv undo-equiv-table)))
>              (if next (setq equiv next))))
>     (setq pending-undo-list equiv))

Indeed.  Or, equivalently, changing `undo' so it only calls undo-more with
argument 1 (and use the above while loop between each call to undo-more).

> Recipe 2:
>   • Insert "aaa"
>   • Insert "bbb"
>   • Mark region around "aaa" but not "bbb"
>   • Undo (in region)
>   • Mark region around "bbb" and where "aaa" used to be
>   • Undo-only
>   • Expected: none of the above insertions are in the buffer
>   • Actual: buffer has aaa and bbb insertions

> The code appears to simply punt on undo-only in region and behaves
> like ordinary undo. Thus it undoes the redo record to bring back bbb.

undo-in-region does not implement undo-only, indeed.  I think the way to
implement undo-only is to change undo-make-selective-list so it also
skips redo entries (depending on undo-no-redo, obviously) using the
above while loop.

        Stefan