Subject: bug#23906: 25.0.95; Undo boundary after process output is not consistent

From: Markus Triska <[email-masked]>
Date: Tue, 12 Jul 2016 23:02:09 +0200

Stefan Monnier <[email-masked]> writes:

>> with the Prolog program itself. For this reason, text properties would
>> not be a good fit for this use case: Users often want to store the query
>> results together with the source code, and using %@ allows that.
>
> I think he meant to use text-properties (actually, I think it would
> probably be an overlay) to *display* the special initial "%@" (which you
> currently insert manually "to give an indication that the query has been
> sent to the process") without actually inserting it in the buffer
> (e.g. with an after-string or some such).

Yes, I also understood it this way. Just to clearify: Eventually, there
actually must be a %@ as real text in the buffer, because otherwise what
the Prolog process emits will make the buffer no longer a valid Prolog
program. So, what the Prolog process emits must not only *appear* as
"commented out" in the buffer, but must actually *be* commented out.

A text property may get us over the initial %@ until process output
arrives, but at that point we will have to actually insert %@ into the
buffer, so that the query result does not interfere with the program
when users save it, or simply reconsult the buffer plus answer.

This is certainly doable, but not sufficient. An interaction with the
Prolog process can span several answers and even involve user input, and
I want all this to be removed again on undo. Please see below for more.

>>    1- just let the user hit undo an extra time when that happens.
>> That is the current state that I consider a bit unsatisfying, so I would
>> like to choose between 2, 3 and 4.
>
> Could you explain a bit why this is unsatisfying in ediprolog's case?

One important reason for this is the way that ediprolog is frequently
used: Typically, you use ediprolog to evaluate small self-contained test
cases and important queries directly within your buffer. Almost always
within a Prolog file, but of course also when composing e-mails to
discuss important Prolog features, bug reports, answer questions etc.

One very typical example: A user sends me a bug report together with
sample code, sample query and its result. Using ediprolog, I can -
directly from within the mail buffer - consult the code and evaluate the
query, and quickly see whether I can reproduce the problem. I leave this
evaluation in the buffer, can work on a fix in the library code,
reconsult the program, re-run the query, and extremely easily compare
the results because the previous result is also still in the buffer and
in fact placed directly on the line below the current one.

As such, I often use ediprolog to try out small self-contained test
cases while I am still developing a feature or working on a fix, to
track the current behaviour. At the same time, the test itself is often
also under development, so I cannot yet solidify this as an automated
unit test. Therefore, what it comes down to is often:

   *) work, work on fix
   *) peek, peek at result
   *) work, work on fix
   *) ...

And for such smaller peeks at the current results, I frequently need to
undo the whole interaction, and it is valuable during develpoment that
undo is extremely consistent in what it does. It is irritating to
always use C-/ for undo, except for 1 out of 10 times in such cases.

> In my shell buffers, I sometimes use undo and am generally happier with
> undo steps that are too fine grained than with undo steps which are too
> coarse because it's easier to just repeat C-/ than to try and recreate
> a missing intermediate point in the middle of an undo step.

I understand this. In the case of ediprolog, the good news is that the
whole interaction is *always* logged in a completely different buffer
too: *ediprolog-history* shows precisely what was sent to the Prolog
process, and what was emitted by the process, and users can always look
at that buffer if there is any doubt in retrospect about what was done.
Therefore, I would rather provide a consistent way for users to undo the
whole interaction at once. It can always be lookep up later if needed.

> IOW, maybe we should we aim to provide that behavior not just in
> ediprolog.el but also in comint, based on some user config.

Yes! Thank you for taking this general perspective. I must say at this
point that I have no experience with how such a "transactional" undo
would actually work out in practice. I can imagine that it is a bit
unusual at first. For ediprolog though, I am quite certain that I would
prefer it because, as explained above, the interactions are typically
short, and breaking up a short interaction into two or more parts only 1
out of N times is definitely worse than always treating it as a unit.

For comint and other modes, I can imagine that it could also be useful.

> In Viper, when you do an insertion ...

Thank you for the explanation!

> Using Viper's approach, you could for example throw away the
> undo-boundaries added since the last process-send-string.  I'd expect
> you'd do it right when you see Prolog's prompt.  So if you undo while
> Prolog is still in the middle of responding you might only undo parts of
> the current response (like now), but once a response is complete it will
> always be undone as an indivisible step.

This sounds like a great approach, thank you! I will try this.

All the best!
Markus