unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Barry OReilly <gundaetiapo@gmail.com>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: 16411@debbugs.gnu.org
Subject: bug#16411: undo-only bugs
Date: Sat, 18 Jan 2014 19:58:14 -0500	[thread overview]
Message-ID: <CAFM41H1-Ud8Kaw0hdShe8HgNUhfkKoyLG8_cxyUj0FeDB3TyRg@mail.gmail.com> (raw)
In-Reply-To: <CAFM41H3Q2je+rOUordHv5WbLmWqKPmXFdm_LdBnmGCZ48wA5AQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3493 bytes --]

After looking at and considering more of the undo code, here's my
current thinking about how to solve bug 2.

The Elisp manual states that undo elements of buffer-undo-list can be
of the form:

  (apply delta beg end funname . args)

Define a "redo element" as an element of buffer-undo-list created
because of an undo command. Suppose we change the way redo elements
are represented to:

  (apply delta beg end 'undo-redo . (undone-element undo-delta))

Where:
  • delta, beg, end are as documented.
  • undo-redo is a new function that copies undone-element, applies
    undo-delta, then calls primitive-undo on it.
  • undone-element is the undone element of buffer-undo-list.
  • undo-delta is (position . offset) indicating how undo-redo should
    modify a copy of undone-element in order to carry out the redo.

When executing undo-only:
  • Assume pending-undo-list can be lazily computed
  • Let undo-skip-set be an empty set of undo elements to skip
  • Iterate over pending-undo-list until prefix-arg undos complete:
    • If the element is in undo-skip-set:
      • Remove it from undo-skip-set
      • Continue loop
    • If the element is of the form for a redo element:
      • Insert its undone-element in the undo-skip-set
    • Else undo the element

Using a BST for the undo-skip-set would be appropriate, but I don't
see that one is available to core Elisp code. A skip list data
structure would be a simple option with similar performance
characteristics. Note: this is a different kind of "skip", you can
duckduckgo "skip lists".

In your earlier reply, you hinted that switching undo-only from using
the undo-equiv-table to calling undo-make-selective-list might create
a noticable performance regression. The latter is O(N*N) for N sized
undo history! I would expect undo-only will generally have an element
to find, in which case, being able to compute next elements of
pending-undo-list as needed instead of in full upfront may be a
sufficient solution.

If it isn't sufficient, I can also make the algorithm O(N*log(N)).
One way to do this is using another skip list to store the
undo-deltas: sort by position, and at each node store the sum of the
offsets over the skip interval following that node. The analogous
thing can be done with a BST: put the sum of a subtree's offsets at
each node. This is more complex in part because the sums need to be
updated during tree rotations.

There's another benefit to my proposed representation for redo
elements. Consider the use case:
  • Delete text X bytes large
  • Do Y cycles of undo and redo

As I understand the current code, the size of undo history grows by
approximately X*Y. With this new way to represent redo elements, undo
history grows approximately Y instead.

This proposal implies recursive calls to primitive-undo. The size of
the Lisp call stack would be a function of how deep redo records refer
to undone redo records. Maybe there are reasonable ways to deal with
that or maybe it's a non issue.

Are there examples of existing code putting (apply delta beg end
funname . args) into the buffer-undo-list? I want to see what the
options might be for pushing redo elements in that format. The best I
can think of right now is a dynamically bound variable set only during
an undo and examined in record functions in undo.c.

There's more I could say about other details, but I'll stop now to get
feedback on the overall idea.

[-- Attachment #2: Type: text/html, Size: 3770 bytes --]

  reply	other threads:[~2014-01-19  0:58 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-10 22:33 bug#16411: undo-only bugs Barry OReilly
2014-01-10 23:54 ` Stefan Monnier
2014-01-11  3:48   ` Barry OReilly
2014-01-11  4:29     ` Stefan Monnier
2014-01-11  5:09       ` Barry OReilly
2014-01-14  0:49         ` Stefan Monnier
2014-01-14  1:52           ` Stefan Monnier
2014-01-14 14:00             ` Barry OReilly
2014-01-19  0:58               ` Barry OReilly [this message]
2014-01-19  3:18                 ` Stefan Monnier
2014-01-19 16:57                   ` Barry OReilly
2014-02-14 18:51                     ` Barry OReilly
2014-02-14 22:29 ` Barry OReilly
2014-02-18 17:40 ` Barry OReilly
2014-02-26 15:20 ` bug#16411: undo in region corrupts existing text Barry OReilly
2014-02-27  5:02   ` Stefan Monnier
2014-05-13 15:01 ` bug#16411: undo-only bugs Barry OReilly
2014-05-14 18:06   ` Stefan Monnier
2014-05-14 18:45   ` Stefan Monnier
2014-05-14 19:55   ` Stefan Monnier
2014-05-14 21:56     ` Barry OReilly
2014-05-15  2:23       ` Stefan Monnier
2014-05-15  3:51         ` Barry OReilly
2014-05-15 13:00           ` Stefan Monnier
2014-05-28 18:42             ` Barry OReilly
2014-06-19 21:35               ` Stefan Monnier
2014-05-14 13:32 ` Barry OReilly

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

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAFM41H1-Ud8Kaw0hdShe8HgNUhfkKoyLG8_cxyUj0FeDB3TyRg@mail.gmail.com \
    --to=gundaetiapo@gmail.com \
    --cc=16411@debbugs.gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /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 public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).