all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: phillip.lord@newcastle.ac.uk (Phillip Lord)
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Emacs-Devel devel <emacs-devel@gnu.org>
Subject: Re: disabling undo boundaries
Date: Mon, 11 May 2015 21:42:08 +0100	[thread overview]
Message-ID: <87oalqrgm7.fsf@newcastle.ac.uk> (raw)
In-Reply-To: <jwv617zx6z7.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Mon, 11 May 2015 15:30:33 -0400")

Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> This fails for me, unfortunately, the user might want to undo in the
>> other buffer. A priori, though, it seems to be a nice idea. I tried this
>> code for instance:
>> #+BEGIN_SRC emacs-lisp
>>   (defvar-local fix-test-on nil)
>>   (defun fix-test-after-change-function (&rest _)
>>     (when fix-test-on
>>       (let (
>>             (undo-inhibit-record-point t)
>>             )
>>         (with-current-buffer
>>             (get-buffer "*scratch*")
>>           (insert "a")))))
>>   (add-hook 'after-change-functions 'fix-test-after-change-function)
>> #+END_SRC
>> And that doesn't have the problem because the inhibit stops record_point
>> from ever setting the undo_boundary.
>
> So, you're saying that the above let binding fixes your problem?
> Then, I guess it's a valid option as well.  It sounds like an obscure
> work-around, so it probably deserves a clear comment.

Sort of. In this particular instance above, it does because
inhibit-record-point stops both the recording of point AND the insertion
of an undo boundary.



>>> - delay the modification of the other buffer (e.g. record in a-c-f the
>>> boundaries of the affected text, and process them later from
>>> post-command-hook).  Not sure if this would really help.
>> Unfortunately that wont work since there there can be many changes on
>> a-c-f for a single p-c-h call. So, I'd have to amalgamate all the
>> changes.
>
> Amalgamate is exactly what I meant by "record the boundaries".
> It's a fairly common approach, typically you only track the beg/end
> enclosing boundaries.

It's difficult in my case. The problem is I have two buffers which I am
keeping in sync. So I need to be able to convert a point location in one
with a point location in another. And I have to do this *before* the
change happens because otherwise the two buffers will hold content which
is not in sync (one has changed, the other hasn't been updated yet).

Unfortunately, the scope of the changes reported by the b-c-f and a-c-f
are not necessarily in agreement with each other -- subst-char-in-region
often gets the before-change region wrong. I have some logic for
detecting this, but it can be fouled by changes that both add and remove
from the buffer at the same time; in these cases, I have to copy the
entire buffer. Amalgamating many changes makes this much more likely to
happen.


>
> E.g. I use it in diff-mode to avoid modifying the buffer right in the
> middle of a-c-f, which tends to break all kinds of assumptions.
>
>>> - change your a-c-f so it records the buffer-undo-list at the beginning,
>>> and it removes the added boundary (if any) at the end.
>> The a-c-f doesn't work, unfortunately because the nil boundary is not
>> present till sometime after the a-c-f has been called (when? not sure).
>
> That is weird.  The code you quoted from record_point should be run
> "right away".  Are you sure you didn't check in the wrong buffer by
> any chance?
>
> I'd expect something like
>
>    (let ((old-ul buffer-undo-list))
>      (with-current-buffer "*scratch*"
>        <doyourthing>)
>      (and (consp buffer-undo-list)
>           (eq (cdr buffer-undo-list) old-ul)
>           (null (car buffer-undo-list))
>           (setq buffer-undo-list (cdr buffer-undo-list))))
>
> to do the trick.  Or, what am I missing?


It's rather more sinister than that. The code is this:

  if ((current_buffer != last_undo_buffer)
         && (MODIFF > SAVE_MODIFF))
     Fundo_boundary ();

  last_undo_buffer = current_buffer;

So, when the after-change-function runs the buffer-undo-list has
*already* been modified. But if the a-c-f function makes an undoable
change, then last_undo_buffer gets reset to the other buffer (*scratch*
in my case).

Now, the *next* change happens, and current_buffer != last_undo_buffer
is true, so we add a boundary BEFORE, we add the next undo. So, the
buffer change in a-c-f adds a boundary before the next change not after
the one that has just been added.


>> I did think of doing this with the pre/post-command-hook -- so, take the
>> car of the b-u-l on the pre-c-h, then on the post-c-h, scan till I get
>> to the old car and delete all nils placed there.
>
> But at that point you won't know which undo-boundaries were added
> because of the buffer-switch and which were added for other reasons.

Yep, that's a problem.

>
>> I can see a few problems with this. First, it will also remove any
>> undo-boundaries added by explict calls to undo-boundary; perhaps not a
>> huge problem as there do not appear to be that many of them in the lisp
>> code base.
>
> Since `doyourthing' shouldn't touch the source buffer, the source
> buffer's undo-list has no reason to have a hand-added undo-boundary.

In between the start and end of a command? That can happen. It's the
point of making undo-boundary a lisp callable function.

I had an evil thought on the way home. Rather than working backwards and
trying to remove the undo-boundary that had been added as a result of
the undo action in another buffer, why not just remove that logic from
undo.c? So, I've tried commenting out the four calls to Fundo_boundary
there and now everything works.

I haven't used this for my daily emacs yet, so perhaps there are demons
lurking, but my question would be, why should a undoable change in
*that* buffer cause a marker boundary in *this*? What is the point of
these undo-boundaries that are causing me all this grief?

Phil









  reply	other threads:[~2015-05-11 20:42 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-10 21:43 disabling undo boundaries Phillip Lord
2015-05-11  1:42 ` Stefan Monnier
2015-05-11 11:46   ` Phillip Lord
2015-05-11 14:45     ` Stefan Monnier
2015-05-11 16:31       ` Phillip Lord
2015-05-11 19:30         ` Stefan Monnier
2015-05-11 20:42           ` Phillip Lord [this message]
2015-05-11 22:23             ` Stefan Monnier
2015-05-12 11:52               ` Phillip Lord
2015-05-12 20:15                 ` Stefan Monnier
2015-05-12 20:59                   ` Phillip Lord
2015-05-13 12:32                     ` Stefan Monnier
2015-05-13 15:40                       ` Phillip Lord
2015-05-14 15:28                         ` Stefan Monnier
2015-05-15 12:27                           ` Phillip Lord
2015-05-15 18:08                             ` Stefan Monnier
2015-05-15 19:49                               ` Phillip Lord
2015-05-15 23:45                                 ` Stefan Monnier
2015-05-16 13:31                                   ` Phillip Lord
2015-05-19 11:59                                     ` Phillip Lord
2015-05-19 19:42                                       ` Stefan Monnier
2015-05-19 21:48                                         ` Phillip Lord
2015-05-20  2:00                                           ` Stefan Monnier
2015-05-20  7:45                                             ` Phillip Lord
2015-05-20 12:53                                               ` Stefan Monnier
2015-05-21 11:15                                                 ` Phillip Lord
2015-05-21 15:44                                                   ` Stefan Monnier
2015-05-21 17:03                                                     ` Phillip Lord
2015-05-27 11:46                                                       ` Phillip Lord
2015-06-29  0:46                                                         ` Stefan Monnier
2015-08-04 14:18                                                           ` Phillip Lord
2015-08-06 21:02                                                             ` Phillip Lord
2015-08-06 22:20                                                             ` Stefan Monnier
2015-08-07 13:40                                                               ` Phillip Lord
2015-08-07 13:59                                                                 ` David Kastrup
2015-08-07 21:10                                                                   ` Phillip Lord
2015-08-08  5:39                                                                     ` David Kastrup
2015-08-08  9:58                                                                       ` Phillip Lord
2015-08-07 17:10                                                                 ` Stefan Monnier
2015-08-08 21:28                                                                   ` Stefan Monnier
2015-08-09 15:39                                                                     ` Phillip Lord
2015-08-09 16:30                                                                       ` Stefan Monnier
2015-08-09 16:50                                                                         ` Phillip Lord
2015-08-09 17:40                                                                           ` Stefan Monnier
2015-08-10  9:27                                                                             ` Phillip Lord
2015-08-10 21:21                                                                               ` Phillip Lord
2015-08-12 21:15                                                                               ` Stefan Monnier
2015-08-12 22:34                                                                                 ` Phillip Lord
2015-08-13  2:23                                                                                   ` Stefan Monnier
2015-08-21  9:40                                                                                     ` Phillip Lord
2015-08-07 23:49                                                     ` Davis Herring
2015-08-08 10:01                                                       ` 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=87oalqrgm7.fsf@newcastle.ac.uk \
    --to=phillip.lord@newcastle.ac.uk \
    --cc=emacs-devel@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 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.